[BEInternship]프로젝트 디렉터리 구조 개선 - 계층형 vs. 도메인형

junghan·2023년 8월 12일
0

BE 인턴십

목록 보기
3/9
post-thumbnail

프로젝트를 진행하며 디렉터리 구조를 어떻게 설계해야 할지 고민하신 경험이 있으실겁니다. 기존의 계층형 디렉터리 구조에서 나타났던 문제와 그를 개선한 도메인형 디렉터리 구조를 소개하려 합니다.

계층형 디렉터리 구조

기존의 계층형 디렉터리 구조는스프링 웹 계층의 대표 클래스 혹은 디렉터리들을 기반으로 패키징하는 방식입니다.

com
 ㄴ example
     ㄴ jung
         ㄴ config
         ㄴ controller
         ㄴ domain
         ㄴ repository
         ㄴ service
         ㄴ security
         ㄴ exception

위 패키지 구조는 일전의 프로젝트에서 계층형 디렉터리 구조를 기반으로 패키징을 한 예시입니다.

스프링 웹계층에 대한 간단한 설명을 해보면 아래와 같습니다.

  • Web Layer : 사용자의 요청과 이에 대한 응답 반환의 전반적인 처리가 일어나는 영역을 의미합니다.
  • Service Layer : Web Layer와 Repository Layer 사이에서 실질적인 어플리케이션 비즈니스 로직이 일어나는 영역입니다.
  • Repository Layer : DB에 접근 및 통신하는 영역입니다.

이러한 각 계층들에는 ControllerServiceRepository 등과 같이 그 계층들을 대표하는 다양한 클래스와 디렉터리가 존재하고, 이들을 기반으로 디렉터 구조를 패키징하는 방식이 계층형 디렉터리 구조입니다.

이는 전체 구조를 빠르게 파악할 수 있는 장점이 있지만, 한 디렉터리에 많은 클래스가 모이게 되어 가독성이 저하될 수 있습니다. 특히 Service 디렉터리에는 많은 역할을 하는 클래스들이 모이게 되어, 개발 중 휴먼 에러가 발생할 가능성이 높아집니다. 이로 인해 코드의 유지보수가 어려워지는 문제가 있었습니다.

계층형 구조는 전체적인 구조를 빠르게 파악할 수 있는 장점이 있지만, 각각의 패키지 디렉터리에 클래스들이 너무 많이 모이게 된다는 단점이 존재합니다.

따라서 저는 아래 설명할 도메인형 디렉터리 구조를 이용해서 패키징 방법을 개선했습니다.


도메인형 디렉터리 구조

com
 ㄴ example
     ㄴ domain
         ㄴ domain
         |   ㄴ user
         |   |   ㄴ api
         |   |   ㄴ application
         |   |   ㄴ dao
         |   |   ㄴ domain
         |   |   ㄴ dto
         |   |   ㄴ exception
         |   ㄴ video
         |   |   ㄴ api
         |   |   ㄴ application
         |   |   ㄴ dao
         |   |   ㄴ domain
         |   |   ㄴ dto
         |   |   ㄴ exception
         |   ...
         ㄴ global
             ㄴ auth
             ㄴ common
             ㄴ config
             ㄴ error
             ㄴ infra
             ㄴ util

위의 디렉터리 패키지 방식은 이번 프로젝트를 진행하면서 도메인형 디렉터리 구조를 기반으로 제 프로젝트의 성격에 맞게 패키징을 구성한 것입니다.

해당 방식은 스프링 웹 계층에 주목하기보다는 도메인에 주목합니다. 이를 통해서 각각의 도메인 별로 패키지 분리가 가능하여 관리에 있어서 계층형 방식보다 직관적이며, 각각의 도메인들은 서로를 의존하는 코드가 없도록 설계하기 적합해서 코드의 재활용성이 향상됩니다.

