웹서버 장단점 비교

Django

장점

  • 굉장히 쉽게 배울 수 있는 프로그램 언어인 Python을 기반으로 한다.
  • 인증, 관리와 같이 거의 대부분의 사이트에서 사용하는 기능들이 기본 모듈로 제공된다.
  • 성공적인 도입 사례가 있습니다.(Instagram 등)
  • 높은 코드 완성도를 유지할 수 있다.
  • python의 강제된 indent가 코드 완성도에는 일조함.
  • IDE 지원이 훌륭한 편이다.(Pycharm, Visual Studio 등)
  • AWS, Google Cloud, Azure등에서 전폭적으로 초기 단계부터 지원한 프레임워크다.
  • deploy 및 운용에 대한 개발 비용을 크게 아낄 수 있다.

단점

  • typeless 언어의 약점은 그대로 보유하고 있다.
  • python에 대한 높은 이해도가 필요하다.
  • Django는 문제를 python으로 해결하는 편이다. (프레임워크 특화 기능보다)
  • 성능 문제에서 자유롭지 못하다.

node.js

장점

  • V8 엔진을 기반으로 한 성능이 뛰어납니다.
  • 오픈소스 문화권하에 있어서만은 아닌, 풍부한 모듈 지원. (유독 많다. 그것도 짧은 기간내에 급속히 증가)
  • C++로 필요한 모듈 작성 가능.
  • 싱글스레드, 비동기 IO 처리에 기반한 빠른 속도
  • 파일 I/O나 네트워크 처리를 이벤트 드리븐 방식으로 처리하기 때문에 빠른 처리가 가능함
  • CPU의 대기시간을 최소화 할 수 있음.
  • CPU 부하가 적고, 많은 커넥션을 동시에 처리해야 하는 구조에 적합.
  • 자바스크립트를 이용해서 개발할 수 있기 때문에 프론트엔드 개발자의 진입장벽이 낮음.
  • 기존 Java 서버에 비해 생산성이 높음

단점

  • 싱글스레드 모델이기 때문에 하나의 작업에 시간이 오래걸리면 시스템 전체의 성능이 급격하게 떨어짐
  • 에러가 발생할 경우 프로세스 자체가 죽어버리므로 주의해야 함(watch dog 등으로 처리 가능)
  • 멀티코어 활용을 위해서 cluster 모듈을 이용해야 하고, 세션을 공유할 경우 부가적인 작업이 필요함
  • 불편한 비동기 프로그래밍 모델
  • 다음 할 일을 계속 콜백(callback) 함수로 넘기는 스타일로 코딩을 하다 보니 Pyramid of Doom이라 불리는 중첩 코드가 나오기 쉽상.
  • 이 문제를 해결하기 위해 비동기 제어 흐름을 좀 더 쉽게 표현하기 위한 async 모듈, underscore 등도 사용했지만, 이러한 프로그래밍 스타일은 Django나 Ruby on Rails에 비교해서 코드의 가독성을 현저히 떨어진다.
  • 초급 프로그래머라도 쉽게 할 수 있다 얘기는 거짓말.
  • 학습 난이도가 높은 편이다.
  • 시스템 관리자에게 쉽지 않은 아키텍쳐.
  • 자바스크립트로 로직을 구현하는 것은 어울리지 않다.
  • typeless 언어가 가져야하는 코드 가독성이 javascript는 부족하기 때문.

rails

장점

  • ruby언어의 장점을 근간으로한 뛰어난 가독성, 그리고 표현력.
  • twitter, github, redmine 이라는 성공적인 도입 사례.
  • 검증된 빠른 개발 속도.
  • rails로 서비스를 개발한 후, 서비스 트래픽이 높아지는 단계에서 다른 플랫폼으로 갈아타는 사례가 많다는 것이 이를 입증함.
  • MVC 모델을 온전히 구현하고 있다.
  • github로 공개된 기능 패키지 수 3위 권을 다 년간 유지하고 있다.
  • 가져다 쓸 수 있는 기능이 아주 많다는 의미.

