테마
Story: E-12-S-06 제외키워드 관리 UI
메타
| 항목 | 값 |
|---|---|
| Story ID | E-12-S-06 |
| Epic | E-12 Keyword Analysis |
| 상태 | backlog |
| 우선순위 | P0 |
| 규모 | M (2pt) |
| 담당 | FE (수민) |
| 의존성 | E-12-S-02 (테이블 UI), E-12-S-05 (API) |
사용자 스토리
As a 제외할 키워드를 선별한 셀러, I want 제외키워드를 등록하고 쿠팡에 붙여넣기할 수 있도록 복사, So that 번거로운 수작업 없이 쿠팡 광고센터에 제외키워드를 등록할 수 있다.
수락 기준 (Acceptance Criteria)
AC-01: 전체 키워드 탭 - 제외키워드 등록
| 항목 | 내용 |
|---|---|
| Given | 전체 키워드 탭에서 키워드를 멀티셀렉트함 |
| When | "제외키워드 등록" 버튼 클릭 |
| Then | 선택된 키워드가 제외키워드로 등록 + 해당 행에 "제외" 뱃지 표시 |
AC-02: 제외 키워드 탭 - 목록 표시
| 항목 | 내용 |
|---|---|
| Given | 제외키워드가 1개 이상 등록됨 |
| When | 제외 키워드 탭 클릭 |
| Then | 제외키워드 목록 테이블 표시 (키워드, 등록일, 성과 데이터) |
AC-03: 제외 키워드 탭 - 복사하기
| 항목 | 내용 |
|---|---|
| Given | 제외 키워드 탭에서 키워드를 멀티셀렉트함 |
| When | "복사하기" 버튼 클릭 |
| Then | 선택된 키워드가 쉼표(,)로 구분되어 클립보드에 복사 + 토스트 메시지 |
AC-04: 제외 키워드 탭 - 제외 해제
| 항목 | 내용 |
|---|---|
| Given | 제외 키워드 탭에서 키워드를 멀티셀렉트함 |
| When | "제외 해제" 버튼 클릭 |
| Then | 선택된 키워드가 제외키워드에서 해제 + 목록에서 제거 |
AC-05: 버튼 활성화 조건
| 항목 | 내용 |
|---|---|
| Given | 키워드 테이블 |
| When | 아무 키워드도 선택하지 않음 |
| Then | "제외키워드 등록", "복사하기", "제외 해제" 버튼 비활성화 |
AC-06: 제외키워드 없음 상태
| 항목 | 내용 |
|---|---|
| Given | 제외키워드가 0개 |
| When | 제외 키워드 탭 클릭 |
| Then | "등록된 제외키워드가 없습니다" + 전체 키워드 탭에서 등록하라는 안내 |
AC-07: 복사 완료 피드백
| 항목 | 내용 |
|---|---|
| Given | 복사하기 버튼 클릭 |
| When | 클립보드 복사 성공 |
| Then | "3개 키워드가 복사되었습니다. 쿠팡 광고센터에서 붙여넣기 하세요." 토스트 |
태스크 분해
Task 1: 전체 키워드 탭 - 제외키워드 등록 AC-01, AC-05
- [ ] 1.1: 액션 영역에 "제외키워드 등록" 버튼 추가
- [ ] 1.2: 멀티셀렉트 상태 관리 (selectedKeywords)
- [ ] 1.3: 선택 개수에 따른 버튼 활성화/비활성화
- [ ] 1.4: 등록 API 호출 + 성공 시 테이블 리프레시
Task 2: 제외 키워드 탭 UI AC-02, AC-06
- [ ] 2.1: ExcludedKeywordsTab 컴포넌트 생성
- [ ] 2.2: 제외키워드 목록 API 연동 (useExcludedKeywords 훅)
- [ ] 2.3: 테이블 UI (키워드, 등록일, 성과 컬럼)
- [ ] 2.4: Empty State (제외키워드 없음)
Task 3: 복사하기 기능 AC-03, AC-07
- [ ] 3.1: "복사하기" 버튼 추가
- [ ] 3.2: navigator.clipboard.writeText() 구현
- [ ] 3.3: 키워드 쉼표(,) 구분자로 join
- [ ] 3.4: 복사 완료 토스트 메시지
Task 4: 제외 해제 기능 AC-04, AC-05
- [ ] 4.1: "제외 해제" 버튼 추가
- [ ] 4.2: 해제 API 호출 + 성공 시 목록에서 제거
- [ ] 4.3: 확인 다이얼로그 (선택적)
Dev Notes
영향 받는 소스 트리
frontend/src/pages/AdsCampaign/Keywords/
├── index.tsx # 로컬 탭 컨테이너
├── AllKeywordsTab.tsx # 전체 키워드 탭 (S-02에서 생성)
├── ExcludedKeywordsTab.tsx # 🆕 제외 키워드 탭
├── hooks/
│ ├── useKeywordList.ts # 기존
│ └── useExcludedKeywords.ts # 🆕 제외키워드 훅
└── components/
└── KeywordActionBar.tsx # 🆕 액션 버튼 영역복사 포맷
javascript
// 예시: 3개 키워드 선택 시
const selectedKeywords = ["봄신상", "여름특가", "할인세일"];
const clipboardText = selectedKeywords.join(",");
// 결과: "봄신상,여름특가,할인세일"
await navigator.clipboard.writeText(clipboardText);참고 구현
| 항목 | 경로 | 설명 |
|---|---|---|
| 멀티셀렉트 | AG-Grid rowSelection: 'multiple' | 기존 패턴 |
| 토스트 | src/components/common/Toast | 기존 토스트 컴포넌트 |
| 클립보드 | navigator.clipboard API | 브라우저 표준 |
충돌 감지
| 항목 | 상태 | 설명 |
|---|---|---|
| 기존 코드 충돌 | ✅ 없음 | S-02 기반 확장 |
| 브라우저 호환성 | ⚠️ 주의 | clipboard API는 HTTPS 필요 |
References
| 출처 | 경로/링크 | 참조 섹션 |
|---|---|---|
| Epic Spec | epic-specs/E-12-keyword-analysis.md | 로직 5: 제외키워드 관리, 페이지 구조 |
| S-02 | stories/E-12-S-02.md | 테이블 UI 기반 |
| S-05 | stories/E-12-S-05.md | API 스펙 |
핸드오프 전 체크리스트
- [x] 사용자 스토리가 명확한가?
- [x] 수락 기준이 Given-When-Then 형식인가?
- [x] 의존성 명시되었는가? (S-02, S-05)
- [x] UI 플로우가 정의되었는가?
검증 결과: ✅ PASS 검증일: 2026-01-28
생성일: 2026-01-28생성자: 📋 Penny
