레이블이 programming language인 게시물을 표시합니다. 모든 게시물 표시
레이블이 programming language인 게시물을 표시합니다. 모든 게시물 표시

2019-04-06

managed language와 unmanaged language?

얼마 전 우연히 이런 글을 보게 됐다. 프로그래밍 언어를 managed language와 unmanaged language로 구분한 것인데 그 기준을 garbage collection(a.k.a. GC)을 하는가 아닌가로 잡았다. 난생처음 들어보는 기준이었다. 인생이 힘들어서 노느라 바쁜 사이 뭔가 새로운 논문이 나왔나 하고 찾아봤다.

역시나 이런 경우 대부분 그렇듯이 다른 나라에서는 안 쓰이고 다른 나라에서는 안 쓰이고 우리나라에서 작성된 블로그만 보였다. 그 블로그들이 공통으로 언급하는 것으로 보아 어떤 사람이 유튜브에서 처음 사용한 것 같다. 사실 다른 나라에서는 안 쓰이는 기준이라는 건 별로 중요하지 않다. 그보다 중요한 건 이 managed language라는 것이 잘못 붙여진 이름이라는 것이다.

일단 managed/unmanaged라는 용어 자체가 없는 것은 아니다. 이건 MS 진영에서 만든 용어다. MS는 managed language 대신 managed code라는 단어를 주로 쓰기는 했지만 말이다. MS에서 만든 managed code는 Common Language Runtime(a.k.a. CLR)에서 실행되는 코드를 의미한다. 반대로 CLR에 의존하지 않는 코드를 unmanaged code라고 부른다.

물론 CLR이 제공하는 기능에 GC가 포함되기 때문에 managed code는 GC을 사용한다. 하지만 GC에 초점을 맞추면 안 된다. 여기서 중요한 것은 virtual machine 위에서 코드가 실행된다는 것이다. virtual machine 위에서 돌기 때문에 컴퓨터 아키텍쳐에 따라 새로 컴파일할 필요 없다거나, 다른 머신에서도 같은 동작을 기대할 수 있다는 등 CLR의 장점에 주목해야 한다.

한때는 managed code를 생성할 것을 목표로 설계된 C#, Visual Basic 같은 언어를 managed language라고 부르기도 했지만, 요새는 잘 안 보인다. 안 쓰이게 된 이유는 모르겠다. 그저 C++을 이용해 CLR을 쓸 수 있게 해주는 C++/CLI 같은 프로젝트가 나오면서 구분할 필요가 없어진 것이 이유가 아닐까 추측할 뿐이다. 그렇다면 MS의 managed code는 둘째치고 GC를 사용하는가 아닌가를 기준으로 managed language라는 새로운 기준을 만들면 안 되는 것일까?

결론부터 말하면 오해를 줄 수 있기 때문에 안 된다. GC를 쓰는가 아닌가를 기준으로 언어를 나눌 수는 있다. 이건 의미 있는 기준이다. 하지만 그 기준으로 붙여진 이름이 managed language이면 안 된다. 이 이름은 메모리를 자동으로 관리하는 방법이 GC뿐이라는 오해를 주게 된다.

10년 전에는 GC를 사용하는 언어를 기준으로 managed/unmanaged를 나눠도 이상하지 않았을 것이다. 당시에는 메모리를 자동으로 관리하는 방법이 GC를 쓰는 것밖에 없었기 때문이다. 하지만 2002년 David Walker 교수가 정리한 linear type system이나 affine type system에 대한 개념을 기반으로 리소스를 안전하게 사용하는 방법에 대한 많은 연구가 있었고, 현대 프로그래밍 언어들은 이에 관한 개념을 적극적으로 반영하고 있다. 심지어 C++마저도 말이다. 특히 저 글에서 unmanaged로 구분하고 있는 Rust 같은 경우가 affine type system을 적극적으로 사용하여 메모리를 관리하는 대표적인 언어다. 즉, 이제는 GC가 메모리를 자동으로 관리하는 유일한 방법이 아니다.

분류는 새로운 개념을 쉽게 배우게 해주는 좋은 도구다. 분류라는 것은 추상적이고 많은 개체의 속성을 분명하고 외우기 쉽게 해준다. 하지만 이것은 어디까지나 기준이 명확하고 용어가 올바를 때의 얘기다. 잘못된 기준으로 분류하거나 잘못 도니 이름을 사용하게 되면 오히려 배움에 방해가 될 뿐이다.

