[Go 공식문서 한국어 정리] ⓪14. Go 리플렉션의 법칙
[Go 공식문서 한국어 정리] ⓪14. Go 리플렉션의 법칙
원문 제목: The Laws of Reflection
작성자: Rob Pike
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 1. 서론 — 이 문서가 다루는 내용
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
리플렉션(Reflection)은 프로그램이 자신의 구조, 특히 타입을 검사할 수 있는 능력입니다.
Go에서 리플렉션은 강력하면서도 혼란스러운 주제입니다.
이 문서는 Go 리플렉션의 세 가지 법칙을 설명합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 2. 핵심 개념
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
① 인터페이스 값에서 리플렉션 객체로
reflect.TypeOf와 reflect.ValueOf는 인터페이스 값에서 타입과 값 정보를 추출합니다.
모든 값은 빈 인터페이스(interface{})로 전달된 후 리플렉션 패키지가 낶부 정보를 복원합니다.
② 리플렉션 객체에서 인터페이스 값으로
reflect.Value.Interface()는 리플렉션 객체를 다시 인터페이스 값으로 변환합니다.
이는 ValueOf의 역함수이며, 결과는 항상 interface{} 타입입니다.
③ 수정하려면 값이 설정 가능(settable)해야 함
리플렉션 객체로 원본 값을 수정하려면 원본의 주소를 전달해야 합니다.
값의 복사본으로 만든 리플렉션 객체는 수정할 수 없습니다(CanSet() == false).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 3. 주요 내용 상세
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Go는 정적 타입 언어입니다. 모든 변수는 컴파일 시점에 고정된 타입을 가집니다.
type MyInt int와 var i int, var j MyInt는 서로 다른 타입입니다.
인터페이스 변수는 구체 값과 타입 설명자의 쌍을 저장합니다.
var r io.Reader = tty가 있을 때, r은 (tty, *os.File) 쌍을 저장합니다.
인터페이스가 제공하는 메서드(Read)만 접근 가능하지만,
낶부 값은 전체 타입 정보를 가지고 있습니다.
타입 어설션을 통해 더 많은 메서드에 접근할 수 있습니다:
var w io.Writer = r.(io.Writer)
빈 인터페이스(interface{} 또는 any)는 모든 값을 저장할 수 있습니다.
어떤 구체 값이든 그 값의 타입 정보를 모두 포함하고 있습니다.
리플렉션의 첫 번째 법칙:
reflect.TypeOf(x)는 x를 빈 인터페이스로 감싼 후 타입 정보를 추출합니다.
reflect.ValueOf(x)는 값 정보를 추출합니다.
Value.Kind()는 기본 타입을 반환합니다(int, float64, slice 등).
사용자 정의 타입 MyInt의 Kind는 reflect.Int입니다.
Type은 MyInt를 구분할 수 있지만 Kind는 기본 타입만 반환합니다.
Value.Int(), Value.Float() 등으로 값을 읽을 수 있습니다.
getter/setter는 가장 큰 타입에서 동작합니다(int64, uint64, float64).
리플렉션의 두 번째 법칙:
v.Interface()는 인터페이스 값을 복원합니다.
fmt.Println(v.Interface())로 원래 값을 출력할 수 있습니다.
리플렉션의 세 번째 법칙:
v.SetFloat(7.1)은 v가 settable하지 않으면 패닉을 일으킵니다.
settability는 리플렉션 객체가 원본 항목을 보유하는지에 따라 결정됩니다.
var x float64 = 3.4
v := reflect.ValueOf(x) // x의 복사본 전달
v.SetFloat(7.1) // 패닉: unaddressable value
수정하려면 포인터를 전달해야 합니다:
p := reflect.ValueOf(&x) // x의 주소
v := p.Elem() // 포인터가 가리키는 값
v.SetFloat(7.1) // 성공
구조체 필드를 수정하려면 구조체의 주소를 전달해야 합니다:
s := reflect.ValueOf(&t).Elem()
s.Field(0).SetInt(77)
s.Field(1).SetString("Sunset Strip")
필드가 exported(대문자)여야만 settable합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 4. 실전 활용 / 예시
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
JSON/XML 직렬화 라이브러리, ORM, 의존성 주입 프레임워크 등에서 리플렉션을 활용합니다.
하지만 정적 타입 언어의 장점을 해칠 수 있으므로 꼭 필요할 때만 사용해야 합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 5. 정리
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
리플렉션의 세 가지 법칙:
1. 인터페이스 값 → 리플렉션 객체
2. 리플렉션 객체 → 인터페이스 값
3. 수정하려면 settable해야 함
이 법칙을 이해하면 Go의 리플렉션이 훨씬 명확해집니다.
강력한 도구이지만 반드시 필요한 경우에만 신중하게 사용해야 합니다.
📎 출처 링크
https://go.dev/blog/laws-of-reflection
#Go #Golang #reflection #interface #공식문서

오뉴노노 님의 최근 댓글
ㅋㅋㅋㅋㅋ 2019 01.14 잘 읽었습니다 2018 12.30 포인트가 없어서 아직 시작을 못하고있는데요! 글은 잘 읽었습니다! 포인트 쌓고 도전할거에요 2018 12.30