본문 바로가기

프로그래밍

물어보는 사람이 많아서 정리했습니다: Go언어

반응형

https://golang.org/

 

The Go Programming Language

Download Go Binary distributions available for Linux, macOS, Windows, and more. // You can edit this code! // Click here and start typing. package main import "fmt" func main() { fmt.Println("Hello, 世界") } Hello, World! Conway's Game of Life Fibonacci

golang.org

https://www.s-core.co.kr/insight/view/%EB%AC%BC%EC%96%B4%EB%B3%B4%EB%8A%94-%EC%82%AC%EB%9E%8C%EC%9D%B4-%EB%A7%8E%EC%95%84%EC%84%9C-%EC%A0%95%EB%A6%AC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4-go%EC%96%B8%EC%96%B4/

 

에스코어

에스코어는 디지털 혁신을 위한 고급 프로페셔널 서비스를 제공합니다. 매니지먼트 컨설팅과 소프트웨어 테크놀로지 서비스 오퍼링을 살펴보세요.

www.s-core.co.kr

 

개발자가 배우고 싶어하는 프로그래밍 언어로 항상 높은 순위에 오르는 Go 언어, 주위 동료들로부터 어떤 장점이 있는지 궁금하다는 질문을 많이 받아서 정리해보았습니다.

Go 언어가 개발되기전 구글(Google)의 인프라 소프트웨어는 대부분 C++로 작성하고 있었습니다. 수천명의 프로그래머들이 개발에 참여하였고 매일 업데이트가 필요한 상황이었습니다. 분산 빌드 시스템이 잘 갖춰져 있었지만 서버 하나를 빌드 하는데 45분이나 걸렸습니다. 반복되는 긴 컴파일 시간에 지친 구글 엔지니어 세명이 웹 서버와 같은 대규모 프로그램을 개발하는데 적합한 언어를 만들어 보겠다고 나서면서 Go 언어의 첫 스케치가 시작되었습니다.

C++의 복잡함과 긴 컴파일 시간을 줄일 수 있는 간결한 언어, 또한 사용자가 배우기 쉬운 언어를 만들어보자는 취지로 2007년 첫 삽을 뜬 Go 언어는 2009년 11월에 리눅스와 맥OS 플랫폼을 대상으로 공식 발표됩니다. 2012년 3월에는 정식 버전(v1.0)을 선보였고 이후 개선을 거듭해 2020년 12월 현재 1.15 버전이 릴리즈 되어 있습니다. 세상에 나온 지 10년이 조금 넘은 지금, Go 언어는 컨테이너와 클라우드 환경 구축에 없어선 안될 도커(Docker) 및 쿠버네티스(Kubernetes)를 비롯해 이더리움(Ethereum) 블록체인의 메인 클라이언트 Geth의 개발에 사용되는 등 성능과 안정성을 인정받으며 시장 입지를 다지고 있습니다.

 

간결한 문법, 빠른 컴파일

Go 언어는 시스템 프로그래밍에 적합하도록 설계되었으며 C와 구문이 비슷합니다. 이는 대부분의 컴퓨터공학 전공자들이 C 언어를 배울뿐더러 기존 시스템 프로그래밍 영역에서 C와 C++이 많이 사용되었기 때문에 개발자들이 새로운 언어에서 빠르게 생산성을 발휘할 수 있도록 하기 위함입니다. Go 언어는 C 와 비슷하지만 키워드가 25개로 C(37개), C++ 11(84개)에 비해 간결합니다. C와 C++의 복잡한 요소를 최대한 줄이고 간결하게 만들어져 C 언어에 경험이 있는 개발자라면 쉽게 배울 수 있습니다.

Go 언어는 C와 구문은 비슷하지만 복잡도를 낮추고 컴파일 속도 향상을 위해 기존에 사용하던 헤더 파일을 정의하는 방식 대신 소스 자체를 패키지화하는 방식을 채택했습니다. 소스 코드 자체를 패키지화하여 변경된 부분만 컴파일 함으로써 컴파일 속도를 향상시켰습니다.

또한 Go 언어는 소스 내에 사용하지 않는 변수나 패키지가 있을 경우 컴파일 시 오류를 발생합니다. 불필요한 패키지 가져오기에 따른 지연 시간을 줄이고 사용하지 않는 변수 및 패키지 선언으로 인해 향후에 발생할 수 있는 버그를 줄이고자 함입니다.

 

풍부한 기능, 유틸리티 제공