2018-05-13

2018년 19번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다.
 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다.


C Primer

Primer를 입문서라고 번역하는 게 맞는지 모르겠지만, 어쨌든 C 입문서라고 이름 붙인 문서 중에서 가장 마음에 든다. 다른 언어는 잘 추상화된 모델을 다루는 것이 중요하지만 C는 아니라고 생각한다. C는 내가 사용한 코드가 어떻게 변환되어 실행되는지 기계 단위로 이해하고 있어야 한다. 그럴 필요가 없는 상황에서는 C가 아닌 다른 언어를 써야 한다.

C Is Not a Low-level Language

C가 low-level 언어는 아니라는 글이다. 전통적으로 low-level 언어는 머신에 대한 추상화 없이 기계어와 일대일 대응되는 언어를 의미한다. 당연히 이런 의미에서 C는 low-level 언어가 아니다. C는 나름의 abstract machine을 가지고 있다. 특히 C11 이후로는 멀티 쓰레드에 대한 개념도 abstract machine에 들어갔기 때문에 전통적인 의미에서 low-level 언어는 아니다.

그렇다고 해서 C가 다른 high-level 언어와 같다는 의미는 아니다. 다른 high-level 언어들은 실제 기계어로 어떻게 번역되는지 몰라도 될 정도로 abstract machine을 정의한다. 하지만 C는 아니다. 사실 나는 C의 abstract machine도 기계를 몰라도 사용할 수 있을 정도로 잘 정의돼있다고 생각한다. 문제는 C를 사용하는 사람들이 실제 기계에서 어떻게 돌아가는지 고려하면서 코드를 작성한다. 이건 C언어 커뮤니티의 문제는 아니다. 사실 기계 레벨에서 어떻게 돌아가는지 고려하지 않아도 되는 프로젝트에서 C를 사용하는 것은 얻는 것에 비해서 비용이 크기 때문이다.

카카오스토리 웹팀의 코드리뷰 경험

코드리뷰 없는 프로젝트는 있을 수 없다고 생각한다. 하지만 발표자가 말하듯이 시스템적으로 반드시 리뷰해야 머지할 수 있는 시스템은 별로라고 생각한다. 경험적으로 이런 시스템은 반드시 문제가 생긴다. 간단한 예로 휴가철에 급하기 hotfix를 넣어야 하는데 휴가 안 간 사람이 한 명밖에 없을 때, 휴가 간 사람이 강제로 업무를 하게 되는 경우가 있다. 굳이 휴가철이 아니더라도 급한 버그를 위해 야근이나 주말 근무를 하는 경우도 마찬가지다. 시스템적으로 머지에 리뷰를 강제하게 되면, 버그를 잡고 머지 하기 위해서 버그 잡는 사람 외에 누군가가 남아있어야 한다. 결코 바람직하지 않은 상황이다.

리뷰를 받을지 말지 패치를 만든 사람의 판단으로 선택해야 한다. 그 패치가 리뷰를 받아야 할지 안 받아도 되는지는 패치를 작성한 사람이 가장 잘 안다. 이건 패치 만드는 사람의 판단을 따라야 한다. 만약 이 정도 판단을 믿지 못한다면, 그 사람에게는 코딩을 맡기면 안 된다. 바람직한 개발 프로세스는 상호 신뢰에서 나온다고 생각한다. 기본적인 신뢰 관계가 없는 팀에서는 아무리 좋은 프로세스를 선택하더라도 유지될 수 없다.

개발 스타일은 툴로 체크해야 한다는 것에도 동의한다. 툴로 체크할 수 있는 걸 사람이 보고 있는 건 시간 낭비다. 다만 윗글에서 나온 대로 수정한 코드에 대해서만 체크할 수 있는 툴은 찾기 어렵다. 그래서 나는 한 번 대대적으로 프로젝트의 스타일을 수정하고 시작하는 것을 더 선호한다. 이렇게 되면 작업하고 있던 사람들과 컨플릭이 나거나 blame으로 찾을 수 있는 이력이 더럽혀진다는 문제가 있다. 하지만 이런 문제가 통일되지 않은 스타일로 프로젝트가 계속 진행되거나, 리뷰마다 스타일을 눈으로 체크하는 것보다는 더 싸게 먹힌다고 생각한다.

By the numbers: Python community trends in 2017/2018

