refactor(common): common 경계 룰 정리 + IP/UA 추출 단일화 (P1-4)#119
Conversation
P1-4 본 작업과 함께, IP/UA 추출 로직이 두 곳으로 분기되어 운영에서 audit log / refresh session 의 IP 가 proxy IP 로 기록되던 문제도 함께 정리. common 경계 룰 정리: - crypto.helper.ts → utils/crypto.ts (순수 함수, NestJS DI 없음) - url-query.helper.ts → utils/url-query.ts (순수 함수) - error.helper.ts → utils/error.ts (HttpException 클래스만 사용, DI 매개변수 없음) - helpers/ 는 ConfigService 등 NestJS 서비스를 매개변수로 받는 경우만 잔존 (현재 config.helper.ts 만 해당) IP/UA 추출 단일화: - 기존 2 구현 분기 (utils/http-meta 의 정밀 + auth helper 의 naive) → utils/http-meta 단일 - utils/http-meta.ts 에 tryClientIp / tryUserAgent 추가 (DB persistence 용, undefined fallback) - 기존 clientIpOf / userAgentOf 는 try* 위에 'Unknown *' fallback 적용 (로깅용) - token.service / seller-credential.service: auth-request-meta 의 naive getIp/getUserAgent → utils/http-meta 의 tryClientIp/tryUserAgent 로 교체. audit log / refresh session 의 IP 가 X-Forwarded-For 기반으로 정확하게 기록되도록 정상화. - src/features/auth/helpers/auth-request-meta.helper.ts 삭제 (callsite 0) trust proxy 설정: - main.ts 에 env-based 적용 (TRUST_PROXY_HOPS). - 미설정 / 0: 비활성 (현 동작 그대로). - 운영에서 실제 reverse proxy hop 수 (ELB=1, ELB+CloudFront=2 등) 와 맞춰 설정해야 X-Forwarded-For 가 정상 신뢰됨. 잘못 설정 시 IP spoofing 위험이므로 인프라 검증 필요. 기타: - TokenService 의 sha256Hex / generateRefreshToken 인라인 구현 → utils/crypto 호출로 교체. 외부 API (TokenService.sha256Hex public method) 는 유지, 내부만 delegation. 부수 효과: - 신규 코드는 utils/ 에서 import (helpers/ → utils/ 경로 변경) - audit log / refresh session 의 ip_address 가 proxy 환경에서 실제 client IP 로 기록 (TRUST_PROXY_HOPS 활성화 시)
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Coverage report
Test suite run success1199 tests passing in 143 suites. Report generated by 🧪jest coverage report action from d474525 |
Summary
P1-4 (common/ 경계 룰 정리) 와 함께, 작업 중 발견한 IP/UA 추출 로직 2 구현 분기 + auth 흐름이 naive 쪽 사용 문제도 함께 정리.
common/utils/: 순수 함수, 외부 DI 0 — 룰 명문화common/helpers/: NestJS 서비스/Config 를 매개변수로 받는 헬퍼만 잔존 (현재config.helper.ts만 해당)ip_address가 X-Forwarded-For 기반 정확 IP 로 정상화 (운영에서TRUST_PROXY_HOPS설정 시)Scope
1. common 경계 룰 — 파일 재배치 (helpers/ → utils/)
common/helpers/crypto.helper.tscommon/utils/crypto.tsnode:crypto만 사용. NestJS DI 매개변수 0. 순수 함수common/helpers/url-query.helper.tscommon/utils/url-query.tsqs타입만 사용. 순수 함수common/helpers/error.helper.tscommon/utils/error.tsHttpException클래스만 사용 (값 클래스, DI 아님). 순수 함수common/helpers/config.helper.tsConfigService를 매개변수로 받음 → helpers/ 룰 일치spec 도 동일하게 이동 (
git mv사용 — diff 가독성 보존). 모든 import site 갱신.2. crypto 중복 제거 — TokenService → utils/crypto 사용
TokenService.sha256Hex내부 구현createHash('sha256').update(raw).digest('hex')→sha256HexUtil(raw)호출로 교체TokenService.generateRefreshToken내부 구현randomBytes(32).toString('hex')→generateRandomToken(32)호출로 교체TokenService.sha256Hex, interface) 는 유지 — 외부 caller 영향 03. IP/UA 추출 단일화
Before — 2 구현 분기
common/utils/http-meta.ts의clientIpOf/userAgentOf: 정밀 (X-Forwarded-For → X-Real-IP → req.ip → socket 순), 로깅에만 사용features/auth/helpers/auth-request-meta.helper.ts의getIp/getUserAgent: naive (req.ip만), refresh session / audit log persistence 에 사용After —
utils/http-meta.ts단일tryClientIp(req): string | undefined추가 — DB persistence 용 (undefined fallback)tryUserAgent(req): string | undefined추가 — DB persistence 용 (raw UA, 512 자 슬라이스)clientIpOf/userAgentOf는 try* 위에'Unknown *'fallback 적용 (로깅용, DRY)token.service.ts/seller-credential.service.ts: naivegetIp/getUserAgent→ 정밀tryClientIp/tryUserAgent로 교체features/auth/helpers/auth-request-meta.helper.ts삭제 (callsite 0)결과: refresh session
ip_address/user_agent, audit logip_address/user_agent가 reverse proxy 환경에서 정확한 client IP 로 기록 (단,TRUST_PROXY_HOPS설정 필요 — 아래 4번)4. trust proxy 환경 변수 추가
main.ts에 env-based 추가:TRUST_PROXY_HOPSgetHttpAdapter().getInstance().set('trust proxy', hops)으로 적용Impact
TRUST_PROXY_HOPS설정 시점부터refresh_session.ip_address,audit_log.ip_address가 정확한 client IP 로 기록. 그 전 기록된 row 는 그대로 (회고용 가치만 변동).tryClientIp/tryUserAgent)TRUST_PROXY_HOPSENV 추가 후 재배포Test plan
common/utils/crypto.spec/url-query.spec/error.spec— 이동 후 통과common/utils/http-meta.spec— 신규tryClientIp/tryUserAgent8 케이스 추가, 모두 통과features/auth/services/token.service.spec—utils/crypto+utils/http-meta교체 후 통과features/auth/services/seller-credential.service.spec—utils/http-meta교체 후 통과global/filters/global-exception.filter.spec/graphql-exception.filter.spec—utils/errorimport 갱신 후 통과TRUST_PROXY_HOPS환경변수 설정 (별도 운영 작업)