모든 글

설계 자원을 쓰기 전에 핵심 개념의 우선순위를 정하라

1급 도메인 개념을 찾고 보조 흐름을 분리해, 제한된 설계 시간을 변화의 중심에 쓰는 실용적인 방법을 설명한다.

출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다. gpt-5.6-sol 모델을 사용해 생성·편집했습니다.

서비스에는 중요한 개념이 많이 있을 수 있지만 모든 개념에 같은 우선순위를 줄 필요는 없다. 시간이 부족하면 팀은 결국 어느 영역부터 개선할지 골라야 한다. 개념에 급수를 정하면 그 트레이드오프를 명시적으로 다룰 수 있다.

먼저 서비스의 중심에 있는 개념을 작은 1급 집합으로 정한다. 1급이 꼭 하나일 필요는 없지만, 실제 결정에 도움이 될 만큼 집합을 작게 유지해야 한다.

급수는 엔티티의 가치를 평가하거나 1급에는 하나, 2급에는 둘을 넣는 식의 숫자 규칙이 아니다. 어떤 개념의 불변식과 이름, 테스트, 소유권 경계를 먼저 선명하게 할지 정하는 도구다. 거의 모든 개념을 1급이라고 부르면 시간이 줄었을 때 아무 선택도 도와주지 못한다. 먼저 작은 1급군을 정하고, 나머지가 그것을 만들거나 유지하는 데 어떤 역할을 하는지 살펴보는 편이 낫다.

신청과 신청이 만들 수 있는 대출을 나눈다

대출 서비스를 생각해 보자. 초기 모델에서는 신청, 심사, 실행, 상환을 하나의 Loan이 가진 상태로 다룰 수 있다. 모양은 단순하지만 모든 대출 신청이 실제 대출이 되는 것은 아니다.

사용자는 신분 확인을 미루거나, 가심사 한도가 기대보다 낮아 포기하거나, 더 나은 조건을 찾아 떠날 수 있다. 실행 전에는 아직 대출이 존재하지 않을 수 있다. 신청은 중심 개념을 만들지 못한 채 끝날 수도 있는 과정이다.

이 관찰을 바탕으로 ApplicationLoan을 나눌 수 있다. 신청은 완료되지 않은 사례까지 포함해 실행 전 단계를 다룬다. 대출은 실행에 성공했을 때 생기고, 상환은 존재하는 대출에서 이어진다. 서비스의 주된 흐름이 실행된 대출부터 시작한다면 Loan을 1급에 두고 Application은 더 낮은 급수에 둘 수 있다.

심사가 있다고 해서 신청 직후 대출이 항상 실행되는 것도 아니다. 상품에 따라 즉시 실행될 수 있지만, 심사를 거쳐 나중에 실행될 수도 있다. 그래서 실행은 하나의 Loan이 신청 중에서 실행됨으로 바뀌는 상태 전환만이 아니라, 아직 없던 대출을 만드는 명시적인 사건으로 볼 수 있다. 그 전까지의 중도 이탈과 심사 흐름은 Application의 생명주기에 남는다.

이것은 해당 서비스를 위한 정의이지 모든 제품에 통하는 법칙은 아니다. 다른 제품은 다른 중심을 선택할 수 있다.

예를 들어 신청 완료율을 높이는 것이 제품의 주된 가치라면 Application이 오히려 1급이 될 수 있다. 같은 업종과 비슷한 화면을 가졌다는 이유만으로 급수를 복사해서는 안 된다. “이 서비스의 주된 가치 흐름은 정확히 어디서 시작하는가?”라는 질문에 답한 뒤 그 답을 코드에 반영해야 한다.

시간이 선택을 강요할 때 급수를 사용한다

낮은 급수의 개념이 가치 없다는 뜻도, 코드를 무성의하게 써도 된다는 뜻도 아니다. 급수는 더 좁은 질문에 답한다. 제한된 설계 시간을 어디에 먼저 쓸 것인가?

출시가 다음 주이고 대출 영역과 신청 영역 가운데 한쪽만 정리할 수 있다고 해보자. 이 예시에서는 1급인 대출 개념을 고른다. 시간이 더 생기면 신청 영역도 당연히 개선한다.