2017, 2018년도 python community를 분석한 글이다. 개인적으로는 Types of Python development 파트에 나오는 파이썬 사용자를 분야별로 나눈 파트다. 보면 파이썬 사용자는 크게 data scientist와 웹 개발자로 나눠진다는 것을 알 수 있다. 특히 data scientist를 다 합치면 웹 개발자보다 많은 비중을 차지한다. 이는 파이썬이 사용하기 편하다는 점도 있지만, numpy, PyTorch, TensorFlow 등 다른 언어에서는 찾기 힘든 좋은 툴들이 많이 있기 때문이라고 생각한다. 당장 나만 해도 개발할 때는 정적 타입 언어를 선호하지만, 자료 분석이나 수치 분석을 할 때 파이썬 외에 다른 언어를 사용하지 않는다.

그 다음으로 눈에 보이는 것은 파이썬과 함께 사용하는 언어로 JavaScript가 1위를 차지했다는 것이다. 개인적으로는 파이썬의 반대되는 컴파일된느 언어나 정적 타입 언어들과 함께 사용할 것이라고 생각했고, 언어적 특성이 비슷한 JavaScript와 함께 사용할 것이라고 생각하지 않았다. 2위가 HTML/CSS인 것을 보면 이는 파이썬 사용자의 절반 정도가 웹 개발을 하기 때문으로 보인다.

다음으로 인상적인 것은 Python 3의 사용자가 Python 2의 3배쯤 사용된다는 것이다. 몇 년 전만해도 많은 Python 2 사용자들이 Python 3로 넘어가지 않고 버티고 있었고, 많은 라이브러리가 Python 2만 지원했었던 것을 생각하면 시대가 많이 좋아진 것 같다.

가장 놀라운 것은 VCS를 안 쓰는 사람이 38%나 된다는 것이다. VCS를 안 쓰고 개발이 관리가 되나 싶은데 안 쓰는 사람이 38%나 된다. 심지어 테스트를 안 짜는 사람(19%)보다 많다.

Quantum resource estimates for computing elliptic curve discrete logarithms

일반적으로 현대 컴퓨터에서 elliptic-curve cryptography(a.k.a. ECC)는 같은 길이의 키를 가지는 RSA 방식보다 더 풀기 어렵다고 말한다. 예를 들어 키 크기가 256 bit인 ECC와 같은 보안 레벨을 가지려면 RSA는 3072 bit 키를 사용해야 한다고 한다. 하지만 양자 컴퓨터가 도입되면 이야기가 달라진다. 양자 컴퓨터로 쇼어 알고리즘을 사용하면 비대칭키 암호화 방식을 깰 수 있는데, 3072 bit RSA를 깨는데 6146 qubit이 필요하지만, 256 bit ECC를 깨는 데는 2330 qubit밖에 필요하지 않다. 여전히 같은 키 크기에서 RSA보다 ECC가 안전하지만, 기존에 안전하다고 여겨지던 것보다는 차이가 많이 줄어든다. 다행이도 아직은 양자컴퓨터가 수십 qubit 수준에서 연구 중이기 때문에 최소한 십 년 운 좋으면 몇십 년 내에서는 별문제 없을 것이라고 생각한다.

Announcing Rust 1.26

Rust 1.26이 나왔다. 일단 눈에 띄는 변화는 다음이 있다.

함수의 인자와 리턴 타입으로 impl Trait 허용

Rust의 trait은 크기가 없기 때문에, 함수의 인자로 받거나 리턴할 수 없었다. 이런 경우 Box로 싸거나, generic을 써야 했다. 이를 impl Trait라는 문법을 추가해서 간단하게 사용할 수 있도록 했다.

레퍼런스 타입 match 할 때, 자동으로 dereference

기존에는 레퍼런스 타입을 매칭하면 패턴 부분에도 전부 레퍼런스라는 것을 명시해야 했다. 이제는 레퍼런스를 자동으로 dereference하기 때문에 &ref를 쓸 필요가 없다.

main 함수가 Result 리턴할 수 있도록 허용

ErrDebug를 구현해야 한다는 제약이 있지만, 이제는 main 함수가 Result를 리턴할 수 있다. 리턴한 값이 Err라면 리턴한 Err를 출력하고 종료한다.

2018-04-29

2018년 17번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다.
보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다.


The Configuration Complexity Clock

