---
title: "고 1.27 미리보기: 제네릭 메서드, JSON v2, 표준 UUID까지 꽤 알찬 릴리스"
published: 2026-08-02T01:35:51.000Z
canonical: https://jeff.news/article/5359
---
# 고 1.27 미리보기: 제네릭 메서드, JSON v2, 표준 UUID까지 꽤 알찬 릴리스

고 1.27은 타입 시스템, 런타임, 표준 라이브러리 쪽 변화가 한꺼번에 들어오는 큰 릴리스다. 제네릭 메서드가 드디어 들어오고, JSON v2가 기본 구현으로 올라오며, UUID 패키지와 포스트 양자 서명, 고루틴 누수 프로파일 같은 실무형 기능도 추가된다.

- 고 1.27의 메인 이벤트는 제네릭 메서드임. 이제 메서드 선언이 receiver의 타입 파라미터와 별개로 자기 타입 파라미터를 가질 수 있음
  - 예전에는 `Box[T]` 같은 제네릭 타입에 `Map`을 붙여도 `Box[int]`를 `Box[string]`으로 바꾸는 메서드를 자연스럽게 만들기 어려웠음
  - 그래서 이런 연산은 타입에 붙은 메서드가 아니라 패키지 레벨 제네릭 함수로 빠지는 경우가 많았는데, 1.27부터는 타입의 API로 더 깔끔하게 표현 가능함
  - 다만 인터페이스에는 아직 타입 파라미터가 붙은 메서드를 선언할 수 없고, 제네릭 메서드로 인터페이스를 만족시키는 것도 안 됨

- 구조체 리터럴도 조금 더 편해짐. 임베디드 구조체에서 승격된 필드(promoted field)를 바로 키로 쓸 수 있음
  - 예전에는 `User{Base: Base{ID: 7}, Name: "Mittens"}`처럼 안쪽 구조체 이름까지 써야 했음
  - 이제는 승격된 `ID`를 구조체 리터럴 키로 직접 넣을 수 있어서, 임베딩을 많이 쓰는 코드에서 잡음이 줄어듦

- 함수 타입 추론도 더 넓게 적용됨. 제네릭 함수를 특정 함수 타입이 기대되는 자리에 넣을 때 타입 인자를 덜 써도 됨
  - 기존에는 단순 변수 할당에서는 추론이 됐지만, 변환이나 복합 리터럴에서는 직접 타입 인자를 적어야 하는 경우가 있었음
  - 1.27에서는 `func([]int) int` 같은 함수 타입이 기대되는 슬라이스에 제네릭 헬퍼를 넣는 상황도 더 자연스럽게 처리됨

> [!IMPORTANT]
> 작은 객체 할당은 일부 케이스에서 최대 30% 빨라짐. 전체 프로그램 기준으로는 할당이 많은 워크로드에서 약 1% 정도 이득이 예상되고, 대가로 바이너리가 약 60KB 커짐.

- 런타임 쪽에서는 크기별 특화 메모리 할당 루틴이 들어감. 코드 수정 없이 그냥 조금 빨라지는 타입의 변화임
  - 대상은 80바이트 미만의 작은 할당 일부고, 워크로드에 따라 개선 폭은 다름
  - 끄고 싶으면 `GOEXPERIMENT=nosizespecializedmalloc`로 빌드할 수 있지만, 이 우회 옵션은 고 1.28에서 제거될 예정임

- traceback에 pprof 고루틴 라벨이 붙는 것도 운영 디버깅에서 꽤 유용함
  - `go.mod`가 고 1.27 이상이면 panic, SIGQUIT, `runtime.Stack` 출력의 각 고루틴 헤더에 `runtime/pprof` 라벨이 표시됨
  - 예를 들어 요청 처리 중 `pprof.Do`로 `{request: 42}` 같은 라벨을 붙였다면, 크래시 덤프에서도 그 맥락이 같이 보임
  - 라벨에 민감한 값이 들어갈 수 있으니 `GODEBUG=tracebacklabels=0`로 끌 수 있고, 이 옵션은 계속 유지될 예정임

- 고루틴 누수 탐지도 실험 기능에서 정식 pprof 프로파일로 올라옴
  - `runtime/pprof`가 `goroutineleak` 프로파일을 제공하고, GC를 한 번 돌려 영원히 막힌 고루틴을 찾아 스택을 보고함
  - 대표적인 누수는 자기만 들고 있는 채널에 send하다가 영원히 block되는 케이스임
  - 실제 서비스에서는 stdout에 찍기보다 `/debug/pprof/goroutineleak` 엔드포인트를 수집하는 방식이 자연스러움

