-
[과제] 일정 관리 앱 만들기 필수 Lv1내일배움캠프/과제 2025. 3. 25. 12:41
✅ Lv1. 일정 생성 및 조회
1️⃣ 과제 조건
- 일정 생성(일정 작성하기)
- 일정 생성 시, 포함되어야할 데이터
- 할일, 작성자명, 비밀번호, 작성/수정일을 저장
- 작성/수정일은 날짜와 시간을 모두 포함한 형태
- 각 일정의 고유 식별자(ID)를 자동으로 생성하여 관리
- 최초 입력 시, 수정일은 작성일과 동일
- 일정 생성 시, 포함되어야할 데이터
- 전체 일정 조회(등록된 일정 불러오기)
- 다음 조건을 바탕으로 등록된 일정 목록을 전부 조회
- 수정일 (형식 : YYYY-MM-DD)
- 작성자명
- 조건 중 한 가지만을 충족하거나, 둘 다 충족을 하지 않을 수도, 두 가지를 모두 충족할 수도 있습니다.
- 수정일 기준 내림차순으로 정렬하여 조회
- 다음 조건을 바탕으로 등록된 일정 목록을 전부 조회
- 선택 일정 조회(선택한 일정 정보 불러오기)
- 선택한 일정 단건의 정보를 조회할 수 있습니다.
- 일정의 고유 식별자(ID)를 사용하여 조회합니다.
2️⃣ 일정 생성
1. 일정을 저장할 Schedule Entity 작성
public class Schedule {private Long id; // PKprivate String schedule; // 일정 내용private String regNm; // 작성자 명private String password; // 비밀번호private LocalDateTime regDt; // 작성일private LocalDateTime modDt; // 수정일}2. 일정 저장을 위한 데이터 요청 Dto 작성
public class ScheduleReqDto {@Schema(description = "일정 내용")private String schedule;@Schema(description = "작성자 명")private String regNm;@Schema(description = "비밀번호")private String password;}3. 일정 반환을 위한 응답 Dto 작성
public class ScheduleResDto {@Schema(description = "PK")private Long id;@Schema(description = "일정 내용")private String schedule;@Schema(description = "작성자 명")private String regNm;@Schema(description = "등록일")private String regDt;@Schema(description = "수정일")private String modDt;}4. Controller @RequestBody 를 활용하여 json 형식으로 data 받음
@PostMappingpublic BaseResponse<ScheduleResDto> saveSchedule(@RequestBody ScheduleReqDto dto) {return BaseResponse.from(scheduleService.saveSchedule(dto));}5. Service 에서는 저장 시간을 LocalDatime.now()를 사용하였다.
@Overridepublic ScheduleResDto saveSchedule(ScheduleReqDto dto) {LocalDateTime now = LocalDateTime.now(); // 현재 시각Schedule schedule = new Schedule(dto.getSchedule(), dto.getRegNm(), dto.getPassword(), now, now);return scheduleRepository.saveSchedule(schedule);}6. Repository에서는 SimpleJdbcinsert 를 사용하여 각 파라미터에 데이터를 넣어 insert 해줌
public ScheduleResDto saveSchedule(Schedule schedule) {SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);jdbcInsert.withTableName("schedule").usingGeneratedKeyColumns("id");Map<String, Object> parameters = new HashMap<>();parameters.put("schedule", schedule.getSchedule());parameters.put("regNm", schedule.getRegNm());parameters.put("password", schedule.getPassword());parameters.put("regDt", schedule.getRegDt());parameters.put("modDt", schedule.getModDt());Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters)); // PK Returnschedule.setId(key.longValue());return new ScheduleResDto(schedule);}3️⃣ 전체 일정 조회
1. @RequestParam 사용하여 수정일, 작성자 정보 입력 받기
@GetMappingpublic BaseResponse<List<ScheduleResDto>> findAllSchedule(@RequestParam(required = false) String modDt, @RequestParam(required = false) String regNm) {return BaseResponse.from(scheduleService.findAllSchedule(modDt, regNm));}조건은 필수가 아니기에 required = false 처리를 해주었다.
2. service 에서 repository 호출
public List<ScheduleResDto> findAllSchedule(String modDt, String regNm) {return scheduleRepository.findAllSchedule(modDt, regNm);}3. Repository
public List<ScheduleResDto> findAllSchedule(String modDt, String regNm) {List<Object> params = new ArrayList<>();StringBuilder query = new StringBuilder().append("SELECT id, schedule, reg_nm, password, reg_dt, mod_dt FROM schedule \n").append(" WHERE 1 = 1 \n");if (StringUtils.isNotBlank(modDt)) { // 수정일 검색조건이 있을 경우query.append(" AND DATE(mod_dt) = ? \n");params.add(modDt);}if (StringUtils.isNotBlank(regNm)) { // 작성자명 검색조건이 있을 경우query.append(" AND reg_nm = ? \n");params.add(regNm);}query.append(" ORDER BY mod_dt DESC");List<Schedule> resultList = jdbcTemplate.query(query.toString(), params.toArray(), this.scheduleRowMapper());return resultList.stream().map(ScheduleResDto::new).collect(Collectors.toList());}modDt 나 regNm의 검색 조건이 있을 경우 where 절을 추가해주었다.
private RowMapper<Schedule> scheduleRowMapper() {return (rs, rowNum) -> new Schedule(rs.getLong("id"),rs.getString("schedule"),rs.getString("reg_nm"),rs.getString("password"),rs.getTimestamp("reg_dt").toLocalDateTime(),rs.getTimestamp("mod_dt").toLocalDateTime());}rowMapper 에서 가져올 데이터를 지정해주었다.
그 후 비밀번호를 제외한 형식으로 ResDto를 생성하여 List 목록으로 return
public ScheduleResDto(Schedule schedule) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");this.id = schedule.getId();this.schedule = schedule.getSchedule();this.regNm = schedule.getRegNm();this.regDt = formatter.format(schedule.getRegDt());this.modDt = formatter.format(schedule.getModDt());}4️⃣ 선택 일정 조회
1. Controller @PathVariable 을 사용하여 일정 id값을 받음
@GetMapping("/{id}")public BaseResponse<ScheduleResDto> findScheduleById(@PathVariable Long id) {return BaseResponse.from(scheduleService.findScheduleById(id));}2. Service
public ScheduleResDto findScheduleById(Long id) {return scheduleRepository.findScheduleById(id);}3. Repository
public ScheduleResDto findScheduleById(Long id) {StringBuilder query = new StringBuilder().append("SELECT id, schedule, reg_nm, password, reg_dt, mod_dt FROM schedule \n").append(" WHERE id = ? \n");List<Schedule> resultList = jdbcTemplate.query(query.toString(), this.scheduleRowMapper(), id);return resultList.stream().findAny().map(ScheduleResDto::new).orElseThrow(() -> new CustomException(CommonExceptionResultMessage.NOT_FOUND, "일정 조회 실패: ID " + id + "에 해당하는 일정 없음"));}pk로 조회. 만약 데이터 조회가 안될 경우 CustomException을 throw
5️⃣트러블 슈팅
그런데 데이터베이스를 열어보면 사용자의 비밀번호가 암호화 되지 않고 보안에 취약한 것을 보았다.
보안에 취약하지 않게 비밀번호를 암호화 하는 방식을 선택했다.
@Overridepublic 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 scheduleRepository.saveSchedule(schedule);}PasswordEncoder 를 사용하여 bcrypt로 비밀번호를 암호화 하여 데이터를 저장하였다.
또 데이터를 입력받을 때 필수데이터를 따로 지정하고 싶었다.
@PostMappingpublic BaseResponse<ScheduleResDto> saveSchedule(@RequestBody @Valid ScheduleReqDto dto) {return BaseResponse.from(scheduleService.saveSchedule(dto));}찾아보았더니 @Valid 를 사용하면 api 데이터를 받을 때 검증을 진행할 수 있었다.
public class ScheduleReqDto {@Schema(description = "일정 내용")@NotBlankprivate String schedule;@Schema(description = "작성자 명")@NotBlankprivate String regNm;@Schema(description = "비밀번호")@NotBlankprivate String password;}각 필수 데이터 별로 @NotBlank 어노테이션을 사용하여 데이터를 필수로 받도록 검증하였다.
'내일배움캠프 > 과제' 카테고리의 다른 글
[과제] 일정 관리 앱 만들기 도전 Lv3 (0) 2025.03.25 [과제] 일정 관리 앱 만들기 필수 Lv2 (0) 2025.03.25 [과제] 키오스크 도전 Lv2 (2) 2025.03.13 [과제] 키오스크 도전 Lv1 (0) 2025.03.13 [과제] 키오스크 필수 Lv5 (1) 2025.03.13 - 일정 생성(일정 작성하기)