Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Deveiw 2012 후기 #2

이 포스팅은 Deveiw 2012 후기 #1에서 이어진 포스팅이다.



node.js를 이용한 단일언어 기반 웹 애플리케이션 개발 - Monoglot web application development with node.js - 채수원(NHN)
PHP 를 할때는 5페이지 만드는데 5시간 정도가 걸렸는데 자바로 넘어왔더니 배워야 할 것들이 엄청나게 많았고 5페이지 만드는게 거의 50시간은 걸리는것 같았다. 더이상 이런 어려움을 겪고 싶지 않았고 팀에서 Node.js로 개발을 하면서 실험한 결과를 공유하기 위한 세션이다. Node.js로 만든 프로젝트는 개발자노트였는데 nForge의 서브프로젝트로 위키와 매뉴얼작성을 위한 웹사이트이고 오픈소스로 제공된다.  이번 프로젝트를 한 의도는 모두가 다 Node.js로 삽질을 하지 말고 먼저 삽질한 경험을 공유해서 다른 사람들은 삽질을 줄일 수 있도록 하고 Node.js를 확산시켜보려는 의도가 있고 Spring 말고 다른 것도 써보고 싶었다. Node.js를 사용한 배경은 NHN의 기술투자적 의미가 있으며 개발자들이 여러 플랫폼을 사용하고 있기 때문에 다양항 픈랫폼을 지원하는 개발환경이 필요했고 대부분 PHP를 배경으로 가지고 있기 때문에 스프링은 잘 몰랐던 것도 한 목했다. Node.js는 자바스크립트이지만 Node.js에 대한  레퍼런스가 많이 없기 때문에 고생할 확률이 높고 개발을 하면서 어떤 방법이 좋은지 판단이 어려워서 계속해서 스타일을 바꿔가면서 하게 됐다.


여러가지 오픈소스 모듈을 사용했는데 Node.js로 프로젝트를 할 때 이 정보들이 도움이 되기를 바란다. 그리고 오픈 소스를 사용할 때는 나중에 해결되겠지 하지 말고 반드시 지금 기능으로 가능한지를 판단해서 선택해야 한다.

  • Express : 웹서버는 익스프레스를 사용했는데 문서가 그리 좋지 않은 데다가 개발자인 TJ가 소위 미친 개발자게 가까워서 개발하면서 API를 자주 바꾸곤 한다. 하지만 대안 별로 없는 편인데 최근에는 로드 존슨도 참여한 Meteor이 주목을 받고 있다.
  • Jade : 뷰템플릿엔진으로 JSP보다는 낫고 익스프레스와 궁합이 좋다. 뷰의 코드량은 줄일 수 있지만 마크업 개발자와 협업이 좀 필요하다.
  • CoffeeScript : 커피스크립트에는 자바스크립트의 베스트 프렉티스가 포함되어 있기 때문에 자바스크립트를 잘 모르니까 커피스크립트를 써보자는 생각으로 적용했다. 코드량이 감소하기 때문에 복잡도도 줄어들고 가독성은 증가하지만 디버깅이 지옥이다. 소스맵이 나오기 까지는 디버깅에서 대안이 없기 때문에 직접 오류난 곳을 찾아야 함다.
  • Mocha : 테스트 프레임웍으로 다양한 리포트와 형식을 지원하고 커피스크립트도 지원하고 있다. 그리고 다른 테스트 라이브러리와 같이 쓸 수 있다는 장점이 있다.
  • Jake : 자바스크립트로 개발하므로 빌드도 자바스크립트로 하고 싶었다.
  • Zombie.js : 웹브라우저 에뮬레이터로 브라우저를 실제로 띄우지 않고도 테스트를 할 수 있다. 클라이언트측 자바스크립트 테스트도 할 수 있다.
  • i18n-node : i18n은 이 모듈이 가장 좋으므로 믿고 딴거 쓰지 말고 이 모듈을 사용해라. 최초 등록시 자동으로 메시지 파일이 생기는 등 아주 쉽게 사용할 수 있다.
  • setp, async : Flow Control을 하는 모듈로 콜백으로 인한 코드의 복잡함을 줄이기 위해서 사용하고 step는 깔끔하지만 기능이 아주 간단하고 Async는 기능이 엄청나게 많기 때문에 잘못하면 오용할 가능성도 있다.
  • 개발도구 : Vi나 Sublime Text2 둘중에 하나를 사용해라. IDE도 좀 있지만 크게 도움은 안되므로 그냥 앞에서 얘기한 두 에디터를 사용하느게 낫다.

프로젝트를 하면서 배운 점들은 콜백으로 인한 오류를 조심해야 한다는 것이다. 단순히 콜백으로 연결된 것은 블럭킹 콜백이고 실제 I/O를 사용해서 호출되는 것이 지연콜백인데 사용해야 하는 것은 지연 콜백이다. 블럭킹 콜백을 사용해서 성능문제가 발생하는 실수를 하지 말아야 하고 비동기로 인한 실행순서를 착각하지 않도록 조심해야 한다. 적용해 보니 처음에는 프론트앤드 개발자가 빨리 배우지만 결국 서버 프로그래밍이기 때문에 나중에는 서버사이드 개발자가 더 많이 나아가는 것 같다. 그리고 개인 생산성은 괜찮은 편이지만 자바스크립트 파일을 여럿이 수정해야 하기 때문에 팀 레벨의 생상선을 그다지 좋지 않다.

