테마
Story: 사업장 검색 API
메타
| 항목 | 값 |
|---|---|
| Story ID | E-02-S-08 |
| Epic | E-02 어드민 강화 |
| 상태 | draft |
| 우선순위 | P1 |
| 규모 | S |
| 담당 개발자 | BE (하록님) |
사용자 스토리
As a CS팀/운영팀 관리자, I want 사업장을 빠르게 검색하고 조회, So that 크레딧/쿠폰/추천인 관리 시 대상 사업장을 쉽게 찾을 수 있다.
수락 기준 (Acceptance Criteria)
AC-01: 사업장 검색
| 항목 | 내용 |
|---|---|
| Given | 검색어 (사업장명, 대표자명, 이메일, 전화번호) |
| When | 검색 요청 |
| Then | 일치하는 사업장 목록 반환 |
요청 파라미터:
GET /admin/biz/search
?q={검색어} // 필수, 2자 이상
&page={페이지번호} // 선택, 기본 1
&size={페이지크기} // 선택, 기본 20, 최대 100응답 필드:
{
items: [{
bizId: number,
bizName: string, // 사업장명
ownerName: string, // 대표자명
email: string, // 이메일 (마스킹: a***@example.com)
phone: string, // 전화번호 (마스킹: 010-****-1234)
planType: string, // 현재 요금제
createdAt: string, // 가입일
storeCount: number // 연동 스토어 수
}],
pagination: { page, size, total, totalPages }
}검색 대상 필드:
- 사업장명 (LIKE 검색)
- 대표자명 (완전 일치)
- 이메일 (완전 일치)
- 전화번호 (완전 일치, 하이픈 제거 후 비교)
AC-02: 사업장 상세 조회
| 항목 | 내용 |
|---|---|
| Given | 특정 bizId |
| When | 상세 조회 요청 |
| Then | 사업장 전체 정보 반환 |
응답 필드:
{
bizId: number,
bizName: string,
ownerName: string,
email: string, // 전체 표시 (어드민용)
phone: string, // 전체 표시 (어드민용)
planType: string,
planStartDate: string,
planEndDate: string,
createdAt: string,
stores: [{ // 연동 스토어 목록
storeId, storeName, platform, linkedAt
}],
creditBalance: number, // 크레딧 잔액
referralCode: string // 추천 코드 (있는 경우)
}AC-03: 검색어 최소 길이
| 항목 | 내용 |
|---|---|
| Given | 검색어 1자 |
| When | 검색 요청 |
| Then | 400 Bad Request + "검색어는 2자 이상 입력해주세요" |
AC-04: 존재하지 않는 사업장
| 항목 | 내용 |
|---|---|
| Given | 존재하지 않는 bizId |
| When | 상세 조회 요청 |
| Then | 404 Not Found |
태스크 분해
Task 1: 사업장 검색 API AC-01, AC-03
- [ ] 1.1:
GET /admin/biz/search엔드포인트 생성 - [ ] 1.2: 검색어 길이 검증 (2자 이상)
- [ ] 1.3: 다중 필드 검색 쿼리 (OR 조건)
- [ ] 1.4: 페이지네이션 처리
- [ ] 1.5: 민감 정보 마스킹 (이메일, 전화번호)
Task 2: 사업장 상세 조회 API AC-02, AC-04
- [ ] 2.1:
GET /admin/biz/:bizId엔드포인트 생성 - [ ] 2.2: Biz + Store + CreditBalance 조인
- [ ] 2.3: ReferralCode 조인 (있는 경우)
- [ ] 2.4: 404 처리
Task 3: 테스트 작성
- [ ] 3.1: 검색 테스트 (각 필드별)
- [ ] 3.2: 페이지네이션 테스트
- [ ] 3.3: 마스킹 테스트
- [ ] 3.4: 404 테스트
Task 4: 마무리
- [ ] 4.1: API 문서화
- [ ] 4.2: PR 생성
Dev Notes (AI Agent 최적화)
영향 받는 소스 트리
src/
├── admin/
│ └── biz/
│ ├── biz.admin.controller.ts # 🆕 신규 생성
│ ├── biz.admin.service.ts # 🆕 신규 생성
│ └── dto/
│ └── biz-search.dto.ts # 🆕 신규 생성
└── tests/
└── admin/
└── biz.admin.spec.ts # 🆕 신규 생성검색 쿼리 예시
typescript
// 다중 필드 OR 검색
const where = {
OR: [
{ bizName: { contains: q } },
{ ownerName: q },
{ email: q },
{ phone: q.replace(/-/g, '') }
]
};마스킹 유틸
typescript
function maskEmail(email: string): string {
const [local, domain] = email.split('@');
return `${local[0]}***@${domain}`;
}
function maskPhone(phone: string): string {
// 010-1234-5678 → 010-****-5678
return phone.replace(/(\d{3})-(\d{4})-(\d{4})/, '$1-****-$3');
}충돌 감지
| 항목 | 상태 | 설명 |
|---|---|---|
| 기존 코드 충돌 | ✅ 없음 | 신규 어드민 API |
| DB 스키마 변경 | ✅ 없음 | 기존 테이블 사용 |
의존성
이 Story를 의존하는 Story:
- E-02-S-03 (쿠폰 관리 UI): 쿠폰 적용 대상 사업장 검색
- E-02-S-05 (크레딧 관리 UI): 크레딧 지급 대상 사업장 검색
- E-02-S-07 (추천인 관리 UI): 추천인/피추천인 사업장 확인
References
| 출처 | 경로/링크 | 참조 섹션 |
|---|---|---|
| Epic Spec | .context/sprints/s53/epic-specs/E-02.md | 어드민 강화 |
| Biz 테이블 | 기존 DDL | Biz, Store |
Dev Agent Record
| 항목 | 값 |
|---|---|
| 생성 Agent | Claude Opus 4.5 |
| 생성일 | 2026-01-27 |
| 마지막 수정 | 2026-01-27 |
| 검증자 | - |
검증 결과: 🔄 PENDING (PO 승인 대기) 검증일: -
생성일: 2026-01-27마지막 수정: 2026-01-27
