"Node.js를 떠나며" - express를 만든 TJ의 글
원문: Farewell Node.js(TJ가 어제 올린 글. 참고로 TJ Holowaychuk는 Express, Jade, Mocha 등을 만든 Node.js 의 대표적인 프로그래머이다.)
Farewell Node.js. node.js 진영을 떠나며..
- 나는 충분히 오랫동안 운영환경에서의 Node.js 와 싸워왔다.
- 그리고 불행하게도 지금은 더이상 재밌게 일할 수 없게 되었다.
- 그래서 공식적으로 작별을 고하고, 새로운 maintainers를 찾고 있다.
- Node는 어떤 것들에는 좋다, 하지만 결과적으로 내가 요즘 흥미로워하는 종류의 소프트웨어를 만들기 위해선 올바른 도구가 아니었다.
- 그래도 여전히 웹사이트에 Node를 사용할 계획이다
- 만약 당신이 어떤것을 maintaining 하고 싶다면 알려달라.
- GitHub 사용자명과 NPM 사용자명, 프로젝트명을 남겨달라.
- 내가 요구하는 건 기존 API들을 drastically하게 변경하지 말아달라는 것이다.
- 만약 그렇게 하고 싶다면 새로운 프로젝트를 시작해라.
Koa
는 내가 계속 maintain하는 프로젝트가 될 것이다.
성배 (The Holy Grail)
- 난 항상
C
를 사랑해왔다.C
는 rewarding 하지만 에러를 만들기 쉽다는 것을 알고 있다.- 매일하는 업무를 위해
C
를 선택하는 것은 정당화하기 힘들다. - 단순한 것에대해 나는 언제나 존경해왔다. 하지만 거대한 양의 boilerplate 없이는 당신은 많은 것을 얻을 수 없다.
- 분산시스템에서 일을 할 수록. 나는 더욱더 usability(사용성)과 robustness(견고함) 보다 성능을 우선하는
Node
의 방향에 대해 frustrated(좌절, 실망, 짜증) 했다.- 일주일 전부터 나는 상대적으로 큰 분산시스템을
Go
로 다시쓰고 있다.- 그것은 더 견고하고, 더 빠르고, 더 유지보수가 쉽고, 게다가 test coverage도 좋아졌다.
- synchronous code(동기적 코드)가 일반적으로 더 좋고 더 단순하다.
- 그것은 더 견고하고, 더 빠르고, 더 유지보수가 쉽고, 게다가 test coverage도 좋아졌다.
- 일주일 전부터 나는 상대적으로 큰 분산시스템을
- 난
Go
가 성배라고 말하고 있는게 아니다.- 그것은 완벽하지 않다.
- 하지만 오늘까지 존재하는 언어들중
Go
는 나에게 가장 좋은 해결책이다. Rust
와Julia
같은 “차세대 언어”들은 자신의 자리를 찾고 성숙해지면, 나는 좀더 많은 해결책을 가지게 될 것이라고 확신한다.
- 개인적으로
Go
에 가장 흥분되는 점은 (Go 언어 프로젝트의) 개발 속도이다.- 그들의 2.0 에 도달하기 위한 열망에 흥분했다.
- 그들은 이미 잘 되어있는 것을 부수고 변경하는 것에 너무 걱정하지 않는다.
- (수정: 약간 오해했던것 같다. 그들은 breaking changes에 대한 열망이 언제나 있는건 아닌것 같다.)
- 이게 진실이면 좋겠다.
- 왜냐하면 나는 언어에 이익이 있다면 빠르게 breaking things 하는게 좋다고 믿기 때문이다.
- 내가 거대한 시스템을 실행시키고 있는건 아니니까. :D
Why Go?
Node
는 여전히 좋은 도구이고, 만약 working 한다면 걱정할 이유가 없다.- 하지만 그것이 당신을 괴롭힌다면, 당신의 box에서 벗어나야 한다는 것을 잊지마라.
- 나는 production에 Go를 써본 처음 몇시간만에 Go에 빠지게 되었다.
- 다시 말하지만, Go는 당신이 사용해야만 하는 절대적으로 가장 좋은 언어는 아니다.
- 하지만 비슷한 나이인 Node에 비해서 (나이에 비해) 아주 성숙하고 견고하다.
- types 리팩토링은 쉽고 단순하고
- profiling, debugging 은 굉장하고
- 커뮤니티는 문서, 포맷, 벤치마킹, API 디자인에 대한 강력한 conventions 갖고 있다. (상욱: TJ는 커뮤니티의 컨벤션을 아주 중요하게 생각하는 듯)
- Go 를 처음 들었을때 Go stdlib 의 일부는 끔찍하다고 생각했다.
- Node의 ultra-modularity에 익숙해져 있었고
- Ruby의 썩은 stdlib 의 경험이 있었기 때문이다.
- Go언어를 좀더 사용해보고 나는 stdlib의 대부분이 요즘의 프로그램을 만드는데 아주 essential 하다는 사실을 깨달았다. (압축, json, IO, buffered IO, 문자열 조작 등)
- 이러한 API들은 잘 정의되어있고 강력하다.
- stdlib만 쓰는 것으로 전체 프로그램을 다 쓸 수 있고, 매우 쉽다.
Third-party Go packages
- 대부분의 Go 라이브러리들은 look and feel이 비슷하고, 내가 써본 대부분의 third-party 코드는 품질이 높다.
- Javascript 는 스킬레벨의 범위가 넓기 때문에 Node에서 좋은 라이브러리를 찾는 일은 어렵다.
- (상욱: JS가 쉬워서 모듈이 난입한다는 느낌은 나도 가졌지만. 이게 JS의 단점이고 Go의 장점이라는 논리는 동의하기 어렵다. ㅎㅎ)
- Go 패키지를 위한 중앙 레지스트리는 없다.
- 그래서 당신이 5~6개의 같은 패키지네임을 보게될 것이다.
- 이것은 약간의 혼란일 수 있지만, side-effect를 가질 수 있기 때문에, 베스트 솔루션을 결정하기 위해 각각을 리뷰해야 한다.
- Node 에는 표준적인 패키지가 있다.
- 예를 들면 redis, mongodb-native, zeromq 등.
- 그래서 당신은 이것이 가장 좋은 것이라고 가정하고, 리뷰를 하지 않는다.
Go versus Node
- 만약 당신이 분산 작업을 하고 있다면, 당신은 Go의 동시성이 아주 좋다는 사실을 알게 될 것이다.
- 우리는 Node의 generators로 비슷한 것을 얻었다.
- 하지만 내 의견은 generators는 Go의 절반만 얻을 수 있다.
- stacks error handling과 reporting을 분리하지 않는 것은 좋게 봐줘도 평범하다. (가장 좋은 방법은 아니다.)
- 솔루션을 알고 있으면서도, 커뮤니티가 defragment(단합)가 될때까지 3년을 기다리고 싶지 않다.
- 내 의견은: Go의 에러핸들링이 더 우수하다.
- Node는 모든 에러에 대해 생각해야만 하고, 무슨일을 할지 생각해야 하고, 당신이 그런 감각이 있는 사람이라면 좋을지도 모른다.
- 하지만 Node는 실패한다. 왜냐하면:
- you may get duplicate callbacks
- 중복 callbacks 을 얻을 수 있다
- you may not get a callback at all (lost in limbo)
- callback 을 전혀 얻지 않을 수 있다
- you may get out-of-band errors
- out-of-band(책임 범위를 벗어난) 에러를 얻을 수 있다
- emitters may get multiple “error” events
- emitters 는 “error” 이벤트 여러개를 얻을 수 있다
- missing “error” events sends everything to hell
- “error” 이벤트를 놓치면(받지 않으면) 모든 것은 지옥으로 떨어진다
- often unsure what requires “error” handlers
- “error” 핸들러를 요구하는지가 불확실하다
- “error” handlers are very verbose
- “error” 핸들러가 아주 장황하다
- callbacks suck
- 콜백 자체가 똥이다
- you may get duplicate callbacks
- Go 에서는 내 코드가 실행이 끝나면, 끝난 거다. 당신은 그 statement를 재실행할 수 없다.
- Node에서는 아니다.
- Node 는 루틴이 완전히 끝났다고 생각해도, 어떤 라이브러리가 갑자기 콜백을 여러번 invoke 하면, 핸들러가 제대로 지워지지 않고, 코드는 재실행될 수 있다.
- 이것은 live production code 가 어떻게 동작하고 있는지를 추적하는 것을 어마어마하게 어렵게 만든다.
- 왜 괴로워하고 있나? 다른 언어는 당신에게 그런 고통을 주지 않는다구.
Node의 미래
- 나는 여전히 Node 가 잘 할것이라는 희망이 있다.
- 많은 사람들이 투자하고 있고, 잠재력도 가지고 있다.
- 나는 Joyent 와 개발팀이 사용성에 초점을 맞출 필요가 있다고 생각한다.
- 성능은 app이 작으면, 디버깅, 리팩토링, 개발만 어렵게 만든다고 생각한다.
- 우리는 4~5년 동안
Error: getaddrinfo EADDRINFO
와 같은 모호한 오류를 봐왔다.- 이것만 봐도, Node 개발자들의 우선순위가 어디에 있는지 알 수 있다.
- 당연하지만, 시스템의 core 에 아주 집중하고 있으면 이러한 실수를 할 수도 있다. (Node 개발자들이)
- 하지만 사용자들이 계속해서 이러한 것들을 표현했다고 생각하는데, 우리는 결과를 보지 못했다.
- Streams 는 깨지고, callbacks 는 좋지 않고, errors 는 모호하고, 도구는 좋지 않고, 커뮤니티는 컨벤션을 가지고 있긴 하지만 Go와 비교하면 부족하다.
- 웹사이트를 만들거나 API 또는 프로토타입을 만든다면 Node 를 앞으로도 사용할 것이다.
- 만약 Node 가 기본적인 문제들을 고친다면, 좋은 기회 겠지만.
- 사용성보다 성능을 우선하는 방향 또는 성능과 사용성을 모두 잡겠다는 방향으로는 해결되지 않을 것이다.
- Node 커뮤니티가 generators를 받아들이고 node의 core를 구현하여 에러처리를 잘 만들 수 있다면, 이것은 아주 좋아질 것이고.
- Node의 사용성과 견고함을 매우 개선할 것이다.
- 누구를 비방할 목적으로 쓴 글이 아니다.
- 내가 말하고 싶은 것은, 당신 스스로의 bubble에 갖혀있지 말라는 것이다.
- 둘러보면 굉장한 솔루션이 널려 있고. 당신은 다시 재밌게 프로그래밍을 할 수 있다!