---
sidebar_label: "감사 로그"
title: "감사 로그 - CyberGo env | 보안 감사 구성"
description: "CyberGo env 감사 로그 설정 가이드로 JSONAuditHandler·LogAuditHandler·ChannelAuditHandler 핸들러와 커스텀 AuditHandler 로 변수 로딩·읽기·수정·삭제 작업을 기록해 보안 감사와 규정 준수에 활용합니다."
sidebar_position: 5
---

# 감사 로그

감사 로그 기능은 모든 환경 변수 작업을 기록하여 보안 감사, 규정 준수 검사 및 문제 해결에 사용됩니다.

## 감사 활성화

### 구성으로 활성화

```go
cfg := env.ProductionConfig()
cfg.AuditEnabled = true
cfg.AuditHandler = env.NewJSONAuditHandler(os.Stdout)

loader, _ := env.New(cfg)
```

### 구성 프리셋

| 프리셋 | 감사 상태 |
|------|----------|
| `DefaultConfig()` | 비활성화 |
| `DevelopmentConfig()` | 비활성화 |
| `TestingConfig()` | 비활성화 |
| `ProductionConfig()` | 활성화 |

---

## 감사 핸들러

### JSONAuditHandler

JSON 형식 로그 출력:

```go
import (
    "os"
    "github.com/cybergodev/env"
)

cfg := env.ProductionConfig()
cfg.AuditEnabled = true
cfg.AuditHandler = env.NewJSONAuditHandler(os.Stdout)
```

**출력 예시:**

```json
{"timestamp":"2024-01-15T10:30:00Z","action":"load","file":".env","success":true,"duration_ns":1234567}
{"timestamp":"2024-01-15T10:30:01Z","action":"set","key":"[MASKED:7 chars]","success":true,"masked":true}
{"timestamp":"2024-01-15T10:30:02Z","action":"set","key":"CUSTOM_VAR","success":true}
```

민감한 키 (예: `API_KEY`) 는 감사 로그의 `key` 필드에서 자동으로 `[MASKED:N chars]`(N 은 키 길이) 로 마스킹되며, 민감하지 않은 키 (예: `CUSTOM_VAR`) 는 원래대로 표시됩니다.

---

### LogAuditHandler

표준 log 패키지 사용 출력:

```go
import (
    "log"
    "os"
    "github.com/cybergodev/env"
)

logger := log.New(os.Stderr, "[AUDIT] ", log.LstdFlags)
cfg.AuditHandler = env.NewLogAuditHandler(logger)
```

**출력 예시:**

```text
[AUDIT] 2024/01/15 10:30:00 action=load success=true reason="" file=.env duration=1.23ms
[AUDIT] 2024/01/15 10:30:01 action=set key=[MASKED:7 chars] success=true reason=""
[AUDIT] 2024/01/15 10:30:02 action=set key=CUSTOM_VAR success=true reason=""
```

---

### ChannelAuditHandler

채널로 비동기 처리:

```go
ch := make(chan env.AuditEvent, 100)
cfg.AuditHandler = env.NewChannelAuditHandler(ch)

// 비동기 감사 이벤트 처리
go func() {
    for event := range ch {
        processAuditEvent(event)
    }
}()
```

**사용 시나리오:**
- 원격 로그 서비스 전송
- 데이터베이스 기록
- 실시간 모니터링 알림

---

### NopAuditHandler

아무 작업도 수행하지 않는 핸들러, 모든 이벤트 폐기:

```go
cfg.AuditHandler = env.NewNopAuditHandler()
```

**사용 시나리오:**
- 일시적으로 감사 비활성화
- 테스트 환경

---

## 감사 이벤트

### AuditEvent 구조체

