HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🧚
[1기]최종 프로젝트 데브코스
/
📜
[팀13] 사각사각 ✏️
/
🎊
기술 문서
/
🍤
MSA 전환 가능한 디렉토리 구조로 변경
🍤

MSA 전환 가능한 디렉토리 구조로 변경

작성자 : 김다희
 
변경 전 디렉토리 구조디렉토리 변경 과정변경 후 디렉토리 구조
 
처음 프로젝트를 시작할 때 controller - service - repository 구조로 디렉토리를 잡았다.
빠르게 개발하고, 프로젝트가 커지는 시점에 다시 리팩토링을 하는게 좋을 것 같다고 판단했기때문이다.
개발 시작이 되고 점점 프로젝트가 커지면서 불편한 단계에 접어 들었다.
 

변경 전 디렉토리 구조

  • 도메인 분리가 안된 상태이다 보니 디렉토리 전환이 많아서 불편했고
  • 더 큰 프로젝트가 되었을 경우에 이를 모듈로 분리, MSA로 전환할 수 있는 구조가 될 수 있을까? 싶었다.
변경 전 디렉토리 구조는 아래와 같다.
notion image
notion image
 

디렉토리 변경 과정

확장성을 고려해서 디렉토리 구조를 변경해나갔다.
  • 도메인을 언제든 원하는 서버에 확장 가능할 수 있는 구조를 중점으로 생각했다
notion image
 
처음엔 위와 같이
  • 도메인 단위로 나누고
  • 도메인의 집합은 각 실행 가능한 서버 단위가 되고
  • 서버는 모듈이 되는 구조를 생각했다.
 
그리고 이 개념을 프로젝트 구조에 적용했다.
 

변경 후 디렉토리 구조

notion image
 
Module이라는 개념을 도입했다.
모듈은 n개의 도메인이 묶인 구조라고 생각하면된다. 도메인안에는 또 여러 도메인이 존재할 수 있다.
 
결론적으로 큰 도메인을 각각의 서버로 분리할 수 있고, 서버의 분리는 확장을 의미한다고 생각했다.
서버의 모음이 모듈이 되어 언제든 원하는대로 확장하고 축소 할 수 있는 구조를 만들었다.
 
그렇다면 정말 서버가 별도 분리되었을 때,
다른 서버, 다른 도메인에 있는 entity, method 를 어떻게 참조할 수 있을까?
현재 프로젝트에는 Series, Write Domain이 존재한다.
SeriesService에서 WriteService를 주입받는 상황이라면 아래와 같은 구조도 충분할 것 이다.
@Service public class SeriesService { private final SeriesRepository seriesRepository; private final WriteService writeService; public SeriesService( SeriesRepository seriesRepository, WriteService writeService ) { this.seriesRepository = seriesRepository; this.writeService = writeService; } @Transactional public SeriesSubscribePost.Response createSeries( Long userId, MultipartFile thumbnail, SeriesSubscribePost.Request request ) { Writer writer = this.writeService.findByUserId(userId); //Do something ... } }
 
하지만 서버가 분리되었다고 생각하면 위와 같은 코드로는 대응할 수 없다.
이 부분을 해결하기 위해 interface 기반 java method call을 이용했다.
interface는 provider라는 네이밍을 적용했고, 코드는 다음과 같이 적용했다.
 
public interface WriterProvider { Writer findByUserId(Long userId); }
@Service public class WriterService implements WriterProvider { private final WriterRepository writerRepository; public WriterService( WriterRepository writerRepository, ) { this.writerRepository = writerRepository; } @Override public Writer findByUserId(Long userId) { return this.writerRepository .findByUserId(userId) .orElseThrow(() -> new UserNotFound("userId=" + userId)); }
@Service public class SeriesService { private final SeriesRepository seriesRepository; private final WriterProvider writerProvider; public SeriesService( SeriesRepository seriesRepository, WriterProvider writerProvider ) { this.seriesRepository = seriesRepository; this.writerProvider = writerProvider; } @Transactional public SeriesSubscribePost.Response createSeries( Long userId, MultipartFile thumbnail, SeriesSubscribePost.Request request ) { Writer writer = this.writerProvider.findByUserId(userId); //Do something ... } }
 
현재는 하나의 서버에 모든 도메인이 있기때문에 interface 기반 java method call을 이용하지 않아도 된다.
하지만 서버가 물리적으로 분리되었을 경우를 생각한다면 대응할 수 없다. 하여 이를 확장가능한 코드로 녹여내기위해 Provider라는 개념을 도입하여 이 부분을 해결할 수 있었다.