[개발] Go 성능 최적화 가이드 - 바르트로미에 플로트카 (디코딩)
Efficient Go - Bartlomiej Plotka
회사 동료분이 관심 있으실 것 같다면서 추천해주신 책이다. 존재는 이미 알고있었지만 이렇게 또 추천을 해주셔서 읽어보지 않을 수 없었다.
일할 때 Go를 사용하고 있기도 하고 최적화를 좋아하기도 해서 흥미가 갔다. 또 현재 직장에서 Observabiltiy 관련 프로젝트를 진행하고 있는데 책의 일부분이 이를 다루고 있고 저자가 Prometheus maintainer라고 하니 기대되기도 했다.
내용이 많아서 글은 한 3-4편 정도로 끊어서 올릴 것 같다.
Chapter 1: 소프트웨어 효율성이 중요한 이유
일반적으로 소프트웨어의 효율성이라 하면 속도의 동의어로 간주하겠지만 저자는 정확도 (소프트웨어가 예상대로 잘 동작하는지), 효율성 (여기서는 자원의 효율성을 의미한다), 속도 (작업을 완료하기 위해 일이 얼마나 빠르게 수행되는지)의 곱으로 이를 정의한다. 그리고 여러 오해들을 바로잡으며 개발 중에도 (그리 까다롭지 않다면) 소프트웨어의 효율성을 고려해서 개발하는 것이 이득이라 이야기한다.
이 세 가지를 언급한 만큼 앞으로 다양한 방면으로 소프트웨어의 효율성을 높일 수 있는 방법에 대해 다룰 것이 기대됐다.
개발을 진행할 때 너무 투머치로 확장성을 생각해서 개발하는 때가 많은데 (책에는 무조건 따르는 것은 좋지 않다 이야기하지만) YAGNI(You Aren’t Going to Need It) 원칙을 상기하도록 노력해야겠다.
Chapter 2: 효율적인 Go 언어
Go 언어의 역사와 철학, 문법에 대해 설명한다.
godoc이라는 문서화 도구의 존재를 모르고 있었는데 잘 활용하면 코드를 빠르게 이해할 수 있어 좋을 것 같았다. (더 신경써서 주석을 달아야겠다.) (외부 패키지를 이해하기 위해 많이 참조하는 https://pkg.go.dev/ 사이트에 생성되는 문서도 godoc을 이용해서 만들어진다고 한다.)
회사 Go 버전이 Generic을 지원하지 않는 줄 알았는데 사용가능할 것 같다. (Go 1.18부터 지원한다고 함.)
대충 Go를 사용하는 이유가 빠르기 때문이라고 알고있었는데 Java가 더 빠른 경우도 있다길래 놀라웠다. 저자는 시간과 여유가 있다면 모든 언어는 기계와 운영체제가 허용하는 만큼 빠를 수 있으며 그렇기 때문에 어떤 언어가 빠른지와 같은 질문은 잘못됐다고 이야기한다. 많은 회사들이 제품들을 Go로 migration한 이유는 효율적인 코드를 보다 쉽게 작성할 수 있는 이유가 크다고 한다.
나도 Go를 써보면서 느꼈지만 Go 문법은 아주 단순하기 때문에 많은 사람들이 코드를 작성해도 그 스타일은 비슷할 수 없다는 점에서 코드의 가독성을 올리고 스타일에 대해 고민할 필요를 없애 장점으로 다가왔다.
자체적으로 제공하는 성능좋은 여러 기본 라이브러리도 Go의 장점 중 하나다.
Chapter 3: 효율성 완전 정복
(챕터 이름처럼 실제로 효율성을 완전 정복한 것 같지는 않다.)
당연한 이야기지만 여러 요소를 잘 tradeoff 해서 최적의 지점과 가깝게 개발하는 것이 좋다고 이야기한다. (물론 tradeoff 없이 성능을 좋게 만든다면 안 할 이유는 없다.)
결론적으로 너무 세세하고 복잡한 것을 다루기 보다는 큼지막한 것들 위주로 최적화하는 것이 좋아보인다. (회사에서도 이런 비슷한 이야기를 들은 적이 있었는데 simple is best라는 말이 괜히 나온 말이 아니다.)
기능 요구사항 FR(Functional Requirements) 에 자원 효율성 요구사항 RAER(Resource-Aware Efficiency Requirements) 를 추가하는 것이 좋다고 한다. 효율성 요구사항을 만들기 위한 좋은 표준 프로세스가 정의되어 있지 않아서 저자가 직접 정의하기까지 하는데 사실 이게 가능한 일일지는 모르겠다.
저자의 풍부한 경험이 어떤 기능을 담은 소프트웨어가 어떤 자원을 얼마나 요구하며 어느정도의 실행 속도를 가질 것인지 예측할 수 있도록 단련시켰는지는 모르겠지만 개발자 대다수가 가능한 일같아 보이지는 않는다.
하드웨어나 소프트웨어의 스팩은 시간이 지나면서 계속 바뀌며 그에 따라 RAER를 유지보수도 해야할 것이다. 이는 곧 그에 수반하는 비용을 의미하며 실제로 유지보수가 가능할지도 문제이다. (특정 package가 업데이트되면서 성능이 좋아졌다고 했을 때 이를 알아차리고 RAER를 업데이트하기란 쉽지 않을 것이다.)
또한 실제로 개발을 했을 때 자원에 영향을 미치는 어떠한 변수가 작용할지 모르기 때문에 개발 전 RAER를 정의한다는 것은 너무 이상적으로 들렸다.