Dev./Spring

[Spring] interface의 default 메서드를 언제 써야 할까

limitation01 2025. 11. 29. 12:34

default 메서드란

설계 확장을 위한 도구

Java 8 이전에는 인터페이스에 추상 메서드만 선언할 수 있었다. 문제는 인터페이스를 이미 여러 구현체가 구현하고 있는 상황에서 메서드 하나를 추가하면 모든 구현체가 깨짐

이문제를 해결하기 위해 default 메서드가 나왔다

public interface Repository<T> {
    Optional<T> findById(Long id);

    default T getOrNull(Long id) {
        return findById(id).orElse(null);
    }
}

 

  • 인터페이스에 기본 구현을 제공
  • 기존 구현체를 깨지 않고 기능 추가 가능

무엇을 담당하는 메서드일까?

모든 구현체에서 동일하게 동작해야 하는 공통 행위
  1. 구현체마다 바뀌면 안되는 로직
  2. 맥락을 몰라도 실행 가능한 로직
  3. 단순하고 중립적인 로직

Repository에서 default 메서드가 허용되는 경우

1) Optional 처리 보조

default User findOrNull(Long id) {
    return findById(id).orElse(null);
}

 

  • Optional을 계속 풀어야 하는 번거로움 감소
  • null이면 어떻게 할지는 Service가 결정

 

2) 조회 패턴 통일

default boolean exists(Long id) {
    return findById(id).isPresent();
}

 

  • 단순히 있다 / 없다만 알려줌

 

3) 의미 없는 예외 (제한적 허용)

default User findOrThrow(Long id) {
    return findById(id)
        .orElseThrow(() -> new IllegalStateException("User not found"));
}

 

 

온전하게 허용되는 경우는 아니지만 가능한 이유는

  • HTTP 없음
  • ErrorCode 없음
  • 비즈니스 메시지 없음
  • 비정상 상태라는 표현만 사용

 

내가 생각해 봐야 할 것

이번 프로젝트에 팀 코드 컨벤션으로 공통 커스텀 예외처리를 적용하였다. default 메서드 예외처리도 다음과 같이 작성했는데

default User findOrThrow(Long id) {
    return findById(id)
        .orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
}

리뷰를 받다보니 예외처리 위치가 레포지토리까지 들어와야 할까 라는 질문을 받았다. 

스스로 생각해본 결과 비즈니스 로직의 해석이 레포지토리, 데이터 계층까지 내려왔다고 판단했다. 그 근거는

  1. Repository가 응답 규약을 이미 알고있음
  2. HTTP 404가 결정됨
  3. ErrorCode는 비즈니스 로직의 예외처리 상수집합인데 ErrorCode 수정시 Repoository도 수정 필요

이와 같은 근거로 서비스단에서 처리되어야 하는게 맞다고 생각했다.

배운 점

default 메서드는 공통 행위를 담는 곳이지 의미를 결정하는 곳이 아니다!