테마
Story: WorkNote 테이블 설계 및 API
메타
| 항목 | 값 |
|---|---|
| Story ID | E-10-S-01 |
| Epic | E-10 업무노트 |
| 상태 | draft |
| 우선순위 | P0 |
| 규모 | M |
| 담당 개발자 | 하록 (BE) |
사용자 스토리
As a 장사왕 서비스,
I want 업무노트 데이터를 저장하고 조회할 수 있는 API,
So that 셀러의 광고 운영 기록을 관리할 수 있다.
수락 기준 (Acceptance Criteria)
AC-01: WorkNote 테이블 생성
| 항목 | 내용 |
|---|---|
| Given | 데이터베이스 마이그레이션 실행 시 |
| When | WorkNote 테이블이 없을 때 |
| Then | WorkNote 테이블이 생성된다 |
sql
WorkNote 테이블 스키마:
- id: UUID (PK)
- userId: String (FK → User)
- createdAt: DateTime
- updatedAt: DateTime
- targetType: Enum ('campaign', 'keyword', 'general')
- targetId: String (nullable)
- targetName: String
- noteType: Enum ('manual', 'advice_applied')
- content: Text
- adviceId: String (nullable)
- adviceType: String (nullable)
- beforeValue: String (nullable)
- afterValue: String (nullable)
- effectTrackingEnabled: Boolean (default: false)
- trackingStartDate: Date (nullable)
- trackingEndDate: Date (nullable)
- beforeMetrics: JSON (nullable)
- afterMetrics: JSON (nullable)
- effectSummary: String (nullable)
- deletedAt: DateTime (nullable, soft delete)AC-02: 노트 생성 API
| 항목 | 내용 |
|---|---|
| Given | 인증된 사용자가 |
| When | POST /api/work-notes 요청 시 |
| Then | 새 노트가 생성되고 노트 ID가 반환된다 |
json
Request:
{
"targetType": "campaign",
"targetId": "campaign-123",
"targetName": "봄 신상품",
"noteType": "advice_applied",
"content": "비검색 입찰가 낮춤",
"adviceId": "advice-456",
"adviceType": "bidding_down",
"beforeValue": "200원",
"afterValue": "120원",
"effectTrackingEnabled": true
}
Response:
{
"id": "note-789",
"createdAt": "2026-01-21T10:30:00Z",
"effectTrackingEnabled": true,
"trackingEndDate": "2026-01-28"
}AC-03: 노트 목록 조회 API
| 항목 | 내용 |
|---|---|
| Given | 인증된 사용자가 |
| When | GET /api/work-notes 요청 시 |
| Then | 사용자의 노트 목록이 최신순으로 반환된다 |
Query Parameters:
- targetType: 'campaign' | 'keyword' | 'general' (optional)
- targetId: string (optional, 특정 캠페인/키워드 필터)
- effectTrackingStatus: 'tracking' | 'completed' (optional)
- limit: number (default: 20)
- offset: number (default: 0)AC-04: 노트 수정 API
| 항목 | 내용 |
|---|---|
| Given | 노트 소유자가 |
| When | PATCH /api/work-notes/:id 요청 시 |
| Then | 노트 내용이 수정된다 |
AC-05: 노트 삭제 API (Soft Delete)
| 항목 | 내용 |
|---|---|
| Given | 노트 소유자가 |
| When | DELETE /api/work-notes/:id 요청 시 |
| Then | deletedAt이 설정되고 목록에서 제외된다 |
태스크 분해
Task 1: 테이블 설계 AC-01
- [ ] 1.1: WorkNote 테이블 스키마 정의 (Prisma/TypeORM)
- [ ] 1.2: 마이그레이션 파일 생성
- [ ] 1.3: 인덱스 추가 (userId, targetId, createdAt)
Task 2: 노트 생성 API AC-02
- [ ] 2.1: POST /api/work-notes 엔드포인트 생성
- [ ] 2.2: 요청 validation
- [ ] 2.3: 효과 추적 활성화 시 trackingEndDate 자동 계산 (+7일)
- [ ] 2.4: beforeMetrics 스냅샷 저장 (E-10-S-05와 연동)
Task 3: 노트 조회 API AC-03
- [ ] 3.1: GET /api/work-notes 엔드포인트 생성
- [ ] 3.2: 필터링 로직 (targetType, targetId, effectTrackingStatus)
- [ ] 3.3: 페이지네이션 적용
- [ ] 3.4: 날짜별 그룹핑 옵션
Task 4: 노트 수정/삭제 API AC-04, AC-05
- [ ] 4.1: PATCH /api/work-notes/:id 엔드포인트
- [ ] 4.2: DELETE /api/work-notes/:id 엔드포인트 (soft delete)
- [ ] 4.3: 소유자 권한 검증
Task 5: 테스트
- [ ] 5.1: 단위 테스트 작성
- [ ] 5.2: API 통합 테스트 작성
Dev Notes
아키텍처 패턴
| 항목 | 내용 |
|---|---|
| 사용할 패턴 | Repository Pattern |
| 참고 구현 | 기존 User 관련 CRUD API 참고 |
| 피해야 할 것 | N+1 쿼리, 무거운 테이블 JOIN |
영향 받는 소스 트리
src/
├── models/
│ └── WorkNote.ts # 🆕 신규 생성
├── repositories/
│ └── WorkNoteRepository.ts # 🆕 신규 생성
├── services/
│ └── WorkNoteService.ts # 🆕 신규 생성
├── controllers/
│ └── WorkNoteController.ts # 🆕 신규 생성
└── routes/
└── workNotes.ts # 🆕 신규 생성충돌 감지
| 항목 | 상태 | 설명 |
|---|---|---|
| 기존 코드 충돌 | ✅ 없음 | 신규 테이블/API |
| API 계약 변경 | ✅ 없음 | 신규 API |
| DB 스키마 변경 | ⚠️ 주의 | WorkNote 테이블 신규 생성 필요 |
| 환경 변수 변경 | ✅ 없음 | - |
이벤트 로깅
| 이벤트명 | 트리거 | 파라미터 | GA4 여부 |
|---|---|---|---|
create_work_note | 노트 생성 | {noteType, targetType} | ✅ |
생성일: 2026-01-21
