[Go 공식문서 한국어 정리] ⓪24. 데이터 레이스 디텍터 상세 가이드
[Go 공식문서 한국어 정리] ⓪24. 데이터 레이스 디텍터 상세 가이드
원문 제목: Data Race Detector
작성자: Go Team
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 1. 서론 — 이 문서가 다루는 내용
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
데이터 레이스는 동시 시스템에서 가장 흔하고 디버깅하기 어려운 버그 유형입니다.
두 고루틴이 동일한 변수에 동시에 접근하고 하나 이상이 쓰기일 때 발생합니다.
이 문서는 Go의 내장 레이스 디텍터를 상세히 다룹니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 2. 핵심 개념
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
① 레이스 디텍터 사용법
-race 플래그를 go test, go run, go build, go install에 추가합니다.
② GORACE 환경 변수
log_path: 레포트 출력 파일
exitcode: 레이스 발견 시 종료 코드
strip_path_prefix: 파일 경로 접두사 제거
history_size: 메모리 접근 히스토리 크기
halt_on_error: 첫 레이스 후 종료 여부
atexit_sleep_ms: 종료 전 대기 시간
③ build tag race
-race 빌드 시 race 태그가 정의됩니다.
// +build !race로 레이스 디텍터에서 제외할 수 있습니다.
④ 전형적인 레이스
- 루프 카운터 레이스: 클로저가 루프 변수를 공유
- 의도치 않은 변수 공유: 고루틴에서 := 대신 = 사용
- 보호되지 않은 전역 변수: 맵 동시 접근
- 기본 타입 레이스: bool, int 등 동시 접근
- 동기화되지 않은 send/close: 채널 동시 작업
⑤ 수정 방법
- 루프 변수 복사
- 고루틴 내에서 :=로 새 변수 선언
- sync.Mutex 또는 sync.RWMutex 사용
- sync/atomic 사용
- 채널 receive로 동기화
⑥ 요구사항
cgo 필요, C 컴파일러 필요(Darwin 제외)
linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64 등 지원
⑦ 성능 오버헤드
메모리 5-10배, 실행 시간 2-20배 증가
defer/recovery마다 8바이트 추가 할당
장기 실행 고루틴에서 메모리가 무한 증가할 수 있음
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 3. 주요 내용 상세
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
루프 카운터 레이스:
for i := 0; i < 5; i++ {
go func() { fmt.Println(i) }()
}
→ 고루틴이 모두 같은 i를 참조하여 55555 출력
해결: go func(j int) { fmt.Println(j) }(i)
의도치 않은 변수 공유:
go func() { _, err = f1.Write(data) }()
_, err = f2.Write(data)
→ err를 공유하여 레이스 발생
해결: go func() { _, err := f1.Write(data) }()
보호되지 않은 맵:
var service map[string]net.Addr
func RegisterService(...) { service[name] = addr }
func LookupService(...) { return service[name] }
→ 맵 동시 쓰기/읽기 불안전
해결: sync.Mutex로 보호
기본 타입 레이스:
type Watchdog struct{ last int64 }
KeepAlive와 Start에서 w.last 동시 접근
해결: atomic.StoreInt64 / atomic.LoadInt64 사용
채널 send/close 레이스:
go func() { c <- struct{}{} }()
close(c)
→ send와 close가 동기화되지 않음
해결: <-c로 receive 후 close
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 4. 실전 활용 / 예시
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
병렬 테스트를 go test -race로 실행합니다.
부하 테스트에서 -race 바이너리를 사용합니다.
CI/CD 파이프라인에 race detection 단계를 추가합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 5. 정리
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
레이스 디텍터는 동시성 버그를 찾는 필수 도구입니다.
거짓 양성이 없으므로 모든 경고를 심각하게 다뤄야 합니다.
테스트 커버리지가 높을수록 더 많은 레이스를 발견할 수 있습니다.
📎 출처 링크
https://go.dev/doc/articles/race_detector.html
#Go #Golang #race #detector #concurrency #공식문서

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