Domain Service / Use Case 분리
↓
Repository Pattern과 Prisma 의존성 관리
↓
Transaction Boundary와 상태 변경 Use Case
↓
Queue/Worker, ExportJob과 알림톡 구조
↓
Webhook, 외부 API 연동과 재시도 전략
↓
Permission Policy, 관리자 권한과 접근 제어
↓
Audit Log, Event Log와 운영 추적성
↓
Error Handling, Exception Filter와 표준 응답 구조
↓
테스트 가능한 구조와 Mock 전략
↓
백엔드 아키텍처 운영 체크리스트
단순히:
코드가 동작한다
실무적으로:
기능별 책임이 분리되어 있다
중요 변경은 transaction으로 보호된다
관리자 권한이 명확하다
외부 API 실패가 서비스 전체 장애로 번지지 않는다
Audit Log로 운영 작업을 추적할 수 있다
에러 응답이 표준화되어 있다
테스트로 핵심 흐름을 검증할 수 있다
핵심:
Controller는 요청/응답 처리
Use Case는 업무 흐름 조합
Domain Service는 핵심 규칙 관리
Repository는 DB 접근 담당
Adapter는 외부 API 연동 담당
핵심:
Prisma query를 여기저기 흩뿌리지 않기
ConsultRepository, ProductRepository, AuditLogRepository로 분리
Repository는 tx를 선택적으로 받을 수 있게 설계
Soft Delete 조건과 select 기준 통일
핵심:
transaction boundary는 Use Case에 둔다
상태 변경 + 상태 이력 + Audit Log는 같은 transaction
외부 API 호출은 transaction 밖으로 분리
동시 수정은 409 Conflict로 처리
핵심:
오래 걸리는 작업은 API 요청에서 분리
ExportJob, NotificationJob으로 작업 상태 관리
Worker가 실제 파일 생성/알림 발송 처리
retryCount, errorCode, startedAt, finishedAt 기록
핵심:
외부 API 호출은 Adapter로 분리
timeout, retry/backoff, idempotency 필요
Webhook은 signature 검증과 providerEventId unique 필요
Webhook 수신과 실제 처리는 분리
핵심:
인증과 인가 구분
Role보다 PermissionCode 기준으로 판단
RequirePermissions decorator와 PermissionGuard 적용
위험 작업은 별도 권한으로 분리
프론트 숨김은 UX, 백엔드 검증은 보안
핵심:
Audit Log는 관리자/시스템 행위 추적
Event Log는 도메인 사건 기록
requestId로 API 로그, Job, Audit Log 연결
beforeValue/afterValue에는 변경 필드만 최소 저장
핵심:
모든 에러 응답 구조 통일
error.code, message, details, requestId 포함
GlobalExceptionFilter 적용
Prisma/외부 API/도메인 에러 구분
민감정보와 stack trace 응답 금지
핵심:
Domain Service는 Unit Test
Use Case + Repository는 Integration Test
Controller/Guard/응답 구조는 E2E Test
외부 API/S3/시간/랜덤값은 Mock
운영 DB와 테스트 DB 절대 분리
consult/
상담 신청, 상담 목록, 상담 상세, 상태 변경, 메모, 중복 처리
product/
상품, 옵션, 통신사, 가격/지원금, 노출 여부, 삭제/복구
admin/
관리자 계정, 로그인, 권한, 역할, 비활성화
audit-log/
관리자 작업 이력, 권한 변경, 상품 변경, 다운로드 기록
export/
엑셀 ExportJob, 파일 생성, 다운로드 URL, 만료 처리
notification/
알림톡/SMS Job, 발송 Worker, 발송 결과, 재시도
webhook/
외부 이벤트 수신, signature 검증, 중복 처리, processor
analytics/
유입 source, visitorId, 광고/SEO/전환 분석
common/
error handling, requestId, logger, clock, idGenerator, config
1. consult
상담 신청과 관리자 처리의 중심
2. product
고객 화면과 판매 조건의 기준
3. admin/permission
관리자 기능의 안전장치
4. audit-log
운영 추적성과 책임 소재
5. export/notification
개인정보 파일과 외부 API 안정성
Controller
↓
Use Case
↓
Domain Service / Policy
↓
Repository
↓
Prisma
↓
PostgreSQL
Use Case / Worker
↓
Adapter
↓
External API
| 계층 | 역할 |
|---|---|
| Controller | HTTP 요청/응답, DTO, 현재 사용자 전달 |
| Use Case | 하나의 업무 흐름 실행 |
| Domain Service | 상태 전이, 중복 정책, 가격 정책 등 규칙 |
| Policy | 권한과 조건 판단 |
| Repository | DB 조회/저장 |
| Adapter | 외부 API, S3, 알림톡 등 연동 |
| Worker | 오래 걸리거나 재시도가 필요한 작업 처리 |
| Mapper | 내부 모델을 응답 DTO로 변환 |
Controller는 얇게
Use Case는 업무 흐름
Domain Service는 규칙
Repository는 DB
Adapter는 외부 세계
@Post(':id/status')
@RequirePermissions('CONSULT_UPDATE_STATUS')
async updateStatus(
@Param('id', ParseIntPipe) consultId: number,
@Body() body: UpdateConsultStatusDto,
@CurrentAdmin() admin: CurrentAdminDto,
@Req() req: Request,
) {
return this.updateConsultStatusUseCase.execute({
consultId,
nextStatus: body.status,
reason: body.reason,
memo: body.memo,
admin,
requestId: req.headers['x-request-id']?.toString(),
ipAddress: req.ip,
userAgent: req.headers['user-agent'],
});
}
CreateConsultUseCase
UpdateConsultStatusUseCase
RequestConsultExportUseCase
DownloadExportFileUseCase
UpdateProductPriceUseCase
SoftDeleteProductUseCase
ResendNotificationUseCase
ReceiveWebhookEventUseCase
이름만 봐도 업무 목적이 보임
한 파일이 너무 크지 않음
transaction 범위가 명확함
외부 API 직접 호출이 없음
Repository와 Domain Service를 조합함
실패 시 어떤 에러가 나는지 명확함
ConsultStatusService:
상담 상태 전이 규칙
DuplicateConsultPolicy:
중복 상담 신청 기준
ConsultSnapshotFactory:
상담 당시 상품 조건 snapshot 생성
ProductVisibilityPolicy:
상품 노출 가능 여부 판단
ProductPricePolicy:
지원금/가격 변경 규칙
ExportPermissionPolicy:
엑셀 다운로드 권한 판단
ConsultPermissionPolicy:
상담 상태 변경 세부 권한 판단
규칙:
Domain Service
권한:
Policy
DB 조회/저장:
Repository
업무 흐름:
Use Case
ConsultRepository
ProductRepository
AdminUserRepository
AuditLogRepository
ExportJobRepository
NotificationJobRepository
WebhookEventRepository
select로 최소 필드만 가져오는가?좋음:
findAdminList
findDetailForAdmin
findActiveById
findDeletedById
updateStatusIfCurrent
createStatusHistory
createWithSnapshot
markJobDone
markJobFailed
나쁨:
get
find
update
save
handle
process
data
findActiveById, findAdminList, findDetailForAdmin처럼 고객/관리자/삭제 조건을 이름에 담는 것이 좋습니다.상담 상태 변경 + 상태 이력 + Audit Log
상담 신청 생성 + NotificationJob 생성
상품 가격 변경 + Audit Log
상품 삭제/복구 + Audit Log
ExportJob 생성 + Audit Log
관리자 권한 변경 + Audit Log
Webhook 이벤트 처리 + 내부 상태 반영
알림톡/SMS 실제 발송
외부 API 호출
S3 업로드
엑셀 파일 생성
대량 파일 처리
긴 반복문 작업
사용자 응답 대기
엑셀 Export
알림톡/SMS 발송
S3 파일 업로드/삭제
Webhook 후속 처리
EP 파일 생성
대량 유입 분석 집계
오래된 Export 파일 cleanup
외부 CRM/광고 API 동기화
PENDING
PROCESSING
DONE
FAILED
RETRYING
CANCELED
EXPIRED
외부 API:
나가는 요청
Webhook:
들어오는 이벤트
공통:
검증, timeout, 중복 처리, 재시도, 로그, 보안
CONSULT_READ
CONSULT_DETAIL_READ
CONSULT_UPDATE_STATUS
CONSULT_MEMO_WRITE
CONSULT_EXPORT
PRODUCT_READ
PRODUCT_CREATE
PRODUCT_UPDATE
PRODUCT_PRICE_UPDATE
PRODUCT_DELETE
PRODUCT_RESTORE
BANNER_READ
BANNER_UPDATE
NOTIFICATION_READ
NOTIFICATION_RESEND
EXPORT_JOB_READ
EXPORT_JOB_DOWNLOAD
AUDIT_LOG_READ
AUDIT_LOG_DETAIL_READ
ADMIN_USER_READ
ADMIN_USER_CREATE
ADMIN_USER_UPDATE
ADMIN_USER_DISABLE
ADMIN_PERMISSION_MANAGE
RequirePermissions decorator가 있는가?PermissionGuard가 실제 route에 적용되어 있는가?프론트:
메뉴/버튼 숨김
백엔드:
최종 권한 검증
주의:
프론트 숨김은 보안이 아님
상담 상태 변경
상담 메모 수정
상품 가격/지원금 변경
상품 삭제/복구
엑셀 Export 요청
Export 파일 다운로드
알림톡 수동 재발송
Webhook 수동 재처리
관리자 권한 변경
관리자 계정 비활성화
actorType
actorId
action
targetType
targetId
beforeValue
afterValue
metadata
requestId
ipAddress
userAgent
createdAt
전화번호 원본
phoneNormalized
passwordHash
accessToken
refreshToken
Authorization header
cookie
DATABASE_URL
API Key
Secret
상담 메모 전체
{
"success": false,
"error": {
"code": "CONSULT_STATUS_CONFLICT",
"message": "이미 다른 관리자가 상담 상태를 변경했습니다.",
"details": null
},
"requestId": "req_123",
"timestamp": "2026-09-02T09:00:00.000Z",
"path": "/admin/consults/10/status"
}
CONSULT_NOT_FOUND
CONSULT_DUPLICATED
CONSULT_STATUS_TRANSITION_INVALID
CONSULT_STATUS_CONFLICT
PRODUCT_NOT_FOUND
PRODUCT_INACTIVE
EXPORT_FILE_EXPIRED
EXPORT_PERMISSION_DENIED
NOTIFICATION_PROVIDER_TIMEOUT
WEBHOOK_SIGNATURE_INVALID
ConsultStatusService
ConsultPermissionPolicy
DuplicateConsultPolicy
UpdateConsultStatusUseCase
RequestConsultExportUseCase
NotificationWorker
ExportWorker
PermissionGuard
GlobalExceptionFilter
Webhook signature 검증
new Date()와 randomUUID()를 Mock할 수 있는가?NODE_ENV=test 확인
DATABASE_URL에 prod 포함 시 실행 중단
운영 Secret 사용 금지
테스트 전후 데이터 초기화
외부 API 실제 호출 금지
/me 응답에 민감정보가 없는가?코드에 Secret 하드코딩 금지
Git 커밋 금지
SSM/Secrets Manager 사용
운영/개발 Secret 분리
Authorization header 로그 금지
DATABASE_URL 로그 금지
외부 API Key 로그 금지
주기적 rotation 고려
배포 완료
↓
health check
↓
로그인 확인
↓
상담 신청 확인
↓
관리자 목록 확인
↓
상태 변경 확인
↓
Worker/Job 확인
/me 권한 응답 정상5xx error 증가
Prisma error 증가
권한 403 비정상 증가
Webhook signature 오류 증가
NotificationJob FAILED 증가
ExportJob FAILED 증가
slow query 증가
DB connection error
# Runbook: 백엔드 장애 대응
## 1. 상황 확인
- 발생 시각:
- 영향 범위:
- 고객 화면/관리자 화면:
- 특정 API:
- 최근 배포 여부:
- 에러 코드:
- requestId:
- jobId:
- 관련 관리자/상담/상품 ID:
## 2. 즉시 확인
- 5xx 로그 증가 여부
- DB connection 오류
- Prisma error
- Worker 상태
- FAILED Job 증가
- 외부 API 장애 여부
- 최근 migration 여부
- 권한/인증 오류 증가 여부
## 3. 분류
- 코드 버그
- DB/migration 문제
- 외부 API 장애
- 권한 설정 문제
- Worker 중단
- 데이터 정합성 문제
- 인프라/배포 문제
## 4. 조치
- 영향 API 임시 차단 여부
- Worker 일시 중지 여부
- rollback 또는 forward fix
- 실패 Job 재처리 여부
- 잘못된 데이터 수동 복구 여부
- 관리자/고객 안내 필요 여부
## 5. 복구 후
- Smoke Test
- 에러 로그 감소 확인
- Audit Log/Job 상태 확인
- 장애 원인 문서화
- 재발 방지 TODO 등록
Controller에 비즈니스 로직 넣지 않기
Use Case 단위로 업무 흐름 작성
Domain Service/Policy에 규칙 분리
Repository에 Prisma query 모으기
transaction은 Use Case에서 관리
외부 API는 Adapter/Worker로 분리
표준 에러 응답 유지
민감정보 응답/로그 금지
테스트 또는 QA 체크리스트 포함
운영 DB 접속 정보 제공 금지
운영 개인정보 제공 금지
운영 migration 자동 승인 금지
destructive migration 자동 적용 금지
운영 dump AI 업로드 금지
Secret/API Key 전달 금지
where 없는 update/delete 금지
작업 목적
수정 범위
건드리면 안 되는 파일/기능
기존 API 응답 유지 여부
권한 기준
transaction 기준
Audit Log 기준
민감정보 금지 기준
테스트/QA 요구사항
변경 파일 목록 요청
docs/
backend/
README.md
architecture.md
module-structure.md
use-case-guideline.md
repository-guideline.md
transaction-guideline.md
permission-policy.md
audit-log.md
error-handling.md
queue-worker.md
webhook-external-api.md
testing.md
deployment-checklist.md
incident-runbook.md
architecture.md전체 계층 구조
Controller/Use Case/Domain/Repository/Adapter 역할
모듈별 책임
금지 패턴
예시 코드 링크
transaction-guideline.mdtransaction boundary 기준
transaction 안에 넣을 작업
transaction 밖으로 뺄 작업
상태 변경 예시
주의사항
error-handling.md표준 응답 구조
에러 코드 목록
Exception Filter 기준
Validation Error 처리
Prisma Error 변환
프론트 공통 처리 기준
testing.mdUnit/Integration/E2E 기준
Test DB 설정
Mock 대상
Seed Factory 사용법
CI 테스트 실행법
우선 테스트할 기능
목표:
상담 상태 변경 흐름 안정화
작업:
- UpdateConsultStatusUseCase 분리
- ConsultStatusService 작성
- ConsultPermissionPolicy 작성
- ConsultRepository 정리
- 상태 변경 + 이력 + Audit Log transaction 적용
- 409 동시성 충돌 처리
완료 기준:
상태 변경 로직이 Controller/Service에서 분리됨
상태 이력과 Audit Log가 누락되지 않음
권한/상태 전이/동시성 기준이 명확함
목표:
관리자 API 접근 제어와 에러 응답 통일
작업:
- PermissionCode 정의
- RequirePermissions decorator
- PermissionGuard 적용
- /me 권한 응답 정리
- AppException 작성
- GlobalExceptionFilter 적용
- 주요 도메인 에러 코드 정리
완료 기준:
권한 없는 요청은 403 처리
엑셀 다운로드/상품 수정/관리자 관리 권한 분리
모든 에러 응답에 error.code와 requestId 포함
목표:
오래 걸리는 작업과 외부 API 발송 분리
작업:
- ExportJob 테이블/Repository
- RequestConsultExportUseCase
- ExportWorker 초안
- NotificationJob 테이블/Repository
- NotificationWorker 초안
- AlimtalkAdapter 분리
- retryCount/errorCode 저장
완료 기준:
엑셀 생성이 API 요청과 분리됨
상담 저장과 알림톡 발송이 분리됨
Job 상태와 실패 사유를 관리자/로그에서 확인 가능
목표:
리팩토링 안전장치와 운영 대응 기준 확보
작업:
- ConsultStatusService unit test
- UpdateConsultStatusUseCase integration test
- PermissionGuard e2e test
- GlobalExceptionFilter e2e test
- Worker Mock test
- backend architecture docs 작성
- deployment checklist / incident runbook 작성
완료 기준:
핵심 흐름이 테스트로 보호됨
AI/Codex 작업 전후 검증 가능
배포/장애 대응 기준 문서화
Service 리팩토링
Repository 추가
권한 Guard 추가
에러 처리 수정
테스트 작성
Worker 추가
상담 상태 변경 로직을 Use Case 단위로 분리하고, 상태 변경·이력 저장·Audit Log 생성을 하나의 transaction으로 묶어 운영 데이터 정합성을 개선했습니다.
관리자 API에 Permission 기반 접근 제어를 도입해 상담 조회, 상태 변경, 엑셀 다운로드, 상품 수정, 관리자 계정 관리 권한을 분리했습니다.
엑셀 Export와 알림톡 발송을 Job/Worker 구조로 분리해 API 응답 지연과 외부 API 장애 영향을 줄이고, 실패 상태와 재시도 기준을 관리할 수 있게 했습니다.
Global Exception Filter와 표준 에러 응답 구조를 적용해 프론트 공통 에러 처리와 운영 로그 추적성을 개선했습니다.
Audit Log와 requestId 기반 추적 구조를 정리해 상품/지원금 변경, 상담 상태 변경, 엑셀 다운로드, 권한 변경 이력을 추적할 수 있게 했습니다.
Domain Service, Repository, Adapter, Worker 계층을 분리해 AI/Codex 기반 리팩토링 시 수정 범위를 통제하고 테스트 가능한 구조를 마련했습니다.
상태 전이, 권한 Policy, 상태 변경 Use Case, Worker 실패 처리에 대한 테스트를 추가해 핵심 운영 흐름의 회귀 버그를 줄였습니다.
간단한 CRUD 하나에 파일 8개 수정
테스트도 없는데 interface만 많음
실제 외부 시스템이 없는데 Event Sourcing 도입
트래픽도 적은데 Redis/BullMQ부터 도입
관리자 2명인데 복잡한 RBAC UI부터 구현
변경 속도보다 구조 유지 비용이 더 큼
단순 조회:
Controller + Service/Repository로 충분
중요 업무 흐름:
Use Case 분리
중복 규칙:
Domain Service/Policy 분리
외부 API:
Adapter 분리
오래 걸리는 작업:
Job/Worker 분리
위험 작업:
Permission + Audit Log + Test
전면 Clean Architecture 강제
모든 Repository에 interface 도입
CQRS/Event Sourcing 전면 도입
Microservice 분리
Kubernetes 기반 Worker 운영
복잡한 권한 관리 UI 선구현
NestJS + Prisma + PostgreSQL 기반 온라인 휴대폰 판매몰 백엔드 아키텍처를 전체 점검하고 싶어.
서비스 상황:
1. 고객 상담 신청, 관리자 상담 목록/상세, 상담 상태 변경, 상담 메모, 상품/옵션 관리, 엑셀 Export, 알림톡 발송, Webhook 수신, 관리자 권한, Audit Log 기능이 있음
2. 상담 상태 변경은 상태 전이 검증, 권한 확인, consults.status 업데이트, consult_status_histories 생성, audit_logs 생성을 하나의 transaction으로 묶고 싶음
3. 엑셀 Export와 알림톡 발송은 API 요청에서 직접 처리하지 않고 ExportJob/NotificationJob + Worker로 분리하고 싶음
4. 외부 API 호출은 Adapter로 분리하고 timeout, retry/backoff, idempotency를 적용하고 싶음
5. Webhook은 signature 검증, providerEventId unique, 빠른 응답, Processor/Worker 처리가 필요함
6. 관리자 권한은 Role 이름보다 PermissionCode 기준으로 판단하고, 엑셀 다운로드/상품 수정/관리자 계정 관리는 별도 권한으로 분리하고 싶음
7. Audit Log는 상담 상태 변경, 상품 가격/지원금 변경, 엑셀 다운로드, 알림톡 재발송, 관리자 권한 변경을 기록하고 싶음
8. 에러 응답은 success=false, error.code, error.message, requestId, timestamp, path 구조로 표준화하고 싶음
9. 테스트는 Unit/Integration/E2E로 나누고 외부 API/S3/시간/랜덤값은 Mock하고 싶음
10. 현재는 1인 개발자 프로젝트라 과한 구조보다는 운영 리스크가 큰 부분부터 점진적으로 개선하고 싶음
요청:
- 현재 구조에서 위험한 부분
- Controller/Use Case/Domain Service/Repository/Adapter/Worker 역할 점검
- transaction boundary 점검
- 권한/Permission Policy 점검
- Audit Log/운영 추적성 점검
- Error Handling/표준 응답 점검
- Queue/Worker/Webhook/외부 API 점검
- 테스트 전략 점검
- 보안/개인정보/Secret 관리 체크리스트
- 4주 개선 로드맵
- 과한 아키텍처를 피하는 기준
- 포트폴리오/경력기술서에 쓸 성과 표현
을 실무 기준으로 정리해줘.
현재 프로젝트의 상담/상품/관리자 흐름을 중심으로 보는가?
무조건 대규모 아키텍처를 강요하지 않는가?
transaction과 Audit Log 정합성을 강조하는가?
외부 API를 transaction 밖으로 분리하는가?
권한을 프론트 숨김이 아닌 백엔드 검증으로 보는가?
엑셀 Export와 개인정보 파일 보안을 중요하게 보는가?
표준 에러 응답과 requestId를 제안하는가?
테스트 DB와 운영 DB 분리를 강조하는가?
AI/Codex 작업 규칙까지 포함하는가?
error.code, message, details, requestId가 포함된 표준 구조로 통일해야 프론트 처리와 운영 추적이 쉬워집니다.