Claude Code Configuration for Spring Developer
1. 아키텍처 원칙
1.1 도메인 이해 우선
- 도메인 파악: 비즈니스 규칙과 핵심 개념을 먼저 이해하고 코드 작성
- Ubiquitous Language: 도메인 전문가와 같은 언어로 커뮤니케이션
- 비즈니스 중심: 기술이 아닌 비즈니스 요구사항으로 아키텍처 결정
- Context 이해: 각 컨텍스트의 경계와 책임을 명확히 정의
- 불변 규칙 식별: 어떤 조건에서도 변하지 않는 도메인 규칙 파악
1.2 클린 아키텍처 핵심 원칙
- Dependency Rule: 내부 계층은 외부 계층을 의존하지 않음 (Domain → Service → Infrastructure)
- DIP (Dependency Inversion Principle): 구체적인 구현이 아닌 추상화(Interface)에 의존
- Single Responsibility: 각 클래스는 변경 이유가 하나여야 함
- No Framework Dependency in Domain: 도메인 계층은 프레임워크에 독립적이어야 함
- Use Case Driven: 비즈니스 요구사항이 아키텍처를 주도
1.3 도메인 객체 원칙 (정보전문가 패턴 & 팩토리 메소드)
기본 원칙
- 정보전문가 패턴: 객체가 필요한 정보를 모두 가지고 있을 때, 그 객체에 책임을 할당
- Private 생성자: 모든 도메인 객체는 private 생성자로 직접 인스턴스화 방지
- 정적 팩토리 메소드: 의미 있는 이름의 팩토리 메소드로만 객체 생성 허용
- 의도 명확화: 메소드 이름으로 “어떤 행위(What)”를 하는지 표현
정보전문가 패턴 핵심 원칙
- 책임 할당: 필요한 정보를 가진 객체가 그 정보로 의사결정하고 행동해야 함
- 응집력 증대: 관련된 데이터와 로직을 같은 객체에 응집
- 결합도 감소: 외부의 복잡한 로직이 없어져 의존성 감소
- 캡슐화 강화: 객체의 내부 상태로 모든 판단이 이루어짐
What 기반 함수명 원칙
함수명은 “어떤 행위를 하는가(What)”를 표현하고 “어떻게 구현했는가(How)”에 의존하지 않음
원칙:
- 구현 독립적: 함수명은 도메인 의도를 표현하고, 구현 기술에 영향받지 않음
- 행위 중심: 메서드가 무엇을 하는지(변환, 검증, 계산 등)를 명확히 표현
- 기술 용어 배제: 데이터베이스, 네트워크, 캐시 등의 기술 용어 제거
- 도메인 언어 사용: Ubiquitous Language로 일관되게 표현
What 기반 네이밍:
getTotalPrice()- 어떤 가격을 구하는가 (구현: 합계 계산)isEligibleForDiscount()- 할인 대상인가를 판단 (구현: DB 조회 또는 메모리 검사)register()- 가입한다 (구현: DB 저장, 캐시 갱신 등)calculateShippingCost()- 배송비를 계산한다 (구현: API 호출 또는 공식 적용)applyPromotion()- 프로모션을 적용한다 (구현: 할인율 계산, 이벤트 발행)
피해야 할 How 기반 네이밍:
saveToDatabase()- 구현(DB 저장)을 노출fetchFromCache()- 구현(캐시 조회)을 노출callExternalAPI()- 구현(API 호출)을 노출calculateWithFormula()- 구현(공식 사용)을 노출doRequest()- 애매한 기술 용어
팩토리 메소드 What 기반 네이밍 규칙
create()- 객체를 생성한다 (기본 행위)register()- 도메인에 등록한다 (가입, 회원가입 등)generate()- 생성한다 (ID, 코드, 토큰 생성)from()- 다른 형태에서 변환한다parse()- 텍스트/포맷을 해석한다restore()- 저장된 상태에서 복원한다 (Repository에서 사용)open(),close()등: 도메인 행위를 직접 표현
팩토리 메소드 사용 패턴
- 기본 생성: 정상적인 도메인 객체 생성 (검증 포함)
- 조건부 생성: 특정 조건에서의 특수한 생성 (초기값 설정)
- 상태 복원: 데이터베이스에서 로드한 객체 복원 (검증 제외)
- 변환: 다른 타입에서 현재 타입으로 변환
팩토리 메소드 선택 기준
- 단순 객체 생성 → Private 생성자 + 팩토리 메소드
- 조건부 생성 → 여러 팩토리 메소드 제공
1.4 계층별 역할
- Domain: 순수 비즈니스 로직, 엔티티, 값 객체, 도메인 이벤트
- Service: Use Case, 서비스 조율, 트랜잭션 관리
- Infrastructure: 데이터 접근, 외부 API 연동, 기술적 구현
- Presentation: HTTP 요청/응답, 라우팅, 예외 처리
1.5 계층별 책임과 역할 정의
Domain 계층 책임
- 비즈니스 로직 중심: 도메인 규칙을 코드로 표현
- 불변 규칙 강제: 엔티티 상태 변경 시 비즈니스 규칙 검증
- 도메인 이벤트 발행: 중요 도메인 변경사항 이벤트로 표현
- 프레임워크 무관: Spring, JPA 등 기술 스택에 독립적
- 재사용성: 어떤 애플리케이션에서든 사용 가능한 순수 로직
Service 계층 책임
- Use Case 구현: 비즈니스 시나리오를 단계별로 구성
- 조율: 도메인, 인프라 계층 조정
- 트랜잭션 관리: 원자성 보장
- 서비스의 데이터 분리
- 명령 : Command 객체 활용 (CreateOrderCommand)
- 조회 : Query 객체 활용 (GetOrderQuery)
Infrastructure 계층 책임
- 구현 세부사항: JPA, 데이터베이스, HTTP 클라이언트 등
- 기술 선택: 구현 기술을 자유롭게 변경 가능하도록
- Port 구현: 도메인이 정의한 인터페이스를 기술로 구현
- 외부 시스템 연동: API 호출, 메시지 큐 등
- 도메인 모델과 기술의 분리: Entity ↔ Domain Model 매핑
Presentation 계층 책임
- HTTP 프로토콜 처리: 요청/응답 매핑
- 입력 검증: 요청 데이터 기본 검증
- 예외 처리: 도메인 예외를 HTTP 응답으로 변환
- 라우팅: API 엔드포인트 정의
- 직렬화/역직렬화: JSON ↔ DTO 변환
- DTO에서 서비스 모델 매핑: DTO를 Command 및 Query 객체로 매핑
1.5 Port & Adapter 패턴
Port (Interface - Domain이 정의)
- 도메인이 필요로 하는 외부 세계와의 계약을 정의
- 도메인 언어와 개념으로 표현
- 네이밍: 도메인 관점의 동작/역할 명시
OrderRepository: 주문을 저장/조회하는 역할NotificationService: 알림을 전송하는 역할PaymentProcessor: 결제를 처리하는 역할UserAuthenticator: 사용자를 인증하는 역할
Adapter (Implementation - Infrastructure가 구현)
- Port를 구체적인 기술로 구현
- 기술 선택에 따라 변경 가능
- 네이밍: 구현의 의도가 명확하게 드러남
PostgresOrderRepository: PostgreSQL을 사용한 주문 저장소EmailNotificationService: 이메일 기반 알림 서비스StripePaymentProcessor: Stripe 결제 처리기JwtUserAuthenticator: JWT 기반 사용자 인증RedisOrderRepository: Redis 캐시를 활용한 주문 저장소KafkaEventPublisher: Kafka 기반 이벤트 발행
사용 예시
도메인 계층:
interface UserRepository
interface OrderRepository
인프라 계층:
class JpaUserRepository implements UserRepository
class JpaOrderRepository implements OrderRepository
class RedisUserRepository implements UserRepository (캐시 전용)
또는
도메인 계층:
interface PaymentGateway
interface EmailSender
인프라 계층:
class StripePaymentGateway implements PaymentGateway
class GooglePaymentGateway implements PaymentGateway
class SmtpEmailSender implements EmailSender
class SendgridEmailSender implements EmailSender
1.6 핵심 디자인 패턴 통합
- Port & Adapter: 도메인 독립성 유지, 기술 선택 유연화
- Strategy Pattern: 다양한 알고리즘 런타임 선택
- Observer/Event: 느슨한 결합을 통한 컨텍스트 간 통신
- Factory Pattern: 복잡한 객체 생성 로직 캡슐화
- Repository Pattern: 데이터 접근 추상화
2. 도메인 중심 개발 프로세스
2.1 요구사항 분석 단계
- 도메인 전문가와 대화: 비즈니스 규칙과 용어 파악
- 핵심 개념 식별: Aggregate, Entity, Value Object 후보 찾기
- 경계 정의: 서로 다른 도메인 컨텍스트 식별
- 불변 규칙 파악: 항상 유지되어야 하는 조건 정의
- 상태 변화 추적: 엔티티의 생명주기와 상태 전이 이해
2.2 도메인 모델 설계
- Aggregate 정의: 트랜잭션 경계 및 루트 엔티티 결정
- Entity vs Value Object: 식별성이 필요한가?
- 도메인 이벤트: 비즈니스 관점에서 중요한 변경사항 정의
- 언어 통일: 도메인 전문가 언어로 클래스/메소드명 정의
- 책임 분배: 각 엔티티의 명확한 책임 정의
2.3 코드 작성 원칙
- Domain First: 도메인 모델을 먼저 설계 후 기술 구현
- Business Logic in Domain: 비즈니스 규칙은 Domain 계층에만
- Framework 후순위: 기술 선택은 도메인 설계 후 결정
- 테스트 주도 개발: 도메인 로직부터 테스트 작성
- 역할 기반 검토: 각 클래스가 자신의 책임을 충실하는지 확인
2.4 각 계층별 개발 순서
- Domain: 비즈니스 규칙과 엔티티 설계
- Port: Domain이 필요한 외부 인터페이스 정의
- Service: Use Case 구현, Port 의존성 주입
- Infrastructure: Port 구현체 작성 (기술 결정)
- Presentation: API 엔드포인트 정의
3. 객체지향 프로그래밍 원칙
3.1 도메인 모델 설계
- 값 객체(Value Object)를 적극 활용하여 불변성 보장
- 엔티티에 비즈니스 로직을 포함하여 도메인 지식 응집
- 도메인 이벤트를 통해 컨텍스트 간 통신
- 애그리게이트 루트를 정의하여 일관성 경계 명확히
- Strategy Pattern: 도메인 내 다양한 계산/처리 방식 표현
3.2 Port & Adapter 패턴
- 도메인이 의존하는 외부 시스템은 Port(Interface)로 정의
- 구체적인 구현은 Infrastructure에서 Adapter로 작성
- Port는 도메인 언어로 표현하되, Adapter는 기술 구현에 최적화
- 기술 변경 시 Adapter만 수정하여 도메인 영향 최소화
3.3 디자인 패턴 활용
Strategy Pattern
- 런타임에 알고리즘 선택이 필요한 비즈니스 로직
- 결제 방식, 할인 정책, 배송 규칙 등 다양한 구현 필요 시 활용
- 각 전략을 별도 클래스로 캡슐화하여 Open/Closed 원칙 준수
Factory Pattern
- 복잡한 도메인 객체 생성 로직 캡슐화
- 객체 생성의 복잡성을 한곳에 집중
- 생성 로직 변경 시 팩토리만 수정하면 됨
- Builder와 함께 사용하여 유연성 극대화
Observer/Event Pattern
- 도메인 이벤트로 Aggregate 간 느슨한 결합 달성
- 주문 생성, 결제 완료 등 중요 비즈니스 이벤트 발행
- 이벤트 구독자는 도메인 계층과 독립적으로 동작
- 도메인 이벤트 저장소를 통한 이벤트 소싱 가능
Repository Pattern
- 데이터 접근 로직을 도메인에서 분리
- Repository는 인메모리 컬렉션처럼 동작하는 인터페이스 제공
- 구현체는 JPA, JDBC, MongoDB 등 자유롭게 선택
- 테스트 시 Mock Repository로 간편하게 단위 테스트
Builder Pattern
- 선택적 매개변수가 많은 복잡한 객체 생성
- 생성 단계를 명확하게 표현하여 가독성 향상
- Lombok의 @Builder 활용으로 보일러플레이트 제거
- 불변 객체 생성에 적합
도메인 객체 불변성 원칙
기본 규칙:
- final 키워드 필수: 도메인 객체의 모든 필드는
final로 선언하여 불변성 보장 - 객체 재할당 불가: 생성 후 상태를 직접 변경할 수 없음
- 상태 변경의 원칙: 상태 변경이 필요한 경우 새로운 객체를 반환
@Builder 설정 규칙:
- access = AccessLevel.PRIVATE: Builder 외부 접근 방지로 캡슐화 강화
- toBuilder = true: 기존 객체로부터 새로운 빌더 생성 가능 (상태 변경)
- 팩토리 메소드로 빌더 노출: 명확한 의도의 팩토리 메소드를 통해서만 빌더 접근
사용 패턴:
@Builder(access = AccessLevel.PRIVATE, toBuilder = true)
public final class Order {
private final String orderId;
private final OrderStatus status;
private final LocalDateTime createdAt;
// 팩토리 메소드로 빌더 노출
public static OrderBuilder builder() {
return new OrderBuilder();
}
// 상태 변경 메소드 - 새로운 객체 반환
public Order approve() {
// 비즈니스 규칙 검증
if (!canApprove()) {
throw new InvalidOrderException("주문을 승인할 수 없습니다");
}
// toBuilder()를 사용해 기존 상태에서 필요한 부분만 수정한 새 객체 반환
return this.toBuilder()
.status(OrderStatus.APPROVED)
.build();
}
// 상태 변경 메소드 - 새로운 객체 반환
public Order cancel(String reason) {
if (!canCancel()) {
throw new InvalidOrderException("주문을 취소할 수 없습니다");
}
return this.toBuilder()
.status(OrderStatus.CANCELLED)
.build();
}
private boolean canApprove() {
return this.status == OrderStatus.PENDING;
}
private boolean canCancel() {
return this.status != OrderStatus.SHIPPED &&
this.status != OrderStatus.DELIVERED;
}
}
불변성의 이점:
- 스레드 안전성: 멀티스레드 환경에서 동기화 불필요
- 버그 감소: 예상치 못한 상태 변경으로 인한 버그 방지
- 예측 가능성: 객체 상태가 변하지 않으므로 코드 흐름 이해 용이 (CQS)
- 함수형 프로그래밍: 순수 함수처럼 동작하여 테스트 용이
- 캐싱 안전성: 불변 객체는 안전하게 캐싱 가능
Value Object Pattern
- 불변성 보장으로 식별성 불필요
- 기본값 동등성으로 비교 간편화
- 업무 로직을 값 객체에 응집 (Money, Percentage 등)
Specification Pattern
- 복잡한 비즈니스 규칙을 조합 가능하게 캡슐화
- 쿼리 조건, 유효성 검사 규칙 등 표현
- 각 스펙을 조합하여 새로운 규칙 생성 가능
3.4 객체 지향 설계 원칙 (SOLID)
- Single Responsibility: 클래스의 변경 이유는 하나
- Open/Closed: 확장에는 열려있고 수정에는 닫혀있음
- Liskov Substitution: 서브타입은 부모타입 계약을 위반하지 않음
- Interface Segregation: 클라이언트별 특화된 인터페이스 제공
- Dependency Inversion: 상위 모듈이 하위 모듈에 의존하지 않음
3.5 도메인 주도 설계(DDD)
- 도메인 언어(Ubiquitous Language) 일관되게 사용
- 바운디드 컨텍스트로 복잡한 도메인 분할
- 애그리게이트로 트랜잭션 경계 정의
- 팩토리 패턴으로 복잡한 객체 생성 로직 캡슐화
4. 최신 Java 언어 기능
4.1 Record (Java 16+)
- DTO와 Value Object에 Record 활용하여 보일러플레이트 제거
- 불변성이 기본으로 보장되므로 동시성 안전성 향상
- 구조적 패턴 매칭과 함께 사용
4.2 Sealed Classes (Java 17+)
- 도메인 모델의 계층 구조 명시적으로 제한
- 상속 가능한 서브타입을 사전에 정의하여 예측 가능성 확보
- 패턴 매칭과 함께 사용하면 더욱 안전한 타입 처리
4.3 Pattern Matching (Java 16+, 지속 개선 중)
- 타입 체크 후 캐스트하는 단계 제거
- instanceof 패턴으로 타입 안전성 강화
- switch 표현식과 함께 사용하여 가독성 및 안정성 향상
4.4 Text Blocks (Java 13+)
- SQL, JSON, XML 등 멀티라인 문자열 처리 간편화
- 가독성 및 유지보수성 개선
4.5 Stream API & Functional Style
- 함수형 프로그래밍으로 선언적 코드 작성
- 컬렉션 처리의 의도를 명확히 표현
- 불변성을 강조하여 사이드 이펙트 최소화
4.6 Virtual Threads (Java 21+)
- 대량의 동시 작업 효율적으로 처리
- 플랫폼 스레드 대비 메모리 사용량 급격히 감소
- 간단한 스레드 모델로 비동기 프로그래밍 간편화
8. 코딩 컨벤션
8.1 Naming Convention
- 도메인 모델: 비즈니스 의미 명확하게 (Order, Customer, Payment)
- Port/Interface: 도메인 관점의 역할 표현 (OrderRepository, NotificationService, PaymentProcessor)
- 구현체: 기술 및 구현의 의도가 명확하게 (JpaOrderRepository, EmailNotificationService, StripePaymentProcessor)
- Service: 동작 기반 네이밍 (CreateOrderService, CancelOrderService)
- Exception: 비즈니스 관점 표현 (OrderNotFoundException, InvalidOrderException)
- 변수: 명확하고 설명적인 이름 (order, customerId, totalPrice)
8.2 코드 스타일 원칙
- 생성자 주입을 기본으로 하여 의존성 명시
- Optional을 적극 활용하여 Null 안정성 확보
- Stream API로 선언적 컬렉션 처리
- Record를 DTO 기본으로, @Getter/@Setter는 최소화
- 한 메소드는 한 가지 일만 수행하도록 유지
8.3 패키지 구조 원칙
- 도메인/기능 중심의 패키지 구성
- 계층별 패키지 분리로 의존성 흐름 명확화
- 공개 인터페이스는 최소화하여 캡슐화 강화
9. Claude Code 사용 가이드라인
9.1 코드 생성 시 기대사항
- 클린 아키텍처의 의존성 규칙 준수
- 도메인 계층은 프레임워크 독립적으로 작성
- Port & Adapter 패턴으로 기술 선택 유연화
- 예외는 비즈니스 의미 중심으로 설계
- 적절한 디자인 패턴 적용으로 유연성과 유지보수성 확보
9.2 리팩토링 시 체크리스트
- 순환 의존성 확인 및 제거
- 도메인 로직이 정확한 계층에 위치하는지 검증
- 과도한 매퍼 및 변환 로직 제거
- 단일 책임 원칙 위반 여부 확인
- 디자인 패턴 적용이 과도하지는 않은지 확인 (과설계 방지)
9.3 파일 생성 시 원칙
- 계층 간 명확한 경계 설정
- Port는 도메인 관점의 역할, 구현체는 기술 의도로 표현
- 객체 생성 로직의 복잡성은 팩토리로 캡슐화
- 비즈니스 규칙은 Strategy, Specification 패턴으로 캡슐화
- 복잡한 흐름은 Command, Chain of Responsibility 패턴 고려
9.4 Port & Adapter 네이밍 가이드
Port (Interface - Domain에서 정의)
데이터 접근:
OrderRepository
UserRepository
ProductRepository
외부 서비스:
NotificationService
PaymentProcessor
EmailSender
UserAuthenticator
WeatherProvider
Adapter (Implementation - Infrastructure에서 구현)
데이터 접근 구현:
JpaOrderRepository
PostgresOrderRepository
RedisOrderRepository
MongoOrderRepository
외부 서비스 구현:
EmailNotificationService
SmsNotificationService
KakaoNotificationService
StripePaymentProcessor
PaypalPaymentProcessor
SmtpEmailSender
SendgridEmailSender
JwtUserAuthenticator
OAuth2UserAuthenticator
OpenWeatherProvider
WeatherApiProvider
9.5 디자인 패턴 선택 기준
- Strategy: 런타임 알고리즘 선택 필요 시
- Factory: 객체 생성 복잡도 높을 때
- Observer: 느슨한 결합 필요한 이벤트 처리 시
- Repository: 데이터 접근 추상화 필요 시
- Builder: 선택적 매개변수 많은 복잡 객체
- Specification: 비즈니스 규칙 조합 필요 시
10. 참고 자료 및 학습
- Clean Architecture by Robert C. Martin
- Domain-Driven Design by Eric Evans
- Building Microservices by Sam Newman
- Release It! by Michael T. Nygard
- Design Patterns by Gang of Four
- Enterprise Integration Patterns by Gregor Hohpe
- Java Language Features Documentation
- Spring Framework Documentation