Go 언어는 개발자의 생산성 향상에 초점을 두고 설계되어 기존 개발자들이 사용하던 IDE(Integrated Development Environment)에서 쉽게 환경을 구성할 수 있습니다. 공식 홈페이지(www.golang.org)에서 Go 언어로 작성된 파일을 컴파일·실행·관리할 수 있는 go 바이너리를 다운로드하고 소수의 환경변수 $GOROOT, $GOPATH($GOPATH를 $PATH에 추가)를 설정하는 것만으로 개발 환경을 구성할 수 있습니다. 다운로드 받은 유틸리티 go 파일은 Go 언어로 작성한 소스파일을 컴파일(build) 하여 실행 가능한 바이너리를 생성하는 것은 물론, 컴파일 후 바로 실행(run)하는 기능을 제공합니다.

Go 언어는 소스에 기술된 패키지 단위로 관리되며 Go 소스로 작성할 수도 있고 이미 정의되어 있는 패키지를 import 문으로 가져와서 사용할 수 있습니다. 필요한 외부 패키지가 있을 경우엔 get 커맨드로 패키지를 받아와 사용합니다.

그 외에도 Go 소스 파일의 형식을 맞춰주는 포맷팅(fmt), 사용되는 패키지 리스트업(list), 테스트 코드 수행 등 Go 언어로 패키지를 작성 및 사용하기 위한 여러 가지 기능을 제공합니다.

 

다양한 패키지

Go 언어는 기본 패키지 이외에도 여러 벤더에서 다양한 패키지를 제공하고 있습니다. 개발자는 이를 활용하여 쉽게 애플리케이션 개발할 수 있습니다. 시스템 프로그램에 자주 사용되는 http 패키지는 물론 통신에 필요한 암호화 모듈까지 기본 내장되어 있어 웹 서버를 쉽게 구축할 수 있습니다. 예를 들어 “hello GO”를 출력하는 웹 서버는 다음과 같이 단 몇 줄로 구현이 가능합니다.

또한 Go 소스 내에 cgo라는 별도 지시자(directives)를 설정함으로써 C 언어로 작성된 라이브러리를 직접 사용하는 것도 가능합니다. 이러한 강점 때문에 기존 인프라 소프트웨어를 대체할 수 있는 언어로 선택되며 대표적인 예로 SSH의 Go 언어 구현체인 텔레포트(Teleport)가 있습니다.

 

동시성(Concurrency)

Go 언어는 시스템 프로그램, 특히 서버 개발용으로 설계되었습니다. 기존에 서버 개발에 널리 사용되던 C, C++, Java는 멀티 코어, 네트워킹 및 웹 애플리케이션 개발이 활발히 이뤄지기 전에 만들어진 언어들이라 사용하기 어렵거나 기능이 제한적이었습니다. Go 언어는 이러한 클라이언트가 있는 웹 서버를 실행하는 멀티 코어 환경에 맞추어 쉽게 프로그래밍할 수 있도록 고루틴(goroutine)과 채널(channel)을 제공합니다. 고루틴은 Go 런타임에서 관리되는 일종의 경량 스레드이며 채널을 통해 고루틴 간에 메시지를 주고 받을 수 있는 매커니즘을 제공합니다. 고루틴과 채널을 활용해 멀티 코어 환경에서 병렬처리를 쉽게 구현할 수 있습니다.

고루틴은 자체 Go 런타임 스케줄러에 의해 관리되며 OS 스레드에 비해서도 경량입니다. OS 스레드를 생성하는데 필요한 메모리가 1MB인 반면, 고루틴은 2KB입니다. 또한 일반 스레드와 달리 메모리의 스택 영역을 사용하며 자체 스케줄러에 의해 관리하므로 컨텍스트 스위칭 비용을 줄입니다. 여기에 Go 런타임에서 사용하는 CPU 코어 수를 지정하는 환경 변수 GOMAXPROC를 지정함으로써 병렬적으로 고루틴을 실행할 수 있습니다. 하나의 프로세스에서 보통 1만개의 고루틴을 실행시킬 수 있으며 몇십만 단위의 고루틴도 실행 가능하도록 스케줄러가 구현되어 있습니다.(스택 메모리가 부족하면 힙영역까지 확장)

 

에러 처리, 함수 흐름 제어

Go 언어는 에러 처리에 있어서 기존의 try-catch-finally 형식이 코드가 복잡하고 읽기 어려워진다고 판단했습니다. 기존 C, C++은 반환되는 값 하나만으로 에러 케이스를 분석하고 그에 따른 조치를 취해야 했기에 흔히 발생하는 에러 케이스를 공통 모듈화 하는 과정에서 상세 정보가 누락되는 일도 많았습니다.

Go 언어에서 함수는 복수 개의 값을 반환할 수 있습니다. 이를 통해 에러가 발생했을 때 일반적인 리턴과 함께 오류 메시지를 반환할 수 있고 이 기능은 에러 처리를 쉽게 합니다. 예를 들어 Go 기본 패키지 os의 Write 함수는 다음과 같이 정의되며 write에 성공한 바이트 수와 에러 메시지를 함께 반환합니다.(Go 언어에서 함수 선언 시 반환 값은 제일 마지막에 변수명, 타입 순으로 정의합니다.)

Go 언어는 200바이트 데이터를 파일에 쓰게 했을 때 “100바이트는 성공적으로 쓰였지만 공간이 없어서 나머지는 실패했다”라는 상황을 감지할 수 있습니다.

복수 개의 반환을 통해 에러를 감지하더라도 어떤 에러는 발생할 경우 더 이상 프로세스가 실행되는 것이 의미가 없어질 수 있으며 이 때 Go 언어는 패닉(panic)을 발생시켜 에러 후 종료하는 것을 권고합니다. 프로그램이 패닉을 만나면 현재 함수의 실행을 즉시 중지하고 실행 중인 스택 상의 고루틴을 하나씩 종료합니다. 고루틴이 모두 종료되면 최종적으로 프로그램이 종료됩니다. 단, 고루틴 내에서 발생한 에러에 대해 조치 후 정상 복구가 가능한 경우에는 고루틴 종료 전에 호출되는 recover 함수에 조치 사항을 정의함으로써 프로그램 자체를 종료하지 않고 정상 재개할 수 있습니다.

recover문과 비슷하게 Go 언어의 defer문은 함수가 종료되기 직전에 수행되는 문장으로 함수 내에서 사용한 리소스 반환 처리와 같은 상황에 유용합니다. 사용되는 리소스를 생성하고 defer문으로 반환 처리를 예약하면 이후에 생길 에러 상황에서 프로그램이 종료되더라도 리소스 해제 누락을 막을 수 있습니다.

 

제약 사항

작고 이해하기 쉬울 뿐만 아니라 기존 인프라 소프트웨어를 대체할 수 있을 만큼 강력한 Go 언어지만 설계 철학에 어긋나는 제네릭(Generic) 같은 일부 기능은 의도적으로 빠졌습니다. 그 외에 C 구문을 따랐다고 하지만 포인터 연산을 없앤 점 등 C와 다른 부분이 분명 존재하기 때문에 커널이나 장치 드라이버, 임베디드 소프트웨어 같은 저수준 프로그램엔 적합하지 않습니다. 또한 상용 하드웨어 전용으로 설계되어 있어 하드웨어 가속을 사용할 수 없습니다.(그래픽스 분야에는 맞지 않음) 따라서 Go 언어는 유틸리티나 네트워크 서비스와 같은 프로그램을 만들 때 유용합니다.

 

마치며

기존의 프로그래밍 언어 연구의 성과와 절차를 무시했다는 혹평을 받기도 하는 Go 언어. 구글의 명성에 힘입어 입지를 굳혔다고 악평을 하는 이도 적지 않습니다. 하지만 순전히 개발자와 현장의 필요에 의해서 만들어진 혁신이 개발 생태계에 파란을 일으키면서 혁명으로 이어진 사례로 기록되며 프로그래밍 언어의 새로운 발전 방향을 제시한 것은 큰 성과라고 볼 수 있습니다.

인프라 시스템 재구축과 같이 코드가 방대해져 유지 관리가 힘들어지는 경우를 중심으로 Go 언어의 사용 빈도가 높아지고 있습니다. 쉽고 간편하게 확장성 있는 시스템 구축이 가능한 Go 언어의 특성 상 앞으로는 클라우드 환경에서 활용도가 높아질 것으로 예측됩니다.

배우기 쉽다는 것은 Go 언어의 가장 큰 장점입니다. 다운로드 받기 전에 먼저 Go 언어의 컨셉을 이해하는데 도움이 될 노래(https://www.youtube.com/watch?v=LJvEIjRBSDA, 겨울왕국 Let it Go를 패러디한 Write in Go)를 들어보시고 투어(https://tour.golang.org)도 다녀오시길 권해 드립니다.

반응형

태그