- 보안 쪽에서는 `crypto/mldsa`가 추가됨. FIPS 204의 포스트 양자 디지털 서명 방식인 ML-DSA 구현임
  - 파라미터 세트는 `MLDSA44`, `MLDSA65`, `MLDSA87` 세 가지이고, 보안 수준과 키/서명 크기 사이에서 트레이드오프가 있음
  - `crypto/x509`의 키와 서명, `crypto/tls`의 TLS 1.3 서명 스킴에도 연결됨

- 드디어 표준 라이브러리에 UUID 패키지가 들어옴. 이건 꽤 오래 기다린 사람 많을 듯
  - 새 `uuid` 패키지는 RFC 9562 기준으로 UUID 생성과 파싱을 제공하고, 난수는 암호학적으로 안전한 소스를 씀
  - `uuid.New()`는 일반적인 용도에 맞는 알고리즘을 고르고, `uuid.NewV4()`는 순수 랜덤, `uuid.NewV7()`은 생성 시간순 정렬에 유리한 형태를 만듦
  - 랜덤 구성 요소를 가진 UUID는 비교 가능해서 `==`로 직접 비교할 수 있음

- `encoding/json/v2`가 실험 딱지를 떼고 기본 제공됨. 조용하지만 영향은 큰 변화임
  - 고 1.25부터 `GOEXPERIMENT=jsonv2`로만 쓰던 `encoding/json/v2`와 저수준 동반 패키지 `encoding/json/jsontext`를 그냥 import할 수 있음
  - 더 큰 변화는 기존 `encoding/json` v1 패키지가 내부적으로 v2 구현 위에서 동작한다는 점임
  - 호환성은 최대한 유지되며, 일부 에러 메시지 텍스트만 달라질 수 있음
  - 문제가 생기면 `GOEXPERIMENT=nojsonv2`로 기존 v1 구현을 되돌릴 수 있음

> [!TIP]
> JSON v2는 map 키를 기본 정렬하지 않음. 골든 테스트나 서명 입력처럼 안정적인 출력이 필요하면 `json.Deterministic` 옵션을 명시해야 함.

- 실험 기능으로 portable SIMD 패키지도 들어옴. 하드웨어 벡터 명령이 있으면 쓰고, 없으면 순수 고 에뮬레이션으로 fallback하는 방식임
  - `GOEXPERIMENT=simd`를 켜야 사용할 수 있음
  - `Float32s` 같은 타입의 lane 수가 고정돼 있지 않고, 머신에 따라 4개일 수도 16개일 수도 있음
  - 표준 라이브러리 내부에서는 이미 Swiss Table 맵 구현의 해시 함수 쪽에 SIMD 기반 인트린식을 쓰기 시작함

- 소소하지만 바로 쓰기 좋은 표준 라이브러리 개선도 많음
  - `strings.CutLast`와 `bytes.CutLast`가 추가돼 마지막 구분자 기준 split을 `LastIndex` 없이 처리할 수 있음
  - `hash/maphash`에는 `Hasher[T]` 인터페이스가 추가돼 해시 테이블이나 Bloom filter 같은 자료구조가 타입별 해시/동등성 규칙을 받을 수 있음
  - `math/big.Int.Divide`는 `Trunc`, `Floor`, `Round`, `Ceil` 같은 명시적 반올림 모드로 몫과 나머지를 같이 계산함
  - `math/rand/v2`의 `(*Rand).N`은 직접 만든 난수 소스에서 정수나 duration 타입의 bounded random 값을 뽑을 수 있게 해줌

- 테스트 쪽 변화는 동시성 코드 다루는 팀에게 꽤 반가움
  - `testing/synctest.Sleep`은 synthetic clock을 전진시키고 고루틴이 안정될 때까지 기다리는 작업을 한 번에 처리함
  - fake clock 안에서는 2초 sleep도 실제 시간 없이 즉시 지나가므로, 동시성 테스트가 훨씬 결정적으로 돌아감
  - `httptest.NewTestServer`는 실제 TCP listener 없이 인메모리 fake network 위에서 서버를 만들고, `t.Cleanup`도 자동 등록함
  - HTTP round-trip이 프로세스 내부 pipe로만 지나가서 포트 충돌이나 실제 네트워크 stack 변수에 덜 흔들림

- 호환성에서 조심할 만한 변화도 있음. 특히 timer channel과 HTTP body close는 기존 가정이 있으면 확인 필요함
  - `time.After`, `time.NewTimer`, `time.NewTicker` 등이 반환하는 채널은 이제 항상 unbuffered이고, 예전 buffered 동작을 되살리던 `asynctimerchan` GODEBUG는 제거됨
  - HTTP/1 응답 body를 닫으면 unread content를 제한 내에서 읽고 버려 connection reuse가 가능해짐
  - 큰 다운로드를 early close로 중단하는 패턴에 기대고 있었다면 `Transport.DisableKeepAlives` 같은 설정을 봐야 함
  - HTTP/2 서버는 RFC 9218 client priority를 반영하고, 예전 round-robin에 가깝게 돌리고 싶으면 `Server.DisableClientPriority = true`를 쓸 수 있음