Configuration을 만들다 보면 Rules engine이나 심할 때는 DSL(Domain Specific Language)까지 만들기도 하는데, 어떨 때는 그냥 하드코딩 하는 것이 가장 적절한 방법일 수 있다는 글이다.

Linus's Law

given enough eyeballs, all bugs are shallow

리누스의 법칙은 위의 한 줄로 정리된다. 오픈 소스의 근간이 되는 문장이고, peer-review가 필요한 이유로도 많이 언급된다. 문제는 최근의 거대한 소프트웨어서는 버그를 발견하는 데 필요한 enough의 수가 너무 크다는 것이다. 게다가 시스템이 복잡하다면, 그 시스템을 이해하지 못한 개발자는 버그를 발견하기 위한 eyeballs 중 하나가 되지도 못한다. 그렇기 때문에 시스템을 단순하게 유지하는 것이 중요하다.

Language Health

각 언어가 오픈 소스에서 얼마나 많이 사용되는지 비교해보는 사이트다. 다만, 어디까지나 오픈소스에서 얼마나 많이 커밋이 있었는지에 대한 비교이지, 얼마나 많은 사람이 사용하는지나, 클로즈드 프로젝트에서 얼마나 많이 사용하는지는 알 수 없다.

An introduction to the GNU Core Utilities

리눅스에서 작업하다 보면 필요한 유틸리티 모음. 터미널에서 작업할 때 알면 좋은 것들이다.

REST APIs are REST-in-Peace APIs. Long Live GraphQL.

GraphQL의 장점에 관해서 쓴 글이다. 근데 여전히 GraphQL을 쓸지는 모르겠다. 복잡한 웹 서버를 짤 일이 있으면 모르겠는데 요새는 웹 서버라기보다는 그냥 간단한 툴의 UI를 웹으로 사용하는 정도로만 웹 코딩을 하고 있다. 이 정도 수준의 앱에서는 GraphQL을 사용하는 것이 오버헤드가 더 클 것 같다. 사실 반대로 말하면 뭘 써도 상관 없는 크기라서 GraphQL을 써도 된다. 하지만 다른 라이브러리에 디펜던시 없이 구현할 수 있는 REST에 비해서 GraphQL을 쓰려면 GraphQL을 구현하는 라이브러리를 써야 하므로 의존성을 추가해야 하는데 아직 그만한 필요성을 못 느끼겠다.

GO's New Brand

GO가 새 로고를 발표했다. 드디어 이상한 쥐를 버린 줄 알았는데 Gopher는 마스코트로 여전히 남겨두는 듯 하다.

Flask 1.0 Released

Flask가 드디어 1.0이 됐다. 사실 전에도 0.X인걸 신경 쓰지 않고 썼기 때문에 상관없지만 1.0을 쓰면 괜히 기분이 좋다.

2018-04-14

2018년 15번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다.

보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다.


실제로 git을 사용하면서 단순히 커맨드를 외워서 사용하는 사람들을 많이 봤다. 보통 그 이유로 크게 두 가지를 든다. 첫 번째로 git의 mental model이 복잡하다는 것이다. git에서 변경된 내용은 크게 다음 상태 중 하나가 된다.

  1. 리모트에 존재하는 상태
  2. 로컬 브랜치에 있는 상태
  3. 브랜치에 머지되지 않았지만 add 돼 있는 상태
  4. 변경은 있지만 add 되지는 않은 상태
  5. stash에 들어있는 상태
  6. 예전에 커밋했었지만 지금은 브랜치로 따라갈 수 없는 상태

이 중에서 내가 수정했던 내용이 어떤 상태인지 모르는 것이 헷갈리게 하는 첫 번째 이유다.
하지만 반대로 왜 이렇게 많은 상태를 가지게 됐을지 생각해보면 git을 사용하는 데 도움이 된다. 이것들은 전부 그냥 추가된 것이 아니다. 애초에 git을 처음 만든 사람은 Linus Torvalds다. 그의 성격상 쓸모없는 것은 추가되지 않았다. 전부 제각각의 목적을 가지고 있다. 이 목적을 이해하는 것이 중요한데 아쉽게도 글로 잘 설명할 자신이 없다. 사실 이걸 이해하는 가장 빠르고 확실한 방법은 svn을 써보는 것이다. 쓰다 보면 불편한 부분들이 자주 생기는데, git에서는 위에서 말한 것들을 이용해 이를 쉽고 빠르게 해결할 수 있다.

