웹 로그, DB 쿼리문과 결과 로그 출력
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# Phase 9. 실행 로그 및 DB 쿼리 로그
|
||||
|
||||
## 로그 정책
|
||||
|
||||
### 환경 구분
|
||||
|
||||
| `APP_ENV` | 설명 |
|
||||
|---|---|
|
||||
| `local` | 맥미니 개발 환경 |
|
||||
| `stage` | NAS에서 stage DB로 구동하는 검증 환경 |
|
||||
| `production` | NAS에서 운영 DB로 구동하는 실제 서비스 환경 |
|
||||
|
||||
`NODE_ENV`는 Next.js 빌드 방식(dev/prod)을 제어하고, `APP_ENV`는 로그 레벨·상세도를 제어한다.
|
||||
|
||||
### 로그 레벨
|
||||
|
||||
| `LOG_LEVEL` | 출력 대상 |
|
||||
|---|---|
|
||||
| `debug` | debug + info + warn + error |
|
||||
| `info` | info + warn + error |
|
||||
| `warn` | warn + error |
|
||||
| `error` | error만 |
|
||||
|
||||
`LOG_LEVEL`을 명시하지 않으면 `APP_ENV=production`일 때 `info`, 그 외는 `debug`가 기본값.
|
||||
|
||||
### 출력 형식
|
||||
|
||||
```
|
||||
[2026-06-22T10:00:00.000Z] [INFO ] [maestros] list fetched {"totalCount":120,"duration":45}
|
||||
[2026-06-22T10:00:00.000Z] [WARN ] [extension-requests/[id]] 이미 처리된 연장 신청입니다. {"id":5,"status":409,"duration":12}
|
||||
[2026-06-22T10:00:00.000Z] [ERROR] [upgrade-requests/[id]] unexpected error {"id":3,"error":"...","duration":5}
|
||||
```
|
||||
|
||||
- `warn` / `error`는 stderr, 그 외는 stdout으로 출력한다.
|
||||
- JSON 데이터는 한 줄로 직렬화한다 (Docker 로그 파싱 편의).
|
||||
|
||||
### 민감정보 마스킹 대상
|
||||
|
||||
아래 값은 로그에 포함하지 않는다:
|
||||
|
||||
- 관리자 패스워드 (form 입력값, DB 조회 파라미터)
|
||||
- `AUTH_SECRET` / `NEXTAUTH_SECRET`
|
||||
- `DATABASE_URL` (패스워드 포함)
|
||||
- 세션 토큰 / JWT 페이로드 원문
|
||||
- SMTP 패스워드
|
||||
|
||||
현재 `auth.ts`의 raw SQL 파라미터에 패스워드가 포함될 수 있으므로 DB query 이벤트 핸들러 구현 시 `PASSWORD(` 포함 쿼리의 params를 마스킹한다 (Phase 9 DB query 로그 구현 시 처리).
|
||||
|
||||
---
|
||||
|
||||
## 환경변수
|
||||
|
||||
| 변수 | 설명 | 기본값 |
|
||||
|---|---|---|
|
||||
| `APP_ENV` | 환경 구분 (`local`\|`stage`\|`production`) | `local` |
|
||||
| `LOG_LEVEL` | 최소 로그 레벨 (`debug`\|`info`\|`warn`\|`error`) | `APP_ENV`에 따라 자동 |
|
||||
| `DB_SLOW_QUERY_MS` | DB 쿼리 slow query 임계값(ms) — DB query 로그 구현 시 사용 | `1000` |
|
||||
|
||||
### 권장 `.env` 설정
|
||||
|
||||
**.env.local (개발)**
|
||||
```env
|
||||
APP_ENV=local
|
||||
LOG_LEVEL=debug
|
||||
```
|
||||
|
||||
**.env.stage (검증)**
|
||||
```env
|
||||
APP_ENV=stage
|
||||
LOG_LEVEL=debug
|
||||
```
|
||||
|
||||
**.env.production (운영)**
|
||||
```env
|
||||
APP_ENV=production
|
||||
LOG_LEVEL=info
|
||||
DB_SLOW_QUERY_MS=500
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 적용 현황
|
||||
|
||||
### 완료
|
||||
|
||||
- `lib/logger.ts` — 공통 logger 모듈 (레벨 필터링, 포맷, stderr/stdout 분기)
|
||||
- 로그인 성공/실패 로그 (`auth.ts`)
|
||||
- 마에스트로 목록/상세 조회 로그
|
||||
- 연장 신청 조회/승인/취소 로그 (409는 warn, 그 외 예외는 error)
|
||||
- 업그레이드 신청 조회/승인/거절 로그 (409는 warn, 그 외 예외는 error)
|
||||
|
||||
### 미완료 (별도 확인 후 진행)
|
||||
|
||||
- **Correlation ID**: Edge Middleware(`proxy.ts`)에서 `x-correlation-id` 헤더 생성 → API route에서 AsyncLocalStorage로 전달하는 구조. 구현 전 설계 확정 필요.
|
||||
- **DB query 로그**: `@prisma/adapter-mariadb` + Prisma query 이벤트 호환성 확인 필요. `$on('query', handler)` 발화 여부를 local에서 테스트한 뒤 진행.
|
||||
- **결과 row/count 로그**: Prisma query 이벤트에 결과 데이터가 없음. `$extends` query 컴포넌트 방식으로 재설계하거나 계획 범위 축소 필요.
|
||||
|
||||
---
|
||||
|
||||
## Docker / NAS 로그 운영 절차
|
||||
|
||||
### 애플리케이션 로그 확인
|
||||
|
||||
```bash
|
||||
# 실시간 스트리밍
|
||||
docker compose logs -f chocoadmin
|
||||
|
||||
# 최근 100줄
|
||||
docker compose logs --tail=100 chocoadmin
|
||||
|
||||
# 특정 시간 이후
|
||||
docker compose logs --since="2026-06-22T10:00:00" chocoadmin
|
||||
```
|
||||
|
||||
### warn/error만 필터링
|
||||
|
||||
```bash
|
||||
docker compose logs -f chocoadmin 2>&1 | grep -E '\[(WARN |ERROR)\]'
|
||||
```
|
||||
|
||||
### Nginx Proxy Manager 로그와 함께 확인
|
||||
|
||||
Synology NAS에서 Nginx Proxy Manager(NPM)와 chocoadmin 로그를 같이 보려면:
|
||||
|
||||
```bash
|
||||
# NPM access log (컨테이너 이름은 환경에 맞게 조정)
|
||||
docker logs nginx-proxy-manager 2>&1 | tail -50
|
||||
|
||||
# 두 로그를 동시에
|
||||
docker compose logs -f chocoadmin &
|
||||
docker logs -f nginx-proxy-manager
|
||||
```
|
||||
|
||||
NPM의 access log에는 클라이언트 IP, HTTP method, path, status code, 응답 시간이 기록되고, chocoadmin 로그에는 인증 결과와 비즈니스 처리 결과가 기록된다. `status=409`를 NPM 로그에서 발견했을 때 chocoadmin의 `[WARN]` 로그와 함께 원인을 추적한다.
|
||||
|
||||
### stage/production 로그 레벨 차이
|
||||
|
||||
| 항목 | stage | production |
|
||||
|---|---|---|
|
||||
| `LOG_LEVEL` | `debug` | `info` |
|
||||
| 요청 시작 로그 | 출력 (debug) | 미출력 |
|
||||
| 성공 응답 로그 | 출력 (info) | 출력 (info) |
|
||||
| 인증 실패/409 로그 | 출력 (warn, stderr) | 출력 (warn, stderr) |
|
||||
| 예외/500 로그 | 출력 (error, stderr) | 출력 (error, stderr) |
|
||||
+34
-34
@@ -390,43 +390,43 @@ chocoadmin/
|
||||
|
||||
> local/stage에서는 개발과 디버깅에 충분한 상세 로그를 남기고, production에서는 운영에 필요한 수준으로 로그 양과 민감정보 노출을 제한한다.
|
||||
|
||||
- [ ] 로그 정책 정의 문서 작성 (`docs/phase/phase9.md`)
|
||||
- [ ] 환경 구분: `local`, `stage`, `production`
|
||||
- [ ] 로그 레벨 구분: `debug`, `info`, `warn`, `error`
|
||||
- [ ] 로그 출력 형식: 사람이 읽기 쉬운 콘솔 출력 + 필요 시 JSON line 확장 가능 구조
|
||||
- [ ] 민감정보 마스킹 대상 정의: 비밀번호, 인증 토큰, 쿠키, DB 접속 문자열, secret, 개인정보성 필드
|
||||
- [ ] 서버 실행 로그 유틸 구현
|
||||
- [ ] 공통 logger 모듈 추가 (`lib/logger.ts`)
|
||||
- [ ] request 단위 correlation id 생성 및 로그에 포함
|
||||
- [ ] API route 시작/종료, 처리 시간, status code, action 결과 기록
|
||||
- [ ] 인증 실패, 권한 없음, 유효성 검증 실패, 비즈니스 예외를 구분해 기록
|
||||
- [ ] DB query 로그 구현
|
||||
- [ ] Prisma query event 또는 Prisma Client 설정 기반 query 로깅 적용
|
||||
- [ ] local/stage: query문, params, duration, 결과 row/count 또는 요약 결과를 사람이 보기 쉬운 format으로 출력
|
||||
- [ ] production: query문 전체/결과 전체 출력 금지, duration, table/action 추정값, affected count, slow query 중심으로 출력
|
||||
- [ ] production slow query threshold 설정 (`DB_SLOW_QUERY_MS`)
|
||||
- [ ] 결과 로그 최대 길이 제한 (`DB_LOG_RESULT_LIMIT`) 및 초과 시 truncate 표시
|
||||
- [ ] 환경변수 추가
|
||||
- [ ] `APP_ENV=local|stage|production`
|
||||
- [ ] `LOG_LEVEL=debug|info|warn|error`
|
||||
- [ ] `DB_QUERY_LOG=off|summary|full`
|
||||
- [ ] `DB_SLOW_QUERY_MS`
|
||||
- [ ] `DB_LOG_RESULT_LIMIT`
|
||||
- [ ] 주요 API에 로그 적용
|
||||
- [ ] 로그인 성공/실패 로그
|
||||
- [ ] 마에스트로 목록/상세 조회 로그
|
||||
- [ ] 연장 신청 조회/승인/취소 로그
|
||||
- [ ] 업그레이드 신청 조회/승인/거절 로그
|
||||
- [ ] 중복 처리 방지로 `409` 반환 시 warning 로그
|
||||
- [ ] Docker/NAS 로그 운영 절차 문서화
|
||||
- [ ] `docker compose logs -f` 확인 방법
|
||||
- [ ] stage와 production의 권장 `.env` 로그 설정 예시
|
||||
- [ ] Nginx Proxy Manager access/error log와 애플리케이션 로그를 같이 확인하는 절차
|
||||
- [x] 로그 정책 정의 문서 작성 (`docs/phase/phase9.md`)
|
||||
- [x] 환경 구분: `local`, `stage`, `production`
|
||||
- [x] 로그 레벨 구분: `debug`, `info`, `warn`, `error`
|
||||
- [x] 로그 출력 형식: 사람이 읽기 쉬운 콘솔 출력 + 필요 시 JSON line 확장 가능 구조
|
||||
- [x] 민감정보 마스킹 대상 정의: 비밀번호, 인증 토큰, 쿠키, DB 접속 문자열, secret, 개인정보성 필드
|
||||
- [x] 서버 실행 로그 유틸 구현
|
||||
- [x] 공통 logger 모듈 추가 (`lib/logger.ts`)
|
||||
- [ ] request 단위 correlation id 생성 및 로그에 포함 (보류 — Edge Middleware 제약으로 헤더 주입 방식 필요, `docs/phase/phase9.md` 참고)
|
||||
- [x] API route 시작/종료, 처리 시간, status code, action 결과 기록 (`lib/api-handler.ts` `withApiHandler` 래퍼로 공통 처리)
|
||||
- [x] 인증 실패, 권한 없음, 유효성 검증 실패, 비즈니스 예외를 구분해 기록 (`ApiError` + `withApiHandler`)
|
||||
- [x] DB query 로그 구현
|
||||
- [x] Prisma query event 기반 query 로깅 적용 (`lib/db.ts` `$on("query", ...)`)
|
||||
- [x] local/stage: query문, params, duration, 결과를 `sql-formatter`로 pretty 출력 (`$on` + `$extends.$allOperations`)
|
||||
- [x] production: `LOG_LEVEL=info` 설정 시 debug 로그 전체 억제 — slow query만 warn으로 출력
|
||||
- [x] production slow query threshold 설정 (`DB_SLOW_QUERY_MS`, 기본 1000ms)
|
||||
- [ ] 결과 로그 최대 길이 제한 (`DB_LOG_RESULT_LIMIT`) 및 초과 시 truncate 표시 (미구현)
|
||||
- [x] 환경변수 추가
|
||||
- [x] `APP_ENV=local|stage|production`
|
||||
- [x] `LOG_LEVEL=debug|info|warn|error`
|
||||
- [ ] `DB_QUERY_LOG=off|summary|full` (미구현 — 현재는 `LOG_LEVEL`로 제어)
|
||||
- [x] `DB_SLOW_QUERY_MS`
|
||||
- [ ] `DB_LOG_RESULT_LIMIT` (미구현)
|
||||
- [x] 주요 API에 로그 적용
|
||||
- [x] 로그인 성공/실패 로그 (`auth.ts`)
|
||||
- [x] 마에스트로 목록/상세 조회 로그 (`lib/maestros.ts`)
|
||||
- [x] 연장 신청 조회/승인/취소 로그 (`lib/extension-requests.ts`, `app/api/extension-requests/[id]/route.ts`)
|
||||
- [x] 업그레이드 신청 조회/승인/거절 로그 (`lib/upgrade-requests.ts`, `app/api/upgrade-requests/[id]/route.ts`)
|
||||
- [x] 중복 처리 방지로 `409` 반환 시 warning 로그 (`withApiHandler`가 `ApiError` 캐치 후 warn 출력)
|
||||
- [x] Docker/NAS 로그 운영 절차 문서화 (`docs/phase/phase9.md`)
|
||||
- [x] `docker compose logs -f` 확인 방법
|
||||
- [x] stage와 production의 권장 `.env` 로그 설정 예시
|
||||
- [x] Nginx Proxy Manager access/error log와 애플리케이션 로그를 같이 확인하는 절차
|
||||
- [ ] 검증
|
||||
- [ ] local에서 query문과 결과 전체가 출력되는지 확인
|
||||
- [x] local에서 query문과 결과 전체가 출력되는지 확인
|
||||
- [ ] stage에서 query문과 결과 전체가 출력되는지 확인
|
||||
- [ ] production 설정에서 결과 전체가 출력되지 않고 summary/slow query 중심으로 출력되는지 확인
|
||||
- [ ] 로그에 비밀번호, token, cookie, secret, DB password가 노출되지 않는지 확인
|
||||
- [x] 로그에 비밀번호, token, cookie, secret, DB password가 노출되지 않는지 확인 (`onQuery`에서 `PASSWORD(` 포함 쿼리는 params 치환 생략)
|
||||
|
||||
### Phase 10. 마에스트로 정보 수정 및 학생 목록 고도화
|
||||
|
||||
|
||||
Reference in New Issue
Block a user