내가 다양한 언어를 익힌 이유

최근에 이런 질문을 여러 차례 받았다.

왜 그렇게 다양한 언어를 하세요?

나는 C언어로 프로그래밍을 시작했고 자연스레 C++을 하게 됐다.

내가 프로그래밍을 배우던 시기나, 그리고 처음 취업을 했던 2005년 게임 업계에서 게임 개발을 위해선 차선이 없었다. C++을 제외한 언어는 툴 개발이나, 일부 스크립팅에 제한적으로 사용했을 뿐이다.

compile 환경을 통한 성능 차이, native 언어라는 성능상 장점을 배제하기 힘든 당시 상황적 제약 때문이었다.

네트웍 기반의 온라인 게임이 활성화 되면서 붉어진 서버 개발에서도 정확한 성능 측정과 임계치 파악, 베이스 라인 설정 등이 아주 중요하다.

즉, 많은 어플리케이션 메트릭들을 최대한 계산된 영역으로 끌어내려야 하는데, managed언어도 잘 쓰려면 깊은 공부가 필요한데다가 양쪽 다 깊은 공부가 필요하다면 게임 업계에선 성능도 무척이나 중요하다고 보고 C++을 선택해온 것이라고 생각한다.

추가로 클라이언트와 유틸리티성 코드나 로직 코드를 공유할 수 있다는 점도 크게 작용했을 것이다.

그렇게 C++만 잘하면 될 것 같았던 나의 미래가, 모바일 시장이 열리면서 조금 달라졌다.


클라이언트 베이스의 게임이 다수 등장하고, 결과 저장을 위한 심플한 서버만 필요했던 시기가 되면서 웹서버가 도입됐다.

이전에는 GM툴 정도만 가동하던 웹서버로 게임 서비스를 진행하면서 다양한 언어가 게임 서버 개발 시장에 도입됐다.

자바, PHP, Node.js, Ruby on Rails 등… 다양한 언어로 구현된 웹서버로 게임이 서비스 되기 시작했다.

이 과정에서, 사내 스터디와 간단한 로그 분석 웹서버로 이용했던 Ruby on Rails를 나는 스타트 업에서 이용해서 서비스를 했고, 이후에는 Django를 통한 게임 서버를 구현하게 됐고, 성능상 이슈로 ASP.NET CORE로 포팅하게 됐었다.

이후 타의반 자의반으로 자바를 통한 게임 서버 개발을 하게 됐는데, 그 과정에서 자바를 익혔고 이후 웹 개발을 Spring Boot로 진행하면서 자바에 익숙해졌다.

사실 취미로 go랑 rust를 간단히 써보고 있었으나, 국내 개인 개발자 분들의 오픈소스가 워낙에 node.js, python, java에 편중되어 있다보니 포킹해서 작업 할 때는 해당 언어로 진행하면서, 더 익숙해진 감도 있다.

이렇게 익숙해진 일부 언어는 업무에서 사용할 기회로 이어지도록 노력하거나, 혹은 지속적으로 데브 토이로만 쓰게 되는 경우도 있다.


이렇게 다양한 언어에 대한 관심과 사용을 하는 이유는, 현대 언어는 서로 영향을 주고 받고 있는지, 어떠한 부분은 언어의 근본적 한계인지, 또 무엇에 대해 아쉬움을 느끼는지 알아야 내가 기술선정을 하게 될 때, 혹은 폴리글랏 프로그래밍을 해야 할 때 인지를 이해하고 싶어서였다.

이런 고민에 도움이 된 책은 임백준씨가 번역해주신 브루스 테이트의 세븐 랭귀지다.

그렇게 배우고나니 확실히 인사이트가 넓어졌다. 특히 C++만 파고들던 시기보다 훨씬 유연해졌다.

현대 개발은 바퀴를 재발명 하진 않지만, 자동차를 조립하기 위한 부품을 얼마나 잘 고르는지가 아주 중요한 문제다.

이는 유연함이 필요하다는 의미고, 그를 위해선 다양한 언어를 이해하고 있는 것이 필요하다.

그를 위해서 시작했던 다양한 언어에 대한 이해, 기술에 대한 편견을 내려 놓는 데에 큰 도움이 됐다.

그 것들이 앞으로의 내 발전에 큰 보탬이 될 요소라고 생각한다.

내가 종종 언급하는 얘긴데, 한국에서는 자바가 한국어 같은 느낌이다. 특정 업계 (게임, 보안, 네트워크 등)에서는 C++ 혹은 C언어지만, 그 비율이 다르다고나 할까?