단점

  • 비동기 API가 너무나 부족함.
  • GIL과 부족한 비동기 API로 인한 성능 이슈가 크게 대두 됨.
  • 성능 문제로 인한 최적화 한계를, 다른 플랫폼으로 풀었다는 것은, rails의 미래에 대한 큰 숙제다.
  • 이로 인해, 고도화 과정이 반드시 필요하며, 고도화 과정은 rails 이외의 영역에 대한 높은 이해도가 필요한 경우가 많다.
  • 과도한 수준의 추상화로, 원리를 이해하는 데에는 여타 플랫폼보다 더 큰 시간이 든다.

asp.net

장점

  • C# 사용 가능
  • Visual Studio 위에서 개발 가능
  • MVC 패턴을 제대로 지원함.
  • Model, View, Controller로 프로그램이 분할되어 복잡성을 다루기 쉬워집니다.
  • ViewState, 서버 기반 폼(server-based form)을 사용하지 않아서, Web 응용 프로그램에 대한 완전한 제어를 원하는 개발자들에게 이상적인 환경입니다. (WebForm에 비해서 MVC는 추상화의 수준이 낮습니다. WebForm의 경우, WebForm만 알아도 어떻게든 돌아가는 Website를 만들 수 있지만, MVC는 그게 안 됩니다. 그러다 보니 1강에서처럼 그렇게 많은 선수 과목이 필요하게 되었습니다. )
  • Website의 흐름을 마음대로 제어할 수 있습니다. 과거 WebForm에서는 blog.net/posts/23 같은 주소로 글을 접근할 수 있게 하려면, IIS를 건드려야 했지만, MVC에서는 매우 쉽게 이 문제를 해결할 수 있습니다.
  • 테스트 주도 개발(Test-Driven Development, TDD)을 하기에 좋습니다.
  • 큰 팀에서 많은 개발자와 디자이너들이 Web 응용 프로그램에 높은 수준의 제어를 원한다면 추천할만합니다.  

단점

  • 윈도우 서버 위에서만 온전히 동작. => 현재는 .NET CORE로 윈도우상에서도 온전히 동작.
  • 개발자 풀이 좁음.
  • 오픈소스권 문화가 아니라서 MS가 제공하지 않는 기능은 .NET 플랫폼 지원언어로 개발해야함.

spring [java]

장점

  • 크기와 부하의 측면에서 경량.
  • 제어 역행(IoC)이라는 기술을 통해 애플리케이션의 느슨한 결합을 도모.
  • 관점지향(AOP) 프로그래밍을 위한 풍부한 지원을 함.
  • 애플리케이션 객체의 생명 주기와 설정을 포함하고 관리한다는 점에서 일종의 컨테이너(Container)라고 할 수 있음.
  • 간단한 컴포넌트로 복잡한 애플리케이션을 구성하고 설정할 수 있음.
  • 대한민국 전자정부 표준 프레임워크의 기반 기술

단점

  • 설정이 복잡한 편이다.
  • 컴포넌트가 다양한 건 사실이나, 컴포넌트로 존재하지 않는 기능을 사용할 경우에 개발 공수가 크다.

play [play]

장점

  • 국내의 많은 교육기관에서 가르치고 있는 Java 기반 프레임워크인 만큼 누구나 쉽게 접근할 수 있습니다.
  • 웹 서버를 내장하고 있어 별도로 서버를 세팅할 필요가 없다.
  • 일반적인 Java 어플리케이션은 빌드하는데 굉장히 오랜 시간이 소모되지만, Play의 경우 변경된 내역에 대해 자동으로 빠르게 빌드하기 때문에 개발 및 테스트 시간을 크게 줄일 수 있습니다.
  • 가장 훌륭한 IDE인 Eclipse와 Intellij에서 Play!를 완벽하게 지원합니다.

단점

  • 한글로 된 문서가 거의 없습니다. 진행중이던 문서화 작업이 중단되었으며, 관련 서적과 블로그를 통해 제공되는 강좌들은 오래되어 Play! 최신 버전과 맞지 않습니다.
  • 번들이라고 하는 서드파티 모듈들이 많지 않고 그나마 있는 것들도 프레임워크 버전에 맞춰서 버전업이 되지 않아 활용 가치가 매우 낮습니다.
  • Twitter의 Rails나 Instagram의 Django와 같은 성공적인 도입 사례가 아직까지 없습니다.
  • Java와 Scala를 골라서 개발할 수 있다고 이야기하지만 실제로 Scala를 공부하지 않으면 개발을 진행하기 어려울 정도로 Scala의 비중이 높습니다.

