Go언어를 소개하는 글에서는 보통 Go언어의 장점을 강조한다. 여러 언어를 비교하는 글에서는 Go언어의 장점과 단점을 모두 설명하지만 집중적으로 다루지는 않는다. 물론 모든 글이 그렇다는 것이 아니라 대개 그렇다는 것이다. 그저 선택과 집중의 문제일 뿐이다. 필자는 Go언어를 좋아한다. 하지만 코드를 작성하다 보면 불편할 때가 있다. 이 글에서는 필자가 코드를 직접 작성하면서, 혹은 생각해본 Go언어의 단점에 대해 끄적여보겠다. 이번 글은 필자의 주관이 잔뜩 들어가 있기에 비판적으로 봐주기를 바란다. 마지막으로 필자는 프로그래밍 언어 중에서는 Go언어를 가장 좋아한다.😉
1. 타 언어들과의 객체지향에 대한 관점의 차이
Go언어는 객체지향 언어이다. 그리고 프로그래밍 언어들 중에 흔하디 흔한 것이 객체지향 언어이다. 그러나 Go언어는 객체지향의 개념이 다른 객체지향 언어들과 근본적으로 다르다. 객체지향적인 면에서는 더 바람직한 방식이긴 한데, 다른 언어에서 Go언어로 넘어오는 데에는 유일한 진입장벽일 것이다. Go언어의 객체지향에 관한 내용은 아래 링크의 글을 참고하길 바란다.
2. 애매한 입지
Go언어는 난이도와 성능 사이에서 균형을 잘 잡은 언어이다. 반대로 말하면 난이도와 성능 둘 다 애매하다는 말이다. Go언어는 Python, Javascript등의 동적 프로그래밍 언어만큼 쉽고 빠르게 프로그램을 작성하지 못한다. 그렇다고 C, C++ 만큼 성능을 극한으로 끌어올릴 수 있는 것도 아니다. C#, Swift, Kotlin처럼 특정 플랫폼을 이용하기 위해 써야하는 언어마저 아니다. 즉, Go언어를 쓸 수 있는 곳은 다른 언어로 대체할 수 있다.
하지만 Go언어만의 특징이 한가지 있다. Go언어는 동시성 프로그래밍에 특화되어 있다. 이 글에서 동시성 프로그래밍이 무엇인지, Go언어에서 어떻게 구현하는지에 관해 서술하지는 않겠다. 동시성 프로그래밍 활용 하는 분야는 분산 시스템, 비동기적 처리 등이 있다. 이쪽 분야에는 나름 독보적인 입지를 가지고 있다.
3. 아직 부족한 인기
위의 항목과 일맥상통한다. 동시에 필자가 구직했을 때 느꼈던 단점이다. Go언어는 성능 및 이용성을 어느정도 인정받기는 했지만 아직 인기 있는 언어는 아니다. 당장 구인 사이트에서 Go언어 구사자를 구하는 직장과 Javascript언어 구사자(Node.JS)를 구하는 직장의 수를 비교해보자. 다행인 점은 Go언어 구사자를 구하는 직장이 점차 늘어나고 있다는 것이다. 2020년에 Jetbrains에서 발표한 개발자 보고서에 따르면, 개발자가 앞으로 사용하고 싶은 프로그래밍 언어 3개 안에 Go언어가 포함되어 있다.
레퍼런스 역시 '비교적' 적다. 한국어로 된 레퍼런스는 말할 것도 없고 외국어로 된 레퍼런스 역시 인기 있는 언어들에 비해서 적다. 다만 언제까지나 비교적 적다는 것이고 웬만한 문제는 레퍼런스를 통해 해결할 수 있다. 다양한 대안이 없어서 아쉬운 정도?
4. 제네릭(템플릿)의 부재
언급한 단점들 중에 아마 가장 많은 사람들이 공감하지 않을까 싶다. 제네릭은 강력한 도구이다. 제네릭은 코드를 자료형과 분리시킴으로써 객체지향을 지키면서 코드의 양을 획기적으로 줄인다. 하지만 Go언어의 개발자들의 생각은 조금 달랐던 것 같다. Go언어의 원칙 중 하나인 간결성에 어긋난다고... 제네릭을 도입한다면 문법적으로는 살짝 복잡해질지 몰라도 전체적인 코드는 간결해질 텐데 말이다.
제네릭의 부재를 가장 크게 느꼈던 때는 프로토타입 패턴을 이용할 때였다. 예를들어 JAVA의 경우에는(이미 내장되어 있지만) Cloneable 인터페이스를 만들기가 쉽다.
interface Cloneable<T> {
T Clone();
}
class Something implements Cloneable<Something> {
private int num = 1;
Something(int n) {
num = n;
}
public Something Clone() {
System.out.println("Clone Success!");
return this;
}
public void Print() {
System.out.println("current : " + num);
}
}
public class Program {
public static void main(String[] args) {
Something a = new Something(1);
a.Print();
Something b = new Something(3);
b.Print();
b = a.Clone();
b.Print();
}
}
반면에 Go언어는 Cloneable 인터페이스를 따로 정의할 수 없다. 리턴 타입을 정할 수가 없기 때문이다. 당연한 소리겠지만 Cloneable 타입으로 리턴하면 복제되어 나온 객체는 Clone()밖에 쓸 수 없다. 타입 캐스팅을 이용할 수는 있겠지만... 당연히 추천되는 방법은 아니다.
다행히도 Go언어는 이전의 발언을 철회하고 제네릭의 도입을 고려해보고 있는 것 같다.
만약 제네릭을 도입한다면 아마 2.0 버전에 도입할 것으로 예상된다.
Go 1.18 버전이 정식 출시되면서 제네릭이 추가되었다!
5. 그 외
문법의 단순성을 중시해서인지 문법이 현대적이지는 않다. 예를 들어 try catch 등의 예외처리 구문이 없고 error타입의 nil 검사를 통해 확인해야 한다. 즉, 코드가 조금 길어진다. Swift와 비교해보면 어떤 느낌인지 확실히 알 것이다. 다만, 단순한만큼 배우기도 쉽고 쓰기도 쉽기 때문에 일장일단이 있다.
쓰지 않는 패키지는 임포트 할 수 없다는 것도 불편할 수 있다. 다만 소프트웨어 공학적으로 볼 때 '당장 삽입하지 않는 기능은 고려하지 않는다'는 원칙에 충실하므로 역시 호불호의 영역이다.
마치며...
완벽한 언어는 없다. Go언어도 예외는 아니다. 다만 필자가 언급한 항목들 중 반이 인기에 관한 것이다. 개인적으로 Go언어는 저평가되어 있다고 생각한다. 물론 이 글에 나온 것이 Go언어의 단점의 전부는 아닐 것이다. 이를 감안해도 단점이 별거 아니라고 느끼고 Go언어의 세계에 뛰어드는 사람이 있었으면 하는게 필자의 바램이다.
참고 자료
- JETBRAINS, The State of Developer Ecosystem-2020, 2020
- Golang Official Homepage, The Next Step for Genereics, 2020.6.16
- 로버트 C. 마틴, Clean Code, 인사이트, 2013