전체 일정 조회 API와 선택 일정 조회 API를 구현할 때, queryForObject와 query의 차이를 명확히 이해하지 못해 혼란이 있었다. 두 메서드는 비슷해 보이지만 반환하는 결과가 다르기 때문에 상황에 맞는 사용이 중요하다.
전체 일정 조회에서는 여러 개의 일정이 반환되므로 query를 사용해야 하지만, 선택 일정 조회에서도 query를 사용하다 보니 단일 결과를 제대로 처리하지 못했다. 결과적으로 선택 일정 조회 시, 결과가 부정확하게 나왔다.
전체 일정 조회의 경우 query를 사용해 다중 행을 리스트로 반환하고, 선택 일정 조회에서는 queryForObject를 사용해 단일 행을 반환하는 것으로 문제를 해결했다.
// 선택 일정 조회 - queryForObject 사용
public ScheduleResponseDto getSchedule(@PathVariable Long id) {
String sql = "SELECT * FROM schedules WHERE id = ?";
return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> new ScheduleResponseDto(
rs.getLong("id"),
rs.getString("userName"),
rs.getString("updateDate"),
rs.getString("contents")
), id);
}
query와 queryForObject는 결과가 여러 개일 때와 하나일 때 명확히 구분해서 사용해야 한다. 특히, 단일 행을 처리할 때는 queryForObject를 사용하는 것이 올바른 선택이다.
초기 API 설계에서 updateDate 필드를 String 타입으로 처리했지만, 날짜와 시간을 LocalDateTime으로 다루고자 했다. 하지만 API 요청과 응답에서 날짜 타입 변환 과정에서 문제에 직면했다.
ResultSet에서 updateDate 값을 String으로 가져와서 LocalDateTime으로 변환하는 과정에서 타입 불일치 오류가 발생했다.엔티티(Schedule)에서 updateDate를 LocalDateTime으로 유지하면서, DTO에서 LocalDateTime을 String으로 변환하여 클라이언트에 전달하는 방법을 선택했다. ScheduleResponseDto에서 DateTimeFormatter를 사용해 LocalDateTime을 ISO 8601 형식으로 변환해 전달했다.
public class ScheduleResponseDto {
private Long id;
private String userName;
private String updateDate;
private String contents;
public ScheduleResponseDto(Schedule schedule) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
this.updateDate = schedule.getUpdateDate().format(formatter); // LocalDateTime을 String으로 변환
this.id = schedule.getId();
this.userName = schedule.getUserName();
this.contents = schedule.getContents();
}
}
LocalDateTime을 API에서 직접 사용하지 않고 String으로 변환하여 처리하는 것이 더 실용적임을 알게 되었다. 클라이언트와 서버 간에 날짜 형식이 일치하지 않으면 오류가 발생할 수 있기 때문에, 이와 같은 변환 과정이 필요하다.
이번 트러블슈팅을 통해 날짜 처리 방식(LocalDateTime)과 쿼리 메서드(query, queryForObject)의 차이를 확실하게 이해할 수 있었다. 앞으로 API 설계 시, 이 부분을 더 신경 써야 할 필요성을 느꼈다.