모바일 RPG 게임서버
리팩토링
천기환 / gujjy97@gmail.com
작성자는…
• Java 웹 개발자
• Spring framework를 주무기로
• SI로 시작, 업무 도메인을 자주 바꾸는게 싫어서
어쩌다 게임 개발로 전향
• 도메인만 게임으로 바뀌었고 기술 스택은 그대로
모바일 게임서버를 웹으
로
• 왜?
• 실시간 서비스가 곤란하다
• 비연결형 서비스에 최적
• 밀리언 아서가 성공해서?
프로젝트와 만남
• 개발 시작 2년정도
• 투입 당시 3개월 후에 론칭한다고
• 전담 서버 개발자 없었어요.
• Java 웹서버는 게이트웨이 및 흐름제어정도
(어디든) 기획은 굴곡진
다
• 아이템 기획을 새로?
• 인벤토리는 캐릭터 귀속? 계정 귀속?
• 반복성 있는 속성에 대한 다양화 기획!?
• 동일 로직인데 대상이 달라
Stored Procedure(SP) 가 어때서?
• DBA가 튜닝과 로직을 동시에 책임
• 웹앱은 DB분산에 대한 흐름관리만
• SP 안에서 트랜잭션(TX) 스콥은 최대한 짧게
• 문제는 CS로 해결
• 테이블 쓰임은 SP에서 확인
SP 가 어때서?
• 흐름은 웹 앱에서, 세부 로직을 확인하려면 SP를 확인
• 버그 처리 역할과 책임이 분할, 소통비용 발생, 일단 혼자니
그다지
• 이쪽 저쪽 확인하기 귀찮…
• SP 작성시 성능 고려, 인덱스만 서너개씩? include 인덱스
는 캐시?
• SP 안에서 SP를 호출, Depth가 서너번인 것을 서너번 반복
• DB에서 직접 수정하면 버전관리는??
• 의존성 확인을 위한 정적 분석이 곤란(테이블/컬럼 삭제하
면?)
• 추상화? 동일 로직 복붙 & 테이블/컬럼명 변경!
PHP에서 Java/Spring으
로
• 회사내 기존 모바일 게임서버는 PHP +
SQLServer
• PHP와 SQLServer 에서 궁합이 않좋았다고
• PHP는 아마 밀리언아서 때문에?
• Java는 커넥션 풀이라는 것을 쓸수가 있대!!!
• 웹 언어를 바꿔도 로직이 DB에 있으면!!!
• 웹은 거들 뿐이었죠!
말만 Java/Spring
• Map/List 로 떡칠.
• 타입? DTO? 그런거 없어요.
• 제네릭? 우걱우걱
• Servlet Container는 상태를 가지는 가지게 할 수
있는 서버인데
• DB간 흐름만 관리하기만 하지도 않아요
일정은 고무줄?
• 아이템.. 또 재기획(8차래요!? 론칭할때는 12차?)
• 서버 개발자는 일단 혼자.
• 바꿀수 있는 시간이 생겼어요!
• 반발을 줄여라! 점진적으로…
• 개발에 지장을 주면 안되요!!!
장애는 안되! 개발서버
라도!
• 훈련은 전투다! 각개전투!
• 실전과 같은 훈련으로 지상전의 승리자가 된다!
• 서버 개발자 한명이 40~50명을 놀게 한다.
• DB Schema 변경은 증분으로, SP 후방 가변(기본
인자)
• 웹 무중단 패치? 아주 잠깐 몇몇은 불안정해도?
무엇부터 할까?
• 바꾼 것이 괜찮음을 확신 할 수 있어야
• API 시나리오 테스트를 만들어요!
• 매번 게임 계정을 새로 생성하게 합니다.
• 개인 컨텐츠 위주입니다.
• Logic In DB… 어차피 단위 테스트는 못합니다!
무엇부터 할까?
• 가장 많이 중복되는 것 => 효과가 크다
• 되돌리기 쉬운 것 => 일괄 치환하자
• 중요하게 여기지 않는 것 => 그러려니 넘어가 줘
요
• 결과 코드 반환하는 부분부터 => DTO를 만들어
서 처리 => Output Param (Multi ResultSet=>
Single ResultSet)
DB는 소중해요
• Scale Up 해야 하는 자원
• 개인 데이터는 Scale Out 하게, But 바란스를 맞추
려면…
• 길드, 친구 같은 소셜컨텐츠는 Scale Up…
• 랭킹은 DB 잡아먹는 괴물!!
• Select 수를 줄이고 싶습니다.
• 로직을 웹앱으로
Map -> DTO
• 네 노가다 좀 했어요
• 변환은 MyBatis가 해줘요
• Request도 Map에서 DTO로
• if ((int)map.get(“xxx”) == 0)
• controller 의 requestMapping 메서드의 return은
못바꿨어요.. Map에다 DTO 개체들을….
에러코드를 웹앱으로
• 에러코드를 문서화 하기 위해 에러를 Checked
Exception으로 변환해서 Controller까지 전달시킵
니다.
• RollbackFor도 RuntimeException이 아니라
Exception으로 바꿨어요.
• 에러코드도 상수화해서 모았어요.
로직을 서서히 웹앱으로
• 과감히 브랜치를 생성
• SP를 CRUD만 하도록
• 로직을 웹으로
• TX도 웹에서
• 리팩토링은 정규업무가 아니잖아요?!
• 서서히 단위 테스트도 만들어 봅니다.
DB 부하 줄인다면서?
• 개인 게임 데이터는 최대한 Session에 넣습니다.
• Non-Sticky라서 memcached-session-manager를 썼
어요.(L7쓰고 싶었습니다.)
• 기초/기준/상수 데이터는 myBatis 캐시 썼어요 =>
Spring Cache로…(MyBatis도 걷었어요)
• 그래도 SP는 남아 있어요. 쿼리 플랜 캐시? PSMT도
되는데…
• ORM은 아직 안되요!!
무엇이 바뀌었나?
• 반복 감소: 아이템 옵션, 충전성 재화, 랭킹
• 책임 위치 분리와 의존성 가시화
• 코드 정적 분석 : PMD, STAN4j, Dependency
Metrics
• 계정, 캐릭터, 경제, 전투, 소셜 순서로 계층적 의
존
• 고가용성 증가 : DB ScaleUp 여유확보, 웹서버 추
가
• 단위 테스트 가능
• 이벤트 기능은 AOP나 Intercepter로 처리가능
무엇이 바뀌었나?
• 최대한 자동화 : 빌드, 상수데이터 exp/imp, SQL
• 최대한 버전관리
• svn -> git
• 타겟서버 = git branch 이름
• 코드리뷰
• batch/shell script 수
‘R&D 프로젝트’라네요
• NoSQL 2가지 사용, 2가지 R&D
• Redis, memcached, infinispan, cassandra
• 웹앱 TX, 웹앱 로직, Session, Cache 사용
• SQLServer : BCP, SQLCMD를 이용한 배포자
동화
• CI 부분 적용
• DBA에게 통계 업무할 여유가 생긴 것 같아요.
사내 첫 지표 자율화 프로젝트!
마치며..
• 뿌듯함..
• 론칭과 운영
• 성능 테스트 그럭저럭 큰탈없이
• 대용량 트래픽
• 종합적인 흐름, 아키텍처를 보는 안목
• 코드 리뷰, 협업, 주거니 받거니
마치며..
• 아쉬움..
• 상용서버처럼 개발서버도…
• ORM, Sticky Session, L7
• 실시간 컨텐츠-소켓도 Java로..
• 소셜 컨텐츠는 MSA로 분리 했으면..
• CI를 믿고 DevOps!
• API 로그를 남겼으면
• 개발 언어, 환경에 대해 공유 노력을 많이 했어야
• 라이브러리는 좀 더 검토해야

