Copyright © Origin Corp. All Rights Reserved.
v1.0.10
로딩 중입니다
행복에는 덕이면 충분하다안티스테네스

코드를 더 똑똑하게 만들수록 팀의 하루가 더 느려질 때가 있다. 작은 수정 하나를 했는데 전체 프로그램이 다시 만들어지는 시간을 기다려야 하고, 누군가가 남긴 복잡한 구조를 이해하느라 실제 변경보다 읽는 시간이 더 길어지는 순간이다. Go는 이런 장면을 배경으로 이해해야 한다.
Go는 2007년 Google 내부에서 Robert Griesemer, Rob Pike, Ken Thompson의 논의로 시작되었고, 2009년 11월 공개 오픈소스 프로젝트가 되었다. 오픈소스란 코드와 개발 과정이 공개되어 여러 사람이 함께 쓰고 발전시킬 수 있는 방식이다. 공식적으로 Go는 Google이 지원하는 오픈소스 언어이며, 단순한 학습, 팀 개발, 내장 동시성, 표준 라이브러리를 강점으로 내세운다.
여기서 중요한 출발점은 “Go가 무엇인가”보다 “왜 그런 언어가 필요했나”에 가깝다. Go는 Google에서 대규모 코드와 많은 개발자가 함께 일할 때 생기는 느린 빌드와 복잡한 개발 흐름을 줄이려는 문제의식에서 출발했다. 대규모 코드베이스는 많은 파일과 모듈, 여러 개발자가 함께 다루는 큰 프로그램 묶음이고, 컴파일은 사람이 쓴 코드를 실행 가능한 형태로 미리 바꾸는 과정이다.
규모가 커지면 언어의 기능이 많다는 사실이 늘 장점으로만 작동하지 않는다. 선택지가 많을수록 읽는 방식도 늘어나고, 빌드와 도구 흐름이 무거워질 수 있다. 그래서 Go의 단순함은 취향이나 초심자 배려만으로 보면 핵심을 놓치기 쉽다.
Go는 새 문법을 많이 발명하려는 언어라기보다, 큰 소프트웨어를 더 다루기 쉽게 만들려는 공학적 도구로 설계되었다고 볼 수 있다. 이 관점에서 보면 Go의 간결한 문법은 빈약함이 아니라 비용을 줄이려는 선택에 가깝다. 다음 질문은 자연스럽다. 문제가 느린 빌드와 복잡한 협업이었다면, Go는 왜 기능을 더 넣는 대신 줄이는 쪽을 택했을까?

