[Go] struct tag 기초: field name mapping, data validation
GoLang Json의 거의 모든 것
[Java/DB] ORM이란? MyBatis와 JPA 비교 및 예제
Custom struct field tags and validate in Golang
데이터 직렬화(serialization)는 무엇이고 왜 필요한가?
MDN: 직렬화 Serialization
CHATGPT
Go 언어로 프로그래밍을 하다보면, 구조체 struct
를 많이 사용하게 된다.
이번에 진행하게 된 HTTP/HTTPS 프로젝트에서 struct tag
를 사용하게 되어, 이에 대해 알아보고자 한다.
Go 언어에서 struct
는 구조체를 정의하는 데 사용된다.
구조체는 여러 필드를 갖는 복합 데이터 타입으로,
각 필드는 서로 다른 타입을 가질 수 있다.
struct tag
는 구조체 필드에 메타데이터를 추가하는 방법이다.
이를 통해 구조체 필드에 대한 추가적인 정보를 제공하거나,
외부 라이브러리에서 이 정보를 활용할 수 있다.
backticks 백틱
(`)으로 감싸서 정의한다.Field tags are part of the struct's field definition
and allow nice and easy way to store meta data
about fields for many use cases
(field mapping, data validation, ORM, etc).
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
}
위 코드에서 json:"name"
, json:"age"
, json:"gender"
는 각각 해당 필드에 대한 JSON 직렬화에서 사용할 키 값을 지정하는 태그이다.
예를 들어, json 패키지를 사용하여 이 구조체를 JSON으로 변환할 때,
Name 필드는 "name", Age 필드는 "age"라는 키로 직렬화된다.
What that means is
when JSON encoder goes over the struct fields,
it will use user-defined field names
instead of default capitalized names.
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
}
func main() {
p := Person{Name: "John", Age: 30, Gender: "Male"}
// 구조체를 JSON으로 직렬화
jsonData, _ := json.Marshal(p)
fmt.Println(string(jsonData))
}
위 코드에서 json:"name"
, json:"age"
, json:"gender"
는 각각 Name, Age, Gender 필드가 JSON으로 직렬화될 때의 키 값이다.
출력 결과는 아래와 같다:
{"name":"John","age":30,"gender":"Male"}
func json.Marshal(v any) ([]byte, error)
: 데이터를 JSON으로 직렬화.
: Marshal returns the JSON encoding of v.
json.Unmarshal(data []byte, v interface{}) error
: JSON 데이터를 구조체로 역직렬화.
1. JSON 직렬화/역직렬화
json
패키지를 사용할 때 자주 사용된다.JSON
키를 매핑할 수 있다.type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
2. Database ORM
ORM
라이브러리에서는 struct
필드를type User struct {
ID int `db:"id"`
Name string `db:"username"`
}
3. XML, YAML 직렬화
4. 기타 메타데이터
위처럼 struct를 정의할 때 field tag를 사용한다.
- field에 대한 메타 데이터를 정의 → marshalling할 때 출력될 필드명 사전 정의
- data validation → 데이터베이스에 값을 적재하기 전에, 의도한 값이 입력 되었는지 검증
field name mapping이란,
해당 struct를 marshalling할 때 해당 필드의 이름을 미리 매핑시켜두는 것을 의미한다.
JSON(JavaScript Object Notation)는
속성-값 쌍의 형식을 가지는 개방형 표준 파일 포맷으로
데이터 교환에 사용 하고 있다.
JSON은 언어 독립적인 데이터 형식이지만
JavaScript 프로그래밍 언어에서 직접 생성하고 읽을 수 있기 때문에, 웹 애플리케이션에서 사용하기에 적합하다.
이런 이유로 특히 웹 애플리케이션에서 널리 사용한다.
1. 특징
2. 기본 문법
{ }
로 감싸고, 키-값 쌍으로 구성된다.[ ]
로 감싸며, 값들의 리스트이다.키는 항상 문자열이어야 하며,
값은 문자열, 숫자, 객체, 배열, true, false, 또는 null일 수 있다.
3. 예시
{
"name": "Alice",
"age": 25,
"isStudent": false,
"skills": ["Python", "Go", "JavaScript"],
"address": {
"city": "Seoul",
"country": "South Korea"
}
}
마샬링(marshalling)은 메모리에 저장된 객체를 다른 시스템에 전송하기에 적합한 데이터 형식으로 변환하는 과정이다.
마샬링된 데이터는 다시 시스템이 쉽게 처리 할 수 있는 객체로 변환해야 하는데, 이를 언마샬링(unmarshalling)이라고 한다.
Marshalling은 데이터를 구조체 또는 객체에서 특정 포맷(JSON, XML 등)으로 변환하는 과정을 말한다.
- Go, Python 등의 프로그램 내 데이터 → JSON/XML 등 텍스트 데이터로 변환하는 것
Unmarshalling은 JSON/XML 등 특정 포맷 데이터를 프로그램 내 구조체 또는 객체로 변환하는 과정이다.
- JSON/XML 등 텍스트 데이터 → Go, Python 등의 프로그램 내 데이터로 변환하는 것
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := Person{Name: "Alice", Age: 25}
// Marshalling: 구조체를 JSON으로 변환
jsonData, err := json.Marshal(p)
if err != nil {
fmt.Println("Error marshalling:", err)
return
}
fmt.Println(string(jsonData)) // 출력: {"name":"Alice","age":25}
}
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
jsonData := `{"name":"Alice","age":25}`
// Unmarshalling: JSON 문자열을 구조체로 변환
var p Person
err := json.Unmarshal([]byte(jsonData), &p)
if err != nil {
fmt.Println("Error unmarshalling:", err)
return
}
fmt.Println(p) // 출력: {Alice 25}
fmt.Println(p.Name) // 출력: Alice
fmt.Println(p.Age) // 출력: 25
}
서버/클라이언트 통신:
서버는 데이터를 JSON으로 직렬화(Marshalling)해서 클라이언트로 전송.
클라이언트는 받은 JSON 데이터를 구조체로 변환(Unmarshalling)해 사용.
파일 입출력:
데이터를 JSON 형식으로 파일에 저장하거나, 파일에서 읽어와 프로그램에서 활용.
API 개발:
REST API의 요청(request)과 응답(response) 데이터 처리에서 필수적으로 사용.