이론/백엔드 개념정리

Repository에서 예외 처리: 단일 책임 원칙(SRP) 위배인가?

블스뜸 2025. 5. 23. 17:47

Repository에서 데이터를 조회하거나 수정할 때 예외를 발생시키는 것이 단일 책임 원칙(SRP)을 위배하는지에 대한 고민을 하게 되었다. 특히 update 기능 구현 시 발생할 수 있는 쿼리 유효성 문제나 접근 불가능 문제와 같은 예외를 어디서 처리해야 할지 명확한 기준이 필요할 것 같아서 조사해보았다

Repository의 주된 책임

Repository는 다음과 같은 핵심 책임을 가진다:

  • 데이터 접근 추상화: 데이터베이스와 같은 영속성 계층에 대한 접근을 추상화하여, 서비스 계층이 특정 데이터 저장 방식(예: RDBMS, NoSQL)에 의존하지 않도록 한다.
  • CRUD 작업 수행: 엔티티의 생성(Create), 조회(Read), 갱신(Update), 삭제(Delete)와 같은 기본적인 데이터 작업을 수행한다.
  • 영속성 기술 관련 예외 처리: 데이터베이스 접근 중 발생할 수 있는 저수준의 기술적 예외를 처리한다.

Repository에서의 예외 처리와 SRP

어떤 예외 처리가 SRP를 위배하지 않는지에 대한 판단 기준은 예외의 성격에 달려 있다.

1. 기술적/영속성 계층 예외 처리 (SRP 위배 아님 - 권장)

  • 목적: 데이터베이스 통신 오류, 제약 조건 위반(예: DuplicateKeyException, DataIntegrityViolationException), 연결 끊김, 트랜잭션 실패 등 영속성 계층에서 발생하는 저수준의 기술적 예외를 처리하는 것은 Repository의 책임 범위 내에 속한다.
  • 방법: 스프링의 경우 DataAccessException 계층으로 추상화된 예외를 던지거나, JPA/Hibernate의 경우 PersistenceException 또는 그 하위 예외들을 처리한다. 필요하다면 이를 좀 더 의미 있는(하지만 비즈니스 규칙과 직접 관련 없는) 상위 추상화된 예외로 변환하여 상위 계층으로 던질 수 있다.
    • 예시: save() 시 DuplicateKeyException이 발생하면, 이를 AlreadyExistsException (도메인 예외는 아님)으로 변환하여 상위 계층으로 던질 수 있다. 데이터베이스 연결 문제 발생 시 DataAccessException을 그대로 던지거나 로깅 후 재시도 로직을 포함할 수 있다.
  • SRP 관점: Repository가 자신의 주된 책임(데이터 영속화)을 수행하는 과정에서 발생하는 기술적 문제를 다루는 것은 그 책임의 자연스러운 연장선이다. 이는 "데이터 접근 로직이 변경될 때 Repository가 변경된다"는 SRP의 본질에 부합한다.

2. 비즈니스 로직 관련 예외 처리 (SRP 위배 가능성 높음)

  • 목적: "재고가 부족합니다", "게시글이 삭제되었습니다", "사용자 권한이 없습니다"와 같이 도메인 특화된 비즈니스 규칙 위반으로 인한 예외를 Repository에서 직접 처리하는 것은 SRP를 위배할 가능성이 높다.
  • 예시:
    • postRepository.findById(id) 호출 후 orElseThrow(() -> new PostNotFoundException("게시글을 찾을 수 없습니다."))와 같이 비즈니스 의미를 담은 예외를 직접 던지는 경우.
    • 댓글 작성 시, commentRepository 내에서 게시글의 상태를 확인하여 PostStatusInvalidException을 던지는 경우.
  • SRP 관점: 이러한 예외는 "게시글 조회" 또는 "댓글 생성"이라는 비즈니스 로직의 유효성 검사 또는 규칙 위반에 해당한다. 이는 서비스 계층의 책임이지, Repository의 책임이 아니다. Repository는 "데이터를 가져오거나 저장하는 것"에 집중해야 하며, 가져온 데이터가 비즈니스 로직 상 유효한지 판단하는 것은 상위 계층(서비스 계층)에 위임해야 한다. Repository에서 비즈니스 예외를 처리하기 시작하면, "비즈니스 규칙이 변경될 때 Repository가 변경되는" 상황이 발생하여 SRP를 위배하게 된다.

결론

Repository에서는 데이터베이스 접근에 따른 저수준의 기술적 예외 (예: DataAccessException, PersistenceException의 하위 예외들)를 처리하고, 필요하다면 이를 더 상위 추상화된 (하지만 비즈니스 규칙과 직접 관련 없는) 예외로 래핑하여 던지는 것은 SRP를 위배하지 않는다.

그러나 "특정 비즈니스 규칙 위반"과 관련된 예외 (예: "상품 재고 부족", "없는 사용자")를 직접 생성하고 던지는 것은 Repository가 아닌 서비스 계층의 책임이며, 이를 Repository에서 처리할 경우 SRP를 위배하게 된다. Repository는 데이터 조회 및 저장 기능에 집중하고, 조회/저장된 데이터의 비즈니스 유효성 판단은 서비스 계층에 위임해야 한다.