하지만 내가 존경하는 대다수의 프로그래머는 자바만 (혹은 C++만) 잘하지 않는다. 잘 가져다 쓴다는 의미에는 상황에 따라 적합한 언어를 선정해야 한다는 의미도 큰 가치를 갖는다.

결국 상황에 따라 폴리글랏 프로그래밍 해야 한다는 얘기다.

자동화를 위해선, 혹은 서비스 로직을 위해선 가끔은 결합도가 낮게 작성한 스크립트 언어가 필요할 수 있다.

AWS 람다같은 서비스가 이에 대한 반증 중 하나라고 본다. 상황에 맞는 적절한 기술적 도입을 위해선, 기술에 대한 유연한 사고가 필요하다.

기술의 발전이 어떠한 메커니즘과 기술적 가치를 중점에 두고 발전하고 있는지는 알아야 한다. 그래야 더 적은 코스트로 더 안정적인 서비스를 구축할 수 있고, 그게 더 현명하고 더 합리적인 판단이다.

그래서 나는 다양한 언어를 익히려 시도했고, 큰 도움이 되고 있다. 내가 언급한 이런 부분에 대한 갈증과 아쉬움이 존재한다면 나와 같은 시도를 해보는게 어떨까?

(서평) 브루스 테이트의 세븐 랭귀지

(국내에선 더더욱) 마이너하지만, 컨셉이 확실해 장점이 있는 언어들의 개념을 이해시켜주는 책이었다.

루비, lo, 스칼라, 프롤로그, 얼랭, 클로저, 하스켈

7개 언어를 이야기하는데, 그 패러다임이 어떤 것인지 이해하는 데에 쉽도록 짤막하게 잘 요약되어 있었다.

  1. 루비
    • 생산성에 특화된 언어
    • 언어의 기능을 확장시켜주는 메타 프로그래밍을 통한 생산성 극대화 가능
  2. lo
    • 논란이 큰 언어.
    • 간결하고 단일한 문법을 기반으로한 동시성 지원으로 높은 생산성을 냄.
    • 독특한 메시징 시스템이 특징.
  3. 프롤로그
    • 아주 오래된 언어.
    • 하지만 극도로 강력함
  4. 스칼라
    • 자바 생태계에 함수형 패러다임을 얹은 언어.
    • 병렬 처리에 대한 장점은 있지만, 순수 함수형 언어라 부르긴 어려운 것도 사실.
  5. 얼랭
    • 동시성, 분산, 장애 방지에 특화된 언어.
  6. 클로저
    • 리스프의 변종
    • 동시성을 지원하기 위해 버저닝이란 방식을 이용해, DB와 비슷한 전략을 사용함.
    • 가장 유연한 프로그래밍 모델을 제공.
  7. 하스켈
    • 순수 함수 언어.
    • 변경 가능한 상태를 어디에서도 발견할 수 없다는 뜻.
    • 강 타이핑을 이용하기에 오류의 가능성이 낮고, 순수 함수형 언어인만큼 모든 코드는 병렬로 수행 가능하다.

책 도입부에 나온 언어별 설명을 요약한 것인데, 나는 이 책과 언어의 발전상과, 기술의 발전상, 요구 사항의 발전상이 나에게 큰 경쟁력을 가져다 줄거라고 믿고 이 책을 읽어나갔다. (물론 이런 부분에 대해 관심도 없는 면접관 혹은 회사라면 아무 가치도 없겠지만, 그건 다른 기술이나 경험도 마찬가지다.)

이미 루비스트였던 나는 당연히 루비 관련 챕터를 더 유심히 읽었는데, 마츠의 즐겁기 위한 프로그래밍, 나 역시 그렇다.

프로그래밍이 여전히 즐겁고, 내 생각과 가장 일치하는 가장 적은 공수로 즐겁게 일할 수 있는 언어는 루비였다.

반면 나머지 언어들 중 하스켈과, 얼랭, 스칼라 외에는 잘 알지 못했는데 이 기회에 대략적인 특징이라도 알 수 있어 좋았다.

특히 하스켈마저도 옛동료가 쓰고 있어서 몇번 전해들었을 뿐인, 순수 함수형 언어라는 말만 들었을 뿐 조금 더 실체화할 수 있어 좋았다.


내가 자주 들은 이야기 중 생각이 바뀐 이야기 중 하나는, 특정 언어 하나에 익숙해지면 다른 프로그래밍 언어는 일주일이면 잘 쓸 수 있다는 얘기다.