또한 OOP 관점과 ORM 기술을 사용함에 있어서 핵심이 되는 Entity의 특성을 기반으로 패키징하는 것이 해당 기술들의 관점과 지향점과도 맞다고 생각이 듭니다.

그 이유는 때문입니다.

아래로는 각각의 패키지와 이를 구성하는 클래스들에 대한 설명을 하겠습니다.

최상위 레벨의 패키지

  • 최상위 레벨에서는 domain과 global로 패키징합니다.
  • domain 패키지에서는 프로젝트와 DB 구조에서 핵심 역할을 하는 domian entitiy를 기준으로 하위 패키지를 구성합니다.
  • global 패키지에서는 프로젝트 전방위적으로 사용할 수 있는 클래스 들로 구성됩니다.

domain 하위 패키지

  • 앞서 설명한 것처럼 uservideo와 같이 핵심 domain entity 별로 패키지가 구성됩니다.
  • 각각의 domian 하위 패키지는 apiapplicationdaodomaindtoexception 패키지로 구성됩니다.
  • api : controller 클래스가 존재합니다. 해당 프로젝트에서 스프링 부트는 Rest API 서버로서의 역할만을 하기 때문에, 명시적으로 api라는 네이밍으로 패키징 했습니다.
  • application : 주로 service 클래스들이 존재합니다. DB 트랜잭션이 일어나며, 주된 비즈니스 로직을 담당합니다. Service 클래스들 뿐만 아니라, handler와 같은 같은 성격의 다른 클래스 또한 포함하기 때문에 application이라는 네이밍으로 패키징 했습니다.
  • dao : daorepository 클래스들로 구성됩니다.
  • domain : entity 클래스들로 구성됩니다.
  • dto : dto 클래스들로 구성됩니다.
  • exception : exception 클래스들로 구성됩니다.

global 하위 패키지

  • 해당 패키지에는 특정 domain에 종속되지 않고, 프로젝트 전방위적으로 사용할 수 있는 클래스들이 모여있습니다.
  • global 패키지는 authcommonconfigerrorinfrautil 패키지로 구성됩니다.
  • auth : 인증인가와 관련된 클래스들로 구성됩니다.
  • common : 공통 클래스 혹은 공통 value 클래스들로 구성됩니다.
  • config : 각종 configuration 클래스로 구성됩니다.
  • error : 공통 exceptionerror와 관련된 클래스로 구성됩니다.
  • infra : 외부 모듈api 등을 사용하는 클래스로 구성됩니다.
  • util : 공통 util성 클래스들로 구성됩니다.

기존의 계층형 디렉터리 구조에 대한 불편을 느끼고 도메인형 디렉터리 구조를 적용함으로써 훨씬 더 직관적으로 프로젝트를 관리할 수 있음을 느끼고 있습니다.

결론

어떤 디렉터리 구조가 최적인지는 프로젝트와 개발자의 선호도에 따라 다를 수 있습니다. 하지만 도메인형 디렉터리 구조는 기존 계층형 구조의 단점을 보완하며 관리의 효율성을 높여줍니다. 프로젝트의 복잡도와 성격에 따라 디렉터리 구조를 유연하게 조정하는 것이 중요합니다. 결국 최선의 패키징 방식은 개발자가 편리하게 관리하고 유지보수할 수 있는 방식일 것입니다.


참고

https://velog.io/@jsb100800/Spring-boot-directory-package
https://cheese10yun.github.io/spring-guide-directory/
https://velog.io/@dhwlddjgmanf/%EA%BC%AC%EB%A6%AC%EB%B3%84-%EC%98%A4%EB%A5%98%EC%9D%BC%EC%A7%80-%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B5%AC%EC%A1%B0%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%A7%9C%EB%8A%94-%EA%B2%8C-%EB%A7%9E%EC%9D%84%EA%B9%8C

!https://velog.velcdn.com/images/jsb100800/profile/b8881d75-d259-45ad-bca1-ba90bd9a52fa/social.jpeg

profile
42seoul, blockchain, web 3.0

0개의 댓글