code igniter [php]

장점

  • PHP 기반 full stack framework 중에서 성능이 매우 뛰어납니다.(Phalcon과 Slim은 경량 프레임워크)
  • 서비스가 성장하여 개발 인력을 늘려야 할 때 비교적 쉽게 관련 기술 보유자를 구할 수 있습니다.

단점

  • RESTful 서비스에 적합한 구조가 아닙니다.
  • Session 처리가 안정적이지 않고, DB Session 만을 지원하기 때문에 File이나 Memory 기반의 Session을 사용하기 위해서는 별도의 개발이 필요합니다.
  • PHP 언어 특성상 구조적으로 깔끔한 코드 작성이 어렵습니다.
  • ORM 기반의 Model이 아니라 코드를 통해 스키마를 파악하기 어렵습니다.

CentOS 7 Redmine 세팅

CentOS7 Redmine 설치

  • 방화벽 개방
    firewall-cmd --permanent --zone=public --add-port=3000/tcp
    firewall-cmd --reload
  • GCC 설치
    yum -y install gcc cpp gcc-c++ compat-gcc-34 gcc-gfortran flex​
    
  • Ruby와 Passenger 빌드에 필요한 헤더파일
    yum install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel​
    
  • Mysql과 헤더파일
    yum install mysql-server mysql-devel
    
  • Apache과 헤더파일
    yum install httpd httpd-devel
    
  • ImageMagick과 헤더파일
    yum install ImageMagick ImageMagick-devel
    
  • Ruby설치
  • Bundler 설치
    gem install bundler --no-rdoc --no-ri
    
  • redmine 설치 3.16 – 안정화버젼이라서 선택함
    cd /usr/local
    wget http://www.redmine.org/releases/redmine-3.1.6.tar.gz
    tar zxvf redmine-3.1.6.tar.gz
    mv redmine-3.1.6 /usr/local/redmine
    
  • 설정 파일
    cd /usr/local/redmine/config
    cp database.yml.example database.yml
    vi database.yml
    
    production:  
      adapter: mysql  
      database: redmine  
      host: localhost  
      username: redmine  
      password: redmine  
      encoding: utf8 
    
  • Gem Package 설치
    bundle install --without development test
    
  • 테이블 생성 및 초기 데이터 입력
    cd /usr/local/redmine
    rake generate_secret_token
    RAILS_ENV=production rake db:migrate
    RAILS_ENV=production rake redmine:load_default_data
    #한국어 ko 입력
    
  • 구동
    bundle exec rails server webrick -e production -d -b 0.0.0.0
    # 데몬으로 실행 여기까지 끝
    
  • 중지
    kill -INT $(cat tmp/pids/server.pid)
    
  • FAQ
    • 설치 중에 bundle install 시 에러 내용을 자세히 보면 마지막 문구에 뭐를 설치하라고 gem 뭐뭐뭐 이렇게 명령어 나오는데 복사해서 그걸 그대로 입력해서 설치 후 bundle install 다시 실행해야 한다.
    • bundle install은 /usr/local/redmine 에서 해야 한다
    • gem install 안될시에 gem query –remote -n 이름-d -a 이 명령어로 버젼 높은걸로 찾아서 인스톨
  • redmine 테마
    • /usr/local/redmine/public/theme 이쪽폴더에 넣고 재시작
  • redmine 플러그인
    • /usr/local/redmine/plugins 폴더에 넣고 /usr/local/redmine 에서 하단을 실행하여 플러그인을 추가해야한다.
      bundle install --without development test
      rake redmine:plugins:migrate RAILS_ENV=production
      
  • redmine 구글이용하여 메일보내기
    cd /usr/local/redmine/config
    
# configuration.yml.example 을 configuration.yml로 만든후
nano configuration.yml
production:
   email_delivery:  
   delivery_method: :smtp  
   smtp_settings:  
   enable_starttls_auto: true  
   address: "smtp.gmail.com"  
   port: 587  
   domain: "smtp.gmail.com"
   authentication: :plain  
   user_name: "계정명@gmail.com"  
   password: "비밀번호"

