고 언어는 기본적으로 하위 버전 호환을 보장하며 업데이트를 하기 때문에 업데이트를 해도 무방합니다.
최근 개발하는 서버에서 go 버전 업그레이드를 하면서 1.25 버전 업그레이드의 간단한 가이드와 무엇이 변경되었는지를 정리했습니다.
덧붙여서 1.23 → 1.24에서의 변화까지 추가로 정리했습니다.
고 버전 업 가이드
고 버전은 로컬에 설치되어있는 go를 업그레이드 하는것과 프로젝트에 설정되어있는 부분들을 업데이트 하는 것 두부분으로 나뉩니다.
로컬 업데이트
asdf install golang 1.25.0
asdf set golang 1.25.0
go env
- GOROOT, GOPATH 변경 확인
asdf install golangci-lint latest
asdf set golangci-lint 2.5.0
golangci-lint version 확인
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.35.1
go언어에 대한 버전관리도구로 asdf 를 사용하고있어서 go, golangci-lint 는 위와같은 방식으로 업데이트를 할 수 있습니다.
추가적으로 다른 cli tool을 사용하고있다면 가이드에 맞게 go install 등으로 새로운 버전을 설치해주면 됩니다.
프로젝트 업데이트
프로젝트에서는 docker를 사용한다면 docker에서 이미지 가져올때 설치하는 go version을 수정해주고, go.mod 파일에 go version을 수정해주면 됩니다.
golang 1.25에서는 무엇이 바뀌었나
릴리즈 노트에서는 크게 Tools, Runtime, Compiler, Linker, Standard library 전반에대한 개선과 함께 실험적인 Garbage Collector, json/v2 두 패키지가 공개되었다고 적혀있습니다.
그럼 하나씩 살펴보겠습니다.
Tools
go.mod 에 ignore 지시자 추가
- 특정 디렉토리를 무시할 수 있음
- go build ./… 등을 수행할때 특정 디렉토리에 오류가 있어도 무시하고 싶은 경우
go doc -http 브라우저 문서 서버
- 디렉토리 구조, 문서 등 프로젝트 전반에 대한 문서화
work 패키지 패턴
- 워크스페이스 구조
company/
├── go.work
├── api/
│ └── go.mod
├── web/
│ └── go.mod
├── shared/
│ └── go.mod
└── tools/
└── go.mod
- go.work 파일
// go.work
go 1.25
use (
./api
./web
./shared
// tools는 포함 안됨
)
- 사용 예시
# 이전: 각 모듈 개별 지정
$ go build ./api/... ./web/... ./shared/...
# Go 1.25: work 패턴 사용
$ go build work
# api, web, shared 모듈 모두 빌드!
# 테스트도 마찬가지
$ go test work
# 워크스페이스의 모든 모듈 테스트
# 의존성 업데이트
$ go get -u work
# 모든 작업 모듈의 의존성 업데이트
Runtime
GOMAXPROCS 자동 설정 변화
- 컨테이너를 인식해서 동적으로 GOMAXPROCS를 설정 (Container-aware GOMAXPROCS)
- 이전에는 컨테이너 환경에서도 호스트 전체 cpu 수를 인식해서 고루틴을 과하게 생성하는 문제가 발생
- gomaxprocs란?
- 동시에 실행할 수 있는 os 스레드(고루틴 스레드 x)의 최대 개수를 설정하는 값
- go 프로그램이 cpu 코어를 최대 몇개를 사용할 것인가? (cpu 코어 개수 제한 한도 내)
- 리눅스에서는 cgroup cpu 대역폭 제한을 자동으로 인식
- Kubernetes 같은 컨테이너 환경에서는 cpu 제한에 맞춰 자동으로 조정
- 런타임에서 cpu 수가 변경되면 동적으로 업데이트
GreenTeaGC 실험적 가비지 컬렉터
- 크기가 작은 객체의 마킹, 스캔 성능 10~40% 개선
- 작은 객체를 많이 사용하는 프로글매 (웹 서버, 마이크로서비스) 등에서 가비지 컬렉션 오버헤드를 줄임
- 실험적 기능이지만 프로덕션 테스트를 권장
- GOEXPERIMENT=greenteagc 로 설정
- locality와 cpu scalability 측면에서 향상
- locality(지역성) : 필요한 데이터가 가까이 모여있어서 캐시 히트율, 접근 속도 등의 향상
- cpu scalability(확장성) : cpu를 늘렸을때 성능도 비례해서 늘어난다. 병렬처리 효율이 좋아짐
Trace Flight Recorder
- 기존 runtime.trace는 강력한 tracing 기능을 제공했지만 크기, 비용 측면에서 비효율적이었다.
- 더 가볍고 효율적인 trace recorder를 제공
- 인메모리 링 버퍼에 지속적으로 트레이스 기록
- 중요한 이벤트 발생 시 마지막 몇 초간의 트레이스만 저장
- 버그 디버깅에 실용적
Compiler
nil pointer bug 수정
- nil pointer 의 지연 체크에 대한 버그
// os.Open시 이전에는 실행됐지만 이제는 패닉
f, err := os.Open("nonExistentFile")
name := f.Name() // nil 포인터 패닉!
if err != nil {
return
}
슬라이스 최적화
- 백킹 스토어를 스택에 할당함으로 성능 향상
표준 라이브러리
testing/synctest 패키지 - 동시성 테스트
- 기존 동시성 테스트
// 기존 방식 - 불안정하고 느린 테스트
func TestCache(t *testing.T) {
cache := NewCacheWithTTL(100 * time.Millisecond)
cache.Set("key", "value")
// 실제로 100ms 기다려야 함
time.Sleep(101 * time.Millisecond)
// 타이밍에 따라 실패할 수 있음 (flaky test)
if cache.Get("key") != nil {
t.Error("expected expired")
}
}
- synctest의 가상 시간
import "testing/synctest"
func TestCacheWithSynctest(t *testing.T) {
synctest.Test(t, func(t testing.TB) {
cache := NewCacheWithTTL(100 * time.Millisecond)
cache.Set("key", "value")
// 가상 시간을 100ms 앞으로!
// 실제로는 0초 걸림! ⚡
synctest.Wait() // 모든 고루틴이 블록될 때까지 대기
// 시간이 즉시 100ms 점프
if cache.Get("key") != nil {
t.Error("expected expired")
}
})
}
- 원리 : 모든 고루틴이 블록되었는지 감지해서 블록되었다면 필요한 시간 만큼 점프
encoding/json/v2
- 벤치마크 결과 기존 encoding/json 대비 2배 빠른 디코딩
- 메모리 사용량 감소
- 더 나은 에러처리 (상세한 에러 표시)
'go' 카테고리의 다른 글
| go 동시성 프로그래밍 part 1 (0) | 2026.02.10 |
|---|