개발

헥사고날 아키텍처 리팩토링 (1)

정재익 2025. 8. 12. 23:13

배경

소셜 로그인 흐름을 정리하는 과정에서 도메인 경계와 책임 배치가 뒤섞여 있었다. 인증 서비스가 사용자 도메인의 내부 포트를 직접 참조하고, DTO에서 쿠키를 만들거나, FCM 토큰 이벤트가 중간 계층에서 발행되는 등 응집도가 낮았다. 목표는 기능 안정성을 유지하면서 아키텍처 원칙을 지키고, 책임을 올바른 계층으로 되돌리는 것이었다.

상황

  • 인증 서비스가 사용자 도메인의 인바드 포트를 직접 호출해 계층 의존 방향이 어긋남.
  • 쿠키 생성이 DTO 내부에서도 이뤄져 책임이 분됨.
  • 블랙리스트 확인 위치와 시점이 일관되지 않음.
  • 로그인의 결과를 담은 DTO에서 “기존/신” 분기 정보가 빠지며 흐름 제어가 모호해짐.
  • 임시 데이터 저장 포트의 메서드 시그니처가 구현/호출부와 어긋나 빌드 오류 발생.
  • 인증 데이터 저장 포트의 회원가입 메서드에 FCM 토큰 인자가 추가된 뒤, 호출부 갱신이 누락돼 파일 에러 다발.

고민

  • 인증 도메인이 사용자 도메인의 인바운드 포트 기대는 것이 타당한가?
  • 키/임시 데이터/토큰/FCM 이벤트처럼 부효과는 어느 계층이 책임져야 응집도가 아지는가?
  • 소셜 로그인 어댑터가 어디까지 처리해야 인증 서비스 흐름 제어에만 집중할 수 있는가?
  • 시 UUID는 누가 생성해야 자연스러운가? (서비스 vs 임시 저장소)
  • FCM 토큰 이벤트는 어느 계층에서 발행해야 사용자 ID를 안전하게 참조할 수 있는?

해결

  • 의존성 바로잡기: 인증 서비스는 사용자 도메인의 내부 포트를 직접 호출하지 않도록 하고, 소 로그인 어댑터 “기존 사용자 조회/프로필 업데이트/토큰 갱신”을 수행하도록 이동. 서비스는 “로그인의 결과를 담은 DTO”의 로그인 유형으로만 분.
  • DTO 로직 비: 쿠키 생성 같은 부수효과를 DTO에서 제거. 쿠는 쿠키 관리 포트에서만 생성.
  • 시 데이터 일관화: 임시 데이터 저장 포트 “uuid, 소셜 사용자 정보, 토큰 정보”만 받아 저장. UUID 생성 책임은 인증 서비스가 가진다. 임시 사용자 데이터 DTO는 FCM 토큰까지 함께 보관.
  • FCM 이벤트 책임 이동: 기존 사용자 로그인/신규 사용자 저장 시점에 인증 데이터 어댑터가 사용자 ID를 보유하고 있으므로 여기서 FCM 토큰 등록 이벤트를 발행. 상위 서비스의 이벤트 발행 로직은 제거.
  • 분기 복원: “로그인의 결과를 담은 DTO”에 로그인 유형(기존/신규)을 복원해 흐름을 명확히.

심 변경 요

  • 소셜 로그인 어댑터: 소셜 전략 호출 → 사용자 존재 여부 판단 → 기존 사용자 프로필/토큰 갱  “로그인의 결과를 담은 DTO(로그인 유형 포함)” 반환.
  • 기존 사용자: 인증 데이터 저장 포트로 “기존 사용자 로그인 처리(쿠키 발행 + FCM 이벤트 위임)”.
  • 신규 사용자: UUID 생성 → 임시 데이터 저장 포트에 저장 → 쿠키 관리 포트 임시 쿠키 생성.
  • 임시 데이터 저장 포트/어댑터: 시그니처 통일(외부 생성 UUID 수신). 임시 사용자 데이터 DTO에 FCM 토큰 보관.
  • 인증 데이터 저장 포트/어댑터: 기존/신규 처리 모두 FCM 토큰을 전달받, 사용자 ID로 FCM 등록 이벤트 발행.
  • 불필요 주석/임시 이벤트 발행/사용되지 않는 import 전부 정리.

키텍처 관점 정리

  • 메인 경계: 인증 서비스는 흐름 제어 의사결정만 담당. 사용자 데이터 조작은 소셜 로그인 어댑터와 인증 데이터 어댑터가 책임.
  • 부수효과의 위치: 쿠키는 쿠키 관리 포트, FCM 이벤트는 사용자 ID가 확실한 인증 데이터 어댑터에서 발행. 테스트 용이성과 응집도가 향상.
  • 데이터 흐름: 임시 데이터(소셜 프로필, 토큰, FCM 토큰)는 임시 저장소에 보관되고, 최종 회원가입 시 인증 데이터 어댑터가 통합 처리(쿠키 발행 + FCM 이벤트).

회고

이번 리팩터링의 본질은 “책임 재배치”였다. 클래스/모듈 이름에 매달리기보다 역할(서비스/어댑터/포트/DTO)에 맞는 책임만 남기자, 의존성도 자연스럽게 안정됐다. 린트·시그니처 오류는 설계 의도를 코드에 일치시켜가는 과정에서 생기는 부산물이었다. 그때그때 빠르게 정리하며 전진한 것이 유효했다. 지금 구조는 단순하고 예측 가능하며, 변경 비용도 줄었다.덧붙이면, 과거에 남겨둔 “서비스에서 FCM 이벤트 발행” 주은 전부 제거해도 된다. 이제 하위 어댑가 사용자 ID 가진 에서 책임을 온전히 수행하고 있고, 상 계층 오케스트레이션에만 집중한다.