FlatBuffers Guide

FlatBuffers Documentation

flatbuffers는 효율적인 크로스 플랫폼 직렬화 라이브러리이다. C++, C#, C, Go, Java, JavaScript, PHP, Python을 지원한다.

이건 원래 구글이 게임 개발과 또다른 성능이 치명적인 프로그램을 위해 만들어졌다.

이것은 아파치 라이센스 v2 기반의 github 오픈소스로써 사용 가능하다.

왜 Flatbuffers를 쓰는가? parsing이나, unpacking 전에도, 직렬화 데이터에 접근 가능하다.

FlatBuffer의 특장점

  • 메모리가 효율이 좋고, 빠르다.
  • 유연하다.
  • 경량 코드
  • 강한 타입 처리
  • 편리한 사용
  • 종속성 없는 크로스 플랫폼 코드

https://google.github.io/flatbuffers/flatbuffers_guide_writing_schema.html

writing a schema

C계열 언어 사용자들과 또 다른 언어 사용자들에게 또한 친숙한 스키마 언어 문법으로 작성된다.

// example IDL file

namespace MyGame;

attribute "priority";

enum Color : byte { Red = 1, Green, Blue }

union Any { Monster, Weapon, Pickup }

struct Vec3 {
 x:float;
 y:float;
 z:float;
}

table Monster {
 pos:Vec3;
 mana:short = 150;
 hp:short = 100;
 name:string;
 friendly:bool = false (deprecated, priority: 1);
 inventory:[ubyte];
 color:Color = Blue;
 test:Any;
}

root_type Monster;

(Weapon & Pickup not defined as part of this example) Tables 테이블은 flatbuffers의 오브젝트를 정의하는 주된 방법이고, 이름과 필드 목록을 가지고 있다.

각 필드는 이름, 타입, 선택 사항으로 기본 값을 가진다.

각 필드의 선택 사항 : 이건 반드시 표현 할 필요는 없다, 그리고 당신은 개별 필드 누락을 선택 할 수 있다.

결과 같이, 당신은 유연하게 데이터의 팽창을 두려워하지 않고, 필드를 추가해도 된다.

이 디자인은 flatbuffers의 메커니즘의 전방위적, 배경적 호환성을 위함 이기도 하다.

Note that: 새 필드는 스키마의 테이블 정의 끝에만 추가할 수 있다. 오래된 데이터는 아직 정확히 읽을 수 있고, 그리고 당신은 읽을 때의 기본 값을 줄 수 있다. 오래된 코드는 단순하게 새 필드를 무시 할 수 있다. 만일 당신이 유연성을 원한다면, 특정 순서 보장을 원한다면, 수동으로 대입 (protbuf와 매우 유사), id 속성 아래를 봐라. 당신은 최신 스키마로부터 필드를 삭제를 할 수 없다, 그러나 단순하게 당신의 그 곳에 데이터를 기록하는 걸 멈추는 것과 거의 비슷한 효과를 낼 수 있다. 위의 예제를 보면 부가적으로 당신은 그 곳에 deprecated  마크를 할 수 있고,  C++로 생성 되어 있던 접근자들로부터  보호 될 거고, 필드가 더 이상 사용되지 않는 것으로 시행하는 방법이다. (조심해 : 이건 깨질 수 있는 코드야!) 이름이 변경 된 것들과 원래와 같은 때 까지 코드가 깨지는지 확인한다면, 필드 이름과 테이블 이름을 바꿀 수 있어.

밑에 스키마 진화 예제를 확인하자~

Structs 테이블과 유사하고, 오직 현재 비어있는 필드는 선택적이고 (그래서 디폴트 없음 쪽이나), 그리고 필드는 추가하지 못하거나, deprecated일 것이다. Structs는 오직 수치형 자료나 또 다른 Structs만을 포함 할 수 있다.

단순한 자료형이나, 매우 확정 적으로 영원히 안 바뀔 것들을 만들 때 써라. ( 꽤 분명한 예는 Vec3)

Structs는 table보다 적은 메모리를 사용하고, 빠른 접근도 가능하다. (그것은 항상 그들의 부모 오브젝트에서 in-line되고, 가상 테이블을 사용하지 않는다)

Types

크기 내장 수치 타입
8bit byte, ubyte, bool
16bit short, ushort
32bit int, uint, float
64bit long, ulong, double

내장 비-수치 타입 다른 타입의 Vector, 계층화 된 벡터는 지원하지 않고, 대신 당신은 테이블안에 내부 벡터로 감쌀 수 있다. string, UTF-8이나 7-bit ASCII로 고정되어 있다. 다른 텍스트 인코딩 또는 일반 바이너리 데이터는 벡터([byte] or [ubyte])로 대체 할 수 있다. 또다른 tables나 structs, enums, unions 참고해라. (밑을 보시오)

필드 타입은 한번 사용되고 나면 바꿀 수 없다, 예외적으로 같은 사이즈 데이터에 reinterpret_cast를 사용하면 원하는 결과를 얻을 수 있다, 예를 들어 현재 사용되고 있던 최상위 비트 값이 없는 경우 uint를 int로 바꿀 수 있다.

https://google.github.io/flatbuffers/md__cpp_usage.html

LightSDK 공개

LightSDK

오픈소스로 올려둔 프로젝트들에 대해서 설명드립니다.

https://github.com/elky84

github에 제가 개인 작업한 라이브러리 및 샘플 공유합니다. 주로 WIN32용 코드가 다수이며, C#및 Unity 코드도 일부 포함되어있습니다.

여러가지 기능에 대한 샘플코드가 많으니 참고해서 도움이 되셨으면 좋겠네요. 감사합니다.

flatbuffer를 사용하기 위해서는 몇가지

  • FlatBuffersPtr
    • LinearNormalBuffer를 이용해, FlatBuffer로 변환된 데이터들의 life-cycle을장해주는 클래스다.
      • FlatBuffers의 변환은, 해당 데이터의 사본을 만드는 것이 아니라, 해당 메모리를 그대로 읽는다. (GetRoot 메소드에 넘긴 버퍼는, 리턴 된 포인터가 유효할 때 까지 유효 해야 한다.)
      • 그래서 그렇게 동작 할 수 있게 (다른 스레드나, 다른 함수 등으로 인자로 넘길 때도 life-cycle이 유지 될 수 있게끔)
  • FlatBuffersHelper
    • flatbuffer를 안정하게 사용하게 도와주는 함수들로 구성되어있다.
    • 이 중에서도 특히 parsing 메소드를 통해 안전하다 확인된 버퍼에 대해서 만 사용해야 한다. 반드시!

redis

  • redis의 publisher/subscriber 기능만 구현되어있다.
    • redis/redisclient.sln 솔루션을 참고하라.
  • 사용한 라이브러리는 redisclient이다.
  • lambda로 callback을 받는데, io_service thread에서 호출 된다는 점을 명심하라.
    • 일반 콜백과 다르게, stack 변수를 그대로 사용할 수 없다.
    • 사본으로 life-cycle을 유지해야 한다.

light-net

  • C++ 기반의 IOCP 서버 라이브러리이다.
    • Network.xml에 정의된 변수 기반으로 동작한다.
    • light-net.h 상단에 있는 상수들도 큰 영향을 준다.
  • Threading 룰은 light-net/readme.md를 참고하면 된다.
  • lock 정책은 spin_lock을 구현해 사용한다.
    • spin_lock.h
  • thread간 겹치는 변수에 대한 접근 및 변경은 std::atomic을 통해 처리한다.
  • 함수 네이밍 정책은, 사용은 동사. callback은 on_동사를 사용한다.
    • 요청 : receive
    • 콜백 : on_receive

