Skip to content

Ohmry/spring-ddd-user-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spring DDD User Example

Clean Architecture 접근 방식으로 Domain-Driven Design (DDD) 원칙을 보여주는 Spring Boot 애플리케이션입니다. 이 프로젝트는 도메인 모델과 인프라스트럭처 레이어 간의 관심사 분리를 보여주며, DDD 모범 사례를 따릅니다.

🚀 주요 기능

  • Domain-Driven Design: 도메인 모델(User, UserPassword)과 JPA 엔티티(UserEntity) 간의 명확한 분리
  • Clean Architecture: 컨트롤러, 서비스, 도메인, 인프라스트럭처 레이어 간 명확한 경계를 가진 계층형 아키텍처
  • 비밀번호 정책: 구성 가능한 규칙으로 강제되는 비밀번호 검증
  • RESTful API: 사용자 관리를 위한 완전한 CRUD 작업
  • 예외 처리: 커스텀 예외를 사용한 중앙화된 예외 처리
  • 포괄적인 테스트: HTTP 레이어를 위한 MockMvc 기반 유닛 테스트

🛠️ 기술 스택

  • Java: 17
  • Spring Boot: 3.5.9
  • Spring Data JPA: 데이터베이스 접근용
  • H2 Database: 개발용 인메모리 데이터베이스
  • Lombok: 보일러플레이트 코드 감소용
  • Spring Security Crypto: 비밀번호 인코딩용
  • JUnit 5: 테스트용
  • Mockito: 테스트에서 모킹용

📁 프로젝트 구조

src/main/java/io/github/ohmry/example/
├── controller/          # REST API 엔드포인트
│   ├── UserController.java
│   └── UserExceptionHandleController.java
├── data/                # DTOs (Data Transfer Objects)
│   ├── ApiResponse.java
│   ├── UserCreateRequest.java
│   └── UserUpdateRequest.java
├── domain/              # 도메인 모델 (비즈니스 로직)
│   ├── User.java
│   └── UserPassword.java
├── entity/              # JPA 엔티티 (인프라스트럭처)
│   └── UserEntity.java
├── exception/           # 커스텀 예외
│   ├── PasswordPolicyViolationException.java
│   └── UserNotFoundException.java
├── repository/          # 리포지토리 인터페이스
│   └── UserRepository.java
├── service/             # 애플리케이션 서비스
│   ├── UserService.java
│   └── UserServiceImpl.java
└── web/                 # 웹 설정
    └── SecurityConfiguration.java

🏗️ 아키텍처

이 프로젝트는 명확한 분리를 가진 계층형 아키텍처 패턴을 따릅니다:

┌─────────────────┐
│   Controller    │  ← REST API 레이어
└────────┬────────┘
         │
┌────────▼────────┐
│    Service      │  ← 애플리케이션 서비스 레이어
└────────┬────────┘
         │
┌────────▼────────┐
│    Domain       │  ← 비즈니스 로직 레이어
└────────┬────────┘
         │
┌────────▼────────┐
│  Repository     │  ← 데이터 접근 인터페이스
└────────┬────────┘
         │
┌────────▼────────┐
│   Entity (JPA)  │  ← 인프라스트럭처 레이어
└─────────────────┘

주요 설계 원칙

  1. 도메인 모델 vs 엔티티 분리

    • User (도메인 모델): 비즈니스 로직과 규칙을 포함
    • UserEntity (JPA 엔티티): 영속성을 위한 순수 데이터 표현
    • 변환 메서드: User.toEntity()User.from(UserEntity)
  2. 값 객체 (Value Objects)

    • UserPassword: 비밀번호 검증 및 인코딩 로직을 캡슐화
    • 도메인 레벨에서 비밀번호 정책 강제
  3. 애플리케이션 서비스

    • UserService: 도메인 작업을 조율
    • 트랜잭션 관리 및 레이어 간 조정
    • 비즈니스 로직 없음 - 도메인 모델에 위임

📡 API 엔드포인트

사용자 생성

POST /user
Content-Type: application/json

{
  "email": "user@example.com",
  "name": "홍길동",
  "password": "Password123!"
}

응답:

{
  "code": "0000",
  "message": "success",
  "data": {
    "id": "uuid",
    "name": "홍길동",
    "email": "user@example.com",
    "password": {
      "value": "encoded-password"
    }
  }
}

사용자 ID로 조회

GET /user/{id}

사용자 수정

PUT /user
Content-Type: application/json

{
  "id": "user-id",
  "newName": "김철수",
  "newPassword": "NewPassword456!"
}

사용자 삭제

DELETE /user
Content-Type: application/json

"user-id"

🔒 비밀번호 정책

애플리케이션은 다음 규칙으로 비밀번호 검증을 강제합니다:

  • 옵션 1: 다음 중 3가지 이상을 포함하여 최소 8자:

    • 대문자
    • 소문자
    • 숫자
    • 특수 문자
  • 옵션 2: 위 유형 중 2가지 이상을 포함하여 최소 10자

유효하지 않은 비밀번호는 오류 코드 1002와 함께 400 Bad Request를 반환합니다.

🚦 시작하기

사전 요구사항

  • Java 17 이상
  • Maven 3.6+ (또는 포함된 Maven Wrapper 사용)

애플리케이션 실행

  1. 저장소 클론:
git clone <repository-url>
cd spring-ddd-user-example
  1. 애플리케이션 실행:
./mvnw spring-boot:run

또는 Maven 사용:

mvn spring-boot:run
  1. 애플리케이션이 http://localhost:8081에서 시작됩니다

  2. H2 콘솔 접근 (선택사항):

    • URL: http://localhost:8081/h2-console
    • JDBC URL: jdbc:h2:mem:testdb
    • 사용자명: sa
    • 비밀번호: (비어있음)

테스트 실행

./mvnw test

또는 Maven 사용:

mvn test

🧪 테스트

프로젝트는 MockMvc를 사용한 포괄적인 테스트를 포함합니다:

  • 유닛 테스트: UserControllerMockMvcTest
    • HTTP 상태 코드 테스트
    • 요청/응답 구조 검증
    • 예외 처리 검증
    • 격리를 위한 서비스 레이어 모킹

특정 테스트 클래스 실행:

./mvnw test -Dtest=UserControllerMockMvcTest

📝 예외 처리

커스텀 예외는 중앙에서 처리됩니다:

  • UserNotFoundException (404): 사용자를 찾을 수 없을 때

    • 오류 코드: 1001
    • 메시지: "User is not exists."
  • PasswordPolicyViolationException (400): 비밀번호가 정책을 충족하지 않을 때

    • 오류 코드: 1002
    • 메시지: "The password does not satisfy the required password rules."

🎯 시연된 핵심 개념

  1. Domain-Driven Design

    • 비즈니스 로직을 가진 풍부한 도메인 모델
    • 캡슐화를 위한 값 객체
    • 집계 루트
  2. Clean Architecture

    • 의존성 역전
    • 레이어 분리
    • 테스트 가능성
  3. 관심사 분리

    • 인프라스트럭처로부터 독립적인 도메인 모델
    • 순수 데이터 컨테이너로서의 JPA 엔티티
    • 조율을 위한 서비스 레이어

참고: 이것은 Spring Boot로 DDD 원칙을 시연하는 예제 프로젝트입니다.

About

Clean Architecture 접근 방식으로 Domain-Driven Design (DDD) 원칙을 보여주는 Spring Boot 애플리케이션입니다.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages