TIL - 20260704

juni·2026년 7월 4일

TIL

목록 보기
393/470

0704 백엔드 실무 심화 (11/N): 로그, 감사 추적과 운영 이력 설계


✅ 1. 로그란 무엇인가?

  • 로그(Log)는 서비스에서 어떤 일이 발생했는지 기록해두는 데이터입니다.
  • 백엔드 서버, 관리자 페이지, DB 작업, 외부 API 호출, 배치 작업, Webhook 처리, 로그인 시도 등 거의 모든 운영 흐름에서 로그가 필요합니다.
  • 로그는 문제가 발생했을 때 원인을 찾는 가장 중요한 근거입니다.
사용자 요청
  ↓
백엔드 처리
  ↓
DB 조회/수정
  ↓
외부 API 호출
  ↓
응답 반환

각 단계에서 필요한 정보를 로그로 기록

➕ 1-1. 로그가 필요한 이유

  • 장애 원인 분석

    • API 500 오류가 왜 발생했는지 확인할 수 있습니다.
  • 운영 추적

    • 누가 상담 상태를 바꿨는지, 누가 엑셀을 다운로드했는지 확인할 수 있습니다.
  • 보안 감시

    • 로그인 실패, 비정상 접근, 권한 없는 요청을 추적할 수 있습니다.
  • 외부 API 문제 확인

    • 알림톡, SMS, 결제, Webhook 처리 실패 원인을 파악할 수 있습니다.
  • 커리어/성과 증명

    • “운영 이력, 장애 대응, 재발 방지 체계 구축”은 경력기술서에 넣기 좋은 실무 근거가 됩니다.

✅ 2. 로그와 감사 로그의 차이

  • 로그라고 해서 모두 같은 목적은 아닙니다.
  • 일반 로그와 감사 로그를 구분하면 운영 설계가 훨씬 명확해집니다.
구분목적예시
애플리케이션 로그서버 동작과 에러 확인API 요청, 에러 stack, DB 오류
접근 로그누가 어떤 요청을 했는지 확인Nginx access.log, API request log
감사 로그중요한 운영 행위 추적관리자 상태 변경, 엑셀 다운로드
보안 로그비정상 접근 감지로그인 실패, 권한 없는 요청
외부 연동 로그외부 API 호출 결과 추적알림톡, SMS, 결제, Webhook
배치 로그정기 작업 성공/실패 확인통계 집계, EP 생성, 파일 정리

➕ 2-1. 감사 로그가 특히 중요한 이유

  • 감사 로그는 단순 디버깅용 로그가 아니라 책임 추적을 위한 기록입니다.
  • 관리자 페이지에서는 “누가, 언제, 무엇을, 어떻게 바꿨는지”가 남아야 합니다.
상담 상태 변경:
김관리자
2026-07-04 14:10
PENDING → DONE
메모: 고객 상담 완료
IP: 123.123.123.123
  • 이런 기록이 있어야 고객 민원, 내부 실수, 운영 사고가 생겼을 때 원인을 확인할 수 있습니다.

✅ 3. 로그를 남겨야 하는 대표 영역

➕ 3-1. API 요청 로그

  • 어떤 API가 언제 호출되었는지 기록합니다.
method=GET
path=/api/admin/consults
status=200
durationMs=124
adminId=3
ip=123.123.123.123
  • 응답 시간이 느린 API를 찾을 때 유용합니다.
  • 특정 관리자나 IP의 비정상 요청도 추적할 수 있습니다.

➕ 3-2. 에러 로그

  • 서버에서 발생한 예외와 오류를 기록합니다.
level=ERROR
message=PrismaClientKnownRequestError
path=/api/admin/consults/export
adminId=3
errorCode=P2002
stack=...
  • 에러 로그에는 원인 분석에 필요한 정보가 있어야 합니다.
  • 단, 개인정보와 Secret은 절대 그대로 남기면 안 됩니다.

➕ 3-3. 관리자 작업 로그

  • 관리자 페이지에서 중요한 데이터를 바꾸는 행위를 기록합니다.
상담 상태 변경
상담 메모 수정
주문 상태 변경
상품 등록/수정/삭제
배너 등록/수정/삭제
관리자 계정 생성/권한 변경
엑셀 다운로드
사전예약 상태 변경
시스템 설정 변경
  • 관리자 작업 로그는 단순 로그 파일보다 DB 테이블로 남기는 것이 좋습니다.
  • 나중에 관리자 페이지에서 검색하고 확인해야 하기 때문입니다.