light-net IOCP

  • Session : connection 맺은 대상과 1:1 대응되는 객체.
    • GQCS와 직접적인 IO를 처리한다.
  • IOCP Worker
    • GQCS를 물고 있는 클래스.
  • Listener
    • TCP 포트를 열어 통신하기 위한 클래스.
    • 주로 서버에서 사용한다.
    • Session을 수용 가능한 사용자 수 만큼 생성.
    • light::net::Listener::AllocThread()에 넘긴 인자 만큼 Worker를 생성한다.
      • 넘어온 인자와 별개로 1개 스레드를 따로 생성해서, Accept 전용 스레드로 사용.
  • Acceptor
    • connection 요구 수용을 위해, accept를 걸기 위해 사용되는 객체.
    • Listener를 통해서 만 사용한다.
  • Connector
    • TCP 서버와 connection을 맺기 위해 사용되는 객체.
    • Session을 1개만 들고 있음.
    • 서버 <-> 서버의 Connection 용으로 써도 된다.
    • light::net::Connector::AllocThread()에 넘긴 인자 만큼 Worker를 생성한다.
    • Connector용으로는 1개를 권장한다.
  • Peer
    • Session과 1:1 대응되는 객체다. 상속을 통해 확장을 유도하며, network 이벤트를 수신 할 수 있게 강제한다.
  • Peer의 주요 메소드
    • on_connect
  • 접속 완료 시 호출 되는 메소드.
    • on_receive
      • verify를 통해 split 된 단위로 호출되는 메소드.
      • 주의 할 점은 Session의 Iocp Receive 버퍼의 포인터가 그대로 넘어온다는 점이다.
      • 이후에도 사용하려는 데이터나, 다른 스레드로 데이터를 넘기는 경우에는 반드시 복사해서 사용해야 한다.
  • on_disconnect
    • 소켓 끊겼을 때 불려지는 메소드.
  • verify
    • 유효한 패킷인지 검증하는 함수다.
    • 오버로딩 안 했을 때는, PACKET_HEADER의 사이즈 검증만 한다.
  • disconnect
    • 접속 해제 요청 메소드
  • reuse
    • peer에 대한 사용이 모두 완료되어, 해당 peer (&session)을 재 사용해도 된다고 알리는 메소드.
  • send
    • 패킷 전송 메소드.

relay_servers

  • 릴레이 서버는 light와 light-net을 이용해 구현되었다.
  • 기본적인 주의 사항은 위 라이브러리들의 주의 사항 위주로 읽으면 된다.
  • 한 가지 추가적인 주의 사항은 threading에 대한 주의 사항이다.
    • 두 가지 thread가 존재한다.
      • redis thread
        • network threads [on_recieve]
        • 부하 분산을 위해, channel 별로 thread를 가른다.
        • 그래서 strand_post_job 시에 주의가 필요하다.
        • 채널 생성 및 관리 등 채널에 접근하는 스레드 지정
          • channel_manager_strand_position
        • 해당 채널 내의 스레드 지정
          • channel_strand_position

서버 개발 및 운영에 필요한 작업

오늘은 많은 서버 개발자 분들이 (그리고 더 많은 다른 파트 개발자 분들이) 알고 계신데 막상 개발 플랜에 누락되는 일이 비일비재한 것들에 대해 이야기 해보고자 합니다.

많은 팀이 겪게되는 가상 시나리오를 그려보겠습니다.

