MSA Phase 3. Common Module

devty·2023년 9월 9일
0

MSA

목록 보기
4/14
post-thumbnail

서론

필요한 이유

  • MSA에서는 대게 도메인 서비스 별로 서비스가 나눠져있다.
    • 예를 들어 유저, 주문, 배송, 상품에 대한 서비스가 나눠져있다고 생각해보자
  • 해당 서비스에는 공통적으로 몇가지가 사용된다.
    • 예를 들어 유틸리티(util), 예외 처리, 인증 및 인가에 대해서 공통적으로 사용된다.
  • 이런 공통적으로 사용하는 것들이 각 서비스에 대한 모든 어플리케이션 안에 들어있다고 생각해보자.
  • 인증 인가에 대해 수정이 있다면 유저 서비스에서만 수정할 문제가 아니고 나머지(주문, 배송, 상품)에 대한 서비스에서도 인증 인가에 대한 코드 수정이 불가피하다. flow를 확인하자면 밑과 같다.
    1. 유저 서비스에 대한 코드 수정 사항 발생
    2. 유저 서비스에 인증 및 인가 코드 수정
    3. 유저를 제외한 모든 서비스에 대한 인증 및 인가 코드 수정
      • 위 상황은 유저를 제외한 모든 서비스이기에 서비스가 커지면 커질수록 수정이 과대해짐.
    4. 수정된 모든 서비스에 대한 배포
  • 간략하게 적어서 flow가 이정도밖에 안 나오지만 각 서비스별로 어플리케이션을 킨 후 코드 수정을 해줘야하므로 서비스가 커지면 커질수록 시간은 오래걸리게 될 것 이다.
  • 따라서 이러한 문제를 해결하기 위해 모든 서비스에서 사용하는 공통된 모듈을 만들 것이다.
💡 모듈이란? 일반적으로 큰 체계의 구성요소이고, 다른 구성요소와 독립적으로 운영되는 것이다. 즉, 독립적으로 운영될 수 있는 의미를 가진 구성요소라고 할 수 있다.

본론

공통으로 필요한 코드 예시

  • 그래서 우리는 모든 서비스에서 필요한 코드가 뭐가 있는지 생각해봐야한다.
  • 나의 예시로는 SelfValidating이 있는데, SelfValidating를 왜 사용하냐면 객체가 생성되는 시점에서 유효성을 검사하기 위해서 사용하였고 코드 중복을 줄이기 위해 사용하였다.
  • 해당 코드는 밑과 같다.
    public abstract class SelfValidating<T> {
    
        private Validator validator;
    
        public SelfValidating() {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            validator = factory.getValidator();
        }
    
        protected void validateSelf() {
            Set<ConstraintViolation<T>> violations = validator.validate((T) this);
            if (!violations.isEmpty()) {
                throw new ConstraintViolationException(violations);
            }
        }
    
    }
    • 이 코드는 Request를 받는 모든 API에 사용이 되므로 모든 서비스에서 사용되고 있다.
    • 따라서 이 부분을 공통 모듈로 따로 뺄 것이다.

공통 모듈 만들기

  • Intellij에서 Root Directory에서 새로운 모듈을 만들면된다.

  • 공통 모듈에 대한 이름은 주로 Common, Global 등을 사용하였는데 나에게는 공통에 대한 의미를 더 부여하기 위해 Common을 사용하였다.

  • 위에서 추가해주었다면 Root Directory에 settings.gradle에 common이 포함되었을 것이다.

  • 그 후 common Directory에서 필요한 클래스를 만든다. 나에게 필요한 클래스는 SelfVaildating이므로 만들어주었다.

  • 여기까지 온 상태에서 다른 서비스(유저, 주문 등등)에 바로 SelfVaildating을 아직은 사용할 수 없다.

    • 왜냐하면 아직 같은 Root Directory에 있다고 사용할 수 있는것은 전혀 아니다.
    • 예시로 사진을 한장 보여주겠다.
      • 사실 생각해보면 공통 모듈에 넣었을 뿐이지 다른 서비스에서는 해당 공통 모듈에 존재하는 클래스를 직접적으로 받아서 사용할수 있는 연결 경로를 설정을 해주지 않았다.
  • 다른 서비스에서 공통 모듈에 있는 클래스를 임포트하기 위해서는 연결 경로를 설정해주어야한다.

  • 공통 모듈에 클래스를 사용하기 위한 다른 서비스는 모두 밑과 같이 작업을 해주어야한다.

    • 예시로 유저 서비스에 build.gradle 파일로 설명하겠다.
      plugins {
          id 'java'
          id 'org.springframework.boot' version '2.6.1'
      }
      
      group = 'user'
      version = '0.0.1-SNAPSHOT'
      
      dependencies {
          // common module
          implementation project(path: ':common')
          
      		// 다른 dependencies....
      }
      • 해당 코드를 보면 우리가 익히 알고 있는 build.gradle 파일이다.
      • 다른점이 있다면, implementation project(path: ':common') 이 부분을 추가해주었다.
        • path: ':common'는 해당 공통 모듈에 대한 Directory 이름으로 지정해주어야한다.
      • 해당 부분을 추가해주면 공통(common) 모듈을 사용할 수 있게 된다.
      • 추가한 뒤 build를 다시 하는 것은 당연히 알고 계시죠😉
  • build를 다시 한 뒤 SelfValidating을 임포트 하게 되면 위 네모박스와 같이 임포트가 된다.

    • 저기 나와있는 import path는 내가 만든 공통 모듈 디렉토리 구조와 일치한다.
  • 따라서 다른 공통 모듈로 만든 다른 클래스도 이제 유저 서비스에서는 계속 사용할 수 있다.

  • 그리고 이제 유저 서비스를 컴파일 하게 되면 common에 대한 즉, 공통 모듈에 대한 컴파일이 먼저 진행 하고 난 뒤 유저 서비스에 대한 컴파일이 진행이 된다.

결론

후기

  • 공통 모듈을 만들기 위해서 모노 레포, 멀티 레포 등 생각해야함.
profile
지나가는 개발자

0개의 댓글