➕ 3-4. 외부 API 로그

  • 알림톡, SMS, 결제, CRM, 광고 API 같은 외부 연동 결과를 기록합니다.
provider=KAKAO
action=SEND_CONSULT_COMPLETE
status=FAILED
relatedType=CONSULT
relatedId=123
errorCode=TIMEOUT
attempts=3
  • 실패한 외부 API는 재시도, 관리자 확인, 수동 재처리와 연결될 수 있습니다.

➕ 3-5. 배치 작업 로그

  • 정기 작업이 언제 실행됐고 성공했는지 기록합니다.
jobName=DAILY_CONSULT_SUMMARY
status=SUCCESS
targetDate=2026-07-03
processedCount=428
durationMs=1530
  • 배치 로그가 없으면 정기 작업이 실제로 정상 실행됐는지 알 수 없습니다.

✅ 4. 좋은 로그의 기준

➕ 4-1. 원인 추적이 가능해야 한다

  • 단순히 “에러 발생”만 남기면 부족합니다.
  • 어떤 요청에서, 어떤 사용자/관리자가, 어떤 조건으로, 어느 단계에서 실패했는지 알 수 있어야 합니다.
나쁜 로그:
Error occurred

좋은 로그:
Failed to export consults
adminId=3
query=status=PENDING,source=NAVER,startDate=2026-07-01
errorCode=DB_TIMEOUT
durationMs=30200

➕ 4-2. 민감정보를 남기지 않아야 한다

  • 로그는 장애 분석용이지만, 잘못 남기면 개인정보 유출 경로가 됩니다.
로그에 남기면 위험한 것:
비밀번호
JWT
Refresh Token
API Key
Secret
전체 전화번호
주민등록번호
결제 카드 정보
인증번호
고객 상담 메모 원문
  • 로그는 보통 여러 사람이 접근할 수 있고, CloudWatch나 외부 로그 시스템으로 전송될 수도 있습니다.
  • 따라서 로그에는 필요한 최소 정보만 남겨야 합니다.

➕ 4-3. 검색 가능한 구조여야 한다

  • 운영 중 로그를 찾으려면 key-value 구조가 유리합니다.
level=INFO
event=CONSULT_STATUS_UPDATED
adminId=3
consultId=123
fromStatus=PENDING
toStatus=DONE
durationMs=42
  • adminId, consultId, event, status 같은 값을 구조화해두면 나중에 검색하기 쉽습니다.

✅ 5. 로그 레벨

  • 로그에는 중요도에 따라 레벨을 나누는 것이 좋습니다.
레벨의미예시
DEBUG개발/디버깅용 상세 정보SQL 조건, 내부 변수
INFO정상적인 주요 이벤트서버 시작, 상태 변경
WARN주의가 필요한 상황재시도 예정, 느린 요청
ERROR실패한 작업API 오류, 외부 API 실패
FATAL서비스 중단급 오류서버 시작 실패, DB 연결 불가

➕ 5-1. 실무 기준

개발 환경:
DEBUG까지 자세히 출력

운영 환경:
INFO, WARN, ERROR 중심

민감정보:
어떤 환경에서도 출력 금지
  • 운영에서 DEBUG 로그를 너무 많이 남기면 비용과 보안 위험이 커질 수 있습니다.
  • CloudWatch Logs를 사용한다면 로그 양이 곧 비용으로 이어질 수 있습니다.

✅ 6. Request ID와 Correlation ID

  • 하나의 요청이 여러 서비스, DB, 외부 API를 거칠 때 흐름을 추적하려면 고유한 ID가 필요합니다.
  • 이를 보통 Request ID 또는 Correlation ID라고 합니다.

➕ 6-1. 필요한 이유

관리자 엑셀 다운로드 요청
  ↓
API 서버 로그
  ↓
DB 조회 로그
  ↓
Queue Job 등록 로그
  ↓
Worker 처리 로그
  ↓
S3 업로드 로그

같은 requestId로 묶으면 전체 흐름 추적 가능

➕ 6-2. 로그 예시

