배경
의사와 직접 상담을 하고 병원 예약을 하는 서비스인 2.0 버전의 핵심 모델은 상담이었습니다. 처음에는 상담과 병원 예약이 가능한 서비스의 형태였는데 이것만으로는 고객이 참여할 요인이 없다고 생각하여, AI 얼굴 타입 및 나이 분석 기능과 연계하여 상담과 자연스럽게 연결되도록 구성했습니다. AI 분석에 대한 것은 다른 글에서 다루고, 이번 글에서는 상담에 초점을 맞춰보겠습니다.
이번 글에서 다뤄볼 것은 다음과 같습니다.
- 상담 모델 설계
- 하위 호환성
- 명확한 의도 전달을 위한 API 분리
상담 모델 설계
도메인
- Factor
- 피부 진단에 대한 카테고리입니다. 팩터와 서브팩터로 나눴습니다. 개념상 값객체로 두어도 충분하다고 생각했었지만, 온보딩을 할 때 메인, 서브팩터의 조회가 필요하고 시술 및 이벤트를 조회할 때도 메인팩터가 필요했었기 때문에 respository를 갖는 에그리게이트로 구성했습니다.
- Concern
- 유저의 고민을 표현한 모델입니다. 유저가 어떤 팩터에 대해 관심을 가지고 있는지 표현합니다. 단순히 유저-팩터 관계테이블로 볼 수도 있지만 도메인 관점에서 “고민”은 엔티티로 표현해야 할 개념이라고 생각했습니다. 또한 이후 유저에게 병원, 시술 등을 추천한다고 했을 때, 유저의 고민이 기준이 될 것이라는 점도 모델 생성의 이유였습니다.
- Consultation
- 유저의 질문과 의사의 답변을 담당하는 모델입니다. 고민이 아닌 팩터와 연결된 이유는 유저의 주된 고민을 기록한 것이 Concern이지만, 상담은 주요 고민과는 다른 요소에 대해 요청할 수 있기 때문입니다.
- 답변 시간은 최신 답변순 정렬과 답변이 된 상담 필터링에 활용됩니다. 만약 요구사항에 정렬기준 등 시간에 대한 사항이 없다면 isReplied 로 구성을 해도 충분할 것입니다.
하위 호환성
하위 호환성이란 서비스를 업데이트했을 때, 이전 버전도 문제없이 동작할 수 있게 하는 것을 말합니다. 개발을 하며 문제가 되었던 것은 팩터와 서브팩터 모델이었습니다. 이런 상황이 발생했을 때 해결책은 3가지 정도가 있습니다. 1) 최대한 대응되는 것에 맞춘다. 2) 정보를 다시 입력하게 한다. 3) 새로운 버전 업데이트를 강제한다. 해결은 나열한 순서대로 하는 게 좋다고 생각합니다. 저희는 결론적으로 회의를 통해 유저에게 새로운 버전 다운을 강제하자는 결정을 내렸지만 그 전까지는 이전 버전이 동작해야 하므로 팩터, 서브팩터 테이블 및 관련 API를 유지하고 새로운 테이블과 API를 구성하여 중간 기간을 대응했습니다.
변경된 첫 번째는 팩터 리스트였습니다. 팀 차원에서 도메인에 대한 이해도가 증가하며 기존에 설정했던 것보다 더 나은 팩터들을 리스트업하였고 갯수와 이름이 변경되며 기존 유저들의 고민, 시술과 이벤트를 묶는 팩터와도 맞지 않게 되었습니다. 둘째, 상담과 연결된 기준 팩터가 서브팩터에서 메인팩터로 변경되었습니다. 두 번째는 상담과 연결된 팩터 종류입니다. 최초에는 서브팩터로 연결을 했지만, 데이터가 많지 않은 상황에서 초기 사용자에게 연관성 있는 상담을 보여주려면 좀 더 포괄적인 메인팩터와 연결하여 보여주자고 결정했습니다. 이때도 기존 유저들이 등록한 상담과 연결된 팩터를 유사한 팩터로 변경하는 작업이 필요했습니다.
변경된 것들이 작아보였지만 막상 코드를 수정하려니 이전 버전의 코드와 현버전의 코드가 혼재되어 있어서 혼란스러웠습니다. 생각해보니 유저와 병원의 어플리케이션 서비스 파일을 나눈 것처럼 이전 버전의 코드를 현 버전과 나눠서 구성하는 것도 좋았을 것 같네요. 그리고 기획 단계에서 논의를 할 때도 이런 호환성을 생각하며 변경 후에도 최대한 대응될 수 있도록 의견을 내는 것도 좋았을 것 같습니다.
명확한 의도 전달을 위한 API 분리
RESTful API 에서 쿼리파람은 필터의 기능을 합니다. 그래서 리스트를 호출하는 get 메서드에서 다양한 옵션들을 쿼리파람으로 구현하기도 합니다. 저는 유사해보이는 상담리스트를 조회하는 기능과 유사한 상담리스트를 불러오는 기능을 구분했는데요. 구분한 이유를 정리해보겠습니다.
처음에는 하나의 API 및 레포지토리에서도 findAll() 메서드로 한번에 구현을 시도했습니다. 그런데 옵셔널 파라미터들로 유저아이디, 의사아이디, 답변여부, 진단여부, 팩터아이디, 시술아이디 등이 들어가며 복잡해지고, 이에 따라 비지니스 로직도 복잡해져서 어떤 기능을 하는 메서드인지를 파악하기가 어려워졌습니다. 추후 변경이 발생했을 때 명확하지 않은 책임이 복잡성을 증가시킬 것이므로 분리를 결정했습니다.
GET /consultations, GET /consultations/similar 분리한 이유를 더 설명하자면, 첫 번째, 내 상담인지 아닌지를 기준으로 기능의 책임을 분리하고, 명확한 의도를 전달하고 싶었습니다. 두 번째, 클라이언트에서의 API 호출을 살펴보면 본인의 상담 리스트를 조회하는 것과 홈화면 및 상담 상세에서 유사한 상담을 조회하는 것이 명확하게 분리되어 있기 때문에 분리를 하는 것이 더 명료하다고 판단했습니다.
'Insight > 회고' 카테고리의 다른 글
[업무회고] 예약 모델 설계 & 배치로직 작성 디테일 (0) | 2025.02.19 |
---|---|
플랫폼 서비스에서 AWS EventBridge를 이용한 자동메시지 기능 구현하기 (0) | 2025.02.11 |
[업무회고] RIZZ 3.0 알림함 & 메시지 예약 발송 기능 설계 및 구현 (0) | 2025.01.14 |
[업무회고] RIZZ 3.0 유저의 병원별 추천 코드를 통한 맴버십 관리 (0) | 2025.01.12 |
2년차 끝자락에서의 반성과 다짐 (0) | 2024.10.01 |