mainlib990의 개인 보고서 #240
Closed
mainlib990
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
0. 개발 회고 요약 (Executive Summary)
이번 프로젝트에서 리뷰(Review) 도메인의 핵심 기능 개발 및 아키텍처 설계를 주도했습니다. 저의 기여는 다음 세 가지 핵심 영역으로 요약할 수 있습니다.
첫째, 유지보수성과 확장성을 고려한 아키텍처를 설계하고 구축했습니다.
Review도메인의 문제를 해결하기 위해, Persistence Model과 Domain Model을 분리하는 것을 시작으로 Hexagonal Architecture를 도입했습니다. 이를 통해 비즈니스 로직의 순수성을 확보하고, 외부 기술 변화에 유연하게 대처할 수 있는 기반을 마련했습니다. 또한, CQRS, 이벤트 기반 처리, 스냅샷 패턴 등을 적용하여 시스템의 확장성과 안정성을 크게 향상시켰습니다.둘째, 기술적 난제를 해결하며 팀의 성장을 이끌었습니다.
created_at기반의 클러스터형 인덱스 생성을 제안하는 등 팀의 데이터베이스 성능에 대한 이해도를 높이는 데 기여했습니다.셋째, 실용적인 엔지니어링과 미래에 대한 깊은 고찰을 병행했습니다.
이 보고서는 위와 같은 저의 고민과 경험, 그리고 프로젝트의 성과와 향후 발전 방향을 상세히 기술합니다.
1. 담당한 작업
프로젝트 내에서 리뷰(Review) 도메인의 핵심 기능 구현을 담당했습니다. 여기에는 리뷰 작성, 조회, 수정, 삭제의 CRUD 기능과 리뷰 좋아요(Like) 기능이 포함됩니다. 기능 구현을 넘어, 복잡한 비즈니스 요구사항을 체계적으로 관리하고 향후 확장성을 고려한 아키텍처 설계를 주도했습니다. 단, 리뷰 모듈 내의 스케줄러(Scheduler) 및 배치(Batch) 처리 부분은 저의 담당 범위에 포함되지 않았습니다.
2. 기술적 성과
단순한 기능 완성을 넘어, 유지보수성과 확장성을 극대화하는 엔지니어링 설계에 집중했으며, 이는 다음의 기술적 성과로 이어졌습니다.
DDD(도메인 주도 설계) 기반의 비즈니스 로직 중심 개발
Aggregate Root를 사용하여 자식 엔티티와의 무결성을 보장하며,Value Objects(예:ReviewRatingDomain)를 적극 활용하여 도메인 로직 수행 전 유효성 검사를 확실히 했습니다.Hexagonal Architecture를 통한 유연한 설계
UseCase Port를 통해 애플리케이션 코어로의 접근점을 만들었으며, Application Service와 Domain Service의 역할을 명확히 구분했습니다. Application Service는 서비스 오케스트레이션과Fail-Fast Principle을 적용한 유효성 검증을 담당했고, Domain Service는 순수 비즈니스 로직에 집중하도록 했습니다.Anti-Corruption Layer (ACL)를 두어 외부 도메인 모델이 내 도메인에 영향을 주지 않도록 분리하고 안전하게 로직을 수행했습니다.CQRS(Command Query Responsibility Segregation)를 고려한 확장성 확보
ReviewCommandService와ReviewQueryService를 분리하여 각 작업의 복잡도를 낮추고, 추후 읽기/쓰기 작업의 부하에 따라 독립적으로 최적화 및 확장할 수 있는 기반을 다졌습니다.3. 문제점 및 해결 과정 (STAR 기법 적용)
Situation (상황):
Review모듈은 도서, 사용자 등 다른 여러 모듈과 상호작용이 많아 프로젝트 내에서 가장 복잡한 도메인 중 하나였습니다. 초기 단계에서 JPA의@Entity를 도메인 모델로 그대로 사용할 경우, Persistence 로직(JPA 어노테이션)과 순수 비즈니스 로직이 한 클래스에 뒤섞여 코드 복잡도가 급격히 증가하고 장기적인 유지보수가 극도로 어려워질 것이라 판단했습니다. 또한,Like기능이나 통계(ReviewStat) 처리와 같이 강한 일관성이 필수는 아닌 비핵심 로직들이 메인 트랜잭션에 엮여 시스템 전반의 확장성을 저해할 우려가 있었습니다.Task (과제):
향후 기능 추가 및 변경이 용이하고, 시스템 전반의 확장성을 확보하며, 복잡한 비즈니스 규칙을 체계적으로 관리할 수 있는
Review모듈을 설계하는 것이 목표였습니다.Action (행동):
Persistence Model과 Domain Model 분리 및 Hexagonal Architecture 도입:
@Entity와 비즈니스 로직의 혼재 문제를 해결하기 위해,Persistence Model과Domain Model을 명확히 분리했습니다.Domain Model은Rich Domain Model로 설계하여 비즈니스 로직을 포함하고,Persistence Model은Anemic Domain Model로 단순한 데이터 저장소 역할을 하도록 했습니다.Port와Adapter패턴을 통해 애플리케이션 코어와 외부 인프라의 의존성을 역전시켜 비즈니스 로직이 외부 기술에 종속되지 않도록 했습니다.Like기능 및 통계 처리 분리 설계:Like기능은 즉각적인 동기화 처리가 불필요하며, 향후 다른 기술 스택(예: Redis)으로 전환 가능성이 높은 비중요 모듈임을 인지했습니다. 이에Review의 핵심 비즈니스 로직과 분리하여 최종적 일관성(Eventual Consistency)을 가질 수 있도록 설계했습니다.ReviewStat과 같은 통계 데이터 처리 역시 강한 일관성을 요구하지 않으므로, 추후 별도 모듈로 분리될 수 있도록 염두에 두고 설계를 진행했습니다.common모듈 변경에 대한 제약으로 동기적 이벤트 발행 방식을 채택했습니다.)Result (결과):
Like나 통계와 같은 비핵심 기능들이 메인 비즈니스 로직에 부담을 주지 않는 확장성 있는 구조를 구축했습니다.common모듈 수정 제약으로 인한 동기적 이벤트 발행 방식은 아쉬운 점으로 남았으나, 이는 현 프로젝트 상황을 고려한 실용적인 결정이었습니다.4. 협업 및 피드백
프로젝트의 목표가 '과정보다 결과에 집중'이었기에, 매 PR마다 코드 리뷰를 진행하기보다는 전체적인 그림을 맞추고 주요 기술적 난제를 함께 해결하는 데 집중했습니다.
동시성 문제 해결을 위한 기술 논의 주도
데이터베이스 성능 향상을 위한 지식 공유 및 논의 주도
created_at컬럼을 기준으로 클러스터형 인덱스를 생성해야 한다고 제안했습니다. 이를 통해 새로운 데이터가 항상 테이블의 끝에 추가되도록 하여 쓰기 성능을 최적화하는 방법을 공유했습니다.5. 테스트 전략 및 고찰
Review모듈은 초기 레이어드 아키텍처에서 Hexagonal 아키텍처로 전환하는 등 구조적인 변경이 매우 클 것으로 예상되었습니다. 이러한 대규모 리팩토링 중에는 TDD 방식이 비효율적이며, 잦은 구현 변경으로 인해 테스트 코드가 계속해서 깨지는 문제를 야기할 것이라 판단했습니다. 이에, 아키텍처가 안정화될 때까지 테스트 코드 작성을 의도적으로 미루는 실용적인 접근을 선택했습니다.ReviewTest.java참고)를 작성하자고 제안했습니다. 이를 통해 핵심 기능의 동작을 보장함과 동시에, 중간 계층을 참조하지 않아 내부 리팩토링에 깨지지 않는 견고한 테스트를 만들 수 있었습니다. E2E로 커버하기 어려운 예외 처리 등은 통합 테스트로 보완하는 방향을 제시했습니다.6. 코드 품질 및 최적화
7. 향후 개선 사항 및 제안
Hexagonal Architecture의 점진적 확대: 제가 담당한 모듈에 성공적으로 적용된 Hexagonal Architecture를, 향후 개발될 다른 복잡한 도메인 모듈에도 점진적으로 확대 적용할 것을 제안합니다. 단, 모든 모듈에 강제하기보다는, 복잡도와 팀의 상황을 고려한 실용적인 접근이 필요합니다. 제가
package-by-feature형태로 패키지 구조를 설계한 것은, 이러한 점진적 전환 및 향후 MSA로의 발전을 용이하게 하기 위함이었습니다.이벤트 기반 아키텍처 고도화 (비동기 및 Black-Box 패턴 적용):
common모듈 변경에 대한 제약으로 인해 동기적 이벤트 발행 방식을 채택했습니다. 하지만 장기적으로는 메시지 브로커(예: 메시지 큐 또는 이벤트 스트리밍 플랫폼)를 도입하여 이벤트를 비동기적으로 처리하고, 발행자와 구독자 간의 의존성을 완전히 분리하는 Black-Box 패턴을 적용할 것을 제안합니다. 이는 시스템의 처리량을 극대화하고, 장애 격리 및 시스템 회복탄력성을 크게 향상시킬 수 있습니다.CQRS 아키텍처의 물리적 분리:
Optimistic Locking 도입을 통한 동시성 제어 개선:
장기적인 아키텍처 진화 방향: Reactive 프로그래밍 모델 도입 검토:
Beta Was this translation helpful? Give feedback.
All reactions