Skip to content

feat(seller): GraphQL Input 전수 class-validator DTO 도입#99

Open
chanwoo7 wants to merge 3 commits into
developfrom
refactor/seller-graphql-input-dto
Open

feat(seller): GraphQL Input 전수 class-validator DTO 도입#99
chanwoo7 wants to merge 3 commits into
developfrom
refactor/seller-graphql-input-dto

Conversation

@chanwoo7
Copy link
Copy Markdown
Member

Summary

  • Seller 도메인의 모든 GraphQL Input 30종을 class + class-validator DTO 로 전환
    • 페이지네이션 베이스 2종 (Cursor / DateCursor)
    • 리스트/필터 4종 (Product / Order / AuditLog / Cursor 파생)
    • 콘텐츠 4종 (FAQ · Banner CRUD)
    • 대화 + 주문 상태 변경 2종
    • 매장 5종 (basic info / 영업시간 / 임시휴무 / 픽업정책 / 일일 캐파)
    • 상품 7종 (CRUD · Active · 이미지 · 카테고리/태그)
    • 옵션 6종 (그룹 + 아이템 CRUD/순서)
    • 커스텀 템플릿 4종
  • 9개 Seller Resolver 가 신규 DTO class 를 @Args 타입으로 사용 (ValidationPipe 검증)
  • 7개 Seller Service 의 import 경로 변경 (type import 유지). 도메인 invariant 검증 (minSelect ≤ maxSelect, banner linkType 조합, SALE_PRICE_EXCEEDS_REGULAR 등) 은 service 에 잔존
  • types/seller-input.type.ts (268 줄) 삭제
  • 일부 optional 필드 (link*Id, openTime, note, reason 등) 는 FE 의 명시적 null 송신 호환을 위해 ?: T | null

ts-jest decorator metadata 분기 해결 (별도 커밋)

  • 증상: 신규 DTO 추가로 global branches 86% → 84.53% 임계 미달
  • 원인: tsconfig isolatedModules: true 하에서 ts-jest 가 type-vs-value 식별 정보 없이 보수적 런타임 가드(typeof T !== "undefined" && T ...)를 emit → istanbul 이 unreachable 분기로 계측
  • 해결: tsconfig 는 그대로 (build 정합), ts-jest transform 에서만 isolatedModules: false override + TS151002 무시. 결과: branches 92.85%, seller/dto/inputs 100%

배경 / Plan 연결

FE 영향

정상 입력 시 응답 동일. 잘못된 형식은 ValidationPipe 가 일관 처리 (extensions.code = BAD_USER_INPUT).
룰별 메시지 본문은 기존 한국어 문구 유지 (해당하는 곳 message 옵션 명시).

Test plan

  • 로컬 yarn lint
  • 로컬 yarn test:cov 1166/1166 (이전 996 + 신규 170)
  • 로컬 yarn dto:check errors 0
  • npx tsc --noEmit
  • 전체 branches 92.85% / lines 97.38% / statements 97.08% / functions 93.49% (모든 임계 통과)
  • Husky pre-push (yarn validate) 실 통과 확인
  • CI: lint / type-check / test:cov / codecov/patch 통과

chanwoo7 added 3 commits May 24, 2026 04:30
A-2 검증 전략 P0-3 단계 4 (Seller Input 전수).

- SellerCursorInput · SellerDateCursorInput 베이스 도입 (limit/cursor +
  날짜 범위). SDL 기본값 limit=20, 상한 100.
- 리스트/필터 DTO 4종: ProductList / OrderList / AuditLogList
- 콘텐츠 DTO 4종: FAQ / Banner Create+Update
- 대화 + 주문 상태 변경 DTO 2종
- 매장 DTO 5종: 기본정보 / 영업시간(dayOfWeek 0-6) / 임시휴무 /
  픽업정책(양수 정수) / 일일 캐파시티
- 상품 DTO 7종: CRUD + Active 토글 + 이미지 추가/순서 + 카테고리/태그
- 옵션 DTO 6종: 그룹 CRUD + 아이템 CRUD + 순서 변경
- 커스텀 템플릿 DTO 4종: 템플릿 upsert/active + 텍스트 토큰 upsert/순서

도메인 invariant (minSelect <= maxSelect, banner linkType 별 link* 조합,
SALE_PRICE_EXCEEDS_REGULAR 등) 는 service 에서 검증 (cross-field 규칙).
일부 link*Id / openTime / note / reason 등 optional 필드는 FE 의
명시적 null 송신 호환을 위해 `?: T | null` 로 정의.

class-validator 데코레이터로 형식·범위·enum 검증을 전수 적용.
각 DTO 에 대응 spec (필수/선택 분기, 형식 오류, 경계값 등 의미 있는
케이스만; coverage 채우기 식 저품질 테스트 금지).
- Seller resolver 9종: @Args 인자 타입을 신규 DTO class 로 교체
  (ValidationPipe 가 검증). 구 interface 다중 import 라인을 개별 import 로 분해.
- Seller service 7종: import 경로를 dto/inputs/* 로 변경 (type import 유지).
- types/seller-input.type.ts (268 줄) 삭제 — 모든 정의가 DTO class 로 이전됨.
- 일부 spec 파일의 `as never` / `as unknown as X` 캐스트가 isolatedModules:false
  하에서 불필요해져 lint-staged 가 자동 정리.
- spec 1건의 startsAt/endsAt 입력을 string 에서 Date 로 정정
  (DTO 가 Date 만 허용; GraphQL DateTime scalar 가 변환 후 도달).

FE 영향: 정상 입력은 응답 동일. 잘못된 형식은 ValidationPipe 가
일관된 BAD_REQUEST 로 응답.
원인: tsconfig 의 isolatedModules: true 하에서 ts-jest 는 파일별 독립
컴파일을 수행하며 type-vs-value 식별 정보를 갖지 못한다. 그 결과 모든
non-primitive type annotation 에 보수적 런타임 가드를 emit:

  __metadata("design:type", typeof (_a = typeof T !== "undefined" && T)
    === "function" ? _a : Object)

이 식은 T 가 type alias 일 때 항상 한쪽 분기만 발화 → istanbul 이
"unreachable 분기" 로 측정 (~5%p global 하락 원인).

해결: tsconfig 는 isolatedModules: true 유지 (build/nest cli 권장),
jest transform 에서만 isolatedModules: false 로 override → ts-jest 가
full type info 로 컴파일, `__metadata("design:type", String)` 같은
단순 emit. nodenext hybrid module 경고(TS151002) 는 diagnostics 로 무시.

효과:
- 전체 branches 84.53% → 92.85% (임계 86% 회복)
- seller/dto/inputs 64.28% → 100%
- 정확한 root-cause 해소이므로 istanbul-ignore 같은 회피 불요
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fcc8e14d-897a-407e-a032-379abb6342c1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/seller-graphql-input-dto

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 97.08% 3293/3392
🟢 Branches 92.85% 1130/1217
🟢 Functions 93.49% 632/676
🟢 Lines 97.39% 3022/3103

Test suite run success

1166 tests passing in 130 suites.

Report generated by 🧪jest coverage report action from a93efac

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant