Benchmark 이해하기
Golang의 benchmark(벤치마크)와 test(테스트)는 코드의 정확성과 성능을 보장하기 위한 핵심 도구입니다. 특히 대규모 트래픽을 처리하거나 고성능 연산이 필요한 애플리케이션을 개발할 때, 테스트와 벤치마크는 선택이 아닌 필수 요소입니다. 본 문서에서는 Golang의 벤치마크 개념과 그 중요성, 그리고 기본적인 사용 방법에 대해 자세히 설명합니다.
Benchmark란?
Golang에서 benchmark란 특정 코드, 함수, 알고리즘 또는 시스템의 성능을 측정하여 실행 속도, 처리량, 리소스 사용량(CPU, 메모리 등)을 분석하는 과정입니다. 이를 통해 코드의 최적화 가능성을 평가하고 여러 구현 방식 간의 성능 차이를 비교하며 병목 현상을 식별하여 효율적인 개선 방향을 찾을 수 있습니다. 특히 Golang에서는 go test -bench 명령어를 활용하여 특정 함수의 실행 시간을 반복적으로 측정하고 평균 실행 시간을 ns/op(나노초/연산) 단위로 확인하고 코드 변경 전후의 성능을 비교하여 보다 빠르고 최적화된 코드 구조를 설계하는 데 중요한 역할을 합니다. 이를 통해 애플리케이션의 전반적인 성능을 향상하고, 최적의 알고리즘을 선택하여 개발하는데 많은 도움이 됩니다.
Benchmark의 중요성
벤치마크는 단순한 성능 측정을 넘어서, 전체 시스템의 품질을 높이는 데 중요한 역할을 합니다.
1) 성능 최적화
코드의 실행 시간을 통해 병목 구간을 찾고, 더 효율적인 구조나 알고리즘을 도입하는 계기가 됩니다. 예를 들어, 반복문 구조 변경만으로도 처리 속도는 크게 달라질 수 있습니다.
2) 비교 분석
동일한 기능을 수행하는 여러 알고리즘을 벤치마크로 비교하면 어떤 구현체가 가장 빠르고 가벼운지 객관적으로 판단할 수 있습니다.
3) 리소스 관리
CPU나 메모리 사용량을 함께 분석하며 비효율적인 메모리 할당이나 불필요한 객체 생성 등 성능 저하를 유발하는 패턴을 쉽게 발견할 수 있습니다.
4) 지속적인 개선
코드가 발전할수록 성능도 유지되거나 개선되어야 합니다. 벤치마크는 기능 변경이나 리팩토링 이후에 성능 회귀(regression)가 발생했는지 확인하는 수단이 됩니다. CI/CD 파이프라인에 벤치마크를 포함하면 자동화된 성능 검증 시스템을 구축할 수도 있습니다.
Benchmark 사용 방법
Go에서는 이 작업을 매우 간단하게 수행할 수 있습니다. 바로 다음 명령어를 사용하여 특정 함수의 성능을 반복적으로 측정합니다.
go test -bench .
벤치마크 결과는 보통 ns/op(나노초/연산) 단위로 출력되며, 코드가 한 번 실행되는데 걸리는 평균 시간을 의미합니다. 이 지표를 통해 코드 변경 전후의 성능을 비교하거나, 여러 구현 방식 중 가장 효율적인 방식을 선택하는 데 큰 도움을 얻을 수 있습니다.
또한 벤치마크는 단순히 “빠른지 느린지”를 확인하는 것이 아니라 병목 지점을 식별하고 최적화 방향을 찾기 위한 중요한 진단 도구로 사용됩니다. 이번 실습에서는 효율적인 함수와 비효율적인 함수를 각각 작성한 후, 벤치마크 테스트를 통해 두 함수의 성능 차이를 비교해 보겠습니다.
Benchmark 테스트 코드 작성하기
먼저 pkg/sum/totalSum.go 파일에 두 숫자를 더해서 합계를 반환하는 비효율적인 함수와 효율적인 함수를 각각 작성했습니다. 그런 다음, 같은 디렉토리에 totalSum_test.go 파일을 작성하여 Go testing 패키지를 활용한 벤치마크 테스트 코드를 포함시켰습니다. 이 코드는 두 함수의 성능을 비교 분석하여 어느 구현 방식이 더 효율적인지 평가할 수 있도록 간단한 실습을 진행하겠습니다.
./pkg/sum/totlaSum.go
1부터 num까지의 합을 구하는 비효율적인 함수와 효율적인 함수를 작성했습니다.
package sum
func InefficientSum(num int) int {
result := 0
for i := 1; i <= num; i++ {
result += i
}
return result
}
func EfficientSum(num int) int {
return (num * (num + 1)) / 2
}
./pkg/sum/totlaSum_test.go
보다 극단적인 테스트를 위해 큰 수에 대해서도 벤치마크를 수행하도록 1000을 곱한 값을 인자로 전달했습니다.
func BenchmarkInefficientSum(b *testing.B) {
for i := 0; i < b.N; i++ {
InefficientSum(i * 1000)
}
}
func BenchmarkEfficientSum(b *testing.B) {
for i := 0; i < b.N; i++ {
EfficientSum(i * 1000)
}
}
Benchmark 결과 확인
go test -run=^$ -bench . ./...
옵션 설명
- -run=^$ : 일반 테스트(TestXxx) 전부 스킵하고 벤치마크만 실행
- -bench . : 벤치마크 함수(BenchmarkXxx) 전부 실행
- ./... : 현재 디렉토리 및 하위 디렉토리 전부 실행

결과를 확인해 보면 InefficientSum 함수는 1471894 ns/op 걸렸고 EfficientSum 함수는 0.2990 ns/op 걸렸습니다. 이를 통해 EfficientSum 함수가 InefficientSum 함수에 비해 훨씬 빠른 실행 속도를 보이는 것을 알 수 있습니다. 이는 EfficientSum 함수가 수학적 공식을 사용하여 합계를 계산하기 때문에 반복문을 사용한 InefficientSum 함수보다 훨씬 효율적이기 때문입니다. 이러한 벤치마크 테스트를 통해 코드의 성능을 객관적으로 평가하고, 최적화할 부분을 명확히 파악할 수 있습니다.
이러한 기능을 이용하여 새롭게 개발된 API Version의 성능이 기존 버전보다 향상되었는지, 또는 특정 알고리즘이 다른 구현 방식에 비해 얼마나 효율적인지를 지속적으로 모니터링할 수 있으며, 팀원들과 성능 관련 논의를 할 때도 객관적인 데이터를 기반으로 의사결정을 내릴 수 있습니다.
실습링크
https://github.com/stdhsw/go-testing
GitHub - stdhsw/go-testing
Contribute to stdhsw/go-testing development by creating an account on GitHub.
github.com
'Go언어' 카테고리의 다른 글
| 안전하게 개발하기 레츠GO! #5 실전 테스트 (0) | 2025.11.23 |
|---|---|
| 안전하게 개발하기 레츠GO! #4 graceful shutdown (0) | 2025.11.21 |
| 안전하게 개발하기 레츠GO! #2 go testing (0) | 2025.11.19 |
| 안전하게 개발하기 레츠GO! #1 디버깅 (0) | 2025.11.18 |
| Go언어의 benchmark와 test (0) | 2025.11.18 |