Tech

프론트엔드에서 Repository 패턴 이용하기

숨고 모바일 챕터에서는 기술(세부사항)보다 도메인에 대한 모델에 집중할 수 있는 아키텍처를 구축해 더 나은 소프트웨어를 만들고자 분투하고 있습니다. 도메인 객체를 얻기 위해 REPOSITORY 패턴을 사용하고 있는 것도 그중 하나인데요. 어떻게 모델에 더 집중할 수 있게 되는지 간단히 정리해봤습니다.

2021-12-07 Jimmy Lee

Photo by Hanna Morris on Unsplash

숨고 모바일 챕터에서는 기술(세부사항)보다 도메인에 대한 모델에 집중할 수 있는 아키텍처를 구축해 더 나은 소프트웨어를 만들고자 분투하고 있습니다. 도메인 객체를 얻기 위해 REPOSITORY 패턴을 사용하고 있는 것도 그중 하나인데요. 어떻게 모델에 더 집중할 수 있게 되는지 간단히 정리해봤습니다.

객체를 얻기

객체를 이용해서 무언가를 하려면 먼저 객체를 얻어야 할 텐데요. 일반적으로 세 가지 방법을 통해 얻을 수 있습니다:

  • 객체를 생성해서 얻기
  • 이미 얻은 객체의 연관 관계를 탐색해서 얻기
  • 데이터 소스(데이터베이스, HTTP API, 시스템 API 등)에 질의해서 얻기

데이터 소스에 질의해서 가져오는 것은 실제로는 생성의 한 부분집합으로 볼 수 있습니다. (데이터 소스에서 가져온 데이터를 토대로 새로운 객체를 만들어내기 때문에) 그래서 DDD에서는 이를 재구성(reconstitution)이라고 부릅니다.

도메인 객체를 얻기

어플리케이션 레이어에서는 유즈케이스(어플리케이션 업무 규칙)를 수행하기 위해 이미 존재하는 도메인 객체를 획득할 수단이 필요한데요. 데이터 소스에 직접 접근할 수 있게 하거나 인프라스트럭처 레이어로부터 별다른 제약 없이 도메인 객체를 쉽게 획득할 수 있게 하면 이런 일들이 일어날 수 있습니다:

  • AGGREGATE나 캡슐화와 같은 특징을 활용하는 것을 우회
  • 필요한 데이터를 얻기 위해 데이터 소스에 직접 질의
  • 객체를 편리하게 획득하기 위해 도메인 모델에 연관 관계를 추가해서 모델이 비대해짐

결과적으로 도메인 로직은 질의와 어플리케이션 레이어로 들어가거나 그냥 사라져 버리고, ENTITY와 VALUE OBJECT는 그저 데이터 컨테이너로 전락하게 됩니다. 어플리케이션 레이어는 금방 복잡해지고, 이는 도메인 계층에 대한 개발자들의 이해 수준을 낮춰 모델을 도메인 계층과 동떨어진 것으로 만듭니다.

모델에 집중하려면

그럼 어떻게 해야 어플리케이션 레이어에서 이러한 문제를 줄이고 도메인 모델에 집중하도록 할 수 있을까요?

핵심은 어플리케이션 레이어로부터

  1. 데이터 소스 접근 메커니즘을 감추고
  2. AGGREGATE 내부에 존재하는 모든 객체는 루트 객체를 통해서만 접근하도록 제한

하는 데에 있는데요.

이러한 제약을 통해 도메인 객체를 얻는 과정에서 모델 외적인 부분을 신경 쓰지 않도록 유도할 수 있습니다.

REPOSITORY

REPOSITORY 패턴은 이러한 핵심을 구현해서 코드가 데이터 조회 기술이 아닌 모델에 집중하게 해주는 단순한 개념적 틀입니다. REPOSITORY는 특정 타입의 모든 객체를 하나의 개념적 집합으로 나타내는데, 마치 정교한 질의 기능이 있는 컬렉션처럼 동작하게 됩니다.

REPOSITORY 패턴을 이용하게 되면 어플리케이션 레이어에서는 대개 특정 속성의 값을 선택 기준으로 갖는 질의 메서드를 이용해 REPOSITORY로 객체를 요청합니다. REPOSITORY는 요청된 객체나 객체 컬렉션을 가져오며, 데이터베이스 질의 및 메타데이터 매핑에 대한 장치와 같은 접근 메커니즘을 캡슐화합니다. 객체뿐 아니라 요약 계산을 반환할 수도 있는데 특정 기준에 부합하는 인스턴스의 개수나 모든 객체의 합계와 같은 것들이 해당합니다.

이점

이 패턴을 사용했을 때 얻을 수 있는 이점으로는 이런 것들이 있습니다:

  • 단순하고 의도를 드러내는 인터페이스를 통해 영속화된 객체를 획득할 수 있습니다.
  • 도메인 모델의 측면에서 필요로 하는 것들을 요청할 수 있도록 합니다.
  • 영속화 기술과 다수의 데이터베이스 전략, 또는 다수의 데이터 소스로부터 어플리케이션과 도메인 설계를 분리합니다.
  • 객체 접근에 관한 설계 결정을 표현합니다.
  • 테스트에서 사용할 가짜 구현을 손쉽게 구현 가능합니다.

구현

REPOSITORY 구현의 기본은 저장, 조회, 질의 메커니즘을 캡슐화 하는 것으로 이상적인 모습은 어플리케이션 레이어로부터 내부 기능을 감춰서 데이터가 어디에 저장되는지와 관계없이 어플리케이션 레이어 코드를 동일하게 유지하는 것입니다. REPOSITORY는 내부에서 적절한 인프라스트럭처 서비스에 위임해서 작업을 완수하게 됩니다.

REPOSITORY에서는 AGGREGATE 루트 객체를 검색하는 인터페이스를 제공하게 됩니다. AGGREGATE의 루트는 일반적으로 ENTITY이지만 간혹 복잡한 VALUE OBJECT이거나 열거형 VALUE이기도 합니다.

어플리케이션 레이어에서 채팅방 객체를 얻는 유즈케이스를 간단한 예로 들어보면 이런 식으로 나타납니다.

결론

제약을 추가하고 나누어서 세부사항보다 도메인 본질에 집중하려는 궁극적인 목적은 요구사항 변화에 튼튼하고 빠르게 대응할 수 있는 소프트웨어를 만들어나가고자 함에 있습니다. 숨고의 성장과 함께 모바일 코드 베이스가 계속 증가해 복잡도가 오르고 있지만, 제품 제공 속도를 계속해서 유지할 수 있었던 것은 튼튼하고 빠른 아키텍처에 대한 팀원들의 열정이 있었기 때문이 아닌가 합니다. 이 글에서는 REPOSITORY만을 다루었지만 기회가 된다면 그때에는 전체 구조의 개괄적인 모습을 정리해보겠습니다.

참고

  • 에릭 에반스, 도메인 주도 설계
  • 로버트 C. 마틴, 클린 아키텍처
Jimmy Lee Soomgo Mobile Engineer
숨고의 성장을 위해 열심히 고민하며 노력하고 있습니다.