본문으로 건너뛰기

Spring Boot

본 문서는 백엔드 애플리케이션의 구조와 그 선택의 근거를 정의합니다.

두 앱에 걸친 구성과 계약, 배포 단위는 디커플드 아키텍처가 소유합니다. 품질 목표와 기술 스택 전제가 거기에 있으며 본 문서는 그 안에서 백엔드가 차지하는 부분만 다룹니다.

세부 규칙은 본문에 직접 기재하지 않고 참조 문서가 원본으로 관리합니다. 본문은 왜 그렇게 나누었는가를 설명하고 참조 문서는 무엇을 지켜야 하는가를 규정합니다.

1. 이 앱이 먼저 잃는 것

도메인의 독립성입니다. 프레임워크와 화면 요구가 양쪽에서 도메인을 끌어당기며, 어느 한쪽이라도 당기기 시작하면 업무 규칙이 그것들의 사정에 따라 바뀝니다.

그래서 참조 문서가 경계와 접근 경로를 먼저 다루고, 도메인의 바깥 의존을 ArchUnit 이 빌드에서 차단합니다. 경계를 지키는 수단이 도구 하나뿐이라는 사실도 함께 적혀 있습니다.

품질 목표는 셋이며 각각 확인 수단을 갖습니다.

목표 이유 확인 수단
구조의 부패 저항 규칙이 문서에만 있으면 먼저 무너지는 곳이 구조입니다 ArchUnit 여덟 규칙이 빌드 게이트에 있습니다
인증의 정확성 인증은 되돌리기 가장 비싼 결함 영역입니다 도메인 단위 테스트와 컨테이너 통합 테스트
교체 가능성 영속성과 메일, 소셜 제공자는 배포 환경마다 다릅니다 포트 뒤에 두고 어댑터만 교체합니다

2. 컨텍스트와 범위

서버가 바깥과 주고받는 것은 넷입니다.

범례: 화살표는 호출 방향입니다. 실선 하나가 하나의 통신 경계이며, 각 외부 의존은 서버 내부에서 포트 뒤에 놓여 교체와 가짜 구현이 가능합니다.

API 계약의 소유자는 서버입니다. 계약을 바꾸는 것은 서버의 변경이며 프론트엔드는 소비자로서 그것을 참조합니다. 계약의 규약은 API 설계에 있습니다.

제약 조건 중 백엔드에만 걸리는 것은 셋입니다.

제약 내용
인스턴스 수 단일 인스턴스를 전제합니다. 시도 제한 카운터가 인메모리이므로 다중화 시 공유 저장소 어댑터로 교체합니다
스키마 소유권 서버가 단독으로 소유합니다. 마이그레이션 파일이 스키마의 단일 원본입니다
프록시 전제 클라이언트 IP가 위조 가능하면 IP 축 시도 제한이 통째로 무력화됩니다. 프록시 구성은 편의가 아니라 보안 요구입니다

3. 아키텍처 전략

3.1 컨텍스트는 애그리거트 소유로 나눕니다

도메인을 컨텍스트로 나누되 기준은 요구사항 묶음이 아니라 애그리거트 소유입니다. 프로필이 별도 컨텍스트가 아닌 이유가 이 기준의 사례입니다. 프로필은 user 애그리거트를 변경하는 유스케이스이고 그 애그리거트의 소유자는 auth 입니다.

3.2 컨텍스트 내부는 피쳐로 자릅니다

내부의 1차 분류는 계층이 아니라 피쳐입니다. 컨트롤러와 서비스, DTO, 포트가 한 폴더에 모입니다. 계층으로 나누면 기능 하나를 고칠 때 네 폴더를 오가야 합니다.

대가는 폴더명만으로 계층을 알 수 없다는 것이고, 그래서 계층은 폴더 위치가 아니라 클래스의 역할로 식별합니다.

3.3 접근 경로를 조회와 명령으로 나눕니다

데이터 접근 경로는 조회와 명령 둘뿐입니다. 화면 데이터를 도메인 저장소로 만들지 않고 조회 포트로 분리한 이유는, 그러지 않으면 화면 요구가 도메인 모델을 끌어당기기 때문입니다. 상세는 조회와 명령에 있습니다.

4. 빌딩블록 뷰