실제 사용해보니 패러다임이 아무리 비슷하다고 해도 언어의 몇가지 특징과 주력 언어와의 차이점으로 인해 잘 쓰기엔 꽤나 긴 시간, 많은 노력이 필요했다.

내가 너무 평범한 프로그래머라서 그렇다면 또 할말은 없지만, 절대 다수인 평범한 프로그래머들에게 통용되지 않는 이야기라면 바뀌어야 되는 거 아닐까?

실제로 언어의 패러다임, 특징, 제약, 확장성 등은 너무나 큰 차이다. 이런 차이가 뚜렷한 수 많은 언어를 단시간에 잘 쓰는 일은 있기 어려웠고, 내가 만난 수많은 훌륭한 프로그래머들도 시간이 꽤나 필요했다.

아마도 명필은 붓을 가리지 않는다처럼 와전된 이야기가 퍼진게 아니었을까 싶다.


이 책 자체가 7개 언어를 다루다보니 깊게 다루지 않는다.

그래서 가볍게 읽을 수 있었고, 다양한 언어에 대한 개념만큼은 빠르게 숙지 가능했던 만큼 자신의 기술 스택과 비교해서 어떠한 언어에 관심이 가는지, 어떠한 언어가 장단점에 대한 이해만으로도 큰 도움이 되는 책이 아닌가 싶다.

100만건이상의 데이터를 다룰때 생기는 RDB성능 이야기

나는 작은 온라인 게임회사에서 커리어를 시작했다. MMORPG 클라이언트 개발자로 시작했던 나는, 길지 않은 시기에 회사가 매각되면서 자연스레 퇴사하게되었다.

그렇게 군입대를 준비하던 중 병역 특례 지정 업체였던 또 다른 온라인 게임 회사에 지원하게 됐고, 면접 과정을 통해 서버 프로그래머 전향을 권유 받으며, 서버 프로그래머로써의 커리어를 시작하게 됐다.

서버 프로그래머가 되었기에 자연스레 DB를 사용해야했는데, 그 당시 난 DB라고는 기본적인 쿼리정도 밖에 몰랐고, 데이터 저장소로만 사용하고 싶었는데 내 마음과 다르게 컨텐츠는 단순한 쿼리로만 구성하게끔 기획될리 없었다. 컨텐츠가 복잡해져갈수록 쿼리도 복잡해져갔다.

그렇다보니 DB는 점차 무거워져갔고, 자연스레 서버 이슈의 반절은 디비 이슈로 이어졌다.

100만건에 근접해져 갈수록 서버는 느려져갔고, 렉이 한둘 생겨나가기 시작했다.

동접은 3000가량을 왔다갔다했지만 누적된 데이터가 늘어날 수록 렉은 심해져갔다.

이에 대한 카운셀링은 나보다 디비를 훨씬 잘 아는 DBA 출신 서버 프로그래머 분이 많은 도움을 주셨다.

그분의 가르침에 따라 여러가지 작업을 수행했다.

  • 쿼리 개수에 대한 통계, 쿼리 수행 시간에 대한 통계 기록
  • 점검때마다 인덱스를 리빌드
  • 레플리카를 통한 Read/Write 경합 감소
  • 쿼리에 맞게끔 전수 검사를 통해서 인덱스를 설정
  • 상황에 따라선 서버 메모리단의 캐싱 처리를 통한 DB 조회 이슈 감소
  • 디비 로그도 남김으로써 서버 로그와 비교

문제가 어디인지 파악할 수 있는 근거를 남기기 시작하자, 동접 대비 DB의 수용량이 결정됐고, baseline을 잡아 이 선이 넘어서는 데이터들을 상시 개선할 수 있는 근거가 됐으며, 이를 기반으로 서비스는 점차 안정화되어갔다.

어떠한 컨텐츠는 서버에서의 호출 횟수를 줄인다거나, 쿼리를 단순화 한다던지 다양한 방식으로 튜닝해나갔으며, DB 관점에서도 단순한 쿼리를 의도하고 어플리케이션이 대신 처리해줄 수 있는 것은 넘김으로써 병목을 줄여나갔다.

데이터는 최대한 가비지가 덜 남는 방식으로 의도했으며, 우리가 사용하는 방식에 맞게끔 하드웨어 스펙을 재조정했다.

우리는 로그성 데이터를 제외하고는 데이터 건수가 적었으므로, 디스크와 RAM을 크게 확보했고 이는 곧 성능향상으로 이루어졌다.

