종류

  • 어떤 스타일의 팀에, 어느정도 규모의 팀에 어울릴지. 무조건 좋은건 없음.

  • 누구는 복합적으로 사용한다고 말할수도 있을텐데, 정확히 어떻게 나눠서 얘기할수있는가?

Multorepo

  • 독자적인 repository로 소스를 관리하는 방법

  • git을 사용할 경우 독자적인 repository를 하나의 repository 안에서 submodule로 구성/관리할 수 있음

  • Polyrepo 구조라고도 불림

  • 각 프로젝트는 높은 자율성을 가지며, 독자적인 개발, 린트, 테스트, 빌드, 게시, 배포 파이프라인을 갖게 됨

  • 팀의 자율성 때문에 선호하기도 함

  • 자율성은 고립(Isolation)에 의해 제공되고 고립은 협업을 방해함

  • 단점

    • 번거로운 프로젝트 생성

    • 패키지의 중복 코드 가능성

    • 관리 포인트 증가

    • 일관성 없는 개발자 경험

    • 다른 패키지의 변경 사항 파악

    • 교차 리포지토리의 리팩터링 비용

  • 일부 단점에 대해서 IntelliJ를 통해서 어느정도 해소 가능하나, 개발자 개개인의 도구 숙련도가 필요함

Monorepo

?

  • monorepo + 1 git repo

    • 어떤 관심사로 repo를 모을 것인가?

  • multi git repo (monolithic?)

    • git submodules + multi git repo

    • intellij 에서 multi git repo에 대한 지원 활용


  • 작은 토이 프로젝트가 아닌 이상 프로젝트는 점차 커지고 효율적인 관리를 위해 소스코드를 분리하게 됨

  • Spring Framework 기반에서 주로 아래와 같은 빌드 툴과 기능을 활용함

  • 프로젝트가 단위별로 나눠지는 것은 당연한 일이라고 할 수 있지만, 어떤 관점으로 어떻게 나누냐는 팀마다 다를 수 있음

Core

  • 재활용이 가능한 중복 코드를 Core라는 패키지, 모듈, 프로젝트 혹은 저장소에 모아두는 구조

  • 코어 기반 구조는 Common, Parent 등으로도 불려짐

장점

  • 중복 코드 제거

  • 중복 코드를 제거할 수 있다.

  • 코드 재활용에 수월하다.

  • 수정해야하는 비지니스를 한번에 관리할 수 있다.

단점

  • 크기

    • 시간이 지남에 따라 점점 비대해진다. 팀원이 많다면 더 빠른 속도로 증가한다.

  • 접근성

    • 누구나 비지니스 로직을 넣기 쉬워진다. 이는 다양한

  • 컴포넌트를 분리하기 어려워진다(싫어진다)

  • 빌드시간이 길어진다 (테스트 포함)

  • 사이드 이펙트

  • 런타임 오버헤드

    • 쓰지도 않는 빈이 같이 올라간다. 부팅시간 올라감

  • 빅브라더

  • 스파게티 코드

    • 한곳만 수정하면 되니 장점으로 말하는 사람도 있을테지만, 장점보다 단점이 더 크지 않은가?

  • 의존성 덩어리

그럼?

  • 무엇을 코어에 두어야 하나

  • 코어라는 이름을 버릴까?

  • enum들이 적당

  • 어노테이션, 각 코드(상수)

  • 유틸, 익셉션, 엔티티, …​

    • 엔티티가 비지니스를 가졌다고 생각든다면 DB 테이블에 대해 추상화가 안된게 아닐까

  • client

Multi Module Project

특징

  • API 클라이언트들이 각 모듈로 나눠져있을 때, build.gradle.kt 만으로 어떤 클라이언트들을 사용하지는지 명확하게 알 수 있음

  • API 클라이언트들이 각 모듈로 나눠져있을 때, 새로운 클라이언트 의존성을 추가할 때 gradle 리로드가 필요함(개발 속도)

  • 너무 잘게 나눠져있을 경우, 새로운 코드짤 때 어디에 넣어야할지 고민하게 됨

  • 불가피한 코드 중복이 발생하게 됨

    • e.g. DB저장용 Country, API 인터페이스용 Country, VO 개념의 Country

관리 방법

  1. 빌드 도구를 활용한 서브 모듈

    • js 진영에서는 monorepo(lerna), workspace(npm)

    • multi-project(gradle)

  2. Git Repository 별로 분리

    • Git을 활용한 submodule 활용 가능

    • 굳이 submodule repo를 만들지 않아도 IDEA 툴에서 원활하게 개발할 수 있도록 지원함

중복 코드에 대한 새로운 관점

  • 리팩토링 책에서 중복 코드에 대해서 메서드 올리기를 통해 부모로 옮기라고 말하지만, 여기서 부모는 core 모듈을 말하는 것이 아닌 상위 호출자를 말하는거라 생각한다.

  • "부모로 옮긴다."에만 포커싱을 갖게 되면 결국 core가 만들어진다.

  • 상위로 올리고, 유틸리티를 만들고, 부모가 커지는 느낌을 받는다면 다시 한번 전체를 살펴보자. (나무가 아닌 숲을 보기)

  • 계층을 갖게되면 다른 고민/문제점이 발생함.

  • 유연함을 생각하자

    • ApiClient 들은 서킷브레이커랑 WebClient 를 주입 받을 것인가?

    • 사용하는 곳마다 ReadTimeout, ConnectionTimeout이 다를텐데?

    • 이와 같이 다를 경우가 얼마나 있을 것인지. 우선 통합해서 사용하다가 추후에 타임아웃 시간과 BaseUrl 정도만 주입받아도 충분할 듯

모든 중복을 제거할 순 없다.

코드 중복은 죄악이 아니다.

Core-Less?

  • 어느정도 중복은 허용하자. 이젠 강력한 기능을 지닌 IDEA에서 중복코드 제거는 껌.

  • 분리가 필요한 시기에 옮겨도 충분. 하지만 무지성으로 코드 중복 제거, 메서드 옮기기 하지 않고 중복을 유지하는게 더 낫다면 유지.

  • 빌드 속도, 어플리케이션 실행 속도에 중점?

  • 디펜던시는 모두 API를 호출하게끔? 이건 결국 API가 코어가 되는게 아닐까?

    • "그럼 무슨 문제가 있는가? 요즘 MSA 기반에서 무슨 문제인가?"

Etc

개인고민

팀원 모두 기술 수준, 이해도가 높다면 걱정 x 어떻게 얼만큼 제한할 수 있는지? 최소한의 제약을?? 패키지로?? 도메인으로?(이게 젤 어려움), 의존성으로?

References