dev.goraebap.devkit
├── auth/            user · account · session · verification 소유
├── mail/            발송 능력만 제공하며 애그리거트가 없습니다
├── todo/            todo 소유. 담당자로 auth 를 참조합니다
├── common/          컨텍스트가 아닌 횡단 계층. 에러 계약과 HTTP 어댑터
├── config/          특정 컨텍스트 없이도 의미가 있는 빈만
└── health/          컨텍스트가 아닌 관측 확장. 스키마 상태 지표

컨텍스트는 셋이며 나머지 셋은 루트 직계이지만 컨텍스트가 아닙니다. 판정 기준은 패키지 배치와 참조 규칙 1절에 있습니다.

todo → auth 가 이 시스템의 유일한 컨텍스트 간 참조입니다. 담당자 지정이 auth 의 contract 를 통과하고, 목록의 담당자 이름은 조회 경로에서 조인으로 가져옵니다. 두 경로가 각각 컨텍스트 협력과 조회와 명령 6.1절의 규칙을 실증합니다.

컨텍스트의 contract 패키지에 놓인 것만 공개이고 나머지 하위 패키지는 전부 internal 입니다. 공개가 필요해지면 파일을 contract 로 옮기며 그 물리적 행위 자체가 의도적인 공개 선언입니다. 근거는 결정-0030이고 배치 규칙 전체는 패키지 배치와 참조 규칙에 있습니다.

파일 저장과 알림 컨텍스트는 계획에 있으나 아직 코드가 없으므로 위 지도에 넣지 않습니다.

5. 런타임 뷰

인증 흐름 하나가 이 시스템의 런타임 특성을 대표합니다. 이메일 소유 증명이 계정 생성보다 먼저 일어납니다.

범례: 실선 화살표는 호출이고 점선은 응답입니다. 두 번째 호출을 통과하기 전에는 user 행이 생기지 않으며, 미검증 계정이 존재할 수 없다는 것이 이 흐름의 목적입니다.

주목할 점이 둘입니다. 메일 발송은 트랜잭션 커밋 이후에 비동기로 일어나므로 발송 실패가 유스케이스를 중단시키지 않습니다. 대기 레코드는 잠금 후 읽습니다. 잠금이 없으면 동시 요청이 서로의 시도 횟수 증가를 덮어써 제한이 무력화됩니다.

6. 리스크와 기술 부채

항목 내용 해소 조건
인메모리 시도 제한 다중 인스턴스로 배포하면 카운터가 인스턴스마다 갈려 한도가 사실상 배수가 됩니다 다중화 시점에 공유 저장소 어댑터로 교체합니다
소셜 로그인의 서블릿 세션 oauth2Login 이 state 와 PKCE 를 서블릿 세션에 보관해 이 경로만 무상태가 아닙니다 스티키 세션 또는 공유 저장소
명세 생성 도구 미도입 API 문서의 정본이 아직 코드와 요구사항 인수조건뿐입니다 springdoc-openapi 도입
남용 방지 1층과 3층 미도입 표적 계정 잠금이 남아 있습니다 배포 시점(결정-0021)

강제 수단의 현황은 다음과 같습니다. 강제 수단이 없는 규칙이 무엇인지를 함께 적는 것이 이 표의 목적입니다.

규칙 강제 수단
컨텍스트 경계와 의존 방향 ArchUnit. 위반은 빌드 실패입니다
코드 포맷과 명명 포맷터와 컨벤션 검사기. 위반은 빌드 실패입니다
버그 패턴 버그 패턴 탐지기. 위반은 빌드 실패입니다
그 외 배치 규칙 문서와 검토뿐이며 강제 수단이 없습니다

7. 무엇이 어디에 있는가

묶음 담는 것 읽는 시점
참조 항목별 세부 규칙과 그 강제 수단 코드를 쓰다가 판단이 필요할 때
결정 기록 선택의 사유와 기각한 대안 규칙을 바꾸려 할 때

규칙을 바꾸기 전에 결정 기록을 먼저 확인합니다. 대부분의 규칙에는 그것을 그렇게 정한 사유와 함께 기각한 대안이 남아 있습니다. 사정을 모르고 되돌리면 같은 논의를 반복하게 됩니다.

목록은 사이드바가 보여주므로 여기에 나열하지 않습니다.

© 2026 dev.goraebap