Go에서 구조체 필드 유효성 검사 기법

Go 언어에서 구조체 데이터의 무결성을 보장하기 위해 github.com/go-playground/validator 라이브러리를 활용할 수 있습니다. 이 라이브러리는 다양한 타입과 조건에 맞는 필드 검증 규칙을 제공하며, 개발자는 간단한 태그로 복잡한 검증 로직을 구현할 수 있습니다.

기본 검증 규칙

  • 길이 제약: 문자열, 슬라이스, 배열, 맵의 길이를 제한합니다. 예: len=10, min=6, max=10, gt=10
  • 값 범위 제약: 숫자형 필드의 최소/최대 값을 지정합니다. 예: min=1, max=100, eq=5, oneof=6 8
  • 비교 연산: eq, ne, gt, gte, lt, lte 등으로 값 비교 가능

네트워크 관련 검증

IP 주소, 도메인, 포트, 메일 주소 등 네트워크 형식에 맞는 데이터를 검증할 수 있습니다.

  • email: 표준 이메일 형식
  • ip, ipv4, ipv6: IP 주소 형식
  • hostname, fqdn: 호스트명 또는 완전한 도메인 이름
  • url, uri: URL 또는 리소스 식별자
  • mac: MAC 주소 형식
  • cidr, cidrv4, cidrv6: CIDR 네트워크 표현

문자열 검증

문자열의 구성 요소와 패턴을 확인하는 데 사용됩니다.

  • alpha: 알파벳만 포함
  • alphanum: 영문자와 숫자만 허용
  • contains=abc: 특정 문자열 포함 여부
  • startswith=hello: 특정 접두사로 시작하는지
  • excludesall=xyz: 주어진 문자들 중 하나도 포함하지 않음
  • lowercase, uppercase: 소문자 또는 대문자만 허용
  • numeric: 숫자만 포함

특수 형식 검증

JSON, UUID, ISBN, SSN, 통화 코드, 시간대, 날짜 등 전문적인 형식을 검증합니다.

  • uuid, uuid4: UUID 형식
  • isbn10, isbn13: 국제 표준 서적 번호
  • ssn: 미국 사회보장번호
  • semver: Semantic Versioning 형식 (예: 2.0.0)
  • json, jwt: JSON 또는 JWT 토큰 형식
  • latitude, longitude: 위도/경도
  • hexcolor: #RRGGBB 형식 색상 코드
  • rgb, rgba: RGB 색상 표현

필드 간 상관관계 검증

다른 필드와의 관계를 기반으로 검증이 가능합니다.

  • eqfield=AnotherField: 현재 필드가 다른 필드와 동일해야 함
  • gtfield=OtherField: 현재 필드가 다른 필드보다 커야 함
  • required_if=Field=value: 특정 필드가 특정 값일 때 해당 필드가 필요함
  • excluded_with=Field: 다른 필드가 존재하면 본 필드는 없어야 함
  • unique: 슬라이스나 맵 내 중복 요소 없음
  • unique=Name: 구조체 슬라이스에서 특정 필드(예: Name) 중복 없음

기본 사용 예제

type Registration struct {
    Username string `validate:"min=3,max=20"`
    Password string `validate:"min=8,max=32,containsany=1234567890"`
    Confirm  string `validate:"eqfield=Password"`
    Email    string `validate:"email"`
}

func validateRegistration() error {
    v := validator.New()
    reg := Registration{
        Username: "ab",
        Password: "secret",
        Confirm:  "wrong",
        Email:    "invalid-email",
    }

    err := v.Struct(reg)
    if err != nil {
        if validationErrors, ok := err.(validator.ValidationErrors); ok {
            for _, e := range validationErrors {
                fmt.Printf("%s: %s (%s)\n", e.Field(), e.Tag(), e.Param())
            }
        }
    }
    return err
}

커스텀 검증 함수 등록

기본 규칙 외에 고유한 검증 로직을 추가할 수 있습니다.

func customPattern(fl validator.FieldLevel) bool {
    input := fl.Field().String()
    match, _ := regexp.MatchString(`^user_[a-z]{5,}$`, input)
    return match
}

// 등록
val.RegisterValidation("custom_user", customPattern)

// 사용
Username string `validate:"custom_user"`

중첩 구조체 간 검증

내부 구조체의 필드와 외부 필드를 비교하여 검증할 수 있습니다.

type Profile struct {
    PIN string `validate:"len=4"`
}

type SignupRequest struct {
    Username string `validate:"min=5"`
    Password string `validate:"eqcsfield=Profile.PIN"` // Profile.PIN과 같아야 함
    Profile  Profile
}

검증 결과는 두 가지 유형의 오류로 반환되며, 반드시 타입 단언을 통해 분리 처리해야 합니다:

  • *validator.InvalidValidationError: 잘못된 인자 전달 시 발생
  • validator.ValidationErrors: 실제 검증 실패 항목 목록 (슬라이스)

태그: go validator 구조체 검증 필드 검사 커스텀 검증

8월 16일 02:46에 게시됨