loading...

Google이 만든 프로그래밍 언어, Go

google이 만든 프로그래밍 언어-go

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

Stack Overflow의 2020년 개발자 서베이 결과에 따르면, 
Python 30%, javascript 18.5%에 이어 
Go언어는  17.9%는 배우고 싶은 프로그래밍 언어에서 3위를 차지했습니다. 
TypeScript 는 17.0%, Rust는 14.6%, Kotlin은 12.6%, JAVA는 8.8%, C++는 8.6%, SQL은 8.2%, C#은 7.3%k swift는 6.6%
[그림 1] Stack Overflow의 2020년 개발자 서베이 결과에 따르면, Go는 "배우고 싶은 프로그래밍 언어"에서 3위를 차지했습니다.

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 언어에는 25개의 키워드(break, default, func, interface,,,,select, case, defer, go,map, chan, else, goto, package, switch, const, fallthrough, if, range, type,continue,for import return,var 등) 가 있습니다.
[그림 2] Go 언어에는 25개의 키워드가 있습니다.

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

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

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

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

go 예제소스 package main import( "fmt" ) func main(){ fmt.Println("hello GO") }

go 소스 실행 명령 $go build hello.go //빌드 후 바이너리를 생성 $./hello hello GO $go run hello.go // 빌드 + 실행까지 한번에 hello GO

[그림 3] hello GO 예제 프로그램과 실행 방법

Go 언어는 소스에 기술된 패키지 단위로 관리되며 Go 소스로 작성할 수도 있고 이미 정의되어 있는 패키지를 import 문으로 가져와서 사용할 수 있습니다. 필요한 외부 패키지가 있을 경우엔 get 커맨드로 패키지를 받아와 사용합니다. 그 외에도 Go 소스 파일의 형식을 맞춰주는 포맷팅(fmt), 사용되는 패키지 리스트업(list), 테스트 코드 수행 등 Go 언어로 패키지를 작성 및 사용하기 위한 여러 가지 기능을 제공합니다.

Go is a tool for managing Go source code. Usage: go command [arguments] The commands are: build compile packages and dependencies clean remove object files and cached files doc show documentation for package or symbol env print Go environment information bug start a bug report fix update packages to use new APIs fmt gofmt (reformat) package sources generate generate Go files by processing source get download and install packages and dependencies install compile and install packages and dependencies list list packages or modules run compile and run Go program test test packages tool run specified go tool version print Go version vet report likely mistakes in packages Use "go help [command]" for more information about a command.

[그림 4] Go 명령을 실행하면 Go tool에서 제공하는 기능을 확인할 수 있습니다.

다양한 패키지

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

source code package main import( "fmt" "net/http" ) func main(){ http.HandleFunc("/hello", helloGo) http.ListenAndServe(":8080",nil) } func helloGo(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "hello GO\n") }

terminal command line $ go run hello.go & $curl localhost:8080/hello Hello GO

[그림 5] “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 언어에서 함수 선언 시 반환 값은 제일 마지막에 변수명, 타입 순으로 정의합니다.)

func (file *File) Write(b []bytes)(n int, err error) [그림 6] Go 기본 패키지 os의 Write 함수 정의 예

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

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

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

f, err := os.Open(filename) if err!=nil{ return "",err } defer f.Close()

[그림 7] defer 문을 사용하여 파일 Close 누락을 막을 수 있습니다.

제약 사항

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

마치며

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

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

배우기 쉽다는 것은 Go 언어의 가장 큰 장점입니다. 다운로드하기 전에 먼저 투어를 다녀오시는 건 어떨런지요. https://tour.golang.org


References
[1] https://talks.golang.org/2012/splash.article
[2] https://golang.org/doc/faq
[3] https://golang.org/doc/effective_go.html
[4] https://insights.stackoverflow.com/survey/2020/#technology-most-loved-dreaded-and-wanted-languages-wanted
[5] https://www.computer.org/publications/tech-news/trends/programming-languages-you-should-learn-in-2020
[6] http://www.itworld.co.kr/news/133382
[7] https://zdnet.co.kr/view/?no=20200205112108
[8] https://www.fullstackacademy.com/blog/nine-best-programming-languages-to-learn
[9] https://www.guru99.com/best-programming-language.html



▶  해당 콘텐츠는 저작권법에 의하여 보호받는 저작물로 기고자에게 저작권이 있습니다.
▶  해당 콘텐츠는 사전 동의 없이 2차 가공 및 영리적인 이용을 금하고 있습니다.


이 글이 좋으셨다면 구독&좋아요

여러분의 “구독”과 “좋아요”는
저자에게 큰 힘이 됩니다.

subscribe

구독하기

subscribe

이주연
이주연 IT 테크놀로지 전문가

에스코어㈜ 소프트웨어사업부 엔터프라이즈플랫폼그룹

분산컴퓨팅그룹에서 근무하던 시절, k8s 분석을 위해 처음 golang을 접하게 되었습니다. 이후 블록체인기술그룹에서 이더리움을, 현재 부서에서 golang으로 구현된 Elastic 및 Metricbeats 커스텀 업무를 담당하고 있습니다.

공유하기