-
[과제] 일정 관리 앱 만들기 필수 Lv2내일배움캠프/과제 2025. 3. 25. 13:09
✅ Lv2. 일정 수정 및 삭제
1️⃣ 과제 조건
- 선택한 일정 수정
- 선택한 일정 내용 중 할일, 작성자명 만 수정 가능
- 서버에 일정 수정을 요청할 때 비밀번호를 함께 전달합니다.
- 작성일 은 변경할 수 없으며, 수정일 은 수정 완료 시, 수정한 시점으로 변경합니다.
- 선택한 일정 내용 중 할일, 작성자명 만 수정 가능
- 선택한 일정 삭제
- 선택한 일정을 삭제할 수 있습니다.
- 서버에 일정 수정을 요청할 때 비밀번호를 함께 전달합니다.
- 선택한 일정을 삭제할 수 있습니다.
2️⃣ 트러블 슈팅
이번엔 먼저 수정사항이 생각이 났다.
Repository는 오직 DB와의 연결만을 구현하도록 하고 다른 로직을 제외하고 싶다는 생각이 들었다.
1. Repository
기존에는 ScheduleResDto 를 return 해주었는데 Entity를 return 해주도록 변경하였고, findScheduleById에서 데이터가 없을 시 throw 해주던 것을 지웠다.
public Schedule saveSchedule(Schedule schedule) { ... Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters)); // PK Return schedule.setId(key.longValue()); return schedule; } @Override public List<Schedule> findAllSchedule(String modDt, String regNm) { ... return jdbcTemplate.query(query.toString(), params.toArray(), this.scheduleRowMapper()); } @Override public Optional<Schedule> findScheduleById(Long id) { ... return resultList.stream().findAny(); }
2. Service
기존에는 Repository 에서 ResDto로 변환하여 준것을 그대로 return 해주었는데 서비스는 로직 담당이므로, Repository에서 하던 서비스들을 Service로 다 옮겼다.
@Override public ScheduleResDto saveSchedule(ScheduleReqDto dto) { LocalDateTime now = LocalDateTime.now(); // 현재 시각 String encodePw = passwordEncoder.encode(dto.getPassword()); // 비밀번호 암호화 Schedule schedule = new Schedule(dto.getSchedule(), dto.getRegNm(), encodePw, now, now); return new ScheduleResDto(scheduleRepository.saveSchedule(schedule)); } @Override public List<ScheduleResDto> findAllSchedule(String modDt, String regNm) { return scheduleRepository.findAllSchedule(modDt, regNm).stream() .map(ScheduleResDto::new) .collect(Collectors.toList()); } @Override public ScheduleResDto findScheduleById(Long id) { return scheduleRepository.findScheduleById(id) .map(ScheduleResDto::new) .orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + " 에 해당하는 일정 없음")); }
3️⃣ 일정 수정
1. Controller
일정 pk값과, 수정할 일정 데이터를 받음
@PutMapping("/{id}") public BaseResponse<ScheduleResDto> updateSchedule(@PathVariable Long id, @RequestBody @Valid ScheduleReqDto dto) { return BaseResponse.from(scheduleService.updateSchedule(id, dto)); }
2. Service
기존에 있던 findScheduleById를 활용하여 유효한 일정인지 먼저 조회 후
passwordEncoder에 있는 matches 함수로 비밀번호가 일치한지 확인
그 후 새로운 정보로 update 해주고 데이터를 update
public ScheduleResDto updateSchedule(Long id, ScheduleReqDto dto) { // 유효한 일정인지 조회 Schedule schedule = scheduleRepository.findScheduleById(id) .orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + " 에 해당하는 일정 없음")); String pw = schedule.getPassword(); // 비밀번호 검사 if (!passwordEncoder.matches(dto.getPassword(), pw)) { throw new CustomException(CommonExceptionResultMessage.PW_MISMATCH); } // 새로운 정보 update schedule.setSchedule(dto.getSchedule()); // 일정 schedule.setRegNm(dto.getRegNm()); // 작성자명 schedule.setModDt(LocalDateTime.now()); // 수정 시간 // 일정 수정 int result = scheduleRepository.updateSchedule(schedule); if (result == 0) { // update 된 row 가 없으면 throw throw new CustomException(CommonExceptionResultMessage.DB_FAIL); } return new ScheduleResDto(schedule); }
3. Repository
public int updateSchedule(Schedule schedule) { StringBuilder query = new StringBuilder() .append("UPDATE schedule \n") .append(" SET schedule = ? \n") .append(" , reg_nm = ? \n") .append(" , mod_dt = ? \n") .append(" WHERE id = ?"); List<Object> params = new ArrayList<>(); params.add(schedule.getSchedule()); params.add(schedule.getRegNm()); params.add(schedule.getModDt()); params.add(schedule.getId()); return jdbcTemplate.update(query.toString(), params.toArray()); // update row 수 return }
4️⃣ 일정 삭제
1. Entity 에 삭제 여부 delDt 추가
public class Schedule { private Long id; // PK private String schedule; // 일정 내용 private String regNm; // 작성자 명 private String password; // 비밀번호 private LocalDateTime regDt; // 작성일 private LocalDateTime modDt; // 수정일 private LocalDateTime delDt; // 삭제일 }
2. 일정 삭제를 위한 DelDto
@Data public class ScheduleDelDto { @Schema(description = "비밀번호") @NotBlank private String password; }
3. Controller, id와 Dto를 받음
@DeleteMapping("/{id}") public BaseResponse<Boolean> deleteSchedule( @PathVariable Long id, @RequestBody @Valid ScheduleDelDto dto) { scheduleService.deleteSchedule(id, dto); return BaseResponse.from(true); }
4. Service
똑같이 비밀번호를 검증하고 Delete 처리
public void deleteSchedule(Long id, ScheduleDelDto dto) { // 유효한 일정인지 조회 Schedule schedule = scheduleRepository.findScheduleById(id) .orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + " 에 해당하는 일정 없음")); String pw = schedule.getPassword(); // 비밀번호 검사 if (!passwordEncoder.matches(dto.getPassword(), pw)) { throw new CustomException(CommonExceptionResultMessage.PW_MISMATCH); } schedule.setDelDt(LocalDateTime.now()); // 삭제 시간 int result = scheduleRepository.deleteSchedule(schedule); // 일정 삭제 if (result == 0) { // update 된 row 가 없으면 throw throw new CustomException(CommonExceptionResultMessage.DB_FAIL); } }
5. Repository
데이터를 실제로 Delete 하지 않고 삭제 여부 컬럼을 추가 해주어 soft 삭제하는 방식을 사용
public int deleteSchedule(Schedule schedule) { StringBuilder query = new StringBuilder() .append("UPDATE schedule \n") .append(" SET del_dt = ? \n") .append(" WHERE id = ? AND del_dt IS NULL"); List<Object> params = new ArrayList<>(); params.add(schedule.getDelDt()); params.add(schedule.getId()); return jdbcTemplate.update(query.toString(), params.toArray()); // delete row 수 return }
5️⃣ 리팩토링
아래의 코드가 삭제랑 수정할 때 중복되는 코드이기에 validSchedule로 묶어주었음.
// 유효한 일정인지 조회 Schedule schedule = scheduleRepository.findScheduleById(id) .orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + " 에 해당하는 일정 없음")); String pw = schedule.getPassword(); // 비밀번호 검사 if (!passwordEncoder.matches(dto.getPassword(), pw)) { throw new CustomException(CommonExceptionResultMessage.PW_MISMATCH); }
private Schedule validSchedule(Long id, String inputPw) { // 유효한 일정인지 조회 Schedule schedule = scheduleRepository.findScheduleById(id) .orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + " 에 해당하는 일정 없음")); String pw = schedule.getPassword(); // 비밀번호 검사 if (!passwordEncoder.matches(inputPw, pw)) { throw new CustomException(CommonExceptionResultMessage.PW_MISMATCH); } return schedule; }
'내일배움캠프 > 과제' 카테고리의 다른 글
[과제] 일정 관리 앱 만들기 도전 Lv4 (0) 2025.03.25 [과제] 일정 관리 앱 만들기 도전 Lv3 (0) 2025.03.25 [과제] 일정 관리 앱 만들기 필수 Lv1 (0) 2025.03.25 [과제] 키오스크 도전 Lv2 (2) 2025.03.13 [과제] 키오스크 도전 Lv1 (0) 2025.03.13 - 선택한 일정 수정