서문
많은 개발자들이 그렇겠지만 Go를 공부하고 Go로 개발해보고 싶다는 생각은 많이들 하는 것 같습니다.
Stackoverflow에서 최근에 시행된 2024 Survey를 보니, Go는 전체 7위로 많이 배우고 싶어 하고, 또 만족감이 높은 언어인 것 같습니다.
https://survey.stackoverflow.co/2024/technology#admired-and-desired-language-desire-admire
Technology | 2024 Stack Overflow Developer Survey
PostgreSQL debuted in the developer survey in 2018 when 33% of developers reported using it, compared with the most popular option that year: MySQL, in use by 59% of developers. Six years later, PostgreSQL is used by 49% of developers and is the most popul
survey.stackoverflow.co
Go 언어를 사용하게 된 계기
저희 팀에서는 다음과 같은 경우에 Go를 사용하고 있습니다.
1. 고성능이 필요한 경우
2. 안정성이 중요한 경우
3. 직접 튜닝해야 할 포인트가 많은 경우
조금이라도 Go를 써 보신 분은 알겠지만, 위와 같은 경우에 매우 유용합니다.
저희 팀에서는 API Gateway, RTC 통신, 인증 등의 여러 도메인에서 Go 언어를 사용중입니다.
Go 언어의 특징과 장단점
Go 언어 자체의 특징과 장단점은 더 객관적으로 잘 이야기하는 곳이 많다고 생각되어 넘기겠습니다.
다만 Go 언어를 소개하는 곳에서는 나와있지 않았지만, 저 뿐만 아니라 인터넷에 보면 Go를 사용하면서 저와 비슷하게 느끼신 분들이 있는 것 같은 부분만 얘기해보겠습니다.
1. 전반적으로 커뮤니티에 DIY의 느낌이 있다.
Go는 사용해보면 다른 언어와 다른 느낌이 있습니다. 일단 HTTP와 같이 다른 언어에서는 서드 파티나 라이브러리에 책임을 주는 영역들도 공식에서 지원하고 있습니다. 그래서 웬만한 것들은 외부 종속성 없이 편리하게 사용 가능합니다.
반대로 다른 언어에서는 라이브러리나 프레임워크로 처리하던 것들이 오픈소스로 많이 공개되어 있지 않고, 커뮤니티를 찾아봐도 "그냥 구현하면 됨" 식인 게 많습니다.
C에서 넘어오는 분들이 많다보니 그런건지는 모르겠으나, 웬만한 것들은 직접 구현하는 걸 (커뮤니티 구성원들이) 선호하고 외부 종속성은 크게 선호하지 않는 것 같습니다.
Go라는 언어가 확장성에 매우 유리하게 설계되어있어서 그런 것 같기도 하구요.
2. goroutine을 잘 사용하면 성능 최적화가 매우 편리하다.
자바에서도 가상 스레드가 있고 코틀린에서도 코루틴이 있습니다. 다른 언어들도 이러한 컨텍스트 스위칭을 일으키지 않는 경량 스레드 개념을 조금씩 가져오고 있습니다만, 아무래도 원조 맛집인 Go와 코틀린만큼은 아직 성숙하지 않은 느낌인 것 같습니다.
goroutine을 써서 코딩하다가 다른 언어로 가면, "아, 고루틴으로 하면 딱 좋겠는데." 하는 생각이 들 때가 많습니다.
3. 아주 낮은 레벨과 높은 레벨의 프로그래밍 그 중간에 있는 느낌이다.
이건 1번과도 조금 겹치는 영역에 있는 것 같습니다.
무슨 말이냐면, 정말 낮은 레벨로 가서 하드웨어에 직접적인 컨트롤을 하는 수준의 도메인(임베디드라든지)으로 가게 되면, C, C++, Rust 등의 강자들이 있습니다.
반대로 높은 레벨로 가서, 많은 것들을 추상화하고 편리하게 개발하려고 보면 이건 Java, Python, JS 같은 강자들이 있습니다.
Go의 포지션은 이 중간에 있는 것 같아요.
Java, Python, JS 같은 느리고 편한(?) 언어들에서 제공하는 편의점들을 버리고 성능을 가져가되, 정말로 낮은 레벨에서 튜닝하기 시작하면 C, C++, Rust 같은 언어들보단 더 편하니까요.
그런데 웹 개발을 하다보면 이 중간에 속하는 영역들이 꽤나 있는 것 같습니다.
비즈니스 로직을 깔끔하게 표현하는 데는 스프링 프레임워크를 사용하면 더 좋은 것 같고, 성능이 중요한 기술 중심의 도메인이 있는 서버면 Go가 좋은 것 같습니다.
이건 스프링이나 JPA 같은 기술들이 Go에는 없는 것도 중요한 요인 중 하나인 것 같아요.
Go로 웹 백엔드 개발을 다 할 수도 있고, 임베디드 프로그래밍도 되겠습니다만은 실용주의적으로 취사선택하면 되지 굳이 Go로 모든걸 해내려는 생각은 할 필요 없으니까요.
Go 사용자들은 JS 사용자들하고는 성격이 좀 다른 것 같아요. Go 사용자들은 모든 걸 Go로 짜야된다는 생각 자체가 이상하다고 생각할 것 같습니다. Go 설계자들의 면면과 커리어를 봐도 그렇구요.
gelf-forwarder를 개발하다
제가 일하고 있는 팀에서는 API Gateway로 krakend를 사용중인데요.
High-performance Open Source API Gateway | KrakenD
KrakenD is a high-performance Open Source API Gateway that enables you to build scalable and resilient microservices architectures.
www.krakend.io
krakend에서는 GELF 형식으로 로그를 export 할 수 있게 되어있습니다.
그 외의 방식을 지원하지 않기 때문에, GELF 형식으로 로그를 받아줘야 했습니다.
GELF에 대해서는 아래의 링크 참고해주세요.
https://go2docs.graylog.org/current/getting_in_log_data/gelf.html
GELF
GELF The Graylog Extended Log Format (GELF) is a log format that avoids the shortcomings of classic plain syslog: Limited to length of 1024 bytes. Inadequate space for payloads like backtraces. No data types in structured syslog. Numbers and strings are in
go2docs.graylog.org
처음에는 GELF 로그도 JSON 형식을 가지고 있으니, otel collector로 바로 보내면 되는 거 아니야? 라고 생각했는데요.
그러나 GELF 로그는 압축 과정이 포함됩니다.
규격을 보면 gzip, zlib 등을 선택할 수 있는 것 같은데, krakend에서는 gzip으로 압축해서 내보냅니다.
이 문제를 해결할 수 있는 방법은 2가지가 있을 것 같은데요.
1. otel collector에서 gelf receiver를 찾는다.
2. logstash처럼 로그 전처리를 해주는 솔루션을 적용한다.
1번의 경우에는 otel collecotor에서 GELF 형식을 받아주는 receiver를 지원하지 않을까? 생각을 했었는데요.
https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33861
New component: [receiver/gelfreceiver] · Issue #33861 · open-telemetry/opentelemetry-collector-contrib
The purpose and use-cases of the new component We're using GELF based logging for all application logs, which have a GELF client in them - refer to golang GELF client. We want to support server-sid...
github.com
그런데 이슈를 보니, not planned로 닫혀버렸습니다.
아마도 GELF 형식으로 로그를 받아주는 건 opentelemetry 쪽에서 관심 없는 것 같습니다.
아마 그건 2번 때문일 것 같은데요.
2번의 경우에, logstash 같은 솔루션을 써서 GELF로 받아서 otel collector로 OTLP 형식으로 쏴 주면 됩니다.
굳이 특정 벤더에 종속적인 receiver를 넣는 것보다, 이 쪽이 더 합리적이라고 생각한 것 같습니다.
물론 이유가 있겠지만, 만약에 그런 이유라면 cloud 벤더들에 맞는 receiver, exporter는 왜 들어간지는 잘 모르겠지만요.
결국 GELF 포맷을 사용하는 사용자 풀의 규모의 문제인 것 같습니다.
이 부분은 logstash를 이용하면 바로 해결이 가능하긴 합니다.
다만 Logstash가 Apache 2.0과 Elastic License를 이중 라이센스로 갖고 있어서, 조금 곤란한 부분이 있습니다.
개인 개발자라면 아무 고민 없이 검증된 Logstash를 써도 되구요.
다만 회사에서 일하시는 분이라면, 아무리 무료 기능에는 Apache 2.0이 붙어있다고는 해도 유료 라이센스가 포함된 소스를 이런 사소한 일에 굳이 넣고 싶지는 않을거라고 생각합니다.
Fluentd 같은 솔루션도 있습니다만, 새로운 솔루션을 도입하는 것도 나름의 비용이 있고, 직접 구현해보고 싶은 마음도 있어서 직접 구현했습니다.
UDP로 들어온 요청을 gzip 압축을 풀어서 otlp로 otel collector로 쏴주는 간단한 로직인데요.
자세한 코드는 아래 오픈된 깃헙 코드를 참고해주시기 바랍니다.
https://github.com/KimJinYeon/gelf-forwarder
GitHub - KimJinYeon/gelf-forwarder
Contribute to KimJinYeon/gelf-forwarder development by creating an account on GitHub.
github.com
나가며
Go 언어로 개발하는 것은 쉽고 재밌습니다. 그래서 고정 팬층이 생기는 것 같습니다.
Rust 언어도 잠깐 배워봤습니다만, 아무래도 제가 담당하는 웹 백엔드 도메인에서는 그렇게 적합하지 않은 것 같더라구요.
Java + Spring Boot Web + JPA 스택으로만 개발하시던 분이라면, Go를 이용한 웹 백엔드 개발을 꼭 해보면 좋은 것 같습니다.
여러 가지 의미로 새로운 시야가 열리고 발전할 수 있는 계기인 것 같아요.
제 경우에는 주로 Java로 개발하다가 스크립팅 언어가 필요할 경우에는 Python, JS를 사용하게 되더라구요.
거기에 Go 언어가 추가되니 Java + Spring Boot Web만큼 비즈니스 로직을 가지고 있는 건 아닌데, 고성능과 유지보수성을 가진 서버를 개발하려고 하면 Go가 편리한 것 같습니다.
(객관적인 기준은 아니지만, 서버가 DBMS/SQL 의존성이 낮을수록 더 추천드립니다.)
제 경우에는 이번에 모니터링 관련된 부분에서 간단한 변환 로직을 구현한 서버를 구현하려고 보니, Go가 딱 적당해서 gelf-forwarder를 개발해봤는데요.
혹시나 비슷한 문제를 가지고 있으셨던 분들, Go를 배워볼까 고민하던 분들께 도움이 됐으면 합니다.
'개발 - Coding > Go' 카테고리의 다른 글
Go 바이너리 실행시 ENOENT(No such file or directory) 문제 해결하기 1편 - C 표준 라이브러리 구현체를 찾아서 (0) | 2025.01.20 |
---|