Field Validation
DD의 field validation 서브시스템은 로그 쓰기 전에 구조화된 Field의 키 이름을 검증하여 이름 규칙을 강제하고 보안 보호를 제공합니다. 이는 일관되지 않은 키로 인한 로그 파싱 어려움을 방지하고, Field 키를 통해 주입된 악성 콘텐츠를 차단합니다.
검증 모드
| 모드 | 상수 | 동작 |
|---|---|---|
| 끄기 (기본값) | FieldValidationNone | 검증 안 함; 모든 키 허용 |
| 경고 | FieldValidationWarn | 규칙에 맞지 않는 키가 stderr 경고 출력; 로그는 여전히 기록됨 |
| 엄격 | FieldValidationStrict | 규칙에 맞지 않는 키가 stderr 에러 출력; 로그는 여전히 기록됨 |
경고 로깅 메서드는 에러를 반환하지 않습니다
로깅 메서드(InfoWith 등)는 에러를 반환하지 않으므로, 검증 실패는 stderr로만 보고될 수 있습니다. 엄격 모드는 로그가 기록되는 것을 방지하지 않지만 stderr에 에러를 명확히 보고합니다.
이름 규칙
| 규칙 | 상수 | 예시 |
|---|---|---|
| 모두 (기본값) | NamingConventionAny | 스타일 검사 없음 |
| snake_case | NamingConventionSnakeCase | user_id, created_at |
| camelCase | NamingConventionCamelCase | userId, createdAt |
| PascalCase | NamingConventionPascalCase | UserId, CreatedAt |
| kebab-case | NamingConventionKebabCase | user-id, created-at |
빠른 시작
옵션 A: 프리셋 Config
package main
import (
"log"
"github.com/cybergodev/dd"
)
func main() {
cfg := dd.DefaultConfig()
cfg.FieldValidation = dd.StrictSnakeCaseConfig()
// 다음과 동일:
// &dd.FieldValidationConfig{
// Mode: dd.FieldValidationStrict,
// Convention: dd.NamingConventionSnakeCase,
// AllowCommonAbbreviations: true,
// EnableSecurityValidation: true,
// }
logger, err := dd.New(cfg)
if err != nil {
log.Fatal(err)
}
defer logger.Close()
logger.InfoWith("user action",
dd.String("user_id", "123"), // ✅ 유효한 snake_case
dd.String("userName", "alice"), // ⚠️ 유효하지 않음, stderr 에러
)
}옵션 B: 커스텀 Config
cfg := dd.DefaultConfig()
cfg.FieldValidation = &dd.FieldValidationConfig{
Mode: dd.FieldValidationWarn,
Convention: dd.NamingConventionCamelCase,
AllowCommonAbbreviations: true,
EnableSecurityValidation: true,
}옵션 C: 런타임 토글
// 엄격한 snake_case 활성화
logger.SetFieldValidation(dd.StrictSnakeCaseConfig())
// 검증 비활성화
logger.SetFieldValidation(nil)
// 현재 config 조회
fv := logger.GetFieldValidation()일반 약어 예외
AllowCommonAbbreviations: true(프리셋 기본값)를 사용하면, 다음 약어는 이름 규칙과 엄격하게 일치하지 않더라도 허용됩니다:
| 약어 | 설명 |
|---|---|
id, url, uri, ip | 기본 식별자 |
http, https, api | 프로토콜 및 인터페이스 |
json, xml, html, sql | 데이터 형식 |
tcp, udp, ssl, tls | 네트워크 프로토콜 |
jwt, oauth | 인증 |
*_id, *_url, *_api 등 | 접미사 조합 (예: user_id) |
보안 검증
EnableSecurityValidation: true(프리셋 기본값)는 이름 규칙 검증 전에 다음 보안 검사를 실행합니다:
| 검사 | 차단 콘텐츠 | 설명 |
|---|---|---|
| Log4Shell 감지 | ${jndi:ldap://...} | 로그 키를 통한 JNDI 주입 방지 |
| 동형이의어 감지 | 키릴 문자 а가 라틴 a를 대체 | 시각적 스푸핑 공격 방지 |
| 과장된 UTF-8 인코딩 | 비최단 형식 인코딩 | 보안 필터 우회 방지 |
위험 제로 값 함정
EnableSecurityValidation을 설정하지 않고 &dd.FieldValidationConfig{Mode: dd.FieldValidationStrict}를 사용하면 false(제로 값)가 되어 보안 검사를 자동으로 건너뜁니다. 항상 DefaultFieldValidationConfig() 또는 이 Field를 true로 설정하는 프리셋 함수(StrictSnakeCaseConfig() 등)를 사용하십시오.
다중 규칙 프로젝트
프로젝트에 Go 백엔드(snake_case)와 JavaScript 프론트엔드(camelCase) 로깅이 모두 있는 경우, 다른 규칙을 가진 다른 Logger를 사용하십시오:
// 백엔드 Logger: snake_case
backendCfg := dd.DefaultConfig()
backendCfg.FieldValidation = dd.StrictSnakeCaseConfig()
backendLogger, _ := dd.New(backendCfg)
// 프론트엔드 로그 수집 Logger: camelCase
frontendCfg := dd.DefaultConfig()
frontendCfg.FieldValidation = dd.StrictCamelCaseConfig()
frontendLogger, _ := dd.New(frontendCfg)검증 규칙
각 이름 규칙에 대한 구체적인 규칙:
| 규칙 | 규칙 |
|---|---|
| snake_case | 소문자 + 숫자 + 밑줄; 선행/후행 _ 없음; 연속된 __ 없음 |
| camelCase | 문자 + 숫자; 첫 글자는 소문자 |
| PascalCase | 문자 + 숫자; 첫 글자는 대문자 |
| kebab-case | 소문자 + 숫자 + 하이픈; 선행/후행 - 없음; 연속된 -- 없음 |
다음 단계
- 구조화된 로깅 -- Field 생성자 및 체이닝
- Configuration -- 전체 Config Field 참조
- 보안 개요 -- 전체 보안 기능 개요