낮은 급수는 지저분한 코드를 영구히 허용하는 이름이 아니다. 둘을 동시에 고칠 수 없는 구체적인 시점에 핵심 대출의 규칙을 먼저 정리하겠다는 상대적 선택이다. 신청 역시 필요한 개념이므로 이후에 개선해야 한다. 다만 제한된 한 시간을 어디에 쓸지 판단할 때 중심 가치에 미치는 영향이 더 큰 곳부터 고칠 수 있게 한다.

모든 개념이 같은 긴급성을 주장하지 못하게 한다는 점에서 급수는 유용하다. 1급이 선명해지면 나머지 개념이 그것을 어떻게 지원하고 어디에서 이어지는지에 따라 거리를 정할 수 있다.

급수가 코드 경계에도 나타나게 한다

이 구분은 코드에도 보여야 한다. 신청은 실행으로 이어지고, 실행에 성공하면 대출이 생긴다. 그 연결 지점을 제외하면 신청 과정의 변경이 대출 개념에 주는 간섭을 가능한 한 줄여야 한다.

신청 화면이나 중도 이탈 사유, 실행 전 심사 절차를 바꿨을 때 이미 실행된 대출의 상환 규칙까지 함께 수정해야 한다면 경계는 아직 이름으로만 나뉜 것이다. 신청 코드는 실행 접점까지 영향을 줄 수 있지만, 그 내부 변경이 Loan 전체로 번지지 않아야 한다. 보조 흐름의 변화가 잦더라도 1급 개념의 불변식을 흔들지 않는 방향으로 의존성을 두는 것이다.

초기의 상태 중심 모델이 불편했던 이유도 여기에 있다. 아직 존재하지 않는 대출 객체에 대출 이전의 신청 상태를 넣었다. 신청 개념을 분리하면 완료되지 않은 시도를 대출 생명주기에 억지로 밀어 넣지 않고 다룰 수 있다.

첫 시도부터 경계가 완벽할 필요는 없다. 신청이 실행보다 앞에 있고, 실행 뒤에 대출이 생기며, 그 대출에서 상환이 이어진다는 현재의 이해를 표현하면 된다.

팀은 몇 가지 질문으로 이 구분을 시험할 수 있다.

  • 핵심 모델을 다시 쓰지 않고 신청 흐름을 바꿀 수 있는가?
  • Loan을 생성하는 실행 사건이 코드에서 명확한가?
  • 대출이 생기기 전의 상태를 Loan이 억지로 들고 있지는 않은가?
  • 일정이 절반으로 줄어도 반드시 지킬 불변식과 테스트는 무엇인가?
  • 유지보수자가 두 영역의 변경 빈도와 소유권 차이를 설명할 수 있는가?

이 질문에 답하기 어렵다면 급수는 다이어그램의 표시에 머물렀을 가능성이 높다. 우선순위가 실제 모듈 경계와 변경 영향에 나타나야 설계 자원을 집중하는 효과가 생긴다.

운영하며 급수를 계속 고친다

서비스를 운영하는 동안 위계도 계속 진화시켜야 한다. 운영은 출시 전 그림만으로 얻기 어려운 통찰을 준다. 팀은 현재 개념과 경계가 실제로 운영하는 서비스에 여전히 맞는지 확인할 수 있다.

사용자가 어느 단계에서 이탈하는지, 정책이 어디에서 자주 바뀌는지, 어떤 데이터의 일관성이 중요하고 어느 코드에서 장애가 반복되는지가 근거가 된다. 보조 개념이 제품 변화와 함께 중심으로 올라갈 수도 있고, 하나처럼 보였던 두 개념의 생명주기가 갈라질 수도 있다. 최초 급수는 영구적인 서열이 아니라 운영으로 검증하고 수정할 가설이다.

도메인 개념의 급수를 정하는 일은 결국 제품의 정체를 정의하는 활동이다. 작은 1급 개념군을 찾고, 이를 지원하는 개념을 알맞은 거리에 두며, 설계 자원이 부족할 때 그 급수를 사용하자. 운영에서 더 알게 된 내용에 따라 이 결정도 계속 다시 살펴야 한다.