이 시간대에 어느 세션을 들을까 많이 고민하긴 했는데 그냥 이 세션을 선택했는데 아주 좋았다. 난 역시 발표는 참 어려운데 채수원님은 맛깔나게 발표를 잘하신다. 올해내내 개발자노트를 Node.js로 진행한 실제 경험을 나누어 주는 세션이라 실무 프로젝트를 못해본 나로써도 그 내용이 궁금해서 들었는데 실제 사용해본 경험이기 때문에 설득력도 있고 내용이 아주 알찼다. 나중에 들으니 뒤에 좀더 있었는데 얘기를 못하셨다고 했는데 그게 아쉽기는 하지만 듣는 사람들에게 여러 모로 도움이 되었을 꺼라고 생각한다. Node.js세션은 500명이 들어가는 큰 곳에서 진행되었는데 자리가 없어서 주위에 앉을 정도로 사람이 많아서 아직도 인기가 좋구나 하는걸 새삼 느끼면서 11월에 진행될 Node 컨퍼런스도 괜찮겠다 싶었다. ㅎ



Netty Internal - 이희승(Twitter)
Netty네트워크 애플리케이션을 빨리 만들 수 있게 해주는 자바 네트워크 어플리케이션 프레임워크로 비동기이면서 이벤트 기반이다. 즉 성능이 좋고 리소스를 적게 사용한다. 그리고 IO를 추상화한 레이어로 API를 제공하고 있기 때문에 코드의 변경없이 NIO, OIO, AIO를 바꿔가면서 사용할 수 있고 이벤트 모델과 쓰레드 모델을 잘 정의해 놓았기 때문에 개발자가 원하는대로 사용할 수 있다. 유연하게 이벤트를 다루기 위해서 bi-directional chain of responsibility pattern을 사용하고 있고 'Separation fo Concerns'가 잘 되어 있으므로 네트워크에만 Netty를 사용하고 프로토콜과 비즈니스 로직은 따로 사용할 수 있도록 설계되어 있다.

이벤트루프는 윈도우의 이벤트 디스패처나 자바의 스윙 이벤트 루프, Reactor와 비슷하다. 사용자의 I/O 요청은 이벤트 루프 스레드내에서 요청했을 경우에는 즉시 처리하고 이벤트루프 스레드 밖에서 요청했을 경우에는 이벤트 루프의 작업 큐에 넣어서 스케쥴링한다. 외부 자극에 반응해서 파이프라인에 알리고 Netty 4에서는 사용자가 원하는 임의 작업을 실행할 수 있다.

파이프라인은 이벤트루프에서 이벤트를 받아서 핸들러에 전달하는 역할을 한다. BiDiCoR(bi-directional chain of responsibility pattern)는 서블릿필터나 데코레이터 패턴과 유사한데 단방향이 아닌 나가고 들어오는 양방향에 모두 적용된 링크드 리스트라고 할 수 있다. 인바운드 이벤트를 이벤트루프가 발생시킨 이벤트로 소켓 연결이나 데이터수신등이 있으며 사용자가 작성한 inbound event handler가 수신할 수 있도록 해준다. 아웃바운드 이벤트는 인바운드의 반대로 쓰기, 읽기, 일시중단 등 사용자가 요청한 동작에 대한 것이다. 사용자가 작성한 outbound event handler가 다른 핸들러에서 요청한 동작을 가로챌 수 있도록 해주는데 최종적으로는 이벤트 루프에 전달되어 실제 I/O가 수행될 수 있도록 해준다.


이벤트 모델에서 기존에는 이벤트를 자바 객체로 만들어서 이벤트가 생기면 자바객체를 파이프 라인에 전달하는 구조로 되어 있었다. 그리고 이벤트 하나를 전달하는데 총 8개의 이벤트가 발생하는데 이는 논리적으로는 문제가 없이만 효율적인지에 대해 의문을 가지게 되었다. GC의 비용이 크지 않다고 판단했지만 극도의 성능이 필요한 곳에서는 이것도 문제가 된다는 것을 알게 되었고 강시에는 JVM의 GC보다 직접 구현한 버퍼풀이 더 좋을 수 있는지에 대한 의문을 가졌고 보통은 직접 구현한게 더 느리다. 하지만 쓰르풋이 높은 경우에는 직접 구현한 버퍼풀의 성능이 더 좋은 경우가 있으며 JVM은 보안상 이슈로 메모리를 모두 0으로 채우는 등의 문제를 처리하면 더 좋은 버퍼풀을 만들 수 있다고 판단하게 되었다. 그렇다면 이렇게 객체와 버퍼를 생성할 필요가 없어진다.

그리고 이벤트가 올때와 닫을 때 각각 3개의 이벤트가 발생하는데 실제적으로는 openBound는 큰의미를 가지지 않았고 실제 사용자가 관심을 가지는 것은 통신을 할 수 있는 상태냐 아니냐는 것이었기 때문에 여기에 맞춰서 개선하기로 했다. 또한 메시지 이벤트의 경우에는 메시지를 프로퍼티로 가지고 있었기 때문에 항상 메모리에 물려있었고 메시지마가 객체가 생기는 구조였다. 그리고 항상 네티가 버퍼를 사용하므로 어떤 버퍼를 사용할 지를 사용자가 제어할 수 없었고 메시지 이벤트는 무조건 하나의 소켓을 사용하도록 되어 있었는데 상황에 따라 연속적인 메시지는 하나의 소켓으로 계속 보내면 성능을 높일 수 있다. 그래서 새로운 이벤트 모델에서는 이벤트를 메서드 호출로 변경해서 새로운 객체를 만드는 대신 이벤트의 해당 메서드를 호출하도록 하였다. 그리고 메시지 이벤트는 제거하고 버퍼에 데이터를 채운 다음에 flush 이벤트로 메시지 이벤트를 대체하도록 하였다.

네티 4의 쓰레드모델은 3.x 대비 이벤트 모델 개성과 함께 가장 중요하고 긍정적인 변화이다. 쓰레드 모델이 필요한 이유는 프레임워크에서 사용자의 코드가 어느 쓰레드에서 언제 실행될 지 충분하고 정확하게 정의하지 않으면 사용자가 방어적으로 코드를 작성해야 한다. 이렇게 잘 정의된 쓰레드 모델로 SSL이 4.0으로 올라가면서 1400라인에서 900라인으로 줄어들었다. 네티는 추상화를 제공하고 있기 때문에 실제 통신을 하지 않고도 통신을 에뷸레이트할 수 있다. 그리고 네티 자체는 가 전송의 정확한 동작을 확인하기 위해서 모든 전송방법과 프로토콜의 모든 조합을 교차테스트 하고 있다.

네 티는 이름은 많이 들어봤지만 실제로 써본 적은 없기 때문에 원래는 이시간대에 다른 세션을 들을 계획이었는데 주위에 네티에 관심갖는 사람도 많은데다가 그리 어렵진 않을꺼라는 얘기도 있었고 이희승님의 발표도 듣고 싶어서 들어갔는데 정말 최고였다. 위에서 설명한대로 Netty 4로 개발하면서 했던 고민들과 변경사항들을 설명해 주셨는데 아주 차분한 말투로 조곤조곤 설명하시는데 진행이 술술되서 귀에 쏙쏙 들어왔다.(한편으로는 이터너티님이 생각나기도...)

설명이 어떻게 했는데 왜 그렇게 생각했고 무슨 문제가 있었고 이렇게 바꿨다 식으로 진행되서 정말 이해하기가 좋았다. 한편으로는 Node.js때문에 이벤트루프나 비동기에 대한 사전 지식이 있었기 때문에 어느정도 이해하면서 들을 수 있었던 것 같다. 내 입장에서는 Netty 정도면 상당한 메인스트림급 오픈소스 프레임웍이라고 생각하고 있었는데 이희승님도 Netty 써본사람 손들어보라면서 반가워 하는걸 보고 다 비슷하구나 하는 생각이 들었다. Netty를 만든 이희승님이 직접 Netty를 설명해 주시는 기회를 놓치지 않아서 아주 다행이다.


Epilogue
컨 퍼런스를 많이 다니다 보니 예전에는 공부하러 갔지만 요즘은 공부하러가는 거 반, 사람들 보러가는 거 반하면서 간다. 컨퍼런스는 한편으로는 축제의 장이라고 생각하는데 국내 컨퍼런스는 쉬는시간이 너무 짧아서 아쉽다. 특히 이번처럼 트랙을 이동하는 컨퍼런스에서는 쉬는시간 10분은 정말 화장실 갔다가 다른 세션으로 이동하기도 벅찬 시간인데 좀 여유있게 진행되었으면 좋겠다. 그래서 자체적으로 2개 세션을 듣고 딱히 관심가는게 없던 한 세션을 그냥 푹~ 쉬었다.(학교 수업들으러 온 건 아니니까...)

실망스 럽다는 얘기도 많이 들었는데 어차피 컨퍼런스는 세션이 핵심이고 그런 면에서 세션들의 수준은 꽤 괜찮은 편이라고 생각해서 만족하고 있다. 그리고 Deview에서 의도했는지는 모르겠지만 메인스트림이라고 하기는 어려운 루비, 스칼라, 노드를 이런 대형 컨퍼런스에서 들을 수 있어서 상당히 반갑고 이런 기술들의 확산에도 꽤 도움이 되었으리라고 생각한다.
2012/09/24 03:18 2012/09/24 03:18