토스 SLASH22 의 ‘지속 성장 가능한 코드를 만들어가는 방법’’ 에 대한 학습 내용을 정리하기 위한 목적의 TIL 포스팅입니다.🙆♂️
- 햄버거 서비스의 생성자를 통해 해당 클래스가 어떤 클래스인지 암시적으로 들어냄.
- 너무 과한 의존성이 걸려있는게 아닌지 고민 필요
- import 문을 기준으로 package, layer, module 세 가지 관점에서 어떤 구조가 지속 성장 가능한 코드인지 설명 예정
Package
- 고정되지 않고 매우 유연해야할것 => 현재 상황을 계속 점검하면서 전략에 따라 응집에 대해 유연하게 지켜내야 하는 가치
- 응집에 대해 고민하며 패키지를 수정
- 카드 관련 개념에 속한 클래스들의 import 문을 없앰
- 특정 도메인 관련 서비스(ex. CardService)가 존재하려면 필요한것들을 같은 패키지에 두어 응집도를 높일것
- 개념 기준으로 클래스들을 응집시켰을때 한 개념에 클래스가 너무 많다면? => 적절한 시기에 개념을 좀 더 세분화 (ex. 카드 owner 라는 개념을 세분화)
Layer
- 토스 페이먼츠의 표준 Layer 규칙
- Presentation Layer:
- Business Layer:
- Implement Layer:
- Data Access Layer:
- 핵심 규칙
- 1)위에서 아래로 순방향으로만 참조되어야 한다. (클린 아키텍처 원칙)
- 2)참조 방향이 역류되지 않아야 한다. (클린 아키텍처 원칙)
- 3)레이어를 건너뛰지 않는다.
- 컨트롤러에서 RQ 를 그대로 비즈니스 레이어에 전달하면 import 참조 방향이 역류되게 됨.
- 도메인 레이어에 있는 클래스를 참조하여 전달하도록 개선
- 레이어간의 잘못된 참조는 장기적으로 코드 복잡도를 높이고 확장에 발목을 잡거나 문제를 만들어냄
Module
- 토스페이먼츠 표준 모듈 구조임
- 실제로 런타임시엔 runnable 한 모듈을 중심으로 의존성이 주입되어 실행됨
- 회색원은 외부 기능을 확장시 새로운 모듈을 만들어나간다는 의미를 나타냄
- 기술을 격리, 각 모듈별로 테스트가 가능, 역할과 경계를 뚜렷하게 정의할 수 있게됨
- 만약 단일 모듈로 작업하게 되면 의도치 않게 비즈니스 로직안에 특정 라이브러리에 대한 의존이 들어갈수있다. 라이브러리 버전 업데이트 또는 내부 요구사항에 의해 변경될수 있다.
- 이럴때 비즈니스 로직에 라이브러리 로직이 침투되어있다면 비즈니스 로직도 같이 수정되어야 하는 상황이된다.
- 이러한 라이브러리에 대한 의존도 import 문을 통해 확인할 수 있다.
- 외부 의존을 줄이려면 모듈을 분리후 격리하면 의존성 침투를 막을수 있다.
- Payments API는 도메인을 가지는 형태로 존재. 또한 API 서빙을 위해 스프링에 대한 의존성을 가지고 있음
- 도메인 모듈이 Payments API 로부터 분리되었고, 스프링과의 의존성이 격리된 상태
- 선택에 따라 스토리지 모듈 자체를 은닉할수도 있다. Payments API 가 스토리지 모듈을 런타임에 의존하게 하고 스트로지 모듈은 도메인 모듈의 명세에 따라 구현체의 역할만 하는 구조로 수정할 수 있다.
- 이 구조에서 Payments API 는 도메인 모듈만 알고 스트리지 모듈의 구현 세부사항은 아예 모르는 형태가 되버린다.
- HTTP 응답으로 JPA Entity 를 사용한다거나 도메인이 HTTP 스펙을 알고 있는 문제를 만들지 않을수 있다.
- 이러한 장점을 활용하여 더 격리된 환경에서 비즈니스를 확장할 수 있게 된다.
- 개선된 코드인데 Presentation 레이어를 참조하지 못하게 격리됨(임포트 불가능)
- 스프링에 대한 import 도 불가능해지고 순수한 코드만 남게됨
모든 코드는 각자 신호를 보내고 있고, 우리는 그속에서 적절한 트레이드오프를 하면서 다음 수준의 설계를 고민해야 한다. 영원히 완벽한 코드와 설계는 존재하지 않는다. 계속 진화해야 한다. 결국 지속 가능한 소프트웨어는 지속 가능한 코드 기반에서 나온다.
- 토스페이먼츠가 소프트웨어를 두 가지 핵심 키워드에 기반을 두며 만들어가고 있다.
- 첫번째는, 통제
- 코드에 지속적인 관심을 두며 소프트웨어를 통제하려 한다.
- 올바른 응집으로 코드를 관리하고 레이어간의 규칙을 지키며 적절한 모듈화로 기술을 격리하여 다양한 변화에 대응할수 있도록
- 두번쨰는, 제어
- 이 통제를 기반으로 소프트웨어를 제어한다.
- 코드의 수명이 길기 떄문에 지속적인 관리와 성장이 필요하다.
- 통제와 제어를 기반으로 지속성장하는 소프트웨어. 통제를 기반으로 코드의 제어권을 얻어 지속 성장가능한 소프트웨어를 효과적이고 안정적으로 만들어내어 산업을 이끌어가는 시스템을 구축하려 노력중