사람들이 git을 어려워하는 두 번째 이유는 명령어가 복잡하다는 것이다. 이건 어쩔 수 없다. 사실 git의 명령어는 규칙성 없이 만들어졌다. 그래서 외우는 수밖에 없다. 하지만 어떤 상황에서 어떤 명령어를 써야 한다는 식으로 외우면 끝이 없다. 그보다는 각 명령어가 어떤 상태와 연관이 있는지를 보는 것이 좋다. git 명령어는 대부분 변화된 내용을 위의 상태 중 하나로 만들거나, 특정 상태로 로컬에 있는 파일을 변경하는 것이다. 따라서 현재 파일이 어떤 상태에 있고 명령어 이후 어떤 상태로 된다는 것을 인지하고 있으면 조금은 더 쉽게 적응할 수 있다.

News is bad for you – and giving up reading it will make you happier

뉴스가 사람의 정신건강에 해롭다는 기사다. 사람들이 흔히 정보를 얻으려고 뉴스를 읽지만, 실제로는 별 도움도 안 되고 시간만 낭비하게 하고 사람의 창의성을 없애고 수동적으로 만든다는 것이다.

Introduction to zkSNARKs

이더리움의 최근 움직임 중에서 zero-knowledge proof인 zkSNARKs을 도입하고자 하는 움직임이 있다. 위 자료는 이더리움 소속으로, 솔리디티 창시자 중 하나이며 zkSNARKs를 구횬하고 있는 Christian Reitwiessner이 zkSNARKs에 대해 간단히 소개한 발표자료다. 자료 이름은 zkSNARKs이지만 대부분의 내용을 zero-knwledge proof가 무엇인지에 설명하는 데 쓰고 있으므로 zero-knowledge proof가 무엇인지 알고 싶은 사람들이 보기에도 좋은 자료다.

RSS is undead

RSS는 이미 수명이 끝났고, 다시 살아날 리 없다는 글이다. 지난번에 소개했던 It's Time for an RSS Revival이나 Why RSS Still Beats Facebook and Twitter for Tracking News의 반대편에 있는 입장이다.

RSS는 소규모 사이트의 글을 구독하는 데는 적절하지만, 대형 사이트의 특정 카테고리의 글을 구독하는 데는 적당한 UX를 제공하지 못하고, 퍼블리셔 입장에서 사용자의 패턴을 파악할 수 없을뿐더러 광고수익을 얻을 수 없기 때문에 사용자와 퍼블리셔 양쪽에게 손해라는 것이다.

What is a “box model”? (UI Element layout)

Web을 비롯하여 현대의 많은 UI framework들이 box model을 사용하기 때문에 프론트엔드 개발을 하려면 한 번 읽어두는 것이 좋다.

The Science of The Job Search, Part III: 61% of “Entry-Level” Jobs Require 3+ Years of Experience

경력 같은 신입을 원하는 건 우리나라뿐 아니라 전세계 공통인듯하다.

A fork on Github is no fork

Git은 decentralized 된 version control system이기 때문에 fork를 하면 어디서 fork 해왔는지와 완전히 독립적인 repository로 존재할 수 있다. 하지만 Github의 fork는 그 모든 설정과 권한이 원본 repository에 종속적이기 때문에 진짜 fork가 아니라는 글이다.
원칙적으로 맞기는 하지만 Github Enterprise나 private repository 유료 모델을 생각해보면 어쩔 수 없는 선택이었다고 생각한다.

Uninhabited types are ZSTs despite partial initialization being allowed in safe code.

Rust 1.24.0 이후 생긴 memory safety가 깨지는 버그다.

Rust는 무한루프나 내부에서 exit 하기 때문에 return 되지 않는 함수를 표현하기 위해서 uninhabited type을 도입했다. 이 uninhabited type으로 product type을 만들면 이 타입도 uninhabited type이 돼서 크기가 0인 type으로 계산되는데, 이 product type의 다른 field를 접근하는 게 가능해서 주소 계산이 잘못되는 버그가 발생했다. Rust에 zst(zero size type)가 도입됐을 때부터 메모리 주소 계산을 잘못 하는문제가 발생하지 않을까 생각했는데 정말로 터져버렸다.

현재 두 가지 해결 방안 중에서 어느 쪽으로 해결할지 논의 중이라고 하니까 다음 버전인 1.26.0에서는 수정될 것으로 보인다.

