1. 계층형 구조
controller
⎿ MemberController
⎿ PostController
⎿ CommentController
service
⎿ MemberService
⎿ PostService
⎿ CommentService
dao
⎿ MemberDao
⎿ PostDao
⎿ CommentDao
domain
⎿ Member
⎿ Post
⎿ Comment
- 애플리케이션에서 사용하는 계층별로 패키지를 구성하는 방식
- 장점
- 프로젝트 전반적인 이해도가 낮아도, 패키지 구조만 보고 전체적인 구조를 파악할 수 있음
- 애플리케이션의 API를 보고 흐름을 파악하고 싶다면, Controller 패키지 하나만 보고 파악할 수 있음
- 계층별 응집도가 높아짐
- 계층별 수정이 일어날 때, 하나의 패키지만 보면 됨
- 프로젝트 전반적인 이해도가 낮아도, 패키지 구조만 보고 전체적인 구조를 파악할 수 있음
- 단점
- 도메인별 응집도가 낮음
- 하나의 도메인 흐름을 보고 싶을 때, 모든 계층 패키지를 봐야 함
- 도메인과 관련된 스펙과 기능이 변경되었을 때, 변경 범위가 커짐
- 규모가 커질 경우, 하나의 패키지에 안에 여러 클래스들이 모여 구분이 어려워지게 됨
- 도메인별 응집도가 낮음
2. 도메인형 구조
Member
⎿ controller
⎿ service
⎿ dao
⎿ dto
Post
⎿ controller
⎿ service
⎿ dao
⎿ dto
Comment
⎿ controller
⎿ service
⎿ dao
⎿ dto
- 도메인을 기준으로 패키지를 나눈 구조
- 장점
- 도메인별 응집도가 높아짐
- 도메인의 흐름을 파악하기 쉬워짐
- 도메인과 관련된 스펙 및 기능이 변경되었을 대, 해당 도메인 패키지에서만 변경이 일어남
- 도메인별 응집도가 높아짐
- 단점
- 애플리케이션의 전반적인 흐름을 한눈에 파악하기 어려움
- 개발자의 관점에 따라 도메인을 구분하는 기준이 다를 수 있음
계층형과 도메인형 중 어느 구조를 선택해야 할까?
패키지 방식에서 정답은 없지만, 최신 기술 동향에 따라 도메인형 구조를 많이 사용하는 추세이다.
계층형을 사용하게 될 경우, 너무 많은 클래스들이 밀집하게 된다. 이렇게 되면 프로젝트의 전체적인 구조를 상위 디렉토리 몇 개로 빠르게 파악할 수는 있지만, 오히려 그 이후로는 더 파악하기가 어려워진다.
도메인형 패키지 구조의 경우, 스프링 웹 계층이 아닌 도메인에 주목하여 계층형 보다 직관적이고, 각각의 도메인 별로 패키지 분리가 가능하여 관리에 있어 계층형보다 더 직관적이다. 또한, 도메인 주도 개발과 OOP 관점 그리고 ORM 기술을 사용하는데 핵심이 되는 Entity(엔티티)의 특성을 기반으로 패키징하는 것이 해당 기술들의 관점에서 더 적합하다고 보는 것 같다.
[도메인형 디렉토리 구조]
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── spring
│ │ ├── SpringBootApplication.java
│ │ ├── domain
│ │ │ ├── member
│ │ │ │ ├── api
│ │ │ │ │ └── MemberApi.java
│ │ │ │ ├── application
│ │ │ │ │ └── MemberSearchService.java
│ │ │ │ ├── dao
│ │ │ │ │ └── MemberFindDao.java
│ │ │ │ ├── domain
│ │ │ │ │ └── Member.java
│ │ │ │ ├── dto
│ │ │ │ │ └── SignUpRequest.java
│ │ │ │ └── exception
│ │ │ │ │ └── MemberNotFoundException.java
│ │ │ ├── item
│ │ │ │ ├── api
│ │ │ │ ├── application
│ │ │ │ ├── dao
│ │ │ │ ├── domain
│ │ │ │ ├── dto
│ │ │ │ └── exception
│ │ │ └── model
│ │ │ │ ├── Address.java
│ │ │ │ └── Email.java
│ │ ├── global
│ │ │ ├── common
│ │ │ │ ├── request
│ │ │ │ └── response
│ │ │ ├── config
│ │ │ │ ├── SwaggerConfig.java
│ │ │ │ ├── properties
│ │ │ │ ├── resttemplate
│ │ │ │ └── security
│ │ │ ├── error
│ │ │ │ ├── ErrorResponse.java
│ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ └── exception
│ │ │ └── util
│ │ └── infra
│ │ ├── email
│ │ └── sms
│ │ ├── AmazonSmsClient.java
│ │ ├── SmsClient.java
│ │ └── dto
│ └── resources
│ ├── application-dev.yml
│ ├── application-local.yml
│ ├── application-prod.yml
│ └── application.yml
- 최상위 레벨 패키지
- domain: 도메인을 담당
- model: Domain Entity 객체들이 공통적으로 사용할 객체들로 구성
- global: 전체적인 설정 관리(프로젝트 전방위적으로 사용)
- infra: 외부 인프라 구조 관리
- domain: 도메인을 담당
- domain 하위 패키지
- api: Controller 클래스 존재. Rest API 서버의 역할을 담당
- domain: 도메인 Entity 클래스와 와 특정 도메인에만 속하는 Embeddable, Enum 같은 클래스로 구성
- dto: 주로 Request, Response 객체들로 구성
- exception: 해당 도메인이 발생시키는 Exception 클래스로 구성
- application: 도메인 객체와 외부 영역을 연결해주는 역할로, 주로 DB 트랜잭션을 처리하고 주된 비즈니스 로직을 담당함(Service 계층과 유사)
- dao: repository와 유사, 조회 전용 구현체들로 구성
- global 하위 패키지
- auth : 인증, 인가와 관련된 클래스들로 구성
- common : 공통 클래스 혹은 공통 value 클래스들로 구성
- config : 각종 스프링 configuration 클래스로 구성
- error : 공통 exception, error와 관련된 클래스로 구성
- infra : 외부 모듈, api 등을 사용하는 클래스로 구성
- util : 공통 util성 클래스들로 구성
- infra 하위 패키지
- 대표적으로 이메일 알림, SMS 알림 등 외부 서비스에 대한 코드들이 존재
[참고]
'Web > Spring, JPA' 카테고리의 다른 글
[SpringSecurity] 스프링 시큐리티 이해(구조, 필터) (0) | 2023.09.17 |
---|---|
[JPA] Entity 생성 방법 (0) | 2023.08.29 |
[Spring Boot] 내장 톰캣 vs 외장 톰캣 (1) | 2022.09.02 |
[Spring] Spring vs Spring Boot (0) | 2022.08.30 |
[Spring Boot] Spring Boot War/Jar 배포해보기 (0) | 2022.08.26 |