나는 보통 디렉토리를 common, domain, infra로 구성해서 관리를 한다.
common : 메인 비즈니스 로직을 위한 설정 파일
domain : 메인 비즈니스 로직이 위치
infra : 외부 저장소, 외부 API, ...
개인 프로젝트의 코드 관리 부분에서 아쉬운 점이 있어서 common 디렉토리 구성 방식을 변경하려고 한다. 아래는 common 디렉토리의 모습이다.
common 디렉토리의 파일을 수정해야 하는 일이 많았다. 그리고 아래와 같은 고민들이 있었다.
- profile별로 다른 빈을 사용하고 싶다.
- 같은 Profile에서 다른 빈을 사용하고 싶다.
- common 디렉토리에서 어떤 빈들이 존재하는가?
- 이 빈이 어디서 참조하는가? 교체해도 큰 문제가 없는가?
하지만 common 디렉토리를 수정하고 관리하려면 내부적으로 중첩된 디렉토리를 다 봐야했다. @Component(주로 이놈을 찾는다.), @Repository, @RestControllerAdvice 같은 것들이 무엇이 있나 확인해야 했다. 더 쉽게 관리할 수 없을까? 고민을 해서 나온 방안은 "common" 디렉토리에서는 모두 @Configuration을 통해서만 빈으로 주입하자.
였다.
@Reposiotry나 @RestControllerAdvice를 사용하는 빈은 다른 디렉토리로 옮겼다. @Configuration + @Bean 으로는 @Repository, @RestControllerAdvice로서 사용한다고 설정할 수가 없었다.(아마도)
@RestControllerAdvice -> "domain" 디렉토리
= 내가 만든 구조에서는 괜찮은 것 같다.
@Reposiotry -> "infra" 디렉토리
= 애매한 부분이 있다. "infra"를 어느정도 수준의 기능을 넣을 것인지 정하지 않았다.
"infra" 디렉토리가 손해를 보는 부분이 있지만 "common" 디렉토리를 정리해서 얻는 이점이 더 강해서 과감하게 바꿔준다.
아래는 기존의 방식이다. TokenService에서만 참조하면 되지만 어떤 곳에서도 다 참조를 할 수 있다. @Component를 모두 제거하고 @Configuration이 정의된 파일에서 직접 인스턴스를 생성한다.
이제 "Common"에 정의된 기능을 사용하고 싶다면 "Config" 클래스에서 주입한 빈만 사용하도록 한다.를 지키도록 한다.
아래는 내가 생각한 장점이다.
public/private
클래스를 구분하기 용이하다. 캡슐화를 원하는 기능은 Config에서 private method로 반환하도록 한다.- 구현체 변경에 용이하다.
profile별로 구현체(RDB, Redis, InMemory)를 다르게 사용
혹은다음 버전에서 구현체가 변경
같은 작업을 1개의 파일에서 할 수 있다.- 어떤 기능들을 제공하는지 파악하기 쉽다.
흔히 global
, common
, config
라고 불리는 기능에 @Component로 정의하고 개발하니 늘 모든 패키지가 열려있었다.(어디 있는지 찾기 위해서) 효과가 좋을지는 모르겠는데 실패해도 좋은 도전이라고 생각한다. ㅎㅎ