Top 10 Bugs in the C++ Projects of 2017

소프트웨어 분석 회사인 viva64에서 2017년 동안 발견했던 버그 중 가장 인상 깊은 버그 10개를 발표하였다. uninitialized memory부터 type error나 단순 실수까지 다양하게 있다.

Don’t Give Away Historic Details About Yourself

자기 정보를 쉽게 제공하지 말라는 글. 특히 우리나라 사람들은 주민등록번호 유출에조차 익숙해져서 그런지 자기 정보를 적는데 아무런 망설임이 없다.

Why Does "=" Mean Assignment?

수학에서는 보통 대입에는 :=를 사용하고 =는 비교에 사용한다. 근데 프로그래밍에서는 왜 =를 대입에 사용하게 됐는지에 관한 글이다. 뭐 지금은 다들 =를 대입연산자로 사용하고, ==를 비교연산자로 사용하는 데 익숙하기 때문에 별 의미는 없지만, 그냥 재미로 읽어봤다.

2016-07-31

Go의 장단점

 지난 4개월 동안 Go로 2개의 프로젝트를 진행하게 되었다.
 한 프로젝트는 비동기적인 웹 서버를 작성하는데, 실행파일이 네이티브 바이너리로 나올 필요가 있었다. C나 C++은 웹서버를 만드는 것도, 비동기적인 작업을 하는 것도 간단하게 되지 않기에 Rust와 Go 중에서 고민하다가 Go를 사용하기로 했다.
 다른 한 프로젝트는 큰 파일을 다운받아서 라인 파싱하고, rest API로 데이터를 요청하고, 그래프를 만들어 자료를 분석하여야 했다. 워낙 큰 파일을 파싱해야 해서 JavaScript는 사용하기 싫었고, 며칠을 밤낮으로 돌아가야 하는 코드인데 별도의 검증을 할 수 없는 Python으로는 실행 중 버그가 발생했을 때 손실되는 시간이 크기 때문에 사용하기는 싫어서 Java, Scala, Go 중에서 고민하다가 Go를 쓰기로 했다.
 이번 글에서는 Go를 사용하면서 느꼈던 장단점에 대해서 간단히 써보도록 하겠다.

장점

학습 속도가 빠르다.

 Go는 공식 튜토리얼만 읽으면 다른 사람이 쓴 코드를 읽고 쓰는데 아무런 문제가 없다. 물론 Go의 튜토리얼 문서가 잘 돼 있기는 하지만, 다른 언어에 비해 크게 뛰어난 것은 아니다. 그냥 Go에는 프로그램을 작성하는데 필수적인 최소 기능들만 들어가 있기 때문이다.

Channel 기반 언어

 Go는 대표적인 채널 기반 언어이다. 스레드라는 것을 명시적으로 주지 않고 goroutine을 생성하면 알아서 스레드를 생성해주고 적절한 스레드에 goroutine을 할당한다. goroutine 사이의 커뮤니케이션을 전부 채널을 통해서 한다면, 귀찮은 동기화 문제를 신경 쓰지 않아도 된다.

네이티브 바이너리가 나온다.

 결과를 배포하는 입장에서 네이티브 바이너리가 나온다는 것은 매우 큰 장점이다. 요즘은 대부분 서버에 파이썬이나 JVM이 설치되어 있지만, 역시 배포는 네이티브 바이너리로 하는 것이 가장 편하다.

컨벤션이 통일되어 있다.

 Go는 컨벤션에 대한 논쟁이 전혀 없다. go에는 컨벤션에 맞춰서 코드를 수정해주는 go fmt라는 기능이 내장되어 있다. 개발자는 그저 go fmt을 돌리기만 하면 되기 때문에, 별도로 스타일 논쟁이 발생할 일이 없다. 코드를 올리기 전에 go fmt을 돌리는 것조차 귀찮은 사람을 위해서 vim-go 같은 플러그인이 있어서 개발자는 스타일을 신경 쓰지 않고 코드를 작성하기만 해도 컨벤션에 맞출 수 있다.

인터페이스 기반의 폴리모피즘

 Go에서 폴리모픽한 코드를 작성하는 유일한 방법은 인터페이스를 인자로 넘기는 것이다. 이 덕분에 인터페이스 단위의 추상화가 자연스럽게 이루어진다.

단점

