GoLang_Struct Tag & JSON & Marshalling

wldbs._.·2024년 12월 6일
1

HTTP & Go

목록 보기
1/5
post-thumbnail

[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를 사용하게 되어, 이에 대해 알아보고자 한다.


1. struct tag란?

Go 언어에서 struct는 구조체를 정의하는 데 사용된다.

구조체는 여러 필드를 갖는 복합 데이터 타입으로,
각 필드는 서로 다른 타입을 가질 수 있다.

struct tag구조체 필드에 메타데이터를 추가하는 방법이다.
이를 통해 구조체 필드에 대한 추가적인 정보를 제공하거나,
외부 라이브러리에서 이 정보를 활용할 수 있다.

  • 구조체 태그의 형식
    : 구조체 태그는 구조체 필드에 직접 붙여지는 문자열로, backticks 백틱(`)으로 감싸서 정의한다.
    일반적으로 이 태그는 key:"value" 형식을 따른다.

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).


1-1. 예시

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-2. 제한 사항

  • 태그의 값은 문자열로만 사용
  • 여러 개의 태그를 한 필드에 정의할 수 있으며, 각 태그는 공백으로 구분
  • 태그의 키는 대소문자를 구분
  • 태그는 주로 외부 라이브러리에서 동작을 정의하기 위해 사용되므로, 기본 Go 언어 기능에서는 직접적으로 활용되지는 않음

1-3. 주요 용도

1. JSON 직렬화/역직렬화

  • json 패키지를 사용할 때 자주 사용된다.
    필드 이름JSON 를 매핑할 수 있다.
type Person struct {
    Name   string `json:"name"`
    Age    int    `json:"age"`
}

2. Database ORM

  • Object Relational Mapping 객체 관계 매핑
    : 객체(Object)와 DB의 테이블을 자동으로 연결(Mapping)시켜 RDB 테이블을 객체 지향적으로 사용하게 해주는 기술
  • ORM 라이브러리에서는 struct 필드를
    데이터베이스의 컬럼 이름과 매핑하기 위해 태그를 사용한다.
type User struct {
    ID   int    `db:"id"`
    Name string `db:"username"`
}

3. XML, YAML 직렬화

  • 다른 직렬화 포맷 (XML, YAML 등)에서 구조체 필드와 태그를 사용하여 매핑

4. 기타 메타데이터

  • 특정 라이브러리나 기능에서 구조체 필드를 동적으로 처리하기 위해 사용

위처럼 struct를 정의할 때 field tag를 사용한다.

  • field에 대한 메타 데이터를 정의 → marshalling할 때 출력될 필드명 사전 정의
  • data validation → 데이터베이스에 값을 적재하기 전에, 의도한 값이 입력 되었는지 검증

+ field name mapping

field name mapping이란,
해당 struct를 marshalling할 때 해당 필드의 이름을 미리 매핑시켜두는 것을 의미한다.


2. JSON

JSON(JavaScript Object Notation)
속성-값 쌍의 형식을 가지는 개방형 표준 파일 포맷으로
데이터 교환에 사용 하고 있다.

JSON은 언어 독립적인 데이터 형식이지만
JavaScript 프로그래밍 언어에서 직접 생성하고 읽을 수 있기 때문에, 웹 애플리케이션에서 사용하기에 적합하다.

이런 이유로 특히 웹 애플리케이션에서 널리 사용한다.

1. 특징

  • 텍스트 형식: JSON 데이터는 텍스트 기반으로, 대부분의 프로그래밍 언어에서 쉽게 처리할 수 있다.
  • 키-값 쌍 구조: 데이터는 키(Key)와 값(Value)의 쌍으로 표현된다.
  • 언어 독립적: JSON은 특정 프로그래밍 언어에 종속되지 않으며, 다양한 언어에서 지원된다.

2. 기본 문법

  • 객체(Object): { }로 감싸고, 키-값 쌍으로 구성된다.
  • 배열(Array): [ ]로 감싸며, 값들의 리스트이다.

키는 항상 문자열이어야 하며,
값은 문자열, 숫자, 객체, 배열, true, false, 또는 null일 수 있다.

3. 예시

{
  "name": "Alice",
  "age": 25,
  "isStudent": false,
  "skills": ["Python", "Go", "JavaScript"],
  "address": {
    "city": "Seoul",
    "country": "South Korea"
  }
}
  • "name": "Alice" → 키는 name, 값은 "Alice"라는 문자열
  • "age": 25 → 숫자 값
  • "isStudent": false → Boolean 값
  • "skills": ["Python", "Go", "JavaScript"] → 배열
  • "address": {...} → 또 다른 객체로 중첩

3. Marshalling

마샬링(marshalling)은 메모리에 저장된 객체를 다른 시스템에 전송하기에 적합한 데이터 형식으로 변환하는 과정이다.

마샬링된 데이터는 다시 시스템이 쉽게 처리 할 수 있는 객체로 변환해야 하는데, 이를 언마샬링(unmarshalling)이라고 한다.

Marshalling은 데이터를 구조체 또는 객체에서 특정 포맷(JSON, XML 등)으로 변환하는 과정을 말한다.

  • Go, Python 등의 프로그램 내 데이터 → JSON/XML 등 텍스트 데이터로 변환하는 것

Unmarshalling은 JSON/XML 등 특정 포맷 데이터를 프로그램 내 구조체 또는 객체로 변환하는 과정이다.

  • JSON/XML 등 텍스트 데이터 → Go, Python 등의 프로그램 내 데이터로 변환하는 것


3-1. 예제

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}
}
  • 구조체 Person을 JSON 문자열로 변환(Marshal 함수 사용).
  • 결과: {"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 문자열을 Go의 구조체로 변환(Unmarshal 함수 사용).
  • JSON 데이터를 파싱해 Person 구조체로 저장.

3-2. 활용

  1. 서버/클라이언트 통신:
    서버는 데이터를 JSON으로 직렬화(Marshalling)해서 클라이언트로 전송.
    클라이언트는 받은 JSON 데이터를 구조체로 변환(Unmarshalling)해 사용.

  2. 파일 입출력:
    데이터를 JSON 형식으로 파일에 저장하거나, 파일에서 읽어와 프로그램에서 활용.

  3. API 개발:
    REST API의 요청(request)과 응답(response) 데이터 처리에서 필수적으로 사용.

profile
공부 기록용 24.08.05~ #LLM #RAG

0개의 댓글