requestId=req_20260704_abcd1234
event=EXPORT_JOB_CREATED
adminId=3
exportJobId=55

requestId=req_20260704_abcd1234
event=EXPORT_FILE_UPLOADED
exportJobId=55
fileKey=private/exports/consults/2026/07/04/file.xlsx
  • requestId가 있으면 여러 로그를 하나의 흐름으로 묶어서 볼 수 있습니다.
  • 장애 대응 속도가 확실히 빨라집니다.

✅ 7. NestJS 요청 로그 Interceptor

  • NestJS에서는 Interceptor를 사용해 요청과 응답 시간을 기록할 수 있습니다.

➕ 7-1. RequestLogInterceptor 예시

@Injectable()
export class RequestLogInterceptor implements NestInterceptor {
  private readonly logger = new Logger(RequestLogInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler) {
    const request = context.switchToHttp().getRequest();
    const { method, originalUrl } = request;
    const start = Date.now();

    return next.handle().pipe(
      tap(() => {
        const durationMs = Date.now() - start;

        this.logger.log({
          event: 'HTTP_REQUEST',
          method,
          path: originalUrl,
          statusCode: context.switchToHttp().getResponse().statusCode,
          durationMs,
          userId: request.user?.id,
          ip: request.ip,
        });
      }),
    );
  }
}
  • 모든 요청의 처리 시간을 기록할 수 있습니다.
  • 운영에서는 느린 API를 찾는 데 도움이 됩니다.

✅ 8. 에러 로깅 Filter

  • NestJS에서는 Exception Filter를 사용해 에러 로그를 공통으로 남길 수 있습니다.
  • 에러 처리를 Service마다 중복으로 작성하기보다 공통 필터를 두면 관리가 편합니다.

➕ 8-1. Exception Filter 예시

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(GlobalExceptionFilter.name);

  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const request = ctx.getRequest();
    const response = ctx.getResponse();

    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : 500;

    this.logger.error({
      event: 'HTTP_EXCEPTION',
      status,
      path: request.originalUrl,
      method: request.method,
      userId: request.user?.id,
      ip: request.ip,
      message:
        exception instanceof Error
          ? exception.message
          : 'Unknown error',
    });

    response.status(status).json({
      success: false,
      message:
        status >= 500
          ? '서버 오류가 발생했습니다.'
          : '요청을 처리할 수 없습니다.',
    });
  }
}
  • 사용자 응답에는 안전한 메시지만 반환합니다.
  • 서버 로그에는 디버깅에 필요한 정보를 남깁니다.
  • 운영에서는 stack trace를 외부 사용자에게 노출하면 안 됩니다.

✅ 9. 관리자 작업 이력 테이블 설계

  • 관리자 작업 이력은 파일 로그보다 DB 테이블로 남기는 것이 좋습니다.
  • 관리자 페이지에서 검색, 필터링, 다운로드, 상세 확인이 필요할 수 있기 때문입니다.

➕ 9-1. AdminActionLog 모델 예시

model AdminActionLog {
  id          Int      @id @default(autoincrement())
  adminId     Int?
  action      String
  resource    String
  resourceId  Int?
  beforeData  Json?
  afterData   Json?
  reason      String?
  ipAddress   String?
  userAgent   String?
  createdAt   DateTime @default(now())

  @@index([adminId, createdAt])
  @@index([resource, resourceId])
  @@index([action, createdAt])
}

➕ 9-2. 필드 설명

필드설명
adminId작업한 관리자
action수행한 작업
resource대상 리소스
resourceId대상 ID
beforeData변경 전 데이터
afterData변경 후 데이터
reason변경 사유
ipAddress요청 IP
userAgent브라우저/클라이언트 정보
createdAt작업 일시
  • beforeData, afterData에 모든 데이터를 넣으면 용량과 개인정보 문제가 생길 수 있습니다.
  • 필요한 필드만 선별해서 저장하는 것이 좋습니다.

✅ 10. 관리자 작업 로그 예시

➕ 10-1. 상담 상태 변경

{
  "adminId": 3,
  "action": "CONSULT_STATUS_UPDATED",
  "resource": "CONSULT",
  "resourceId": 123,
  "beforeData": {
    "status": "PENDING"
  },
  "afterData": {
    "status": "DONE"
  },
  "reason": "고객 상담 완료"
}

