방구석 IT

[Language] Go 본문

실무 탐방/기술 탐방 및 소개

[Language] Go

펭잉 2026. 6. 12. 14:05

Go란?


Go는 Google에서 설계해 공개한 정적 타입 컴파일 언어이다. 서버 프로그램, 네트워크 서비스, CLI, 클라우드 네이티브 도구처럼 장시간 실행되고 배포 단위가 명확한 소프트웨어를 단순하게 만들기 위해 등장했다. 문법은 작게 유지하고, 빠른 컴파일, 가비지 컬렉션, 표준 도구 체인, 내장 동시성 모델을 언어와 런타임의 핵심으로 둔다.

Go의 강점은 화려한 문법보다 운영 가능한 기본값에 있다. `go fmt`로 코드 스타일을 통일하고, `go test`, `go vet`, `go mod`, 프로파일링, race detector 같은 도구를 기본 생태계 안에 넣는다. 그래서 팀 단위 개발에서는 “어떻게 빌드하고 테스트하고 배포할 것인가”에 대한 논의가 비교적 짧아진다.

Go는 단순한 문법, 빠른 빌드, 런타임 동시성, 풍부한 표준 라이브러리를 묶어 서버와 인프라 소프트웨어를 안정적으로 만들기 위한 언어이다.

Go의 실행 모델은 개발자가 작성한 goroutine과 channel을 런타임 스케줄러, 네트워크 폴러, GC가 뒷받침하는 구조로 이해할 수 있다.

설계 배경과 언어 철학


Go는 C 계열 언어의 컴파일 성능과 배포 편의성, 스크립트 언어의 생산성, 현대 서버 환경의 동시성 요구를 함께 다루려는 시도에서 출발했다. 공식 문서는 Go를 빠른 정적 타입 컴파일 언어이면서 동적 언어처럼 가볍게 느껴지도록 설계된 언어로 소개한다.

이 철학은 언어 기능의 “추가”보다 “제거”에서 더 분명하다. 상속, 예외 중심 흐름 제어, 암시적 타입 변환, 복잡한 메타프로그래밍을 제한하고, 대신 명시적인 오류 반환, 구조적 인터페이스, 패키지 단위 구성, 표준 포맷터를 제공한다. 단순함은 기능 부족이 아니라 대규모 코드베이스에서 읽기 비용을 낮추기 위한 선택이다.

Go의 핵심 철학은 적은 개념으로 많은 서버 문제를 풀고, 팀 전체가 같은 방식으로 읽고 빌드하고 운영하게 만드는 데 있다.

타입 시스템과 인터페이스


Go는 정적 타입 언어이지만 클래스 상속 중심의 객체지향 언어는 아니다. 메서드는 특정 타입에 붙일 수 있고, 인터페이스는 어떤 타입이 가져야 하는 메서드 집합을 표현한다. 중요한 차이는 명시적인 `implements` 선언이 없다는 점이다. 어떤 타입이 인터페이스가 요구하는 메서드를 가지고 있으면 자동으로 그 인터페이스를 만족한다.

이 구조적 타입 방식은 작은 인터페이스를 만들 때 강력하다. 예를 들어 `io.Reader`처럼 하나의 동작만 표현하는 인터페이스는 파일, 네트워크 연결, 메모리 버퍼 등 다양한 구현체를 같은 추상화로 다룰 수 있게 한다. 반대로 너무 큰 인터페이스를 먼저 정의하면 Go다운 조합성이 사라지고 테스트와 교체가 어려워진다.

Go 인터페이스는 상속 계층을 만들기보다 작은 행위 단위를 표현하고, 구현체가 자연스럽게 그 계약을 만족하게 하는 데 초점이 있다.

goroutine, channel, 런타임 스케줄러


Go 동시성의 중심은 goroutine이다. 함수 호출 앞에 `go`를 붙이면 별도의 goroutine에서 실행된다. goroutine은 OS 스레드 자체가 아니라 Go 런타임이 관리하는 가벼운 실행 단위이며, 런타임 스케줄러가 많은 goroutine을 더 적은 OS 스레드 위에 배치한다.

channel은 goroutine 사이에서 값을 주고받는 타입 있는 통로이다. 공유 메모리를 직접 잠그는 방식도 가능하지만, Go는 “메모리를 공유해 통신하지 말고, 통신으로 메모리를 공유하라”는 관용구를 강조한다. 이 말은 mutex를 쓰지 말라는 뜻이 아니라, 소유권과 데이터 흐름이 분명한 구조를 우선 고려하라는 뜻이다.