verbose 한 코드

 Go는 템플릿도 매크로도 없다. 이는 Go의 코드를 단순하게 만들어주는 장점도 있다. 하지만 템플릿도 매크로도 없어서 단순한 코드가 반복해서 등장한다.

type introspection

 모든 폴리모피즘이 인터페이스를 기반으로 돌아가기 때문에 구체적인 구조체 타입별로 다른 동작을 하기 위해서는 type introspection을 통해서 타입을 체크해야한다. 그래서 Go는 정적 타입 언어임에도 불구하고 아래처럼 동적 언어에서나 볼법한 코드가 나온다.

interface{}

 게다가 표준 라이브러리는 interface{}의 사용을 적극적으로 권장한다. 예를 들어 list 같은 자료 구조의 경우 템플릿이 존재하지 않기 때문에 특정 타입의 값을 담는 자료구조를 만들 수 없어서 interface{} 타입의 값을 추가하고 interface{} 타입의 값을 리턴하는 자료구조를 만들 수밖에 없다. 이러한 자료구조 때문에 type introspection을 자주 사용할 수밖에 없고, 동적 타입 언어에서나 볼법한 코드가 나오게 된다.

어설픈 최적화

 Go는 함수를 inline 시키는 최적화를 하지 않는다. 다른 언어라면 별문제 없을 수도 있다. 하지만 Go는 함수를 사용할 일이 많다.
 예를 들면 자원 관리나, recover 등을 위해서 defer를 사용할 일이 많은데 defer는 함수 단위로 호출된다. 따라서 특정 시점에서 자원을 해제시키고 싶다면 새로운 함수를 만들어 새 안에서 defer 함수를 호출해야 한다. 이 모든 함수가 인라이닝 되지 않기 때문에 실제로 스택 프레임을 변경시켜가며 함수를 호출했다 해제하는 일을 한다.

라이브러리 버전 관리

 Go는 언제나 하나의 실행파일을 컴파일한다. 정적 라이브러리나 동적 라이브러리를 배포할 수 없고, 소스를 가져와서 컴파일하는 방식을 사용한다. 이는 딱히 나쁜 방식이 아니다. 현대의 패키지 매니저 중 많은 것들이 이런 방식을 취한다.
 문제는 Go에는 라이브러리의 버전을 명시할 방법이 없다는 것이다. 만약 사용하고 있던 라이브러리가 버전업을 해서 인터페이스가 변경되거나 버그가 발생하거나 해서 옛 버전을 사용해야 할 경우 문제가 되는 라이브러리뿐 아니라 모든 라이브러리의 버전업을 할 수 없다.

변화에 민감한 스타일과 문법

 Go는 컨벤션이 정해져 있는 것이 장점이라고 위에서 말했다. 컨벤션이 정해져 있다는 사실은 꽤 편하다. 하지만 몇몇 부분에서 잘못된 스타일을 사용한다.
  예를 들면 Go는 필드의 타입 부분을 인덴트를 맞춘다. 따라서 아래와 같이 짧은 이름의 필드만 있던 구조체에 긴 이름의 필드가 추가되면 긴 이름에 맞춰서인덴트를 바꾼다. 이런 컨벤션은 보기 좋아 보일 수도 있다. 하지만 이런 스타일은 이력을 더럽히기 때문에 좋지 않다.  위와 같은 변경이 있으면 실제로는 필드가 한 개 추가된 것이지만, 버전 관리 도구에서는 한 개의 필드를 지우고 2개의 필드를 추가한 것처럼 나오게 된다. 지난번 포스트에서도 말했듯이 코드의 스타일은 사용하는 도구를 따라가야 하고, 개발에서 버전 관리 도구는 때놓을 수 없으므로 버전 관리 도구에 친화적인 스타일을 사용하는 것은 중요하다.

결론

 Go는 장점이 분명하다. 러닝 커브가 완만하므로 팀원에 누가 들어오더라도 쉽게 적응할 수 있다. 하지만 이 점을 제외하면 단점이 장점보다 많다. 다만, 지금까지 썼던 네이티브 바이너리가 나오는 언어 중에서 가장 학습하는데 걸리는 시간이 짧았다는 점은 중요하다고 생각한다. 네이티브 바이너리가 나오는 것이 가장 중요한 요구 사항이라면 Go를 고려해볼 만 하겠지만, 그 외의 상황에서 Go를 사용하지는 않을 것 같다.