➕ 10-2. 엑셀 다운로드

{
  "adminId": 3,
  "action": "CONSULT_EXPORT_REQUESTED",
  "resource": "EXPORT_JOB",
  "resourceId": 55,
  "afterData": {
    "type": "CONSULT",
    "query": {
      "status": "PENDING",
      "source": "NAVER",
      "startDate": "2026-07-01",
      "endDate": "2026-07-04"
    },
    "rowCount": 1200
  }
}

➕ 10-3. 상품 정보 수정

{
  "adminId": 2,
  "action": "PRODUCT_UPDATED",
  "resource": "PRODUCT",
  "resourceId": 88,
  "beforeData": {
    "isVisible": false,
    "price": 1200000
  },
  "afterData": {
    "isVisible": true,
    "price": 1150000
  }
}
  • 로그를 남길 때는 “나중에 이걸 보고 상황을 이해할 수 있는가?”를 기준으로 판단하면 됩니다.

✅ 11. 로그와 개인정보 마스킹

  • 로그에 개인정보가 그대로 남으면 위험합니다.
  • 특히 상담 신청, 주문, 인증, 알림 발송 기능에서는 전화번호와 이름이 자주 다뤄집니다.

➕ 11-1. 마스킹 기준 예시

전화번호:
01012345678 → 010****5678

이름:
홍길동 → 홍*동

이메일:
test@example.com → te**@example.com

토큰:
앞 6자리만 표시 후 나머지 마스킹

➕ 11-2. 마스킹 함수 예시

export function maskPhone(phone?: string) {
  if (!phone) {
    return phone;
  }

  return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3');
}

export function maskEmail(email?: string) {
  if (!email) {
    return email;
  }

  const [local, domain] = email.split('@');

  return `${local.slice(0, 2)}**@${domain}`;
}
  • 로그를 남기기 전에 마스킹하는 습관이 필요합니다.
  • 특히 외부 API request/response payload를 그대로 저장하는 것은 위험합니다.

✅ 12. 외부 API 로그 설계

  • 외부 API는 실패했을 때 원인 추적과 재처리가 중요합니다.
  • 단순 로그 파일보다 DB에 호출 이력을 남기면 운영자가 확인하기 좋습니다.

➕ 12-1. ExternalApiLog 모델 예시

model ExternalApiLog {
  id             Int      @id @default(autoincrement())
  provider       String
  action         String
  status         String
  relatedType    String?
  relatedId      Int?
  requestId      String?
  requestPayload Json?
  responseBody   Json?
  errorCode      String?
  errorMessage   String?
  attempts       Int      @default(0)
  createdAt      DateTime @default(now())
  completedAt    DateTime?

  @@index([provider, action])
  @@index([status, createdAt])
  @@index([relatedType, relatedId])
}

➕ 12-2. 사용 예시

알림톡 발송 실패:
ExternalApiLog에 FAILED 저장

관리자 페이지:
실패 건 조회

재발송:
Queue에 재처리 Job 등록

성공:
ExternalApiLog 상태 SUCCESS 변경
  • 외부 API 실패가 조용히 묻히면 운영자가 고객에게 알림이 안 간 사실을 모를 수 있습니다.
  • 실패를 눈에 보이게 만드는 것이 중요합니다.

✅ 13. 배치 작업 로그 설계

  • 배치 작업은 정기적으로 실행되기 때문에 성공/실패 이력을 남겨야 합니다.
  • 특히 통계, EP 생성, 백업, 파일 정리 작업은 실패하면 운영 데이터에 영향을 줍니다.

➕ 13-1. BatchJobLog 모델 예시

model BatchJobLog {
  id             Int      @id @default(autoincrement())
  jobName        String
  status         String
  targetDate     DateTime?
  startedAt      DateTime
  endedAt        DateTime?
  durationMs     Int?
  processedCount Int?
  successCount   Int?
  failCount      Int?
  errorMessage   String?
  createdAt      DateTime @default(now())

  @@index([jobName, startedAt])
  @@index([status, startedAt])
}

➕ 13-2. 배치 로그 예시

