/Munchkin

2021 Entry6.0 backend repository

Primary LanguageJavaMIT LicenseMIT

Entry6.0 LTS

구성

기획 배경

지난 버전 회고

Entry5.0을 마치고 진행한 회고에서 애플리케이션의 문제보다는 UX적인 문제점이 많이 지적되었습니다. 실제로 올해 서비스는 99.849%의 성공률을 기록하며 성공적으로 마무리되었으며, 발생했던 치명적인 오류는 없었습니다.

문제 인식 및 개선할 점 도출

1기 선배님들부터 5년동안 시스템을 구축하며 생긴 노하우를 바탕으로 잘 돌아가는 어플리케이션 구축에는 무리가 없지만 유지보수에는 어려움이 있다는 문제가 있었습니다. 따라서 저희는 유연성재사용성을 최우선으로 고려하여 유지보수가 가능한 코드를 작성하고자 하였습니다. 궁극적으로 견고한 모노리스 어플리케이션을 구축하여 추후 더 다양한 시도를 할 수 있도록 하는 기반을 다지고자 하였습니다.

문제 해결 방안

유연하고 재사용성 높은 코드를 작성하기 위해 해결 방안을 탐색하던 중 우아한 테크세미나에서 발표된 <우아한 모노리스>의 모듈형 모노리스 적용 사례를 접하게 되었습니다. 각 도메인을 모듈로 분리하여 하나의 서비스로 동작하도록 하며 분리된 서비스들을 조립하여 애플리케이션을 구성한다면 문제를 해결할 수 있을 것이라고 판단하였습니다.

구현 방안

사례 분석

완성도 있는 모듈형 모노리스 애플리케이션을 구성하기 위해서 우선 <우아한 모노리스>의 사례를 분석했습니다. <우아한 모노리스>에서는 다음과 같은 전략들을 사용하여 애플리케이션을 분해하였습니다.

  • 도메인 지향적 멀티모듈 프로젝트 구성
  • 공통적인 관심사는 common 모듈에서 관리
  • 구현 세부사항은 private로 외부 접근 방지
  • 외부 모듈과는 인터페이스로만 교류
  • 의도하지 않은 빈의 공유 방지를 위해 모듈별로 컨텍스트 분리
  • 분리된 컨텍스트들은 하나의 루트 컨텍스트를 부모로 가짐
  • 의도적으로 공유하고자 하는 인터페이스 빈은 @Published 어노테이션을 통해 루트 컨텍스트로 등록하여 간접적으로 공유

분해한 서비스는 하나의 모듈에서 결합되어 사용되므로 서비스간의 결합도를 최소화함에 따른 개발상의 이점과 동시에 서비스의 자유로운 분리/결합으로 인한 운영상의 이점을 모두 취할 수 있었습니다.

전략 설계

<우아한 모노리스>의 사례를 바탕으로 애플리케이션을 구성하기로 하였습니다. 기존 전략은 그대로 가져가도록 하되, 웹 어플리케이션에 맞게 몇 가지 전략을 추가하였습니다.

  • 루트 컨텍스트에 등록된 빈(@Published어노테이션이 붙은 빈) 중 @RestController어노테이션이 붙은 빈은 SERVLET 컨텍스트로 복사하도록 하여 SERVLET 컨텍스트에서 Controller에 라우팅이 가능하도록 하였습니다.

  • 컨텍스트 분리와 재결합에 따른 빈 순환 참조 문제를 해결하기 위하여 도메인의 의존 방향을 정의하였으며, 빈 초기화 순서에 따른 문제를 해결하기 위하여 모듈에 우선순위를 부여하여 참조되는 컨텍스트의 빈을 먼저 초기화 하도록 하였습니다.

구현

애플리케이션 분해

우선 도메인 지향적 모듈화를 위해 기획에서 도메인을 도출하고, 각 도메인마다 하나의 모듈을 구축하여 최종적으로 5개의 모듈의 서비스가 상호작용하며 Entry6.0을 구성합니다.

  • 지원자 : 입학전형 시스템의 주체이며, 지원 서비스를 통해 원서를 접수합니다.
  • 관리자 : 접수된 원서를 확인하고 상태 서비스를 통해 지원자를 관리합니다.
  • 지원 : 지원자의 원서 정보를 관리합니다.
  • 성적 : 지원자의 성적 정보를 관리합니다.
  • 알람 : 지원자의 상태에 따라 지원자에게 알림을 전송합니다.

