아파치 모듈로 개발된 API 서버, 이음 베이론을 소개합니다.

안녕하세요. 저는 이음소시어스에서 서버사이드 개발을 하고 있는 오영식(다람)입니다. 개발팀 블로그의 첫 글로 우리의 새로운 API 서버 마개조 프로젝트, 이음 베이론을 소개해 드리려고 합니다.

Introduction

2년쯤 전, 카카오톡에서 “겁나빠른황소” 프로젝트를 적용하였습니다. 초반에는 빠르게 작동하던 카카오톡이 사용자가 늘어남에 따라 속도 또한 느려져 전체적으로 시스템을 개편한 것입니다. 이전부터 카카오톡을 사용해 보신 분들은 아시겠지만, 메시지 전송을 할 때 항상 보이던 바람개비가 그 이후에는 구경조차 어렵게 바뀌었습니다.

이와 비슷하게, 이음 또한 사용자가 많이 늘어나면서 수많은 데이터가 쌓여감에 따라 빠릿빠릿하게 작동하던 어플리케이션이 점점 느려져 사용에 불편함을 느낄 정도가 되었습니다. 또한, 기존에 개발되어 있는 소스코드에 계속해서 기능을 추가하다 보니 소스코드의 양이 너무 방대해져 유지보수가 어렵게 되어, 전면적인 소스코드 개편을 고려하게 되었습니다. 그 결과로 만들어진 것이, 이름하여 베이론 프로젝트입니다.

베이론?

먼저 전혀 중요하지 않지만 베이론이라는 이름은 매우 빠른 서버를 만들자는 취지에 따라 구글에서 자동차 제로백 순위로 검색해 나름 있어 보이는 이름으로 지었습니다.

 

1

실제로 소스코드 저장소 위키에도 이렇게 써 있습니다.

 

베이론은 아파치 웹 서버의 모듈로 개발이 되어 있습니다. 물론 C로 개발하고 있고, 이 때문에 기존의 Spring framework를 사용한 서버보다 훨씬 빠르고 더 적은 리소스로 구동이 가능합니다.

맨 처음 개편을 고려할 때 많은 언어들을 고려했습니다. Rails, PHP, Python, Node.js, Java로 다시만들기(!) 등 많은 선택지가 있었는데, 아파치 모듈(C)를 선택한 이유 몇 가지를 추려보면:

  1. 웹 개발 언어가 많은 연산을 필요로 하지는 않고 대부분의 병목이 DB에서 남에도 불구하고, 생각보다 많은 속도 저하가 웹 어플리케이션 내부에도 존재합니다. C는 (잘 짜면)매우 좋은 성능을 보장해줍니다.
  2. 좋은 성능에도 불구하고 메모리 관리와 같이 컨트롤하기 까다로운 문제도 존재하고, 데이터 저장 및 수정이 타 언어에 비해 불편한 것이 사실입니다. 하지만 아파치가 내부적으로 사용하는 라이브러리(APR)이 매우 강력해 C로도 충분히 빠른 시간 안에 좋은 퍼포먼스의 웹 어플리케이션을 개발 할 수 있습니다.
  3. 스프링, 레일즈와 같은 프레임워크는 웹 개발자에게 매우 편리한 강력한 기능들을 많이 제공하고 있습니다. 하지만 프레임워크는 아무리 좋은 성능을 내더라도 프레임워크 없이 잘 짜여있는 어플리케이션보다 느린 것이 사실이고, 처음에 익히는데 시간이 드는 것이 단점입니다. 따라서 프레임워크에 의존하지 않는 방식으로 개발을 하게 되었습니다. 언젠가 스프링 배치의 퍼포먼스와 개발속도에 분노해 아예 바닥부터 짜버린 배치의 사연도 소개하게 되겠지요.
  4. 사실 C로 API를 구현한다는 사실이 매우 생소하긴 하지만, (NHN에서 통합검색 서버를 개발하신 제 옆의 모 개발자님께서 말씀하시길) 수많은 트래픽을 감당하고 있는 네이버 검색 웹 서버 또한 대부분 아파치 모듈로 개발되어 있어, 이는 충분히 사용할만하고 검증되어 있는 방식이라고 할 수 있습니다.