이는 철저히 perfmon의 성능 카운터를 근거로 이루어졌기 때문에 실질적인 성능 향상으로 이어지는 결과를 맞이할 수 있었다.


그러고 난 뒤 나는 궁금해졌다.

100만건이 넘어가면 성능 이슈가 스물스물 올라오기 시작했다. 이는 과연 우리프로젝트만 겪는 문제인가?
그렇진 않았다. 하드웨어 스펙에 따라 N은 달라질 수 있으나 RDB의 한계상 데이터 row 수에 따라 성능 이슈가 대두되었고, 각종 대책 (샤딩, 레플리카, 하드웨어 성능 확보, 쿼리수 감소, 쿼리 큐잉, redis와 같은 캐시 서버, nosql 도입 등)을 통해서 우회하고 있을 뿐이었다.

100만건 이라는 수치가 직접적으로 언급되는 이유는 아마도, 100만건 이상의 테이블을 다룰 때 그런 테이블 여럿을 조인하거나 갱신해야 할 때 이슈가 많이 생겼음을 많은 개발자가 겪었다보니, 100만건이 마치 빅테이블의 기준처럼 불리게 된 것 같다.

물론 테이블 설계 및 예술적 쿼리 작성을 통한 해결도 있겠지만 이보다 다른 해결책을 통한 파훼가 더 합리적이라는 판단을 많이 한게 아닐까 싶다.

실제로 DB의 성능 이슈를 복잡하디 복잡한 쿼리로 해결하려는 접근을 여전히 하는 곳은 많지만, 그 때 보다 더 많은 데이터를 다루는 요즘 웹 업체 (트위터, 페이스북, 넷플릭스, 구글 등)는 그런 접근으론 단기적인 대안밖에 될 수 없다는 것을 인지하지 않았나 싶다.


사실 DB 성능 이슈를 겪고나서 더 많이 배우게 된 것은 지표 기반으로 판단하고 개선하기라 할 수 있었다. 그리고 그것들 간의 상관관계를 몸소 체험하면서, 생각의 폭이 넓어졌다.

이는 내 첫 서버 프로그래머 경험에서 가장 값인 수확이 아니었나 싶다. 이후에도 나는 계속 지표를 남기고 이를 기반으로 개선하는 작업의 중요성과 재미를 느끼게 됐으니 말이다.

지표는 누군가를 설득하기에도, 검증하기에도, 원인을 파악하기에도 유용하다. 엔지니어링의 기본이 지표라는 것을 깨닳고 나니 시야가 한층 넓어진 기분이었다.

또한 내가 다뤘던 게임 서버보다 더 많은 데이터 처리량을 소화하기 위해선 무엇을 해야 하는가에 대해서도 관심을 갖게 됐고, 이는 내가 학생 수준을 벗어나지 못한 풋내기 프로그래머에서, 소프트웨어 엔지니어로 성장하는데에 큰 도움을 준 계기가 되지 않았나 싶다.

샤딩과 레플리카

  • 샤딩을 왜 할까?
    • 샤딩은 단일 논리적 데이터 셋을 다수의 데이터 베이스에 쪼개고 나누는 방법이다.
  • 레플리카란 뭔가?
    • 이중화를 의미하며, 미러링, 백업 디비 등의 용어로도 통용되는데 다양한 방식으로 구현되는 복제를 지칭한다.

샤딩의 목적은 데이터를 분산 저장함으로써, 트래픽 분산에 목적이 있다. 샤딩도 디테일에서 여러방식으로 갈리는데, 샤딩된 노드끼리 통신해야 할 경우에는 트래픽이 다시 몰리는 경우가 있다. (여러 노드의 데이터를 조합해서 결과를 내야 하기 때문)

샤딩은 분산된 데이터 그 자체로 의미가 있을 때는 샤딩 그 자체가 트래픽 분산이 깔끔하게 이루어진다. 실질적으로 이 경우는 샤딩이라 부르기보단 DB 분산 (또는 파티셔닝. 게임의 경우 월드 단위 DB를 따로 쓰는 등의)이라고 부르는 경우도 많은 것이 그 이유다.

필요할 경우 샤딩된 각 디비에서 데이터를 꺼내와서 원하는 결과를 보여주거나, 원하는 처리를 해야 할 때가 있는데, 이 코스트가 꽤나 큰편이다. 어디에 샤딩되어있으며, 샤딩된 결과를 다시 배포해줄 때의 동기화 이슈나 충돌 이슈 등에 대한 문제가 커, 트래픽 분산이 목적이었는데 적지 않은 트래픽과 운용 이슈를 만들기도 한다. 여러 개 샤드에서 데이터를 꺼내와서 그 결과를 다시 분산 처리하고 이 과정에서의 무결성을 유지하는 것은 꽤나 어려운 문제다.