모바일 Rpg 게임서버 리팩토링

  • 1.
  • 2.
    작성자는… • Java 웹개발자 • Spring framework를 주무기로 • SI로 시작, 업무 도메인을 자주 바꾸는게 싫어서 어쩌다 게임 개발로 전향 • 도메인만 게임으로 바뀌었고 기술 스택은 그대로
  • 3.
    모바일 게임서버를 웹으 로 •왜? • 실시간 서비스가 곤란하다 • 비연결형 서비스에 최적 • 밀리언 아서가 성공해서?
  • 4.
    프로젝트와 만남 • 개발시작 2년정도 • 투입 당시 3개월 후에 론칭한다고 • 전담 서버 개발자 없었어요. • Java 웹서버는 게이트웨이 및 흐름제어정도
  • 5.
    (어디든) 기획은 굴곡진 다 •아이템 기획을 새로? • 인벤토리는 캐릭터 귀속? 계정 귀속? • 반복성 있는 속성에 대한 다양화 기획!? • 동일 로직인데 대상이 달라
  • 6.
    Stored Procedure(SP) 가어때서? • DBA가 튜닝과 로직을 동시에 책임 • 웹앱은 DB분산에 대한 흐름관리만 • SP 안에서 트랜잭션(TX) 스콥은 최대한 짧게 • 문제는 CS로 해결 • 테이블 쓰임은 SP에서 확인
  • 7.
    SP 가 어때서? •흐름은 웹 앱에서, 세부 로직을 확인하려면 SP를 확인 • 버그 처리 역할과 책임이 분할, 소통비용 발생, 일단 혼자니 그다지 • 이쪽 저쪽 확인하기 귀찮… • SP 작성시 성능 고려, 인덱스만 서너개씩? include 인덱스 는 캐시? • SP 안에서 SP를 호출, Depth가 서너번인 것을 서너번 반복 • DB에서 직접 수정하면 버전관리는?? • 의존성 확인을 위한 정적 분석이 곤란(테이블/컬럼 삭제하 면?) • 추상화? 동일 로직 복붙 & 테이블/컬럼명 변경!
  • 8.
    PHP에서 Java/Spring으 로 • 회사내기존 모바일 게임서버는 PHP + SQLServer • PHP와 SQLServer 에서 궁합이 않좋았다고 • PHP는 아마 밀리언아서 때문에? • Java는 커넥션 풀이라는 것을 쓸수가 있대!!! • 웹 언어를 바꿔도 로직이 DB에 있으면!!! • 웹은 거들 뿐이었죠!
  • 9.
    말만 Java/Spring • Map/List로 떡칠. • 타입? DTO? 그런거 없어요. • 제네릭? 우걱우걱 • Servlet Container는 상태를 가지는 가지게 할 수 있는 서버인데 • DB간 흐름만 관리하기만 하지도 않아요
  • 10.
    일정은 고무줄? • 아이템..또 재기획(8차래요!? 론칭할때는 12차?) • 서버 개발자는 일단 혼자. • 바꿀수 있는 시간이 생겼어요! • 반발을 줄여라! 점진적으로… • 개발에 지장을 주면 안되요!!!
  • 11.
    장애는 안되! 개발서버 라도! •훈련은 전투다! 각개전투! • 실전과 같은 훈련으로 지상전의 승리자가 된다! • 서버 개발자 한명이 40~50명을 놀게 한다. • DB Schema 변경은 증분으로, SP 후방 가변(기본 인자) • 웹 무중단 패치? 아주 잠깐 몇몇은 불안정해도?
  • 12.
    무엇부터 할까? • 바꾼것이 괜찮음을 확신 할 수 있어야 • API 시나리오 테스트를 만들어요! • 매번 게임 계정을 새로 생성하게 합니다. • 개인 컨텐츠 위주입니다. • Logic In DB… 어차피 단위 테스트는 못합니다!
  • 13.
    무엇부터 할까? • 가장많이 중복되는 것 => 효과가 크다 • 되돌리기 쉬운 것 => 일괄 치환하자 • 중요하게 여기지 않는 것 => 그러려니 넘어가 줘 요 • 결과 코드 반환하는 부분부터 => DTO를 만들어 서 처리 => Output Param (Multi ResultSet=> Single ResultSet)
  • 14.
    DB는 소중해요 • ScaleUp 해야 하는 자원 • 개인 데이터는 Scale Out 하게, But 바란스를 맞추 려면… • 길드, 친구 같은 소셜컨텐츠는 Scale Up… • 랭킹은 DB 잡아먹는 괴물!! • Select 수를 줄이고 싶습니다. • 로직을 웹앱으로
  • 15.
    Map -> DTO •네 노가다 좀 했어요 • 변환은 MyBatis가 해줘요 • Request도 Map에서 DTO로 • if ((int)map.get(“xxx”) == 0) • controller 의 requestMapping 메서드의 return은 못바꿨어요.. Map에다 DTO 개체들을….
  • 16.
    에러코드를 웹앱으로 • 에러코드를문서화 하기 위해 에러를 Checked Exception으로 변환해서 Controller까지 전달시킵 니다. • RollbackFor도 RuntimeException이 아니라 Exception으로 바꿨어요. • 에러코드도 상수화해서 모았어요.
  • 17.
    로직을 서서히 웹앱으로 •과감히 브랜치를 생성 • SP를 CRUD만 하도록 • 로직을 웹으로 • TX도 웹에서 • 리팩토링은 정규업무가 아니잖아요?! • 서서히 단위 테스트도 만들어 봅니다.
  • 18.
    DB 부하 줄인다면서? •개인 게임 데이터는 최대한 Session에 넣습니다. • Non-Sticky라서 memcached-session-manager를 썼 어요.(L7쓰고 싶었습니다.) • 기초/기준/상수 데이터는 myBatis 캐시 썼어요 => Spring Cache로…(MyBatis도 걷었어요) • 그래도 SP는 남아 있어요. 쿼리 플랜 캐시? PSMT도 되는데… • ORM은 아직 안되요!!
  • 19.
    무엇이 바뀌었나? • 반복감소: 아이템 옵션, 충전성 재화, 랭킹 • 책임 위치 분리와 의존성 가시화 • 코드 정적 분석 : PMD, STAN4j, Dependency Metrics • 계정, 캐릭터, 경제, 전투, 소셜 순서로 계층적 의 존 • 고가용성 증가 : DB ScaleUp 여유확보, 웹서버 추 가 • 단위 테스트 가능 • 이벤트 기능은 AOP나 Intercepter로 처리가능
  • 20.
    무엇이 바뀌었나? • 최대한자동화 : 빌드, 상수데이터 exp/imp, SQL • 최대한 버전관리 • svn -> git • 타겟서버 = git branch 이름 • 코드리뷰 • batch/shell script 수
  • 21.
    ‘R&D 프로젝트’라네요 • NoSQL2가지 사용, 2가지 R&D • Redis, memcached, infinispan, cassandra • 웹앱 TX, 웹앱 로직, Session, Cache 사용 • SQLServer : BCP, SQLCMD를 이용한 배포자 동화 • CI 부분 적용 • DBA에게 통계 업무할 여유가 생긴 것 같아요. 사내 첫 지표 자율화 프로젝트!
  • 22.
    마치며.. • 뿌듯함.. • 론칭과운영 • 성능 테스트 그럭저럭 큰탈없이 • 대용량 트래픽 • 종합적인 흐름, 아키텍처를 보는 안목 • 코드 리뷰, 협업, 주거니 받거니
  • 23.
    마치며.. • 아쉬움.. • 상용서버처럼개발서버도… • ORM, Sticky Session, L7 • 실시간 컨텐츠-소켓도 Java로.. • 소셜 컨텐츠는 MSA로 분리 했으면.. • CI를 믿고 DevOps! • API 로그를 남겼으면 • 개발 언어, 환경에 대해 공유 노력을 많이 했어야 • 라이브러리는 좀 더 검토해야