어떤 언어는 편리한 기능을 더해 문제를 푼다. Go는 반대로, 먼저 줄여서 문제를 작게 만들려 했다. 그래서 Go를 처음 볼 때 “문법이 적어서 쉬운 언어”라고만 이해하면 중요한 지점을 놓치기 쉽다. Go의 단순함은 비어 있음이 아니라, 복잡성이 어디서 생기는지 강하게 의식한 결과에 가깝다.
Go는 정적 타입의 컴파일 언어다. 정적 타입이란 실행 전에 값의 종류를 코드 단계에서 확인하는 방식이고, 컴파일 언어란 코드를 미리 실행 가능한 형태로 바꾸는 방식을 뜻한다. Go는 여기에 빠른 컴파일, 가비지 컬렉션, 동시성 기능을 함께 제공하는 언어로 소개된다. 가비지 컬렉션은 더 이상 쓰지 않는 메모리를 자동으로 정리하는 기능이다.
이 조합에서 중요한 것은 “기능이 많다”가 아니라 “작업 흐름을 예측 가능하게 만든다”는 점이다. Go는 미리 컴파일되는 언어의 단순성과 예측 가능한 실행 특성을 중요하게 본다. 코드를 고치고, 빌드하고, 다시 실행해 보는 과정이 무거워질수록 개발자는 언어 자체보다 주변 복잡성에 더 많은 시간을 쓴다. Go가 간결한 문법과 빠른 컴파일을 앞세운 이유도 이 흐름과 맞닿아 있다.
특히 Go의 단순함은 문법 표면만의 문제가 아니다. 의존성, 타입 시스템, 동시성, 메모리 관리 방식을 의도적으로 정리한 결과로 설명할 수 있다. 언어가 여러 방식의 표현을 많이 허용하면 작성자는 편할 수 있지만, 읽는 사람은 더 많은 가능성을 해석해야 한다. 팀 단위 개발에서는 이 차이가 작지 않다.
초기 Go가 제네릭 없이 출발한 점도 이 맥락에서 볼 수 있다. 제네릭은 여러 타입에 공통으로 쓸 수 있는 코드를 만들게 해 주는 기능이지만, 타입 시스템과 런타임의 복잡성도 함께 고려해야 한다. 런타임은 프로그램이 실행될 때 함께 작동하는 언어의 실행 환경이다. 초기 Go는 편리함을 늘리는 선택보다, 그 편리함이 가져올 구조적 비용을 더 크게 본 셈이다.
그래서 Go의 간결함은 “못 넣은 것”이라기보다 “넣을 때 생기는 비용을 계산한 것”에 가깝다. 초심자에게 이 관점은 꽤 중요하다. Go를 배울 때 기능 목록만 보면 단순해 보이지만, 실제로는 코드를 빠르게 읽고 바꾸고 빌드하기 위한 절제된 설계가 숨어 있다. 문법과 컴파일이 이렇게 정리되어 있다면, 다음으로 봐야 할 것은 이 단순함이 실제 협업 도구 경험에서 어떻게 이어지는가다.
Go에서 단순함은 파일 안의 문법만을 뜻하지 않는다. 팀 개발에서는 코드 자체보다 그 코드를 둘러싼 작은 결정들이 시간을 잡아먹을 때가 많다. 들여쓰기 방식, 줄바꿈 취향, 파일을 어떻게 빌드하고 문서화할지 같은 문제는 사소해 보이지만, 매일 반복되면 꽤 큰 비용이 된다.
코드 리뷰를 떠올려 보면 이해하기 쉽다. 리뷰어가 실제 변경의 의미를 보기 전에 “이 줄은 왜 이렇게 나눴지”, “여기는 공백이 왜 다르지” 같은 문제에 먼저 걸리면, 협업의 초점이 흐려진다. Go에는 gofmt라는 공식 포맷 도구가 있어 코드 형식을 자동으로 맞추는 문화가 강하다. 이 도구는 스타일을 개인 취향의 영역에 오래 남겨 두지 않고, 팀이 같은 모양의 코드를 보게 만드는 쪽으로 작동한다.
여기서 Go의 관점이 조금 달라진다. Go는 단지 문법이 짧은 언어라기보다, 코드를 쓰고 빌드하고 문서화하고 점검하는 과정 전체의 사용감을 함께 고려한 언어에 가깝다. 이런 전체 흐름을 도구 경험이라고 부를 수 있다. 언어를 배운다는 것이 문법 규칙을 외우는 일에 그치지 않고, 같은 방식으로 코드를 다루는 습관을 익히는 일이 되는 것이다.
이 점은 초심자에게 특히 중요하다. 처음에는 gofmt가 단순히 코드를 예쁘게 정리해 주는 기능처럼 보일 수 있다. 하지만 팀에서는 그 이상의 의미가 있다. 형식 논쟁을 줄이면, 사람들은 코드가 실제로 무엇을 바꾸는지에 더 쉽게 집중할 수 있다.
Go의 단순함은 작은 코드를 쉽게 쓰는 데서 끝나지 않고, 단순한 설계를 깨끗하게 키워 가려는 목표와도 연결된다. 여기서 코드 적응성이 중요해진다. 코드 적응성이란 처음에는 작게 시작한 설계를 시간이 지나도 유지보수 가능한 구조로 키워 갈 수 있는 성질이다. Go가 문법과 도구를 함께 단순하게 유지하려는 이유도, 결국 팀이 코드를 오래 읽고 고치며 키워 가야 하기 때문이다.
그래서 Go의 절제는 개인의 취향보다 팀의 반복 작업을 줄이는 방향으로 읽는 편이 더 정확하다. 문법을 적게 만든 것만이 아니라, 사람들이 같은 기준으로 코드를 정리하고 같은 흐름으로 작업하도록 돕는 데까지 생각이 이어져 있다. 그렇다면 다음 질문은 자연스럽다. 여러 일을 동시에 처리해야 하는 서버 개발에서는, Go가 어떤 방식으로 복잡함을 줄이려 했을까.