이는 샤딩의 장점보다 단점이 크게 사용되는 사례이지만, 이처럼 샤딩은 성능 문제를 위한 솔루션일 뿐 이외의 장점은 없다고 봐도 무방하다.

샤딩과 레플리카의 본질적 목적과 효과가 다르다.

레플리카는 fail-over나 read/write 경합 감소(또는 제거), read 코스트 분산 등에 치중되어있다.

fail-over시에는 복제 디비를 둠으로써, 메인 디비가 장애가 생겨도 복제 디비에서 정상적인 서비스를 빠르게 구성할 수 있게 구성하는 것이 목적이다.

read/write node를 분리함으로써 성능 분산도 처리할 수 있다. (특히 경합이 이루어질 경우 성능 저하도 우회할 수 있다.)

디비에서의 또다른 전략으로는 파티셔닝이 있는데 주로 사용되는 파티셔닝은 다음과 같다. 이 역시 개념적인 것에 명칭을 붙인것이므로, 더 다양한 방법의 파티셔닝이 존재한다.

  1. 수직 파티셔닝
    • 컬럼들 중 특정 컬럼을 나누어 파티셔닝 하는 것.
  2. 수평 파티셔닝
    • 값을 기준으로 파티셔닝 하는 것.
      • Key or hash 기반 파티셔닝이라고도 불림.
      • 샤딩도 수평 파티셔닝으로 구현되는 경우 많아 동의어로 사용되기도 함.
  3. 범위 기반 파티셔닝
    • 기능 별로 파티셔닝 하는 것.

조금 길게 왔는데 요약하자면 아래와 같은 개념이라고 요약할 수 있다.

  • 샤딩, 파티셔닝
    • 데이터 분산 저장
      • 데이터가 한 곳에 저장되지 않으므로, 분리되어 있는 데이터들을 합쳐서 연산하기 위해선 어플리케이션 레이어나, 플러그인, 서드파티 솔루션 등으로 극복해야하나 많은 기술적 제약이나, 리스크를 가진다.
  • 레플리카
    • 데이터 복제 저장
      • 일정 수준 이상의 지연은 생길 수밖에 없지만 이를 감안하고 지연 복제하는 경우가 일반적.

주의할 점은 분산된 결과를 복제하는 과정 (샤딩+레플리카)이나, 레플리카 구성시 마스터 슬레이브 개념이 없을 시 동기화 이슈가 크게 발생하곤 한다. 양방향 동기화는 오류의 여지가 커지기 때문에 그렇다.

또한 샤딩 사용시 노드를 추가할 경우 리밸런싱은 일반적으로 지원되지 않는다. 이를 위한 작업은 많은 양의 데이터를 재배치하고, 이에 대한 해싱 키등을 재조정하는 큰 작업이므로 점검을 통해 진행되곤 한다. 그래서 운용에 무리가 없을 만큼의 샤드 노드를 확보하거나, 적절한 시점 오토 스케일링, 백그라운드 리밸런싱 등을 고려해야 운영 포인트를 크게 감소 시킬 수 있다.

개념적으론 둘다 쓰면 좋은거 아닌가 싶겠지만, 복잡한 구성을 하면 할 수록, 고민할 여지나 운용 이슈가 발생할 부분이 있다. 특히 내가 설명한 개념과 다르게 구현된 DBMS도 여럿 있을 것이기에 이를 감안한 리서치와 검토, 검증이 필요하다.

L4 스위치 도입시 생겼던 이야기

예전 회사 이야기다.

적어도 나는 알지 못하던 상태에서 L4 스위치가 점검 시간에 도입이 됐다.

네트워크 트래픽 제어는 기존 라우터에서 중간 L4 스위치를 하나 더 거치게 됐다.

나로썬 왜 되입되는지 이유를 알 수 없었다. 왜냐면 TCP 서버이다보니 로드밸런싱의 주체는 로직이 들어간 우리 게임 서버 일부이기 때문이다.

브로드 캐스팅 대상을 좁히기 위함이라고 생각하면 그럴순 있을 것 같았다. 나중에야 알게 된 사실이지만, 개발팀 누구도 L4 스위치 도입시 검토해야 될 이슈나, 설정 값 검토, QA 서버에 선 도입 해볼 생각을 하지 못했고, 그렇게 위험을 감지도 불안정한 상태에서 L4는 도입됐다.

