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: 실제 검증 실패 항목 목록 (슬라이스)