1 / 37

가상의 온라인 게임으로 살펴보는 리팩토링의 솔직한 이야기

가상의 온라인 게임으로 살펴보는 리팩토링의 솔직한 이야기. 2008.11.14 김익중 2008 (R) http://rhea.pe.kr/. Contents. 가상의 온라인 게임으로 살펴보는 리팩토링의 솔직한 이야기 1) 일러두기 2) 리팩토링 3) 가상의 온라인 게임 NEMO Online 4) NEMO Online 제작기 5) 개발 중 리팩토링 6) 실패 사례 분석 7) NEMO Online 리팩토링 8) 배포 9) 반성하기 10) 결론. 일러두기.

Télécharger la présentation

가상의 온라인 게임으로 살펴보는 리팩토링의 솔직한 이야기

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 가상의 온라인 게임으로 살펴보는리팩토링의 솔직한 이야기 2008.11.14 김익중 2008 (R) http://rhea.pe.kr/

  2. Contents 가상의 온라인 게임으로 살펴보는 리팩토링의 솔직한 이야기 1) 일러두기 2) 리팩토링 3) 가상의 온라인 게임 NEMO Online 4) NEMO Online 제작기 5) 개발 중 리팩토링 6) 실패 사례 분석 7) NEMO Online 리팩토링 8) 배포 9) 반성하기 10) 결론

  3. 일러두기 • 우리 나라의 온라인/네트워크 게임의 특징 • 중박(?) 이상의 힛트를 치긴 무척 힘들다 • 한번 히트를 친 게임은 쉽게 스테디셀러 게임이 된다 • 온라인 게임의 특성상 스테디 셀러가 된 이후에도 • 꾸준한 업데이트가 필요하다.

  4. 리팩토링 • 리팩토링이란? (from 위키백과) • 소프트웨어 공학에서 리팩토링(refactoring)은 주로 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다. 주로 가독성을 높이고 유지보수를 편하게 한다. • 버그를 없애거나 새로운 기능을 추가하는 행위는 아니다. • 사용자가 보는 외부 화면은 그대로 두면서 내부 논리나 구조를 바꾸고 개선하는 유지보수 행위이다. • 왜 리팩토링에 관심을 가져야 하는가? • 원래 SI 쪽이나 오랜 시간 version up 을 해온 해외 애플리케이션들만의 영역 • 몇 년 사이 한국의 온라인 게임들에게 필수적인 상황이 되었음 • 80:20 법칙은 게임 개발에도 통한다 • 이제까지 80%는 기존 코드에 대한 추가/업데이트였으며 전혀 새로운 코드로 채우는 것은 20%에 불과하였다.

  5. 리팩토링 • 리팩토링이 필요할때는? • 코드가 유지보수하기 힘들어졌을때 • 몇년간 서비스를 지속하는 게임에서만 일어나는 과정이 아님 • 신규 게임 제작을 하더라도 기존 라이브러리는 반드시 참조/이용하게 됨 • 결국 소스 코드의 생명력은 게임 생명 주기보다 훨씬 길어지게 됨 • 리팩토링은 항상 해야만 하는 것(애자일 개발) • 개발 완료후 유지보수 단계에서만 일어나는 일이 아니다 • 잘못된 생각 : • "이 게임은 시장에서 딱 2년만 서비스하면 되는 것이거든요? 그러니까 그런거 신경쓸 필요는 없어요."

  6. 리팩토링 • 리팩토링이 자주 발생하는 프로그램은? • 특정 영역사이의 브릿지 프로그램 • 특정 클래스 사이의 브릿지 클래스 • 특정 담당자가 없는 프로그램 • 서로 다른 팀업무 사이에 놓인 프로그램 • → 한마디로 만만한 프로그램

  7. 가상의 온라인 게임 NEMO Online • 가상의 온라인 게임 "NEMO Online" • 개발 시작은 2003년 무렵 • 게임의 특징 • 풀스크린일 경우 4:3 모니터와 16:9 모니터에 알맞게 최적화 • 윈도우 모드에서는 리사이즈 가능 및 UI 구성요소 재배치 • 로비에서 대부분의 정보는 리스트 컨트롤 형태로 제작 • 게임 중에도 로비에 위치한 유저와 통신 및 100% 동일한 기능을 사용할수 있어야 한다 • 다중 세션의 허용 - 한 클라이언트에서 동시에 플레이어를 2개 이상 배치가능 • 서버 구분 없음 - 접속자가 늘게 되면 서버를 구분할려고 기획함 • CPU 대전 지원

  8. 가상의 온라인 게임 NEMO Online • 코드의 특징 • 개발자라면 누구나 '잘' 만들려고 한다. • 개발자는 소스 코드내 동일함수의 이중 코딩을 엄격히 제한 • C++의 폴리모피즘과 인터페이스의 철저한 사용 • 자주 사용하게 될 기능은 전부 Static Library로 구성 • 모든 자료구조는 STL만을 이용함(Map, List, Vector 등...) • 게임 사이트내 표준 UI, 표준 요구사항을 기존 플랫폼이 아닌 호환성 있는 독자적인 플랫폼으로 재구성 • 유니코드 • Win98에서도 작동가능 • 개발중 수시로 리팩토링을 시도함

  9. NEMO Online 제작기 • 세션 클래스 • 로긴 이후사용자 정보를 유지하는 기본 클래스 생성 • 세션정보가 필요한 모든 구성요소는 세션 클래스에서 상속 • 실제로 엄청난 분량의 다중상속들로 구현

  10. NEMO Online 제작기 • 전체 사용자 정보를 유지 • 클라이언트는 RAM이 많고 인터넷도 빠르므로 모든 정보를 갖고 있자. • 서버에게 상세 정보 요청을 하지 않는다. • 로비 혹은 게임의 어느 위치에 있던 접속된 모든 사용자 정보를 생성, 업데이트, 삭제 • 이로 인해 빠른 위치(Zone) 이동 가능 • 전체 사용자 정보 클래스에서 상속을 이용하여 세분화된 사용자 정보 클래스 구현 (전체정보, 게임정보, 사이트 공통 정보, 친구 정보, etc...) • 싱글턴 패턴으로 전역변수화 시킴 • 모든 정보는 리스트화 시켜 표현 • UI 리스트는 팩토리 패턴 이용

  11. NEMO Online 제작기 • 전체 화면시 모니터 해상도 비율 • 4:3과 16:9 에서 각각 UI 구성요소가 다름 • 16:9 로비에서는 사용자 정보 리스트가 추가됨 • 화면을 구성하는 추상 인터페이스 선언 • 인터페이스를 상속 받아 해상도 비율에 따른 독립적인 UI 구성

  12. NEMO Online 제작기 • 리사이즈 • 리사이즈시 필요한 정보(창의 너비, 높이)를 위해 각각의 가상 윈도우 개념을 도입 • 전체 윈도우 사이즈를 기반으로 WM_SIZE를 이용하여 구성 • 가상 윈도우는 GDI 정보와 D3D 를 기반으로한 모든 컨트롤 형태를 지원 • 가상 윈도우는 전체 게임 화면에서 차지하는 퍼센트(%) 비율로 위치를 구함

  13. NEMO Online 제작기 • 로비는 하나로 통일 • 네트워크 구조는 밸런싱 서버를 거쳐 로비 서버로 접속 • 게임서버와 로비 서버로의 이동은 서버 사이드내에서 발생 • 클라이언트/서버 관게에서 접속과 해제는 오로지 로비 서버뿐. • 게임 중에도 로비에서 발생하는 모든 정보를 받음 • 친구찾기, 위치추적(따라가기) 가능 • 대게의 경우 로비와 게임은 다른 프로젝트로 구성되는 사례가 많음 • 로비와 게임의 통신방법은 소켓, FileMap 등 다양

  14. NEMO Online 제작기 • 게임룰 • 템플릿을 이용한 Generic Algorithm으로 구현 • 게임룰은 결코 변경되지 않을 것이라 가정했음 • 외부 데이터 관리 • INI 파일 – 초기 데모용 데이터 관리방법을 그대로 사용함 • 자체 스크립트 언어

  15. 개발 중 리팩토링 • 상기의 사항들로 제작도중일차적으로 개발자를 괴롭힌 것은 빌드 시간 • STL의 빌드문제 • 매크로 - 가상 윈도우 시스템, 운영체제 구별용 전처리기 • 추상 인터페이스와 상속 • 세션클래스들의 일반 상속 • 개발도중 우선 적용했던 해결책 • CImpl 패턴사용 • Visual AssistX가 심볼을 찾지 못함 • 헤더파일의 엄격한 참조검사 • 별 도움이 안됨

  16. 개발 중 리팩토링 • Win98문제 • INI 파일의 한계가 64KB – 서비스중 데이터 로더 재작성 • 유니코드 문제 – IncrediBuild 빌드 불가능 • 대부분 전처리기(#ifdef)로 해결

  17. 실패 사례 분석 • 개발자 입장에서 결코 성공적인 아웃풋으로 만들어 내지는 못함 • 보통은 기능추가 중 프로젝트가 망가지게 되나, • NEMO Online의 사례는… • 지독히 이해하기 힘든 소스문제 • 리팩토링 도중 디자인 패턴을 위한 디자인 패턴의 사용 • 강박적인 일반화 사용과 의미없는 폴리모피즘 • 세션 윈도우와 가상 윈도우의 디버깅 난이도 • 빌드 시간

  18. 실패 사례 분석 • 세션 클래스 • 세션 클래스를 상속받은 클래스들은 결국 UI 클래스 • 결국 세션 정보와 UI가 한 인스턴스로 합쳐짐 • 데이터와 UI가 분리되지 못하는 결과를 초래 • 리스너 구조의 범람으로 전혀 상관없는 모든 인스턴스에게 정보를 전달 • 성능 및 디버깅에 악영향 • UI가 합쳐지며 전체적인 성능은 극도로 나빠짐 • 세션 클래스의 설계는 서버 개발자의 아이디어 • UI가 붙은 코드를 평소 접해보지 못했음

  19. 실패 사례 분석 • 사용자 정보 • 서버가 분리되지 않은채 전체 사용자 정보를 담고 있어 클라이언트 성능에 악영향 • 사용자 정보를 추상 인터페이스를 바탕으로 상속받아 변경시 너무 많은 수정을 요구 • 초기 커넥션시 약 3MB 분량의 사용자 정보를 소켓으로 받음 • 아무리 클라이언트 환경이 빨라졌어도 상기의 시도는 시기상조였음 • 모니터 해상도 비율 • 인터페이스 상속에 따른 구현의 이중성 • 굳히 인터페이스 상속을 통해 구현해야 했을까?

  20. 실패 사례 분석 • 리사이즈 • UI 배치 수정에 악영향 • 특히 모서리에 라운딩 처리가 된 UI 구현시, 일정 초과의 주범 • 1px 가상 윈도우들로 간격조절 • 너무 많은 UI클래스들을 생성시킴 • 로비 • 채널변경은 필수적은 기능 • 초기 기획에 채널 변동이 없었더라도 채널 변경을 고려한 설계가 있었어야 했음 • 전체 정보를 송수신하는 이유로 서버 성능 저하 초래 • 네트워크 게임의 기본을 망각한 사례 • 보이지 않는 것은 그리지 않고들리지 않는 것은 듣지 않는다

  21. 실패 사례 분석 • 일반화된 게임룰 • STL과 템플릿을 이용한 코드는 누구나 만들수 있다 • 개발자의 겉멋이 프로젝트를 망치게 하는 대표적인 사례 • 일반화 코드는 예외상향 변경시 의미가 없어진다 • 게임의 룰은 반드시 바뀐다 • 아이템은 게임룰을 바꾸는 대표적인 사례 • CPU 대전과 실제 접속자들과의 대전에서 문제 발생 • 약간의 변동이 생길때마다 두 부분의 룰을 고침

  22. 실패 사례 분석 • 엄격한 헤더파일 구분 • 네트워크 패킷 클래스에도 적용 • 네트워크 패킷 구분화로 헤더파일의 재정의하는 사례가 생김 • 서버와 다른 define을 사용하는 데이터 발생 • 외부 데이터 관리 포맷 • 외부 자료 관리 구조는 누구나 만들수 있지만 200~300개 정도의 자료를 다루게 되면 지옥이 된다 • 검증툴이 반드시 필요 • 웹브라우저처럼 “새로고침”을 할수 있는 기능이 필요

  23. 실패 사례 분석 • Static Library • 왜 라이브러리를 만드는가? • 함수 기준으로 라이브러리로 만드는 것은 아무런 의미가 없다 • 라이브러리 코드에 절대 컨텐츠 코드가 포함되어서는 안된다. • 라이브러리에 컨텐츠 코드가 포함되는 순간 그 라이브러리는 의미가 없다 • 라이브러리를 만들기는 쉬워도 재활용은 정말 어렵다 • 솔루션에서 라이브러리 프로젝트는 빨리 없애버려라

  24. NEMO Online 리팩토링 • Re리팩토링 시작 (2007~2008) • 시대가 바뀌어도 여전히 개발자가 믿을 것은 OOP이다 • 캡슐화 • 클래스를 추상클래스로 만들고 전달값을 클래스의 파생클래스로 만들자 • 상속 • virtual 함수 • 다형성 • 각각의 virtual 함수들을 추상클래스의 이름으로 작동시키자

  25. NEMO Online 리팩토링 • 기본 원칙 • 변수는 ADT(abstract data type)를 사용하자 • 함수호출은 폴리모피즘을 활용한 Plug-In을 이용하자 • DLL 구조로 변경 • 규정된 Plug-In으로 호출되지 않는 일반 함수는 오버로딩 금지 • ConnectToServer(☺☺☺…) • ConnectToServer(♠♠♠) • ConnectToServier_Web_DebugOn() • ConnectToServier_Local_DebugOff() • ......

  26. NEMO Online 리팩토링 • 컨텐츠 코드와 라이브러리 코드는 각각 다른 EXE, LIB, DLL로 구현해야 한다 • UI와 자료구조는 절대로 한 클래스 속에 혼합되어서는 안된다 • "자주 사용하는 기능" 이 아닌 컨텐츠와의 분리 • 리소스를 절대 실행 파일 내에 두지 말것 • 깨어진 유리창의 시작이 된다 • 갓 졸업한 신규입사자가 와도 매주 컨텐츠를 뜯어 고칠수 있어야 한다. • 스크립트에 지나친 의존을 하지 않는다 • 기획자, 디자이너가 작업하지 않으면 의미가 없다

  27. NEMO Online 리팩토링 • 세션윈도우 • 무분별한 상속과 다중상속 대신 포함을 고려함 • 상속에 대한 정답은 1997년에 COM이 나오며 다 나왔다. • 가상 윈도우 갯수 줄이기 • 대부분의 컨트롤들은 그림 장난으로 충분하다 • UI 요소에 지나친 개체지향은 금물 • 진행바같은 것은 StrechBlt 로 충분

  28. NEMO Online 리팩토링 • 사용자 정보 • 리팩토링 과정에서 기획 리뉴얼로 채널을 구분하게 됨 • 사용자 정보의 수는 줄어들었으나 여전히 리팩토링의 대상임 • 게임 중에는 로비에 있는 사용자 정보를 받지 않기로 함 • 기획과 밀접한 관련이 있음 • 위치상 떨어진 사용자들의 변경 정보는 시간 간격으로 모아서 전송 • 리사이즈 • 사이즈 정보의 리스너 / 옵저버 패턴으로 구현

  29. NEMO Online 리팩토링 • 모니터 해상도 • 4:3 과 16:9라도 UI구성을 통일시킴 • 추상 인터페이스와 상속 자체가 무의미해짐 • 추상 인터페이스 의미 자체가 사라졌지만 아직 UI 구성 추상인터페이스를 없애지 못함 • 추상 인터페이스 제거 비용이 너무 큼 • 앞으로의 연구과제 • 현재 여전히 UI를 변경시킬때는 인터페이스 작업부터 들어가야 함

  30. NEMO Online 리팩토링 • 게임룰 • 좋은 사례란 알고리즘(구현)의 재활용이 아니라 인터페이스의 재활용이다. • CPU 대전과 네트워크 대전 • 네트워크 패킷을 재활용 • CPU 대전과 네트워크 대전을 동일한 패킷 전송으로 구현 • 함수 Call 과 send()/recv() • 천재적인 코드를 만들지 말라 • 섣부른 일반화를 적용시키지 말것 • 이 세상은 일반화 시키기에는 달라지는 것들이 너무나 많다. • 100% 일반화가 가능한 게임은 테트리스의 행렬변환 뿐이다. • 특히 UI의 일반화는 디자이너와 전쟁을 유발시킨다.

  31. NEMO Online 리팩토링 • 네트워크 개발자를 괴롭히는 것들 • 빈번한 추가사항 • 프로모션, 로비 배너, 방생성 옵션, 아이템, 리스트 정렬.... • 게임 서버를 경유하지 않도록 수정 • 웹서버와 WinINET의 활용 • 파일 쓰기를 제외한 모든 툴(주로 DB에 툴)은 웹언어로 작성하는 것이 가장 효율적 • 아이템툴, 밸런싱 • 기획자, 디자이너의 영역으로 완전 이동 • 보안이 중요하지 않은 데이터라면 HTTP 이용 • 단 TRACE같은 것을 남겨서는 안됨

  32. NEMO Online 리팩토링 • 더미 클라이언트 • 누가 사용하는가? • 누가 기능별로 매시간 테스트하는가? • 게임은 단위 테스트 적용이 힘든 프로젝트 • TDD툴로 활용할 수 있음 • 스크립트 지원이 되는 더미 클라이언트는 100명의 QA가 부럽지 않다. • 더미 클라이언트는 서버와 첫 Connect 할 시점부터 꾸준히 함께 만들어야 한다 • 디버그/릴리즈를 구분하지 않고 웹에서 실행이 아닌 직접 실행 시킬수 있는 방법을 만들어야 한다. • 퇴근시 실서버에 클라이언트 접속 해두기 • 소스분석이 곤란할 경우 WM_COPYDATA로 작동하는 로봇을 만듦

  33. NEMO Online 리팩토링 • 코딩 • 주석을 사용하지 말것 • 주석이 필요하다면 이미 잘못 만든 코드이다. • 대부분의 주석은 본인에게도 의미가 없다. • 주석처리한 코드를 다시 분석하는 일은 없다. 당장 지워버려라 • 주석 대신 빌드중 메시지 출력을 활용 • 좋은 소스코드란 개발자에게 소설처럼 읽혀야 한다.

  34. 배포 • 디자인 결과에 따라 파일 구조가 달라진다 • 런처와다운로드는 리팩토링의 결과에 따라 함께 설계가 달라져야 한다. • 게임 사이트라면 다운로더는 다양한 파일구성 타입의 게임을 런칭 • 만만한 레이어? • 사실 가장 많은 리팩토링이 필요로 하는 부분은 배포과정이다 • 클라이언트와 서버가 편하기 위해 배포과정을 더럽히지 말라 • 보안 프로그램이나 백그라운드 실행기는 클라이언트가 직접 하는 것이 옳다 • 각 회사마다 전설? • 로긴, 배포, 게임실행, 삭제 과정을 전부 이해하는 개발자가 없다

  35. Nemo Online 반성하기 • 개발자스러운 삽질 • 있는 것 다시 만들기, 보다 그럴싸 하게 만들기… • 보통 리팩토링 요구사항이 발생하는 이유는 끊임없는 기능 추가 단계에서다. • Nemo Online은 디자인 패턴을 활용한 리팩토링 자체에 의미를 두었다. • 개발중의 리팩토링은 권장하나 자체가 목적이 되어선 안된다. • 코드를 리팩토링하는 수단으로써 디자인 패턴 • 그럼 디자인 패턴을 리팩토링하는 것은? • 극단적인 패턴추구가 정답은 아니다 • C++ 코딩 재미에 빠져 목표를 잃었다

  36. 결론 • 패키지 게임이 아닌 이상 리팩토링이 끝나는 시점은 없다 • 패키지 게임이라도 라이브러리는 다시 리팩토링이 되어야 한다 • 쉽고 단순하게 만들라 • 디자인 패턴의 남용을 의심하라 • 제네릭 프로그래밍이 타당한지 의심하라 • 컨텐츠와 라이브러리는 절대 만나서는 안된다. • 라이브러리에 코드 욕심을 부려라 • 컨텐츠 코딩은 딱 Visual C++ 바이블 수준이 최선의 코드이다. • 그 한계에 대한 조율이 좋은 유지보수하기 좋은 상태로 유지시킨다

  37. NEMO Online 리팩토링 • Q/A

More Related