{
  "jobName": "DAILY_CONSULT_SUMMARY",
  "status": "SUCCESS",
  "targetDate": "2026-07-03",
  "durationMs": 1450,
  "processedCount": 428,
  "successCount": 428,
  "failCount": 0
}
  • 배치 로그가 있으면 “어제 통계가 왜 안 맞지?” 같은 문제를 추적하기 쉽습니다.

✅ 14. 보안 로그 설계

  • 보안 로그는 비정상 접근과 계정 위험을 감지하기 위한 기록입니다.

➕ 14-1. 남겨야 하는 보안 이벤트

관리자 로그인 성공
관리자 로그인 실패
비밀번호 변경
비밀번호 재설정 요청
권한 없는 API 접근
관리자 계정 생성
관리자 권한 변경
관리자 계정 비활성화
비정상적으로 많은 요청
IP 차단 또는 Rate Limit 발생

➕ 14-2. SecurityLog 모델 예시

model SecurityLog {
  id          Int      @id @default(autoincrement())
  adminId     Int?
  event       String
  ipAddress   String?
  userAgent   String?
  result      String
  reason      String?
  createdAt   DateTime @default(now())

  @@index([adminId, createdAt])
  @@index([event, createdAt])
  @@index([ipAddress, createdAt])
}
  • 보안 로그는 문제가 생긴 뒤 확인하는 것도 중요하지만, 이상 징후를 미리 발견하는 데도 필요합니다.

✅ 15. 로그 저장 위치

  • 로그는 목적에 따라 저장 위치가 달라질 수 있습니다.
저장 위치용도
콘솔 로그개발/간단한 운영 확인
파일 로그서버 내부 로그
DB 테이블관리자 작업 이력, 외부 API 이력
CloudWatch LogsAWS 운영 로그 중앙화
Sentry애플리케이션 에러 추적
Slack/Email 알림중요한 장애/실패 알림

➕ 15-1. 실무 기준

일반 서버 요청/에러:
CloudWatch Logs 또는 파일 로그

관리자 작업 이력:
DB 테이블

외부 API 발송/실패 이력:
DB 테이블

심각한 장애:
Slack/Email 알림

프론트/백엔드 에러 추적:
Sentry 같은 도구
  • 모든 로그를 DB에 넣으면 DB가 커지고 성능 문제가 생길 수 있습니다.
  • 반대로 중요한 운영 이력을 파일 로그에만 남기면 검색과 추적이 어렵습니다.
  • 목적에 맞게 나눠야 합니다.

✅ 16. 로그 보관 기간

  • 로그는 무한히 보관하면 비용과 보안 위험이 커집니다.
  • 로그 종류별로 보관 기간을 정해야 합니다.

➕ 16-1. 보관 기간 예시

로그 종류보관 기간 예시
API 요청 로그7일 ~ 30일
에러 로그30일 ~ 90일
관리자 작업 이력6개월 ~ 1년 이상
엑셀 다운로드 이력1년 이상 검토
보안 로그6개월 ~ 1년 이상
배치 로그3개월 ~ 1년
외부 API 로그3개월 ~ 1년
  • 회사 정책, 개인정보 처리 기준, 비용 상황에 맞게 조정해야 합니다.
  • 민감정보가 포함될 수 있는 로그는 오래 보관할수록 리스크가 커집니다.

✅ 17. CloudWatch Logs 운영 기준

  • AWS에서 운영한다면 CloudWatch Logs를 통해 EC2, 애플리케이션, 배치 로그를 중앙에서 볼 수 있습니다.
  • 하지만 로그를 무제한 보관하면 비용이 계속 증가할 수 있습니다.

➕ 17-1. 확인할 것

  1. 로그 그룹이 서비스별로 나뉘어 있는가?
  2. 로그 보관 기간이 설정되어 있는가?
  3. 에러 로그를 검색할 수 있는가?
  4. 특정 requestId로 흐름을 추적할 수 있는가?
  5. 너무 많은 DEBUG 로그가 쌓이고 있지 않은가?
  6. 민감정보가 전송되고 있지 않은가?
예시:
togethermall-prod-api
togethermall-prod-worker
togethermall-prod-batch
togethermall-prod-nginx
  • 로그 그룹을 역할별로 나누면 문제를 찾기 쉽습니다.

✅ 18. 로그 기반 알림

  • 로그는 저장만 해서는 부족합니다.
  • 중요한 에러나 실패는 알림으로 이어져야 합니다.

