개발 기록/회고
Node.js 인증 서비스의 구조적 문제와 개선을 위한 리팩토링 여정
JeongPark
2025. 5. 8. 17:08
728x90
기존 구조의 문제점
지금까지의 auth-service는 기능적으로는 정상 동작했지만, 아키텍처적 관점에서 다음과 같은 구조적 문제를 안고 있었습니다.
1. 절차적(Procedural) 서비스 구조
- registerUser, loginUser 등의 함수가 한 파일에 모여 있고,
- 각 함수는 다음과 같은 다양한 책임을 동시에 수행했습니다:
- DB 접근 (User, Session, Token)
- 비즈니스 로직 (비밀번호 비교, 토큰 발급 등)
- 인프라 처리 (Redis, 이메일 등)
이는 단일 책임 원칙(SRP)을 위반하며, 수정 및 테스트가 어렵고 재사용성이 떨어집니다.
2. 책임 분리 미흡
- 비즈니스 로직과 유틸 로직(bcrypt, jwt, redis, email)이 뒤섞여 있었습니다.
- 결과적으로 도메인 규칙과 인프라 구현이 혼재되어 높은 결합도를 유발했습니다.
3. Use Case 기반 구조 부재
- 예: registerUser나 loginUser 같은 함수들은 사용자의 행위 흐름을 그대로 나열하는 방식이었습니다.
- 이러한 구조는:
- 비즈니스 규칙 테스트가 어려워지고
- 새로운 흐름 추가(예: 소셜 로그인, 관리자 계정 처리 등)에 큰 제약을 줍니다.
4. 서비스 간 경계 불분명
- TokenService, ResetCodeService는 추상화되어 있지만,
- 이들을 전역 객체처럼 임의로 가져다 사용하며 명확한 경계 없이 엮여 있었습니다.
5. 테스트/유지보수의 어려움
- 단위 테스트를 위해선 Redis, DB, 이메일 등 모든 외부 의존성을 함께 띄워야 했고,
- 로직 수정 시 여파 범위를 예측하기 어려웠습니다.
리팩토링 방향 및 적용 내용
책임 분리
- TokenService, ResetCodeService, SessionService 등 역할 기반 클래스 정의
- JWT 발급, Redis 저장, 이메일 발송 등을 유틸 함수로 추출
반복 코드 공통화
- getRepo()를 통해 Repository 접근을 통일
- saveRefreshTokenEntity()를 통해 RefreshToken 저장 로직 공통화
컨트롤러 ↔ 서비스 계층 분리
- Express 컨트롤러에서는 요청/응답만 담당
- 모든 비즈니스 로직은 서비스 계층에서 수행
향후 개선 방향: Use Case 지향 구조
현재는 Procedural 구조 기반으로 역할 분리를 시도한 수준이지만,
다음과 같은 방향으로 확장 가능성을 고려하고 있습니다.
Use Case 지향 구조란?
- 서비스 함수가 아닌 도메인 행동 단위로 파일 및 클래스 구성
- 예: RegisterUserUseCase, LoginUserUseCase
- 각각은 1개의 책임만을 가지며, Command 기반 핸들러 구조도 가능
장점
- 확장성과 유지보수 용이성 증가
- 테스트 용이 (각 UseCase는 독립적이고 외부 주입 기반)
- 도메인 중심 설계 (DDD 등으로도 확장 가능)
정리하며
이번 리팩토링은 기능 개선보다도 구조적 건강성을 목표로 진행한 작업이었습니다.
현재는 Procedural 구조와 객체 기반 구조가 혼합된 과도기 형태이며,
앞으로 점진적으로 Use Case 지향 구조로 발전시켜갈 계획입니다.
관련 GitHub 커밋
해당 리팩토링의 실제 코드는 다음 커밋에서 확인하실 수 있습니다:
이 커밋에는 다음과 같은 변경 사항이 포함되어 있습니다
- TokenService, ResetCodeService 도입
- Redis/DB RefreshToken 저장 로직 통합
- getRepo() 도입으로 TypeORM repository 접근 공통화
- 비밀번호 해시 로직 유틸 분리
반응형