벤치마크

베이론 서버와 기존 Java로 개발된 서버는 많은 부분에서 퍼포먼스 차이를 보여줍니다. 이 글에서는 두 가지 관점에서 비교를 해 보겠습니다. 첫 번째는 사용자가 직접 체감하게 되는 Latency이고, 두 번째는 서버 개발자들이 항상 전전긍긍하며 바라보게 되는 CPU 사용률입니다. 먼저, Latency를 비교해 보도록 하겠습니다.

(1)   Latency

    1. Java 서버
2

Java 서버의 Latency

 

대체로 평소에는 0.1~0.2초대의 응답속도를 보여줍니다. 그렇지만 우리 서비스의 특성상 특정 시간에 매우 많은 트래픽이 발생하는데, 이 시간대에는 0.7초까지 응답속도가 늦어지는 것을 볼 수 있습니다.

      1. 베이론 서버
3

베이론 서버의 Latency

전체적으로 응답속도가 0.1초 아래로 나온다는 점도 훌륭하지만, 주목하셔야 할 점은 서비스 이용자가 몰리는 시간과 그렇지 않은 시간의 차이가 전혀 없다는 사실을 보아주세요. 어떠한 서비스던 그렇겠지만, 우리처럼 특히 특정 시간에 많은 트래픽이 몰리는 서비스의 경우에는 이러한 항상성(?)은 서비스의 큰 안정성을 보장하게 됩니다.

(2)   CPU 사용률

      1. Java 서버
4

Java 서버의 CPU 사용률

기본적으로 차지하는 CPU 사용률도 최소 5%이고, 이용자가 몰리는 시간에는 특히 30~40%대의 CPU 사용률을 가지고 있습니다. 따라서 안정적인 서비스 제공을 위해서는 좋은 CPU를 가진 인스턴스를 이용할 수 밖에 없습니다.

      1. 베이론 서버
5

베이론 서버의 CPU 사용률

굉장히 들쭉날쭉한 것 같아 보이지만, 평소에는 거의 0%대의 CPU 점유를 하고 있다가 사용자가 몰리는 시간에는 무려 3%까지(!!!) 차지하고 있습니다. 사실상 CPU는 거의 놀고 있습니다. Java서버와 비교하면 정말 큰 차이가 드러나고 있습니다.

(3)   기타

위 벤치마크 자료에는 드러나 있지 않지만 더 무서운 사실이 존재합니다. Java서버는 이용자가 몰리는 시간에 자동으로 인스턴스가 4대로 변경되며, CPU사용률에 따라 6대까지 늘어납니다만, 베이론 서버는 단 2대로 운영이 되고 있습니다. 이 사실까지 감안한다면, 베이론 서버의 압승이라고 볼 수 있겠지요.

단점도 있지 않을까요?

음, 사실 저도 베이론 프로젝트를 맨 처음 들었을 때 복잡한 C로 작성한다는 것이 매우 두려웠는데, 막상 진행을 하다 보니 아파치에서 제공하는 라이브러리를 통해 정말 쉽게 작성할 수 있었습니다. 그나마 있는 단점이라고 하면, 조금 생소하다는 점이 있겠네요. 아파치 모듈로 API를 작성하는 경우는 거의 없으니까요. 또, 필요한 기능이 있으면 직접 구현(!)해야 한다는 단점도 존재합니다.

그러나, 여전히 C는 API를 구현함에 있어 정말 좋은 언어입니다. 이 글에서는 단순히 아파치 모듈의 설명과 벤치마킹 자료만 올려 놓았지만, 나중에 추가로 기본적인 아파치 모듈의 작성 방법에 대해 글을 작성할 수 있을 것 같습니다.

기타