➕ 18-1. 알림이 필요한 상황

API 500 에러 급증
외부 API 실패 급증
배치 작업 실패
Webhook 처리 실패
관리자 로그인 실패 반복
RDS 연결 실패
Queue 적체 증가
Export 생성 실패

➕ 18-2. 알림 메시지 예시

[API ERROR] 상담 Export 생성 실패

환경: production
requestId: req_20260704_abcd1234
adminId: 3
path: /api/admin/consults/export
errorCode: DB_TIMEOUT
durationMs: 30000
  • 알림에는 원인 파악에 필요한 정보만 넣어야 합니다.
  • 전화번호, 토큰, Secret 같은 민감정보는 포함하면 안 됩니다.

✅ 19. 관리자 페이지에서 보여주면 좋은 운영 이력

  • 운영 이력은 백엔드에만 있어도 되지만, 관리자 페이지에서 볼 수 있으면 운영 효율이 크게 올라갑니다.

➕ 19-1. 추천 메뉴

관리자 작업 이력
엑셀 다운로드 이력
알림톡/SMS 발송 이력
Webhook 수신 이력
배치 작업 이력
로그인/보안 이력
Export 생성 이력

➕ 19-2. 필터 조건

  • 관리자
  • 작업 종류
  • 리소스 종류
  • 리소스 ID
  • 상태
  • 기간
  • IP
  • 실패 여부
예시:
2026-07-01 ~ 2026-07-04
action=CONSULT_EXPORT_REQUESTED
adminId=3
status=SUCCESS
  • 로그/이력 화면은 처음에는 단순 목록으로 시작해도 됩니다.
  • 중요한 것은 “나중에 문제가 생겼을 때 찾을 수 있는가?”입니다.

✅ 20. 로그 설계에서 자주 하는 실수

➕ 20-1. 로그를 전혀 남기지 않음

문제 발생:
상담 상태가 바뀜

확인 불가:
누가 바꿨는지
언제 바꿨는지
이전 상태가 무엇이었는지
  • 이런 구조는 운영이 커질수록 위험합니다.

➕ 20-2. 로그에 민감정보를 그대로 남김

console.log(dto)
console.log(headers)
console.log(token)
console.log(apiKey)
  • 개발 중에는 편하지만 운영에서는 큰 보안 사고로 이어질 수 있습니다.

➕ 20-3. 로그가 너무 많아서 못 찾음

  • 모든 값을 DEBUG로 쏟아내면 중요한 로그를 찾기 어렵습니다.
  • 비용도 증가합니다.
매 요청마다 전체 body 출력
매 DB 조회마다 전체 결과 출력
외부 API 응답 전체 저장
  • 로그는 많다고 좋은 것이 아니라, 필요한 정보를 구조화해서 남기는 것이 중요합니다.

➕ 20-4. 파일 로그에만 의존

  • EC2가 재생성되거나 로그 파일이 삭제되면 이력이 사라질 수 있습니다.
  • 중요한 운영 이력은 DB나 중앙 로그 시스템에 남겨야 합니다.

✅ 21. 실무 체크리스트

➕ 21-1. 로그 설계 체크리스트

  1. API 요청 로그를 남기는가?
  2. 에러 로그를 공통으로 처리하는가?
  3. 요청 처리 시간을 기록하는가?
  4. requestId로 요청 흐름을 추적할 수 있는가?
  5. 관리자 작업 이력을 DB에 저장하는가?
  6. 외부 API 호출 결과를 저장하는가?
  7. 배치 작업 성공/실패 이력을 저장하는가?
  8. 보안 이벤트를 별도로 기록하는가?

➕ 21-2. 보안 체크리스트

  1. 비밀번호, 토큰, Secret이 로그에 남지 않는가?
  2. 전화번호와 이름은 필요한 경우 마스킹하는가?
  3. 외부 API request/response payload를 그대로 저장하지 않는가?
  4. 로그 접근 권한이 제한되어 있는가?
  5. 로그 보관 기간이 정해져 있는가?
  6. 오래된 로그 삭제 또는 보관 정책이 있는가?
  7. 알림 메시지에 민감정보가 포함되지 않는가?