운영 환경에서는 goroutine 누수, 닫히지 않는 channel, context 취소 누락, fan-out 이후 회수되지 않는 작업이 실제 장애로 이어질 수 있다. 따라서 timeout, cancellation, backpressure, worker 수 제한을 설계에 포함해야 한다.

Go의 동시성은 문법 하나로 해결되는 기능이 아니라, 런타임 스케줄러와 channel, context, 동기화 도구를 함께 설계해야 하는 실행 모델이다.

빌드, 배포, 운영 특성


Go 프로그램은 보통 단일 바이너리로 배포하기 쉽고, 크로스 컴파일 경험도 좋은 편이다. 이 특성은 컨테이너 이미지, 서버리스 런타임, 운영 자동화 도구에서 장점이 된다. 표준 라이브러리에는 HTTP 서버와 클라이언트, TLS, JSON, 테스트, pprof 프로파일링 등 서버 개발에 필요한 기반이 폭넓게 포함되어 있다.

가비지 컬렉션은 개발자가 수동 메모리 해제를 관리하지 않아도 되게 해 생산성을 높인다. 다만 GC가 있다는 것은 지연 시간과 메모리 사용량을 관찰해야 한다는 뜻이기도 하다. 높은 처리량의 네트워크 서비스에서는 allocation 패턴, buffer 재사용, pprof 분석, latency budget을 함께 봐야 한다.

Go는 배포와 운영의 기본값이 좋아 인프라 코드에 강하지만, 성능을 중시하는 서비스에서는 GC, 할당량, goroutine 수, 네트워크 대기 시간을 꾸준히 관찰해야 한다.

선택 기준과 트레이드오프


  • 잘 맞는 경우: HTTP API, gRPC 서비스, 프록시, 에이전트, CLI, 배치 작업, 컨테이너와 Kubernetes 주변 도구처럼 배포 단위가 명확하고 동시 I/O가 많은 시스템에 적합하다.
  • 주의할 경우: 매우 풍부한 제네릭 추상화, 복잡한 도메인 모델링, 고급 함수형 패턴, 런타임 플러그인 구조가 핵심인 프로젝트에서는 언어의 단순성이 오히려 반복 코드로 느껴질 수 있다.
  • 운영 리스크: data race, context 누락, 무제한 goroutine 생성, 큰 interface 설계, 전역 상태 남용, 에러 무시가 대표적인 품질 저하 원인이다.
  • 마이그레이션 관점: 기존 시스템을 한 번에 바꾸기보다 네트워크 경계가 분명한 작은 서비스, 운영 도구, 성능 병목 구간부터 도입하는 방식이 현실적이다.
Go를 선택할 때는 문법 취향보다 배포 형태, 동시성 요구, 팀 규모, 운영 관측성, 생태계 적합성을 먼저 따져야 한다.

Go Gopher는 Renée French가 디자인한 Go 커뮤니티의 대표 이미지이며, Go 공식 블로그와 Go Wiki는 해당 이미지를 Creative Commons Attribution 4.0 라이선스로 안내한다. 출처: Go Blog, The Go Programming Language.

사례


Kubernetes는 Go 생태계를 대표하는 대규모 인프라 프로젝트이다. 컨테이너 오케스트레이션처럼 네트워크, API 서버, 컨트롤 루프, 에이전트가 얽힌 시스템에서 Go의 배포 편의성과 동시성 모델이 잘 드러난다.

Docker와 containerd도 Go 기반 도구 생태계의 중요한 사례이다. 단일 바이너리 배포, Linux 시스템 호출과 네트워크 처리, CLI와 데몬 구조가 결합된 영역에서 Go가 널리 쓰인다.

Cloudflare는 네트워크와 동시성이 중요한 여러 서비스에 Go를 사용해 왔다고 공개적으로 설명했다. 특히 DNS, SSL, 고지연 HTTP 연결 처리, 부하 테스트 같은 영역은 Go의 동시 I/O 모델과 운영 편의성이 강점으로 작동하는 사례이다.

Go 공식 자료: Documentation, Effective Go, FAQ, Go Concurrency Patterns: Pipelines and cancellation, Go Wiki: Gopher, Cloudflare Blog: What we've been doing with Go.

'실무 탐방 > 기술 탐방 및 소개' 카테고리의 다른 글

[Language] Dart  (0) 2026.06.16
[Language] Swift  (0) 2026.06.15
[Language] Kotlin  (0) 2026.06.12
[Language] Assembly  (0) 2026.06.11
[Language] SQL  (0) 2026.06.11