```go
type AuditEvent struct {
    Timestamp time.Time   // 타임스탬프
    Action    AuditAction // 작업 유형
    Key       string      // 키 이름
    File      string      // 파일 이름
    Reason    string      // 사유
    Success   bool        // 성공 여부
    Masked    bool        // 마스킹 여부
    Details   string      // 상세 정보
    Duration  int64       // 소요 시간 (나노초)
}
```

### AuditAction 작업 유형

| 상수 | 값 | 설명 |
|------|---|------|
| `ActionLoad` | `load` | 파일 로딩 |
| `ActionParse` | `parse` | 파싱 작업 |
| `ActionGet` | `get` | 변수 읽기 |
| `ActionSet` | `set` | 변수 설정 |
| `ActionDelete` | `delete` | 변수 삭제 |
| `ActionValidate` | `validate` | 검증 작업 |
| `ActionExpand` | `expand` | 변수 확장 |
| `ActionSecurity` | `security` | 보안 이벤트 |
| `ActionError` | `error` | 오류 이벤트 |
| `ActionFileAccess` | `file_access` | 파일 접근 |

---

## 커스텀 핸들러

### FullAuditLogger 인터페이스 구현

`FullAuditLogger`는 최소 인터페이스 `AuditLogger`(LogError 메서드만 포함) 를 확장한 완전한 감사 로그 인터페이스입니다:

```go
type FullAuditLogger interface {
    AuditLogger  // 최소 인터페이스 임베딩 (LogError)
    Log(action AuditAction, key, reason string, success bool) error
    LogWithFile(action AuditAction, key, file, reason string, success bool) error
    LogWithDuration(action AuditAction, key, reason string, success bool, duration time.Duration) error
    Close() error
}
```

### 예시: 데이터베이스 감사 핸들러

```go
package myhandler

import (
    "database/sql"
    "time"
    "github.com/cybergodev/env"
)

type DatabaseAuditHandler struct {
    db *sql.DB
}

func NewDatabaseAuditHandler(db *sql.DB) *DatabaseAuditHandler {
    return &DatabaseAuditHandler{db: db}
}

func (h *DatabaseAuditHandler) Log(action env.AuditAction, key, reason string, success bool) error {
    _, err := h.db.Exec(`
        INSERT INTO audit_log (timestamp, action, key, reason, success)
        VALUES (?, ?, ?, ?, ?)
    `, time.Now(), string(action), key, reason, success)
    return err
}

func (h *DatabaseAuditHandler) LogError(action env.AuditAction, key, errMsg string) error {
    return h.Log(action, key, errMsg, false)
}

func (h *DatabaseAuditHandler) LogWithFile(action env.AuditAction, key, file, reason string, success bool) error {
    _, err := h.db.Exec(`
        INSERT INTO audit_log (timestamp, action, key, file, reason, success)
        VALUES (?, ?, ?, ?, ?, ?)
    `, time.Now(), string(action), key, file, reason, success)
    return err
}

func (h *DatabaseAuditHandler) LogWithDuration(action env.AuditAction, key, reason string, success bool, duration time.Duration) error {
    _, err := h.db.Exec(`
        INSERT INTO audit_log (timestamp, action, key, reason, success, duration_ms)
        VALUES (?, ?, ?, ?, ?, ?)
    `, time.Now(), string(action), key, reason, success, duration.Milliseconds())
    return err
}

func (h *DatabaseAuditHandler) Close() error {
    return nil
}
```

---

## 전체 예시

### 프로덕션 환경 구성

```go
package main

import (
    "log"
    "os"
    "github.com/cybergodev/env"
)

func main() {
    // 감사 로그 파일 생성
    auditFile, err := os.OpenFile("/var/log/app/env-audit.log",
        os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
    if err != nil {
        log.Fatal(err)
    }
    defer auditFile.Close()

    // 구성
    cfg := env.ProductionConfig()
    cfg.AuditEnabled = true
    cfg.AuditHandler = env.NewJSONAuditHandler(auditFile)
    cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}

    // 로더 생성
    loader, err := env.New(cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer loader.Close()

    // 설정 로딩
    err = loader.LoadFiles(".env")
    if err != nil {
        log.Fatal(err)
    }

    // 검증
    err = loader.Validate()
    if err != nil {
        log.Fatal(err)
    }

    // 설정 사용
    log.Println("Configuration loaded successfully")
}
```