➕ 21-3. 운영 이력 체크리스트

  1. 상담 상태 변경 이력이 남는가?
  2. 주문 상태 변경 이력이 남는가?
  3. 상품/배너 수정 이력이 남는가?
  4. 엑셀 다운로드 이력이 남는가?
  5. 관리자 권한 변경 이력이 남는가?
  6. 실패 알림톡/SMS 이력을 확인할 수 있는가?
  7. Webhook 실패 이력을 확인하고 재처리할 수 있는가?
  8. 배치 실패를 확인할 수 있는가?

✅ 22. AI를 활용해 로그/감사 이력을 설계할 때 질문법

  • 로그 설계는 단순히 console.log를 어디에 넣을지 묻는 문제가 아닙니다.
  • 어떤 로그는 파일/CloudWatch에 남기고, 어떤 이력은 DB에 남겨야 하는지 구분해야 합니다.

➕ 22-1. 좋은 질문 예시

NestJS + Prisma + AWS 기반 관리자 서비스에서 로그와 감사 이력 구조를 설계하고 싶어.

상황:
1. 관리자 페이지에는 상담 관리, 주문 관리, 상품 관리, 배너 관리, 엑셀 다운로드 기능이 있음
2. 상담 상태 변경, 주문 상태 변경, 상품 수정, 배너 수정은 이력을 남겨야 함
3. 엑셀 다운로드에는 개인정보가 포함될 수 있어 다운로드 이력이 필요함
4. 알림톡/SMS 외부 API 발송 성공/실패 이력을 남기고 싶음
5. Webhook 수신과 배치 작업 성공/실패도 추적하고 싶음
6. AWS에서는 CloudWatch Logs를 사용할 예정
7. 로그에 전화번호, 토큰, API Key 같은 민감정보는 남기면 안 됨
8. requestId로 요청 흐름을 추적하고 싶음

요청:
- 로그 종류별 저장 위치
- AdminActionLog 모델
- ExternalApiLog 모델
- BatchJobLog 모델
- SecurityLog 모델
- NestJS Interceptor/Filter 구조
- 개인정보 마스킹 기준
- CloudWatch Logs 운영 기준
- 관리자 페이지에서 보여줄 이력 메뉴
를 실무 기준으로 설명해줘.

➕ 22-2. AI 답변 검증 기준

  1. 일반 로그와 감사 로그를 구분하는가?
  2. 관리자 작업 이력은 DB 저장을 권장하는가?
  3. API 요청/에러 로그는 중앙 로그 시스템이나 CloudWatch를 고려하는가?
  4. 외부 API, Webhook, 배치 로그를 별도로 설계하는가?
  5. requestId 또는 correlationId를 설명하는가?
  6. 비밀번호, 토큰, API Key, 전화번호 로그 노출을 금지하는가?
  7. 로그 보관 기간과 비용을 고려하는가?
  8. 관리자 페이지에서 검색 가능한 운영 이력 구조를 제안하는가?

📌 요약

  • 로그는 서비스에서 어떤 일이 발생했는지 기록하는 데이터이며, 장애 분석, 운영 추적, 보안 감시, 외부 API 실패 확인에 필요합니다.
  • 일반 애플리케이션 로그와 관리자 감사 로그는 목적이 다르므로 구분해서 설계해야 합니다.
  • API 요청 로그, 에러 로그, 관리자 작업 로그, 외부 API 로그, Webhook 로그, 배치 로그, 보안 로그를 목적별로 나누는 것이 좋습니다.
  • 관리자 작업 이력, 엑셀 다운로드 이력, 외부 API 발송 이력처럼 운영자가 나중에 검색해야 하는 데이터는 DB 테이블로 남기는 것이 유리합니다.
  • 요청 흐름을 추적하려면 requestId 또는 correlationId를 사용해 API, Queue, Worker, 외부 API 로그를 연결해야 합니다.
  • 로그에는 비밀번호, JWT, Refresh Token, API Key, Secret, 인증번호, 전체 전화번호 같은 민감정보를 남기면 안 됩니다.
  • AWS 운영에서는 CloudWatch Logs를 활용하되, 로그 보관 기간과 DEBUG 로그 양을 관리해야 비용이 커지지 않습니다.
  • 중요한 장애, 배치 실패, 외부 API 실패 급증, Webhook 실패는 로그 저장에 그치지 말고 알림으로 연결하는 것이 좋습니다.

0개의 댓글