ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [golang] 마샬링(Marshaling)
    개발언어/Go 2020. 9. 26. 01:30

    1. 일반적인 관점에서의 마샬링

    참고) 위키백과에서의 Marshaling 정의

    더보기

    컴퓨터 과학에서 마셜링(marshalling, l을 하나만 사용하여 marshaling이라고도 표기)이란 한 객체의 메모리에서 표현방식을 저장 또는 전송에 적합한 다른 데이터 형식으로 변환하는 과정이다. 또한 이는 데이터를 컴퓨터 프로그램의 서로 다른 부분 간에 혹은 한 프로그램에서 다른 프로그램으로 이동해야 할 때도 사용된다. 마셜링은 직렬화(serialization)와 유사하며 한 오브젝트, 여기서는 직렬화 된 오브젝트로 멀리 떨어진 오브젝트와 통신하기 위해 사용된다. 이는 복잡한 통신을 단순화 하기 위해, 기본 요소(primitives) 대신 통신을 위한 맞춤형 오브젝트를 사용한다. 마셜링의 반대 개념으로 언마셜링(unmarshalling)이 있다 (디마셜링-demarshalling-이라고도 불리며, 역직렬화-deserialization-와 유사하다). 

     소프트웨어는 바이트 단위로 데이터를 인식하기때문에, 바이트를 정수로 읽어들일지, 문자로 읽어들일지에 따라 출력되는 값이 달라진다. 예를들어, 메모리에 올려진 100을 정수로 인식하면 그대로 100이 되는것이고, 이것을 문자로 읽으면 'd'라는 문자가 된다. 메모리에 올려진 값을 정수 또는 다른 타입으로 변환하는 과정을 마샬링(Marshaling)이라고 한다.

     

    2. Go에서의 마샬링

     go에서는 보통 정수형이나 구조체같은 타입을 바이트 슬라이스로 변경하는 것을 마샬링이라고 한다. 그리고 이 역할을 encoding/json 패키지의 json.Marshal 함수가 이 역할을 해주며, 함수형은 아래와 같다.

    func Marshal(v interface{}) ([]byte, error)

    위의 Marshal 함수는 interface를 받아서 byte 슬라이스로 변환해준다. 이제 이것을 활용해보자.

    b, _ := json.Marshal(true)
    fmt.Println(b)         // [116 114 117 101]
    fmt.Println(string(b)) // "true"

     위의 코드를 보면 알 수 있듯이 json.Marshal을 통해 true라는 문자가 바이트 슬라이스의 형태로 변환이 된다. 그리고 그 변환된 바이트 슬라이스형을 다시금 문자열로 변형해주면 true라는 값으로 돌아오는 예제이다.

     

    구조체를 마샬링 하는 것도 가능하다. 아래의 예제를 보자.

    type Person struct {
    	Name string
    	Age  int
    }
    
    func main() {
    	var p = Person{"Pikachu", 72}
    	bytes, _ := json.Marshal(p)
    	fmt.Println(bytes)         // [123 34 78 97 109 101 34 ... ]
    	fmt.Println(string(bytes)) // {"Name":"Pikachu","Age":72}
    }

    구조체로 타입을 정의할 때, 태그를 이용하면 프로퍼티 명을 바꿀 수 있다. 즉, Json 형태로 데이터가 나올 때, 나오는 결과값을 변형해서 출력하게 할 수있다. 예제로, JSON키는 보통 소문자로 시작하니까 위의 구조체의 Name, Age의 대문자를 소문자로 변형해서 출력되도록 해보자.

     

    type Person struct {
    	Name string `json:"name"`
    	Age  int    `json:"age"`
    }
    
    func main() {
    	var p = Person{"Pikachu", 72}
    	bytes, _ := json.Marshal(p)
    	fmt.Println(bytes)         // [123 34 78 97 109 101 34 ... ]
    	fmt.Println(string(bytes)) // {"name":"Pikachu","age":72}, Name -> name, Age -> age로 변경됨
    }

     

     위의 방법 이외에도 마샬링의 출력을 제어할 수도 있다. 아래의 예제는 특정 값을 출력하지 않는 예제이다.

    type Person struct {
    	// 미출력
    	Name string `json:"-"`
    	Age int `json:"age"`
    }
    
    func main() {
    	var p = Person{"Pikachu", 72}
    	bytes, _ := json.Marshal(p)
    	fmt.Println(bytes)         // [123 34 78 97 109 101 34 ... ]
    	fmt.Println(string(bytes)) // {"age":72}
    }

     

     물론, 데이터의 가독성을 위해 json.MarshalIndent함수를 통해 indent를 줄 수도 있다. 

    func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

     

    type Person struct {
    	Name string `json:"name"`
    	Age  int    `json:"age"`
    }
    
    func main() {
    	var p = Person{"Pikachu", 72}
    	bytes, _ := json.MarshalIndent(p, "", "  ")
    	fmt.Println(string(bytes))
    }
    

     

    실행결과)

    {
      "name": "Pikachu",
      "age": 72
    }

     

    3. Unmarshaling

    Marshaling의 반대 개념으로 바이트 슬라이스나 문자열을 논리적 자료 구조로 변경하는 것을 언마샬링(Unmashaling)이라고 하며, json.Unmarshal 을 통해 언마샬링을 할 수 있다.

    참고) unmarshal 원형

    func Unmarshal(data []byte, v interface{}) error
    

     

     아래의 예제를 보면 알 수 있듯이, Unmarshal의 첫번째 인자로, byte 슬라이스로 된 값을 주고, 변환된 값을 받을 변수의 주소를 Unmarshal의 인자로 주면 Unmarshal을 할 수 있다.

    var b bool
    json.Unmarshal([]byte("true"), &b)
    fmt.Printf("%t\n", b) // true

     

     위에서 보여주었던 태그를 통해 변환된 값들도 아래의 방법을 사용하면 원래의 값으로 돌려놓을 수 있다.

    func main() {
    	var s = `{"name":"Pikachu","age":72}`
    	var p Person
    	json.Unmarshal([]byte(s), &p)
    	fmt.Printf("%+v\n", p) // {Name:Pikachu Age:72}
    }

    JSON 문자열을 바이트 슬라이스 형태로 넘겨주고 Person 타입 변수 p의 포인터를 전달한다. 함수가 실행되면 문자열이 파싱되어 Person 값이 생성된다.

    '개발언어 > Go' 카테고리의 다른 글

    [Golang] 마이크로서비스 공통패턴  (0) 2020.10.14
    [Golang] RPC API  (0) 2020.10.12
    [Golang] go에서 RPC 다루기  (0) 2020.10.11
    [Golang] net/http 패키지  (0) 2020.09.30
    [golang] 인터페이스(Interface)  (0) 2020.09.24
Designed by Tistory.