프로토타이핑이 성공적이었습니다! 개발팀이 세팅 됩니다. 개발 언어, 플랫폼, 엔진 (or 프레임워크)등을 정하게 되죠. 베이스 작업 기간으로 한달 정도 잡습니다. 컨텐츠별로 1주~2주 사이를 잡습니다. 그리고 각 컨텐츠가 다 완성되고 폴리싱 작업으로 한달 잡네요. 네. 좋습니다. 대략 컨텐츠가 8개 정도 되네요. 평이한 컨텐츠가 다수라 8주라 예상해봅시다. 베이스 작업+컨텐츠해서 3달 나왔네요. 폴리싱까지 4달이었죠? 여유 기간 포함해서 5달 질러봅니다. 오오!! 승인됐네요. 자~ 작업에 들어갑니다. 베이스 작업은 예상대로 잘 됩니다. 오히려 시간이 조금 남았네요? 작은 오차들과 예상외 변수가 있었지만 그럭저럭 개발 기간을 맞췄군요! 기능도 오류가 좀 있지만, 폴리싱 기간에 집중하면 될거 같은 양입니다. 출시 문제 없겠네요. 하하하~ … 헌데… 예상치 못한 일들이 끼어들어오기 시작합니다. GM툴과 사용법을 달라고 하시는군요. … 헐...꼭 해줘야할까…? 고민도 되고 반려도 하고 싶지만, 서비스를 위해 꼭 필요한 기능이죠. 갑자기 머리가 아파집니다. 우선 GM툴이 만들어질때까지, DB쿼리를 만들어 테스트를 지원합니다. 자...다른 일정을 몇개 양보받고, 시간을 쪼개고 쪼개서 GM툴을 만들어 제공합니다. 이전보다 원활한 테스트가 진행되는군요. 자 이제 출시 준비를 하려는데… 통계툴을 요청받습니다. ….-_- 더 시간을 확보할 방법도 없는데… 최소한의 기능만 볼 수 있게 끼워 넣습니다… 남기고 있는 로그가 추출하기 적절한 로그가 아니라, 로그 기록 작업을 하느라 더 시간 소모가 컸군요. 어라? 당연히 필요한 결제 기능이 없었군요? 지원 해야 될 스토어가 세종류네요… 스토어별로 처리 방식이 달라, 세번 다 따로 구현해야 되겠군요... 자 어떻게든 선택과 집중을 통해 몇몇 기능과 퀄리티를 양보하며, 필요한 백엔드 작업을  그럭저럭 마친 것 같습니다. 게임을 출시합니다. 가아아아암동~ 몇달간의 노력이 드디어 빛을 발할 때 입니다. 유저가 몰립니다. 우오오오오~~ 서버를 증설합니다! 이제 서버가 50대로 구성됐습니다. 이제 점검을 할 때마다 50대에 배포 해야 되네요… 한대당 2분 잡아도 패치만 100분이군요. 다행히 우린 서버 프로그래머가 2명이니 50분 정도면 될까요? 부족한 운영툴의 기능으로, 서버 데이터 패치로 이벤트를 진행합니다. 밤이 되었습니다. 유저는 여전히 많네요. 불안불안합니다. 새벽 3시가 됐음에도 유저는 별로 줄어들지 않네요. 혹시 몰라 서버 50대를 순회하며, 오류 로그를 모니터링합니다. 헐…! 사고가 났네요. 복구 및 보상을 해줘야겠습니다. … 점검시점에서 모든 유저에게 보상을 주자니 너무 많네요. 로그인시 아이템을 지급하는 보상 시스템을 구현합니다… …하… 복구를 하려했더니 백업된 데이터가 부족하네요. 백업/복구 시스템을 못갖춰놨었습니다. 이대로 롤백해야 되는걸까요…?

자… 이쯤 되면 감이 오시나요? 서버라는 포지션 자체는 당연하게도 서비스를 위해 존재합니다.

비지니스 로직이 아닌 작업이 이렇게나 많이 필요하고, 당연히 많은 시간이 필요합니다.

물론 제가 나열한 작업 중에 여러 작업이 지원 부서가 있는 회사. 혹은 퍼블리셔에서 제공되는 기능들도 많습니다.

하지만 의외로 원하는 기능들 중 빠졌거나, 기능은 제공되지만 세부적인 기능이 달라 사용할 수 없는 일도 비일 비재합니다.

혹은 원하는 기능이 모두 있는 서비스는 비용이 비싸서 사용하기 부담스러운 경우도 생기지요.

가장 큰 문제는 이런 백엔드 작업들이 개발 초기 단계부터 일정 산정에 고려 대상이 아닐 때가 많다는 점입니다.

개발 담당자가 직접 어필하지 않으면, 백엔드 작업은 프로젝트 전체 일정 산정에 고려되지 않을 공산이 큽니다.

개발 초기 서비스 일정을 산정하셔야 되는 분들이라면, 이 글을 읽으시고 하나라도 더 떠올리시어 백엔드 작업 일정과 작업 계획도 수립하시길 바라며 마치겠습니다.

컨텐츠 제외 필요 작업 요약

  • GM툴
  • 통계툴
  • 로그 기록 작업
  • 결제 기능
  • 배포
  • 이벤트
  • 모니터링
  • 보상 시스템
  • 백업/복구 시스템