Files
project-auth-server/docs/topics/02-clean-architecture/03-adr-boundary-refactoring.md
T

3.7 KiB

ADR-003: AGENTS 기준 레이어 경계 리팩토링

Status

Accepted

Date

2026-04-14

Context

AGENTS.md와 standards/examples는 레이어별 소유 책임을 명확히 나누지만, 일부 구현은 편의상 경계 관심사를 직접 들고 있었다.

  • presentation 응답 모델이 MDC와 현재 시각을 직접 읽었다.
  • OAuth2 callback controller와 mapper가 Spring Security 타입과 provider registration 해석을 직접 다뤘다.
  • repository adapter가 transaction boundary를 소유했다.
  • Vault Transit client가 ad-hoc JSON/URL/header 조립을 핵심 로직 안에 섞고 있었다.

이 결정은 기능을 바꾸기보다, 같은 인증 플로우를 유지하면서 경계 위반 가능성을 줄이기 위한 것이다.

Decision Drivers

  • 응답 DTO/model은 순수 transport 계약이어야 한다.
  • 현재 사용자와 provider registration 해석은 web/security boundary에서 끝나야 한다.
  • transaction은 application use case 작업 단위에서 소유해야 한다.
  • infrastructure adapter는 기술 번역을 담당하되 business workflow를 소유하지 않아야 한다.
  • 같은 위반이 재발하지 않도록 ArchUnit 테스트로 구조를 검증해야 한다.

Considered Options

Option 1: 기존 구조 유지 후 국소 수정

  • 장점: 수정 파일 수가 적다.
  • 단점: ApiResult, controller, mapper, repository adapter에 섞인 책임이 남아 같은 문제가 반복된다.
  • 트레이드오프: 단기 변경은 작지만 standards/examples와 계속 어긋난다.

Option 2: 경계별 소유자를 다시 지정

  • 장점: presentation은 HTTP 계약, bootstrap은 request/security context, application은 transaction, infrastructure는 기술 번역에 집중한다.
  • 단점: 조립 코드와 테스트 fixture 수정이 필요하다.
  • 트레이드오프: 초기 변경량은 늘지만 이후 기능 추가 시 경계 판단 비용이 줄어든다.

Decision

Option 2를 선택해 request metadata, OAuth2 provider mapping, transaction boundary, external integration DTO/translation의 소유 위치를 각 레이어 기준에 맞게 재배치한다.

Consequences

긍정적 결과

  • ApiResult는 MDC나 clock을 모르는 순수 envelope가 되었다.
  • OAuth2 controller는 Spring Security Authentication 대신 presentation 전용 principal을 받는다.
  • provider registration ID와 redirect path는 bootstrap security configuration에서 조립한다.
  • repository adapter의 transaction annotation을 제거하고 application collaborator가 transaction boundary를 가진다.
  • Vault Transit client는 typed request/response와 명시적 infrastructure exception translation을 사용한다.
  • ArchUnit이 presentation의 SecurityContext 직접 접근, ApiResult의 시간/MDC 의존, infrastructure transaction 소유를 막는다.

부정적 결과

  • controller/advice 생성자에 ApiResultFactory 의존성이 추가된다.
  • use case 내부 collaborator가 늘어나면서 bootstrap bean wiring이 길어졌다.
  • OAuth2 callback 테스트는 Spring Security token 대신 전용 principal fixture를 사용한다.

위험 완화

  • 외부 API 응답 shape와 endpoint path는 유지한다.
  • ./gradlew test로 application, presentation, infrastructure, bootstrap 테스트를 모두 통과시킨다.
  • DB provider별 필수 필드는 Flyway constraint로 한 번 더 보호한다.

후속 정리

본 ADR 시점에 정리된 Vault Transit client 는 이후 ADR-002 Keycloak 전환 에서 자체 JWT 발급 책임이 사라지면서 통째로 제거됨. 자세한 제거 범위는 04-adr-token-ownership-cleanup.md.