도입되자마자 이슈가 터졌고, 커넥션 유실이 두 종류가 발생했다.

  1. 디비 커넥션 유실
    하나는 디비 커넥션이 끊어지면서, 나약하게 짜여져 있던 ODBC를 이용하는 코드에서 무한루프가 돈 것이다. 장애가 나고나서야 덤프를 떠서 확인하고, 처리했다.
    DB 서버와 게임 서버간의 커넥션이 끊어지는 일이 없어서 발생하지 않았던, 코드 자체의 while 문 조건이 잘못되어있던 코드의 문제였다.

  2. 사용자와의 커넥션 유실
    L4 스위치 자체에서 일정 시간 이상 지난 커넥션을 자동으로 제거했기 때문이다. 제거 원인은 배포된 클라이언트나 서버에서 지정된 KeepAlive 패킷을 주고 받는 주기보다 L4 스위치에서의 KeepAlive 유효성 판단 주기가 짧아 발생했다.

이 값을 늘림으로써 임시적으로 해결됐지만, 과연 이 장비 도입 이슈가 적절했는가에 대한 생각을 떨칠 수 없었다.

이런 장애를 겪고나니 인프라, 네트워크에 대한 궁금증이 생겨나기 시작했다.


아주 간단히 설명하자면, 내가 관리하는 최상단 라우터까지 들어올 수 있는 대역폭은 계약 및 인프라에 달려있다.

이게 초당 10GB라고 하자. 그리고 내 라우터가 처리할 수 있는 데이터가 마찬가지로 10GB로 치자. 깔끔해보이는가?

잘못됐다. 내 라우터는 그 밑에 물려있는 장치마다 브로드캐스트를 거친 뒤에야 적절한 대상지를 정할 수 있다.

라우터 내부 통신에서도 대역폭을 사용한다.

그러므로 외부 트래픽 유입+내부 트래픽+대상지 선정을 위한 브로드캐스트를 합친 양이 라우터보다 커야 한다.

스위치는 주로 로드밸런싱이나, 경로 탐색 코스트를 낮추기 위해 사용한다. 같은 스위치 내에서의 통신은 라우터의 대역폭을 사용하지 않고 통신 할 수 있기 때문이다.

즉 L4 스위치 도입 자체가 문제는 아니나, 내부통신보다는 외부 통신이 많은 경우에는 로드밸런싱의 잇점을 이외에는 얻을 수 없었는데, 이마저도 장비의 설정값과 어플리케이션 설정값 간의 검토가 필요했는데 이 절차 없이 바로 실기에 도입된 것은 철저히 엔지니어링 관점에서 큰 실수라고 할 수 있었다.


로드 밸런싱은 웹서버에서 좀 더 적절하다. 특히 스케일 아웃이야 그렇다쳐도, 스케일 인에서는 어플리케이션 레이어의 커넥션 스위칭 이슈, 처리중이던 메모리 데이터 이전 등의 복잡한 문제들을 해결을 위한 많은 준비가 이루어져야 하기에 그렇다.

무중단 패치가 웹 서버에서 훨씬 쉬운 것은 stateless한 경우가 많기 때문이다.
반면 TCP 서버에 도입하려 할때는 많은 검토와 검증이 이루어져야 했다.

특히 이미 L7 로드밸런서가 존재하는 상황에서 그 앞단의 로드밸런서는 큰 의미가 없기도하다. 내부 트래픽 감소를 위한 결정이었다손 치더라도 서버 프로그래머와의 소통없이 이루어진 도입은 운이 좋아 문제가 없을 순 있어도, 장애 가능성이 지나치게 높았던 전형적인 인재가 아닌가 싶다.

또한 내부 트래픽 감소가 그렇게 큰 가치가 있는 상태의 게임 서버 구조가 아니었다. 서버간 통신은 극도로 적은 편이었고 대다수 트래픽은 라우터를 거치는 외부 트래픽이었기 때문이다.

결론적으로 이해도가 부족한 상태에서의 무리한 도입은 리스크이고, 사건 사고를 불러온다는 결론을 내릴 수 있었다. 이 과정에서 내가 부족했던 네트워크 장치에 대한 이해도를 부분적으로나마 보충하고자 하는 계기가 됐고, 전체적인 네트워크 아키텍쳐를 구성하는 데에 도움이 되긴했으나 여러모로 씁쓸 할 수 밖에 없는 사건이었다.