- 툴체인도 은근히 실무형으로 다듬어짐
  - `go test`는 `stdversion` vet check를 기본으로 돌려서 `go.mod`에 적힌 고 버전보다 새 표준 라이브러리 심볼을 쓰는 실수를 잡아줌
  - `go doc pkg@version`으로 특정 모듈 버전의 문서를 볼 수 있음
  - `go doc -ex`는 runnable example 목록을 보여줌
  - `go mod tidy`는 고 1.27 이상 모듈에서 require block을 direct와 indirect 두 덩어리로 정리하면서 주석은 보존함
  - compile, link, asm, cgo, cover, pack 도구가 GCC 형식의 response file을 지원해서 긴 명령줄에 걸리는 빌드 시스템에 도움이 됨

- 릴리스 노트 밖의 숨은 변화도 꽤 큼. 고 1.26에서 1.27 사이에 약 1,600개 커밋이 들어갔음
  - `net/http`의 HTTP/2 지원은 오랫동안 `h2_bundle.go`라는 12,226줄짜리 생성 파일에 묶여 있었는데, 이제 `net/http/internal/http2`라는 실제 패키지로 정리됨
  - HTTP/3는 아직 공개 API는 없지만, `net/http` 내부에 pluggable hook이 들어가고 테스트 스위트 상당 부분이 HTTP/3에서도 돌도록 준비됨
  - 컴파일러에는 known bits dataflow, loop-invariant code motion, switch lookup table 최적화가 기본으로 켜짐
  - 타입 메타데이터는 linker에서 `.go.type` 섹션으로 재정리됐고, `reflect.typelinks` 같은 내부 심볼에 `//go:linkname`로 기대던 라이브러리는 테스트가 필요함
  - 허가되지 않은 `//go:linkname` 사용도 더 빡세져서, 표준 라이브러리가 승인하지 않은 내부 연결에 기대는 코드는 1.27에서 빨리 검증해봐야 함

---

## 기술 맥락

- 고 1.27의 핵심 선택은 ‘언어를 크게 흔들기보다 라이브러리와 런타임의 마찰을 줄이는 쪽’이에요. 제네릭 메서드는 타입에 속해야 자연스러운 API를 다시 타입 쪽으로 가져오는 변화라서, 라이브러리 설계에서 패키지 함수가 불필요하게 늘어나는 문제를 줄여줘요.

- JSON v2를 기존 `encoding/json` 밑으로 넣은 것도 흥미로운 결정이에요. 새 API만 따로 두면 생태계 전환이 느려지거든요. 그래서 겉보기 동작은 유지하고 내부 구현을 바꾸되, 문제가 생기면 `GOEXPERIMENT=nojsonv2`로 되돌릴 수 있게 한 거예요.

- 런타임 성능 개선은 ‘개발자가 코드를 바꾸지 않아도 되는 최적화’에 가깝습니다. 80바이트 미만 작은 할당을 크기별 루틴으로 보내면 allocation-heavy 서비스에서 전체 1% 정도라도 얻을 수 있는데, 서버 비용이 큰 조직에서는 이런 1%가 생각보다 큽니다.

- 테스트 기능 개선은 고가 동시성 코드를 언어의 정체성처럼 밀어온 것과 맞닿아 있어요. synthetic time과 인메모리 HTTP 서버는 flaky test를 줄이는 데 직접적이라서, 타이머와 goroutine, HTTP handler가 섞인 코드를 운영하는 팀일수록 체감이 커요.

## 핵심 포인트

- 제네릭 메서드가 도입돼 타입에 붙은 메서드도 독립적인 타입 파라미터를 가질 수 있게 됨
- 작은 메모리 할당은 최대 30% 빨라지고, 실제 할당 많은 프로그램에서는 전체 성능이 약 1% 좋아질 것으로 예상됨
- encoding/json/v2가 실험 플래그 없이 제공되고, 기존 encoding/json도 내부적으로 v2 구현을 쓰게 됨
- 표준 라이브러리에 UUID 패키지가 추가되고, TLS 1.3에는 포스트 양자 서명 ML-DSA가 들어옴
- 고루틴 라벨 traceback, 고루틴 누수 프로파일, synthetic time 테스트, 인메모리 HTTP 테스트 서버 등 운영과 테스트 편의 기능이 꽤 많음

## 인사이트

고는 여전히 ‘천천히 바뀌는 언어’처럼 보이지만, 1.27은 개발자가 매일 만지는 코드 구조, 테스트, 디버깅, JSON 처리까지 꽤 넓게 건드린다. 특히 제네릭 메서드와 JSON v2는 라이브러리 작성자 입장에서 바로 체감될 변화다.