Go에서 동시에 일하게 만드는 방법은 문법상 매우 간단하다. 함수 호출 앞에 go 키워드를 붙이면 그 일은 별도의 고루틴으로 시작된다. 고루틴은 Go에서 가볍게 시작할 수 있는 동시 실행 단위이고, 서버나 네트워크 프로그램처럼 여러 일을 겹쳐 처리해야 하는 상황에서 자주 등장한다.
하지만 “쉽게 시작할 수 있다”는 말이 “항상 써야 한다”는 뜻은 아니다. 동시성은 여러 일을 겹쳐 진행하도록 프로그램을 구성하는 방식인데, 동시에 움직이는 일이 많아질수록 프로그램의 흐름도 그만큼 추적하기 어려워질 수 있다. 초심자에게 중요한 질문은 “Go는 동시성이 좋다”에서 멈추는 것이 아니라, “Go는 동시성을 어떤 방식으로 생각하게 만드는가”로 옮겨 가는 것이다.
Go의 채널은 고루틴 사이에서 값을 주고받는 통로다. 여러 작업자가 같은 칠판을 동시에 고치는 대신, 필요한 내용을 서로 건네주는 장면에 가깝게 이해할 수 있다. 그래서 Go의 채널은 공유 메모리를 직접 함께 만지는 방식보다 메시지 전달에 가까운 사고를 권한다. 다만 이것이 채널이 모든 동시성 문제의 정답이라는 뜻은 아니다.
경우에 따라서는 뮤텍스처럼 공유 데이터를 동시에 건드리지 못하게 잠그는 동기화 도구가 더 알맞을 수 있다. Go의 고루틴과 채널은 중요하지만, 가능하다고 해서 항상 써야 하는 기능은 아니다. 이 균형이 Go를 이해할 때 꽤 중요하다. Go는 동시성을 내세우지만, 동시성을 과시하기보다 복잡함을 다루는 선택지를 단순한 형태로 제공하려 한다.
Go의 단순함도 완전히 멈춰 있는 것은 아니다. 단순함을 중시하지만 언어가 영원히 고정된 것은 아니며, Go 1.18에서는 제네릭이 추가되었다. 중요한 점은 기능이 하나 늘었다는 사실 자체보다, Go를 기능 목록으로만 기억하면 핵심을 놓치기 쉽다는 데 있다. Go는 많은 기능을 쌓아 올린 언어라기보다, 팀 단위 서버 개발에서 읽기, 빌드, 협업, 동시 작업의 복잡성을 줄이려 한 절제된 언어로 기억하는 편이 더 정확하다.
Go의 단순함은 기능이 부족해서가 아니라, 대규모 코드와 여러 개발자가 함께 일하는 환경에서 빌드, 읽기, 협업의 부담을 줄이려는 선택에 가깝다. 문법만 줄인 것이 아니라 의존성, 타입 시스템, 동시성, 메모리 관리, 그리고 gofmt 같은 도구 경험까지 함께 정리하려 한 언어로 볼 수 있다.
물론 고루틴과 채널이 중요하다고 해서 모든 동시성 문제의 정답이 되는 것은 아니다. 그래서 Go는 많은 기능을 자랑하는 언어보다, 팀 단위 서버 개발에서 읽기 쉽고 빠르게 빌드되며 동시 작업을 다루기 쉽게 하려는 절제된 설계 선택으로 기억하는 편이 정확하다.
2
개