### 비동기 감사 처리

```go
package main

import (
    "encoding/json"
    "log"
    "os"
    "github.com/cybergodev/env"
)

func main() {
    // 감사 이벤트 채널 생성
    auditChan := make(chan env.AuditEvent, 1000)

    // 비동기 프로세서 시작
    go processAuditEvents(auditChan)

    // 구성
    cfg := env.ProductionConfig()
    cfg.AuditEnabled = true
    cfg.AuditHandler = env.NewChannelAuditHandler(auditChan)

    loader, _ := env.New(cfg)
    defer loader.Close()

    // 정상 사용...
}

func processAuditEvents(ch chan env.AuditEvent) {
    file, _ := os.OpenFile("/var/log/app/audit.log",
        os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
    defer file.Close()

    encoder := json.NewEncoder(file)

    for event := range ch {
        // 필터링, 집계 등 로직 추가 가능
        if event.Action == env.ActionError {
            log.Printf("Audit error: %+v", event)
        }

        encoder.Encode(event)
    }
}
```

---

## 보안 주의 사항

### 감사 기록과 마스킹

감사 로그는 민감한 키의 `key` 필드를 자동으로 마스킹합니다 (기본적으로 `[MASKED:N chars]`로 표시, N 은 키 이름의 문자 수. 민감하지 않은 키는 원래대로 표시). **쓰기 작업만 감사 이벤트를 기록합니다**: `Set` / `Delete` / `LoadFiles` 등은 `ActionSet` / `ActionDelete` / `ActionLoad` 등의 이벤트를 트리거하며, 이벤트에 마스킹된 키 이름을 기록합니다.

읽기 작업은 감사를 생성하지 않습니다: `Get` / `GetString` / `GetInt` / `GetSecure` 등의 **정상적인 읽기는 감사 로그를 기록하지 않습니다**. `ActionGet` 이벤트는 `GetInt` / `GetBool` / `GetFloat64` 등의 타입 변환 **파싱 실패** 오류 경로에서만 트리거됩니다 (`success=false`). 예:

```go
// 쓰기 작업: 감사 이벤트 기록 (민감한 키는 마스킹 후 기록)
_ = loader.Set("API_KEY", "sk-1234567890")
// 감사 기록: {"action":"set","key":"[MASKED:7 chars]","success":true,"masked":true}

// 읽기 작업: 정상 읽기는 감사 미생성
secret := loader.GetSecure("API_KEY") // 감사 로그 미생성
_ = loader.GetInt("PORT")             // 파싱 성공, 감사 로그 미생성
_ = loader.GetInt("API_KEY")          // 파싱 실패 시 ActionGet 이벤트 생성 (success=false)
```

### 감사 로그 권한

```bash
# 감사 로그 파일 권한 설정
chmod 600 /var/log/app/env-audit.log

# 애플리케이션 사용자만 읽기/쓰기 가능하도록 설정
chown app:app /var/log/app/env-audit.log
```

### 로그 순환

logrotate 를 사용하여 감사 로그를 관리하는 것이 좋습니다:

```bash
# /etc/logrotate.d/app-env-audit
/var/log/app/env-audit.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0600 app app
}
```

---

## 관련 문서

- [보안 개요](/ko/env/security/) - 보안 아키텍처 및 핵심 기능
- [프로덕션 체크리스트](/ko/env/security/production-checklist) - 감사 구성 확인
- [인터페이스 정의](/ko/env/api-reference/interfaces) - AuditLogger 인터페이스
- [컴포넌트 팩토리](/ko/env/api-reference/factory) - 감사 핸들러 팩토리