또한 분리된 애플리케이션을 조립하기 위해서 메인 모듈을, 인증이나 로깅과 같은 수직적 관심사를 공통적으로 구축하기 위해서 공통 모듈을 각각 구축하여 서비스간의 결합이 원활하게 이루어질 수 있도록 하였습니다.

서비스 모듈 구성

<domain>
    ㄴ src
        ㄴ main
            ㄴ java
                ㄴ kr.hs.entrydsm.<domain>
                    ㄴ presenter
                        ㄴ web
                    ㄴ usecase
                        ㄴ dto
                        ㄴ exception
                    ㄴ domain
                        ㄴ entity
                        ㄴ repository
                    ㄴ infrastructure
                        ㄴ database
                    ㄴ integrate
                        ㄴ <other domains>
                    <domain>ModuleConfiguration.java
                    Enable<domain>Module.java
            ㄴ resources
        ㄴ test
  • presenter 계층은 애플리케이션의 최외곽 계층으로, 외부와의 상호작용을 담당합니다. 주로 @RestController 어노테이션이 붙은 클래스가 위치합니다.
  • usecase 계층에서는 애플리케이션의 핵심 비즈니스 로직이 위치합니다. 애플리케이션의 @Service 어노테이션이 붙은 클래스와, 해당 클래스의 인터페이스 및 DTO, 로직 처리 중 발생할 수 있는 exception이 위치합니다.
  • domain 계층에서는 도메인의 속성과 행위를 정의합니다. @Entity 어노테이션이 붙은 클래스와 @Repository 어노테이션이 붙은 클래스의 인터페이스가 위치합니다.
  • infrastructure 계층에서는 서비스가 운영되는 인프라에 대한 부분을 구성합니다. 현재는 DB 관련 로직만 위치하고 있습니다.
  • integrate 계층에서는 모듈과의 상호작용을 위한 로직을 구성합니다. 다른 컨텍스트와의 공유를 필요로 하는 domain이 위치합니다.
  • <domain>ModuleConfiguration 클래스에서는 모듈의 설정사항을 구성하고 컨텍스트에 빈을 등록하는 역할을 수행합니다. 공통 모듈의 ModuleConfiguration 추상 클래스를 상속받아 구현합니다.
  • Enable<domain>Module 어노테이션에서는 <domain>ModuleConfiguration 클래스를 Import하여 어노테이션화합니다.

메인 모듈 구성

main
  ㄴ src
    ㄴ main
      ㄴ java
        ㄴ kr.hs.entrydsm.main
          ㄴ configuration
          ㄴ integration
            ㄴ <domain>
              ㄴ <domain>Integrate<another domain>Service.java
            .
            .
            .
          ㄴ MainApplication
      ㄴ resources
    ㄴ test
  • configuration 패키지에서는 메인에서 다른 모듈들을 통합할 때에 고려해야 할 전략들을 구현합니다.
  • integration 패키지에서는 의존하는 모듈에서 의존받는 모듈로의 통합을 구현합니다.

공통 모듈 구성

common
  ㄴ src
    ㄴ main
      ㄴ java
        ㄴ kr.hs.entrydsm.common
          ㄴ context
            ㄴ beans
              ㄴ Published.java
              ㄴ PublishedComponentRegisteringPostProcessor.java
          ㄴ ModuleConfiguration.java
          ㄴ Module.java
      ㄴ resources
    ㄴ test
  • PublishedComponentRegisteringPostProcessor 클래스에서는 @Published 어노테이션이 붙은 컴포넌트를 루트 컨텍스트로 등록시키는 로직을 구현합니다. <우아한 모노리스>에서 공개된 코드를 바탕으로 최적화하여 구현하였습니다.
  • ModuleConfiguration 클래스는 서비스 모듈 내에 있는 설정사항 파일의 추상 클래스입니다.

Coded By 🔥

EntryDSM

EntryDSM은 대덕소프트웨어마이스터고등학교 입학전형 시스템 개발팀으로, 학교 특성상 매 해마다 진행되는 서류 원서 접수와 면접을 통한 신입생 선발 프로세스를 개선하고자 하는 목표를 가지고 다양한 기술을 탐구하며 요구사항과 팀의 상황에 알맞게 해당 기술을 도입하여 매 해마다 Entry series를 개발합니다.

Entry series

EntryEntryDSM에서 매 해마다 신입생 원서 접수와 면접을 위해서 개발하는 입학전형 시스템 프로젝트입니다. 원서 접수 기간동안 수 만 건의 요청을 안전하게 처리하는 것을 최우선으로 프로젝트가 진행됩니다.