C로 개발하면 API는 몰라도 웹은 어렵지 않을까? 하는 생각을 하실 수도 있겠다는 생각이 들었습니다. 우리는 API를 C로 개발한 뒤에, Front는 Ruby 혹은 Python처럼 빠르고 간결하게 작성할 수 있는 언어로 개발한 뒤 API를 호출하여 결과값을 얻어내는 방식을 고려하고 있습니다. 이 부분은 레진코믹스의 경우와 비슷한데요, 위의 링크를 참고하시면 좋을 것 같습니다. 이렇게 작성하면 C의 빠른 속도와 스크립트 언어의 빠른 개발 속도를 모두 취할 수 있다는 장점이 있습니다. 물론, 웹에서도 API를 이용하기 용이하도록 잘 설계했다는 전제조건이 있어야겠지요.

결론

 

 …Write in C

Q: 모바일 api가 느린데 어떻게 하면 좋을까요?
A: C로 짜면 됩니다.

11

  • snibug

    자바서버는 어떤 서버로 올리셨는지 하드웨어 스팩은 어떤 기준으로 하셨는지 궁금합니다. 자바 서버 또한 여러 프레임웍이 있고 Play Framework나 Netty 같은 framework로 비교를 해봐 주셨으면 좋을것 같습니다.

    • Youngsik Oh

      베이론과 자바 모두 아마존 EC2를 사용하고 있습니다. 자바 프레임워크는 위쪽에 살짝 언급하였다시피 Spring framework를 사용하고 있습니다.
      Spring 외에 다른 프레임워크에 대한 벤치마킹은 조금 미흡했던 것 같습니다. 다음 번 비슷한 내용을 다룰 때에는 조금 더 체계적으로 벤치마킹을 하도록 하겠습니다.

  • Hwang Dongseong

    cpu utilization peak가 3%라는것 부터 병목이 cpu가 아님을 반증하는 증거 같습니다. 게다가 이종언어를 바인딩하면 결국 디버깅 헬게이트가 열리게 되죠. 개인적으로 c, c++빠지만 이것이 좋은 결정이라고 확신하긴 힘들어 보입니다. 괜히 사람들이 서버를 node.js 혹은 python, scalar등으로 짜는 건 아니겠죠.

    • Youngsik Oh

      예. 말씀하신 대로 병목은 DB에서 발생합니다. 저희는 두 가지 언어를 같이 두지는 않고 모든 API를 C로 옮겨 베이론으로만 개발 할 예정입니다.

  • blob

    [물론 C로 개발하고 있고, 이 때문에 기존의 Spring framework를 사용한 서버보다 훨씬 빠르고 더 적은 리소스로 구동이 가능합니다.]
    이건 좀 이해가 안되고…
    DB가 주로 병목이라고 쓰셨는데 DB병목은 그냥 두신거 같고…
    apr이 괜찮은건 맞지만 많이 뒤숭숭해요..

    • Youngsik Oh

      네. DB병목은 DB 구조 전체를 변경해야 하는 일이기 때문에 라이브 서비스에 적용하기에는 어려웠습니다.

      • blob

        혹시 그러면 ‘베이론’은 왜 피크에서 성능이 저하되지 않는지 분석은 해보셨나요?
        아니면 반대로 이전 시스템에서 피크 시스템에서 왜 그런 성능 저하가 발생했는지에 대한 어떤 분석이 있었는지 궁금하네요
        그리고 그 문제에 대해서 어떤 한계점에 닿았길래 유지보수 지옥으로 문열고 들어 가셨는지도 궁금하구요

        • Yu-heung Jeon

          C개발자 입니다.

          왜 C로 만들면 유지보수의 지옥이 되는지 궁금하네요..
          웹 서비스는 꼭 JAVA로 짜야 하다는 제한이 있는 것도 아니고..
          다만 웹쪽이 PHP, JAVA인력이 많다는 이유 만으로 유지보수의 지옥이라는건 무리가 있는거 같네요..

          또한 생짜로 전체 System을 개발 한것도 아니고
          Apache의 모듈형식으로 개발이 되었다면.. 그건
          Apache라는 프레임웍을 사용 했다고 봐도 무관해 보입니다만..

          웹은 C로 짜면 안돼~ 라는건 무리가 있다고 보입니다.

          불과 96년도 98년도만 해도 C로 CGI형식으로 많은 프로그램들이 만들어 졌었으니깐요..

  • guest

    이음정도 사이즈면 스프링이냐 apr이냐의 문제가 아니라 스프링으로도 잘 짜면 충분히 latency가 많이 튀는 일 없이 짤 수 있었을텐데요. 어차피 그 날 매칭이 열리는 시간의 보틀넥이 문제가 아니었던가요? 대부분의 병목이 디비에서 발생하는걸 알고계셨으면서 저런 결정을 내린것도 이상하네요. 또 프레임웍이 아무리 좋은 성능을 내더라도 프레임웍 없이 잘 짠 서버보다 느리다는건.. 말씀하신 프레임웍이라는것의 경계가 상당히 모호한데, 어떤 프레임웍의 코드를 읽어보셨는진 잘 모르겠지만 프레임웍은 단순히 웹개발을 편하게 하는것보다 훨씬 더 많은 일을 하는 경우가 많습니다. (단순히 아 프레임웍을 쓰는것보다 그냥 한번 만들어봤더니 latency가 낮구나. 그러니까 그냥짜는게 빠르고 좋은거구나 라고 생각할게 아니라는 말씀을 드리고 싶습니다). 아무 프레임웍 없이 개발해도 api 만드는건 일도 아닙니다. 다만 단기간에 그것보다 퍼포먼스가 더 나오게 (단순한 latency와 cpu usage 벤치마크를 말하는게 아닙니다) 짜는게 어렵기때문에 프레임웍을 쓰는거고요.

    • Youngsik Oh

      프레임워크가 좋은 것도 사실이고 짧은 시간에 좋은 퍼포먼스를 보여주는것도 사실이지만, 저희 서비스 개발에 사용하는 기능에 비해 너무 많은 것을 제공하고 있습니다.

      DB에 관한 내용은 아래 댓글에 함께 달았듯, 라이브 서비스에는 DB구조를 변경하기 매우 힘들어 이와 같은 결정을 내렸습니다.

  • Jong Wook Kim

    JVM의 포텐셜에 비해 스프링이 확실히 덩치가 너무 크고 굼뜬 것 같긴 합니다. reactive programming 이 점점 대세를 얻고 있던 중 이걸 보니 벼룩 잡겠다고 집에다 핵 발사한 느낌?… 벼룩을 잡긴 했는데ㅎ

    nginx도 아니고 아파치 모듈로 만들어진 디자인 결정은 네이버 통합검색 개발자님의 영향이 컸던 것 같네요.

    사족- ‘서비스던’ -> ‘서비스든’이 맞습니다.

    • Youngsik Oh

      nginx대신 아파치를 선택한 이유는 모듈 개발이 아직은 nginx보다 아파치가 편하기 때문입니다.

      그리고 생각하시는것보다 아파치 모듈 개발이 그렇게 어렵지는 않습니다. 오히려 프레임워크 익히고 공부하는 것보다 나을 수 있지 않을까 하는 생각이 드네요.

      • Jong Wook Kim

        C모듈이 어려워서 핵발사했다고 비유한 것은 아니구요. 결국 C로 갈아탄 것이 유지보수에 악영향을 줄 것이 분명하고 1리퀘스트=1프로세스인 아파치의 구조상 scalability도 한계가 있을 것이란 생각에서 의견 드렸습니다. 네이버 통합검색은 서버가 10000대 가량이라죠?ㅎ

        • Hoseung Kim

          네이버 통합검색 최상위 레이어의 웹서버는 제가 퇴사한 시기인 2013년 4월에 100대 이하였습니다. 1리퀘스트=1프로세스인 것은 prefork 모델에서는 맞는 말이지만 스레드 기반인 worker 나 event 모델에서는 틀린 말입니다. scalability 의 경우는 앞단에 load balancer 를 두고 있기 때문에 장비를 늘리면 해결이 되겠지만 현재 시점에서는 더 필요한 상황이 아닙니다. 마지막으로 유지보수에 악영향을 준다는 것이 분명하다는 것의 근거가 무엇인지 궁금하네요

          • Jong Wook Kim

            결국 한 리퀘스트를 처리하는 동안 하나의 스레드/프로세스를 독점하고 있는 건 똑같죠. 현재 스케일에서는 문제 없는 방법은 맞지만 fully async한 netty나 play framework 등 다른 스택에 비해 조금 트렌드에 역행하는 것 같습니다.

            유지보수성은 상대적인 얘기였습니다. 고수준 언어가 생긴 이유가 있으니까요. 다른 분들이 지적하였듯이 저수준 언어로 하드웨어의 한계까지 성능을 끌어낼 필요가 없는 web api frontend에 C를 사용하는건 앞으로를 생각하기보단 관성에 의한 것 같다는 느낌이 강합니다.

          • Hoseung Kim

            트렌드에 따르기 위해 진행한 프로젝트는 아니었습니다. 트렌드에 따르는 것이 효율이나 성능을 보장하는 것은 아니니까요. 말씀하신 netty나 play framework 가 어느 정도의 성능이 나오는지 궁금해지네요

          • 최중한

            호승! 이런거 밝혀도 되나? ㅎㅎ 지난번에 이음 갔다가 인사도 못하고 왔네!

          • Hoseung Kim

            아.. 담엔 연락주세요 ㅋㅋ

            100대 이하에는 많은 숫자가 있지요
            두루뭉술하게 써서 괜찮을거에요 ㅋㅋ

  • 한상헌

    흥미로운 내용 잘 읽었습니다.

    PHP에서도 비슷하게(?) Phalcon이라는 C 언어로 만든 프레임워크가 있는데 속도면에서 잇점이 있어 보이더군요. 모듈 방식이라 Nginx + PHP-fpm으로 구성하면 꽤나 성능을 얻을 수 있을 것 같긴 합니다.

    그래도 새로 개발을 하는 상황이라면 PHP가 Perl 보다 느리기 때문에 굳이 이런 것까지 써가면서 PHP를 고집 할 이유는 없을 수도 있겠지만, 기존에 PHP로 개발된 부분이 있다면 한 번 살펴 볼 필요는 있을 듯 합니다.

    • Youngsik Oh

      다음에 작은 규모의 프로젝트에 고려해 보면 좋겠네요. 의견 감사합니다.

    • Tael Kim

      후훗 상헌님을 여기서뵙는군요.
      언제한번 모듈쪽을 들여다보고싶네요.
      생산성과 성능 두가지 토끼를 잡아야하는 상황이 왔으면좋겠는데…

  • 김윤호

    Java 로 API 서버가 구현되어 있을 때 CPU 사용량이 5~30%라고 하셨는데 혹시 어디서 CPU를 사용하고 있는지 프로파일링등을 통한 분석 결과가 있으신가요? 해당 부분이 왜 Java에서는 CPU를 꾸준히 사용하고 C에서는 사용하지 않는지 궁금합니다. 특별히 담당 로직이 바뀌지 않았다면요.

    • powerumc

      제 경험상 부하 시에 부하 절반 정도는 가비지 컬렉션 작업에서 로드가 발생합니다.

  • Eungju Park

    이 글을 읽는 사람들에게 도움이 되도록 C로도 쉽게 API 서버를 만들 수 있었 방법도 알려주시면 좋을 것 같습니다. 위 글에서 얻을 수 있는 정보는 ‘요구사항이 간단하다’, ‘apr의 도움을 받았다’ 두 가지인데요. 같이 개발했던 C로 API 서버 개발을 처음 하시는 분들이 예상했던 어려움은 A, B, C가 있었는데, A, B는 막연한 두려움이었고, C는 apr의 어떤 기능을 이용하면 쉽게 구현할 수 있다. 이런 내용도 공유를 해주시면 좋겠습니다.

    • Youngsik Oh

      네. 고려해 보겠습니다. 의견 감사합니다.

  • Igor Sysoev

    어떤 언어를 쓰는지는 중요한 문제는 아닌 것 같네요. 언어에 상관없이 API 서버라면 네트워크 지연을 고려해도 10ms 이내에 응답할 수 있어야 할 것 같네요 처리 시간만 생각한다면 1ms 이내에서도 가능할텐데요.

    • Youngsik Oh

      1ms가 될 때까지 열심히 노력하겠습니다.ㅋㅋ

  • 김승익

    라륀쒸~라륀쒸이~라륀쒸~
    잘보고갑니당ㅋㅋㅋ