Spring 7기 프로젝트/일정관리 프로젝트

[트러블슈팅] Repository에서 예외 처리와 Optional 패턴

JuNo_12 2025. 5. 13. 16:55

문제 상황

  • findById 등에서 DB에 특정 값이 없을 때,
    • 직접 예외를 던지는 게 좋은지,
    • 아니면 Optional로 감싸서 반환하는 게 좋은지 고민이 들었다.

 

 

두 가지 패턴

1. Repository에서 비즈니스 예외 바로 던지기

@Override
public Optional<Schedule> findById(Long id) {
    try {
        Schedule schedule = jdbcTemplate.queryForObject(sql, new Object[]{id}, rowMapper);
        return Optional.of(schedule);
    } catch (EmptyResultDataAccessException e) {
        throw new ScheduleNotFoundException("해당 ID의 일정이 없습니다. ID = " + id);
    }
}

단점

  • Repository에서 곧장 비즈니스 레이어의 예외()를 다루게 됨 → 계층 분리가 깨질 수 있음 ScheduleNotFoundException
  • 데이터를 "없음"으로 처리할 때도 무조건 예외가 발생함

2. Optional.empty()를 반환하고 Service에서 예외 처리

@Override
public Optional<Schedule> findById(Long id) {
    try {
        Schedule schedule = jdbcTemplate.queryForObject(sql, new Object[]{id}, rowMapper);
        return Optional.of(schedule);
    } catch (EmptyResultDataAccessException e) {
        return Optional.empty();
    }
}
// Service 계층에서
Schedule schedule = scheduleRepository.findById(id)
    .orElseThrow(() -> new ScheduleNotFoundException("해당 일정 없음: ID = " + id));

장점

  • Repository는 단순히 "데이터 있음/없음"만 표현
  • 비즈니스적 결정(예외 발생)은 Service 계층에서 담당!
  • 계층 간 책임이 명확해지고, 유연성이 높아짐

결론

  • Repository에서는 Optional.empty()로 "데이터 없음"을 반환하는 게 가장 좋다!
  • 비즈니스 예외 변환은 Service 계층에서 처리하자.

 

반환 타입이 Optional인 이유

  • Optional<T>로 반환한다는 건
    → "이 데이터를 요청했을 때, 없을 수도 있음"을 명확하게 보여주기 위함
  • 즉,
    • 1개의 값이 나올 수도 있고
    • 아무 결과도 없을 수도 있다라는 것을 반환 타입에 적극적으로 드러낸다.
  • 단일 PK(id)로 조회할 때
    • "해당 id의 Schedule이 DB에 없으면 어떻게 할 거야?"를 생각해야 함!

 

List<> vs Optional<> 어떤 차이가?

반환 타입 의미 관례
Optional<Schedule> "최대 1건 조회, 없을 수도 있음"을 명확히 표현 단건(PK) 조회 표준
List<Schedule> "결과가 0개~N개 모두 가능하다" 복수건(조건검색 등)에서 표준
(null) Schedule 없음은 null로 표현(비권장) 권장하지 않음
  • 단건 조회: Optional을 주로 사용
  • 복수건(검색 등): List을 주로 사용
  • 단건(PK로 조회한 결과 등)인데 List를 쓰면 "왜 여러 건이 나올 수 있지?" 혼동을 줄 수 있음