runtime-role-smoke-20260714.../docs/adr/ADR-001-controller-service-repository-boundaries.md

3.3 KiB

ADR-001: Controller-Service-Repository 경계 정의

Context

본 프로젝트(runtime-role-smoke-202607140500)는 Spring Boot 기반의 역할 관리 시스템이다. 다층 아키텍처에서 각 계층의 책임과 의존성 방향을 명확히 정의하여:

  • 코드 유지보수성 향상
  • 단위 테스트 용이성 확보
  • 계층 간 결합도 최소화

를 목적으로 한다.

Decision

1. Controller 계층

책임:

  • HTTP 요청/응답 처리
  • 입력 검증(Validation) 수행
  • Service 계층 호출 및 결과 매핑
  • 예외를 HTTP 응답으로 변환

금지 사항:

  • 비즈니스 로직 직접 구현 금지
  • Repository 직접 호출 금지
  • @Transactional 선언 금지

구현 규칙:

@RestController
@RequiredArgsConstructor
public class RoleController {
    private final RoleService roleService;
    
    @PostMapping("/roles")
    public ResponseEntity<RoleResponse> createRole(@Valid @RequestBody RoleRequest request) {
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(roleService.createRole(request));
    }
}

2. Service 계층

책임:

  • 비즈니스 로직 수행
  • 트랜잭션 관리
  • 도메인 객체 조작
  • Repository 호출 및 결과 가공

금지 사항:

  • HTTP 요청/응답 직접 처리 금지
  • @RequestBody, @RequestParam 등 HTTP 어노테이션 사용 금지

구현 규칙:

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class RoleService {
    private final RoleRepository roleRepository;
    
    @Transactional
    public RoleResponse createRole(RoleRequest request) {
        // 비즈니스 로직
        Role role = Role.create(request.getName(), request.getDescription());
        Role savedRole = roleRepository.save(role);
        return RoleResponse.from(savedRole);
    }
}

3. Repository 계층

책임:

  • 데이터베이스 접근
  • CRUD 연산 수행
  • 쿼리 메서드 정의

금지 사항:

  • 비즈니스 로직 포함 금지
  • Service 계층 직접 호출 금지

구현 규칙:

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
    Optional<Role> findByName(String name);
    boolean existsByName(String name);
}

4. 의존성 방향

Controller → Service → Repository → Domain/Entity
                ↑
            (Domain Event를 통한 역방향 허용)

의존성 규칙:

  • 상위 계층은 하위 계층에만 의존
  • 동일 계층 간 직접 의존 금지
  • Domain 객체는 어떤 계층에도 의존하지 않음

Alternatives

대안 1: Transactional Script 패턴

  • 모든 로직을 Controller에 포함
  • 단점: 테스트 어려움, 코드 중복
  • 채택하지 않음

대안 2: 도메인 주도 설계(DDD)

  • Aggregate, Entity, Value Object 세분화
  • 단점: 과도한 복잡성, 학습 곡선 높음
  • 현재 프로젝트 규모에 과도하여 채택하지 않음

Consequences

Positive:

  • 각 계층의 책임이 명확하여 코드 가독성 향상
  • 단위 테스트 시 Mock 객체 사용 용이
  • 향후 MSA 전환 시 서비스 분리 용이

Negative:

  • 간단한 CRUD 연산에도 다중 계층 코드 작성 필요 -初期開発時に多少のオーバーヘッド

Mitigation:

  • Lombok, MapStruct 활용으로 보일러플레이트 감소
  • 공통 응답/예외 처리基础设施建设