프로젝트 M2 아키텍처 리뷰: 완벽한 MMO 클라이언트 설계에의 도전, 파트 2

A presentation at 넥슨 개발자 컨퍼런스 2012 in April 2012 in Seoul, South Korea by Jubok Kim

Slide 1

Slide 1

NDC2012 | 김주복 해당 이미지는 DSP 엔터테인먼트의 자산입니다 Ⓒ 2012 NEXON Corporation & devCAT Studio. All Rights Reserved M2 team, Game Development Team for Project M2 in longCAT (The 3rd New Development Division in NEXON Corp.). M2 team Director is Kim, Dong-Gun | Project M2 is produced by Kim, Dong-Gun GT-R team, Engine Development Team for Project M2 and more. GT-R Team Technical Director is Jeon, Hyeong-Kyu

Slide 2

Slide 2

이 강연을 저의 멘붕 방지에 지대한 도움을 주신 카라 멤버 여러분과 DSP 미디어에 헌정합니다 죽어라 들은 건 점핑인데 사진은 루팡 맥락없이 카라 짤이 나오니 양해를…

Slide 3

Slide 3

Previously on NDC2010… NDC2010 – M2 아키텍처 리뷰, 완벽한 MMO 클라이언트 설계에의 도전

Slide 4

Slide 4

컴퍼넌트 시스템 논의의 연장 프로시저 레이어의 문제 해결 방안 등 뻔하고 당연한 이야기 게다가 페이지 수도 글자도 많… 해당 이미지는 네이버 만화와 김성모 프로덕션의 자산입니다

Slide 5

Slide 5

w o r k i n p r o g r e s s 이 강연은 현재 개발 중인 게임의 구현 방식에 대한 것으로, 최종적으로 발매된 게임은 전혀 다른 형태로 구현되어 있을 수도 있음을 알려드립니다

Slide 6

Slide 6

해당 이미지는 DSP 엔터테인먼트의 자산입니다 개념 미제 소고 지속효과 지속효과 클래스 탈출처리 메시지 트랜잭션 피처 의존성 금지와 사건 통지 프리젠테이션 액터 이터레이션 속도 설계 원칙과 인지적 한계 기획자 무용론? 재활용에 대한 관점 설계 목표 재변경

Slide 7

Slide 7

김주복 넥슨12년차|NDC강연6년차 @eiaserinnys | beforu.egloos.com 2001 2001 2003 2005 2006 2008 2009 2010 2011 무선사업팀 도트디자이너 마비노기팀 리드 프로그래머 마비노기 프로그래밍팀 팀장 그 룹 웨 어 개 발 팀 팀 장 W 팀 테 크 니 컬 디 렉 터 개 발 3 본 부 3 실 실 장 마비노기 2 개발 디렉터 신규개발3본부 1실 실장 GDC 엔지니어링 세션 강연

Slide 8

Slide 8

지속효과 지속효과클래스 탈출처리 메시지트랜잭션 피처 해당 이미지는 DSP 엔터테인먼트의 자산입니다

Slide 9

Slide 9

컴퍼넌트의 상호의존성을 전면금지하는 설계를 시험 설계 원칙을 엄밀하게 지키는 것이 유지보수에 더 나은 코드가 될 것이다! NDC2010 – M2 아키텍처 리뷰, 완벽한 MMO 클라이언트 설계에의 도전

Slide 10

Slide 10

익숙하지 않은 설계가 이상한 구현으로 발현 절차와 객체가 서로 책임을 떠넘기는 이상한 세계 NDC2010 – M2 아키텍처 리뷰, 완벽한 MMO 클라이언트 설계에의 도전

Slide 11

Slide 11

나름대로 기준을 세워 프로시저 함수군을 정리 게임의 규칙에 해당하는 함수와 컴퍼넌트를 구성하는 함수로 분류 NDC2010 – M2 아키텍처 리뷰, 완벽한 MMO 클라이언트 설계에의 도전

Slide 12

Slide 12

개별 작업자가 각자 이해한 상태를 기준으로 작업 이 시스템이 뭔지 잘 모르겠긴 한데 일은 해야 하는데 어쩔 거야 수많은 버그로 귀결 일어나다가 다시 쓰러진다거나 위치가 이곳저곳으로 튄다거나 T 포즈로 굳은 채로 이동한다거나 뒷목이 뻣뻣한 채로 디버깅한다거나 어째 아침에 회사 가기가 싫다거나 이게 사는 건가

Slide 13

Slide 13

엔지니어링 리부트란 이름으로 4개월간 진행 개발 진도가 상당히 나간 프로젝트에서는 이례적인 결정 엔지니어링 리부트 OT NDC2011 – 이무림, 고양이가 개발한다

Slide 14

Slide 14

“복합액션(현행 액션) 도입계획” 엔지니어링 리부트 – 복합액션 도입계획

Slide 15

Slide 15

여러 게임 시스템에서 공통적으로 등장 대표적인 사례가 날리기 전작 전투 시스템의 상징과도 같은 시스템 동적 분기가 필요한 몇 가지 변화가 추가 굉장히 간단해 보이는 변화인데…

Slide 16

Slide 16

DefenderReationImplementation:: ProcessHitReaction CCombatant:: ResolveAsAttacker StartBlowAction:: Execute BlowHandlers:: StartBlow StartBlowProcedure Handle TrivialCase CCombatMgr:: ScheduleHitEvent Handle NormalCase ProcessWallCollision (BlowEnd::Fall) AdjustBlowEndByKynapse (BlownEnd::Wall) ReserveBlowEndOperation CombatMgr:: OnAnimationEvent Caction:: CombatBlowAway FallEnd:: Execute WallSmashed::Execute ‘WallSmashed*Blowed’ LifeAndDeath:: FallEnd WallSlide::Execute ‘WallSlide’ ‘WallToSlideToDownPose’ Bounce:: Execute

Slide 17

Slide 17

  1. 액션이 데이터화 액션 로직이라고 부름 게임 디자이너가 제어 타이밍, 이동 가능 여부 등 이터레이션 시간을 줄여줌 타당한 요구사항

Slide 18

Slide 18

  1. 동적 분기가 필요한 디자인이 추가 액션 로직에서 제어는 어려움 서버 상에서 판정을 받아야 하는데, 기술 가능하다고 해도 게임 디자이너가 작성하는 것은 무리 코드가 데이터를 ‘잇는’ 처리 ‘액션 로직을 단순히 처리하는 과정’에서 ‘특정한 상황인 경우 다른 데이터로 연결하는 과정’으로의 전환

Slide 19

Slide 19

Write-Only-Code 데이터와 비동기 처리가 연달아 이어짐 사실 작업자는 있는 도구로 성실하게 구현한 것 프로시저 레이어의 혼돈과 맞물려 상승작용 비동기 처리의 중간 단계 코드가 여기저기 파편화되어 존재

Slide 20

Slide 20

액션에는 어떤 효과가 수반되는 것이 보통 공격은 보통 일정 시간 동안 이동과 추가 공격이 불가 피격은 보통 처음부터 끝까지 이동이나 여타 동작이 불가 이동할 수 없고 다른 짓할 수 없고 등등… 마법 시전을 시작하면서 별도 조작계로 변경

Slide 21

Slide 21

효과는 반드시 종료되어야 이전엔 액션 로직 단위로 처리했으나… 시작하는 시점에 설정한 효과를 처리가 종료되는 시점에 일괄 해제 분기가 들어가며 문제 효과가 액션 로직이 바뀌어도 유지되어야 함 분기가 발생할 때 해제하고 다시 설정하면 오동작의 가능성

Slide 22

Slide 22

지옥 입구에 오신 것을 환영합니다 RideHandlers:: RideOnVehicleReplied FinishLiftingExecution:: Execute RideHandlers:: RideOnTurretReplied InterationExecution:: Execute RideHandlers:: RideOnVehicleReplied ItemAction:: DropOrHold ItemAction:: ReleaseItem PickUpItemExecution:: Execute DefenderReactionImpl:: CancelPropLift StartReviveExecution:: Execute ThrowLiftedExecution:: Execute TryLiftingSuccessExecution:: Execute 어쩌지…

Slide 23

Slide 23

정의 게임이 인지하는 객체 동작의 최소 단위 사실 게임 디자이너는 블로우~벽에 부딪히는 동작을 별개라고 인지하지 않는다 ex. 공격 동작, 날리기 과정 전체 등 특성 코드에서 구현 액션 로직의 분기를 처리 끝날 때 종속된 효과를 모두 해제 ☆☆☆ 서로 중첩되지 않음 ☆☆☆ 새로운 액션이 실행되면 이전 액션이 종료됨

Slide 24

Slide 24

Slide 25

Slide 25

괄호 닫기 처리의 완결성 확보 어떤 경로를 타고 실행되더라도 액션이 끝나면 정리됨 서로 중첩되지 않는다는 특성으로부터 가능

Slide 26

Slide 26

복잡도의 본질을 해결한 것과는 거리가 있다 있는 도구를 바탕으로 요구사항에 대응해서 생긴 문제를 해결한 것 뿐 +

당연히 문제들은 산더미처럼 남아있고…

Slide 27

Slide 27

“스테이터스 리뉴얼 계획” 엔지니어링 리부트 – 스테이터스 리뉴얼 계획

Slide 28

Slide 28

ex. 탈것에 탑승 탑승한 상태에는 연결 관계가 성립 애니메이션 포즈를 계산할 때, 탑승물의 특정 본과 탑승자의 특정 본을 연결 내리는 시점에 연결 관계를 해제 문제는…

Slide 29

Slide 29

탑승 – 중립 – 공격 – 중립 – 하차 괄호 닫기 처리를 제대로 하려면 액션보다 큰 단위가 필요

Slide 30

Slide 30

복잡한 종료 조건 중 하나라도 누락하면…

Slide 31

Slide 31

정의 별도의 중립 포즈를 강제하는 지속적인 캐릭터의 상태 ex. 스탠딩→탑승 포즈 특성 ☆☆☆ 액션과 중첩될 수 있음 ☆☆☆ 연관된 액션 셋트를 갖는 일이 많음 끝날 때 종속된 효과를 모두 해제 서로 중첩되지 않음

Slide 32

Slide 32

경험적으로 이런 문제는 뭔가 예쁘게 해결되지 않는다 뭔가 생각지도 못한 상황은 항상 생기고 때우다 보면 코드는 망가지고 퇴근은 늦어지고 가정이 무너지고 국가가 무너지고

Slide 33

Slide 33

스테이터스는 임의의 시점/사유로 종료된다 액션과 스테이터스가 가장 크게 다른 점

Slide 34

Slide 34

연관 없는 시스템의 간섭이 중단의 원인 ex. 필드에 탑승물을 남긴 채로 로그아웃하면 탑승물은 자기 상태를 정리해야 함 조합 폭발의 가능성 새 시스템이 기존 구현을 찾아서 검토해야 함 탑승 → 피격 탑승 → 로그아웃 탑승 → 지역이동 탑승 → 거래 탑승 → 물건 집기 탑승 → …

Slide 35

Slide 35

로그아웃 죽을 때 지역 이동 시 보기만 해도 딱 ‘이 골치아픈 것들…’이란 생각이 드는데,

Slide 36

Slide 36

또 다른 종류의 괄호 닫기, 상태 이상 액션/스테이터스와는 다르다 ex. 독, 스턴, 슬로우와 같은 상태 이상 걸려있는 동안 특정한 효과가 지속 보통 공격(액션)하거나 탑승(스테이터스)하더라도 끊기지 않음

Slide 37

Slide 37

당연하다, 게임의 모든 효과는 둘 중 하나 순간적이고 영구적이거나, 레벨업이 되어 체력의 최대치가 증가하는 연산은 순간적이고 영구적으로 반영된다 지속적이고 단기적이다 독에 걸려 체력이 감소하는 효과는 지속적이고 끝나면 사라지는 단기적인 것이다 vs. 해당 이미지는 Activision Blizzard의 자산입니다

Slide 38

Slide 38

처리하고 지나가면서 잊어버리면 된다 체력을 회복하거나, 위치를 이동하거나… DB에 반영하는 문제로 가면 또 다른 문제가 되긴 하지만

Slide 39

Slide 39

처리가 시간적으로 분산 적용 시점, 지속되는 도중, 종료 시점 등 업데이트 시작 끝

Slide 40

Slide 40

예상할 수 없는 사유의 종료에 대응해야 하기 때문 고로 게임에서 괄호 닫기가 중요한 문제인 것은 너무나 당연 ( )

Slide 41

Slide 41

정의 수명을 가짐 시작/종료 시점과 지속 중 정해진 효과를 실행 ☆☆☆ 종료할 때 괄호 닫기를 수행 ☆☆☆ 모든 효과를 클린업 많은 개념에 연계 여러 동작이 지속효과를 수반 액션, 스테이터스, 상태이상 등 사실 마음에 드는 이름은 아닌데 명확하면서 길지 않은 표현이 잘 없어서… 차라리 괄호 효과라고 할까

Slide 42

Slide 42

( ( ) )

Slide 43

Slide 43

( ( )( )( 중립

Slide 44

Slide 44

지속효과의 속성은 조금씩 다르다 액션 상태이상 스테이터스 예외적 중단 가능? 배타적? × × ○ ○ × ○ 기왕 분류해보는 거 제대로 해보면…

Slide 45

Slide 45

배타성/예외적 중단 가능 여부에 따른 분류 예외적 중단 가능? 배타적? 예제 클래스 1 × × 상태이상 클래스 2 × ○ 액션 클래스 3 ○ ×

클래스 4 ○ ○ 스테이터스, 다자관계

Slide 46

Slide 46

클래스1 체력감소 ( 예외적중단× 배타적× 독 상태이상 이동금지 ( ( ) 공격 액션 부착관계 탑승관계 스테이터스

Slide 47

Slide 47

클래스1 ( 예외적중단× 배타적× 클래스2 예외적중단○ 배타적○ 독 상태이상 ( ) 이동금지 ( 예외적중단× 배타적○ 클래스4 체력감소 공격 액션 부착관계 탑승관계 스테이터스

Slide 48

Slide 48

클래스1 체력감소 ( 예외적중단× 배타적× 독 상태이상 클래스2 ( 예외적중단× 배타적○ 클래스4 예외적중단○ 배타적○ ( 이동금지 공격 액션 부착관계 탑승관계 스테이터스 )( )( ) 이동금지 피격 중립

Slide 49

Slide 49

예) 탑승, 거래, 컷신… …하다가 맞으면? …하다가 독으로 죽으면? …하다가 네트웍이 끊겨서 로그오프하면? …하다가 (운영자가 불러서) 워프되면?

Slide 50

Slide 50

  1. 유사한 처리가 여러 곳에 분산 2. 추가되는 기능 때문에 필요한 처리가 늘어남 3. 구 코드에는 새 시스템을 위한 처리가 누락 4. 왜죠

Slide 51

Slide 51

지역이동 피격 잡기 해제 처리 같은 동작이지만 구현이 다름 탑승 종료 처리 공통이어야 하지만 리전 이동 시에만 처리 중

Slide 52

Slide 52

사건은 지속 효과을 모름 리전이 이동을 알려주기 위해서 탑승, 거래 등에 대해서 다 알아야 하나? 지속 효과는 사건을 모름 탑승, 거래 등이 리전 이동, 로그오프, 피격 등 모든 사건을 다 알아야 하나? 어느 쪽의 책임도 아니다! 중재자를 도입하자!

Slide 53

Slide 53

정의 클래스 4 지속 효과가 예상하지 못한 방식으로 종료되는 경우 클린업하는 처리 “예상된 정상적인 전이가 아닌 경우, 먼저 기존 상태에서 탈출한다”

Slide 54

Slide 54

Slide 55

Slide 55

Slide 56

Slide 56

물론 이걸 아무 대책 없이 대응하는 게임은 당연히 없는데…

Slide 57

Slide 57

ㅁㅂㄴㄱ의 지역 이동 탈출 처리의 의존성 CServerWorld:: CharacterLeaveRegion CCharacter:: OnLeaveRegionBefore CCharacter:: LeaveRegion CCharacter:: OnLeaveRegionBegin CCharacter:: OnLeaveRegionEnd CQuestComponent:: DestroyAllInstantQuests CTransportComponent:: OnLeaveRegionBegin CSummonMaster:: OnLeaveRegion CShowdownComponent:: OnLeaveRegion CDemiGodComponent:: OnLeaveRegion CPetPVPComponent:: OnLeaveRegion CTameMgr:: OnLeaveRegion CFashionComponent:: OnLeaveRegion CAviationComponent:: OnLeaveRegion CTransportComponent:: OnLeaveRegion CEventComponent:: OnLeaveRegion CVehicleComponent:: OnLeaveRegion CConditionComponent:: OnLeaveRegion CJoustComponent:: OnLeaveRegion

Slide 58

Slide 58

현재 지역 이동 탈출 처리의 의존성 ㅁㅂㄴㄱ보다 구현된 시스템 요소 수가 적어서 단순한 요인은 제외하고 GrappleProcedure. EndGrappleAndSync EscapeSequence. EndGrapplingRelation ByGrappler EscapeSequence. EscapeAndSync WorldProcedure. LeaveRegion EscapeSequence. EndGrapplingRelation ByGrappledOne LeanbackProcedure. EndAndSync EscapeSequence. EndLeanBack PropProcedure. SetPropInstaller EscapeSequence. EndRidingRelation PropProcedure. DestroyInstalledProp EscapeSequence. EndCurrentAction ByLeavingRegion RidingProcedure. RideOffVehicleAndSync ActionProcedure. End LocationComponent. OnLeaveRegion

Slide 59

Slide 59

Slide 60

Slide 60

장점 사건/지속효과 양쪽의 코드가 단순해짐 유사한 처리의 파편화를 방지 구현부가 일원화되어 있으므로, 새로운 전이와 모든 조합에 대해서 검토해 보게 됨 단점 탈출 처리기는 모든 사건/지속효과를 알아야 함 손 댈 수 없이 거대한 코드 블록으로 자라날 가능성이 있음 테이블화시켜서 비교적 단순한 형태로 줄이는 것이 가능하리라고 예상 어떻든 문제 해결?

Slide 61

Slide 61

ex. 탑승 중 피격 function 피격 { 탈출처리요청(사유:피격) { 탑승자를 탑승이 아닌 상태로 전환 탑승물을 태운 사람이 없는 상태로 전환 } 피격에 수반되는 실제 처리 } 피격 처리는 이 과정에 대해서 전혀 인지하지 못함

Slide 62

Slide 62

  1. 처리가 발생할 때마다 발송? function 피격 { 탈출처리요청(사유:피격) { 탑승자를 탑승이 아닌 상태로 전환 탑승물을 태운 사람이 없는 상태로 전환 } 피격에 수반되는 실제 처리 } 각각의 시점마다 클라이언트가 상응하는 동작을 하도록 메시지를 발송

Slide 63

Slide 63

  1. 전체를 하나의 메시지로? function 피격 { 탈출처리요청(사유:피격) { 탑승자를 탑승이 아닌 상태로 전환 탑승물을 태운 사람이 없는 상태로 전환 } 피격에 수반되는 실제 처리 } 전체를 “탑승 중 피격”이라는 하나의 메시지로

Slide 64

Slide 64

처리가 발생할 때마다 발송하는 경우 클라이언트에서 메시지를 동시에 받지 못함 이후 메시지가 늦게 도착할 경우 이상한 모습이 보이거나 심지어 그 사이에 조작도 가능해짐

Slide 65

Slide 65

전체를 메시지로 보내는 경우 취지에도 어긋나고 논리적으로 불가능 외부에서는 탈출처리에서 어떤 지속효과에 영향을 미칠 지 모르고, 따라서 전체 메시지가 무슨 동작을 해야 할 지 모름 가능하다고 해도 낭비 (각기 다른 탈출처리 이유)×(각기 다른 지속효과)의 조합만큼 메시지를 만들어야 함 On…Handler() 같은 형태로 코드가 만들어지는 이유 사실 이런 형태로 구현하는 것은 메시징 방식의 제약 안에서 문제를 풀어야 하기 때문이기도 함 ………… 완전히 다른 접근이 필요하다는 결론

Slide 66

Slide 66

한 요청에 대한 응답을 한 번에 발송 처리가 발생할 때마다 메시지를 쌓아둠

Slide 67

Slide 67

순차적으로 실행하면서 공지가 필요한 변경을 그때그때 바로 누적

Slide 68

Slide 68

장점 코드가 단순해짐 탈출처리가 적용 가능해지기 때문에 메시지 구성을 위해서 다양한 맥락을 고려하지 않아도 됨 몇 종류의 응답 프로토콜을 범용적으로 활용 예를 들어 특정 락을 걸고 풀거나, 스테이터스를 설정하거나, 액션을 실행하는 등의 간단한 동작은 조합해서 메시지를 발송 이터레이션 가속화의 가능성 해당 이미지는 한승연 본인의 자산입니다 미제를 설명하면서 다시 설명할 예정 단점 메시지의 크기를 통제하기 어려움 작은 메시지를 합산하면서 헤더의 오버헤드가 늘어나고, 얼마나 커질지 파악하기가 어려움 자주 쓰이는 형태의 조합을 컴파일하는 방법으로 최적화가 가능할 것으로 예상 뭐 어쨌든 간에…

Slide 69

Slide 69

지속효과 괄호 닫기를 개념화하여 안전한 클린업을 보장 탈출처리 다른 지속효과간의 전이 과정을 단순화 메시지 트랜잭션 전이 과정을 자연스러운 형태로 코딩 가능

Slide 70

Slide 70

복기: 프로시저 레이어 컴퍼넌트는 다른 컴퍼넌트에 의존 불가 컴퍼넌트 간 협업이 필요한 작업을 프로시저로 분리

Slide 71

Slide 71

복잡하고 불편하다! 한 컴퍼넌트를 두 개로 나눠서 만들어야 함 분류 기준이 없다! 컴퍼넌트 소속이 아닌 프로시저군은 분류가 어렵다

Slide 72

Slide 72

딱히 문제도 아니고 문제가 아닌 것도 아니고… 맞는 방향이란 생각은 드는데 이론적 기반이 없는 것이 문제 객체 지향 패러다임에서 크게 벗어난 접근 지속 가능한 개발 방법론으로 정립할 수 있을지 의문 해당 이미지는 아마도 한승연…본인의 자산입니다

Slide 73

Slide 73

<도메인 주도 설계> ‘소프트웨어의 복잡성을 다루는 지혜’라는 부제 뭔가 막 해결될 것 같은 기분이 든다 레드썬 좀 날림으로 소개를 하자면…

Slide 74

Slide 74

소프트웨어는 도메인 지식의 반영 소프트웨어를 사용하는 사용자의 활동이나 관심사 해결해야 하는 핵심 문제 영역을 의미 은행용 소프트웨어라면 계좌 개설이나 대출 업무 절차에 관한 지식과 개념들 게임이라고 하면 게임 디자인 UI 애플리케이션 도메인 인프라스트럭처

Slide 75

Slide 75

온라인 게임에서는 익숙한 모델 클라이언트 언어가 C++이라 서버까지 객체 지향 패러다임이 강력히 주도한 덕분? OOP 따라서 객체 모델링하고 함수가 쿼리 DB에 직접 날리지 말고 중간에 대리자 넣고… 같은 당연한 이야기 당장의 내용과는 무관하지만 강력히 읽어보실 것을 추천

Slide 76

Slide 76

Slide 77

Slide 77

=객체로 모델링하는 것이 부자연스러운 연산 1. 객체를 구성하는 게 아니라 도메인의 개념과 관련 2. 인터페이스가 모델의 외적 측면에서 정의 3. 연산이 상태를 갖지 않는다 오늘날 흔히 하는 실수는 행위를 적절한 객체로 다듬는 것 을 너무나도 쉽게 포기해서 점점 절차적 프로그래밍에 빠지는 것이다. 하지만 객체의 정의에 어울리지 않는 연산을 강제로 객 체에 포함시킨다면 해당 객체는 자신의 개념적 명확성을 잃어버 리고 이해하거나 리팩터링하기 힘들어질 것이다. 복잡한 연산은 단순한 객체를 손쉽게 궁지로 몰아넣어 해당 객체의 역할을 불 분명하게 만들 수 있다. pp107, 도메인 주도 설계 프로시저 레이어의 특성과 일치! 해당 이미지는 DSP…, 아니 셀카니 아마도 한승연…본인의 자산입니다

Slide 78

Slide 78

게임 로직을 서술하는 서비스 컴퍼넌트를 조작하는 과정을 기술 상태의 정합성은 컴퍼넌트가, 절차는 피처가 책임 독립된 게임 시스템의 기능 집합 게임 디자이너가 보는 게임 시스템의 단위 ‘새로운 기획을 만들었다’고 할 때, 기획 하나와 피처 하나가 대강 대응 ex. 전투, 거래, 마법, 원거리교전, 탑승, …

Slide 79

Slide 79

파트 1에서 지적했던 문제 컴퍼넌트가 메시지를 핸들링하는 것은 설계 원칙에 어긋난다 피처에 두면 된다! 메시지 = 게임 시스템의 기능 명세이므로

Slide 80

Slide 80

Slide 81

Slide 81

Feature ServiceContract RequestA ReplyA RequestB ReplyB : IFeature MessageHandler FunctionA : IFeatureFunction Use() Do() FunctionB IFeatureContract RequestA() 메시지 분배기 로직 처리 ReplyA() = 0 Use() RequestB() Do() ReplyB() = 0 자동생성 클라이언트 서버

Slide 82

Slide 82

메시지 컨트랙트 정의 피처 펑션으로 토스하는 어댑터 피처 구성 메시징 코드 (자동 생성) 피처 펑션

Slide 83

Slide 83

Slide 84

Slide 84

장점 설계 원칙 면에서 깔끔하다! 탈출 처리, 메시지 트랜잭션과 함께 개별 기능 구현이 다른 기능에 의존하지 않는 높은 독립성을 획득 가능 피처와 컴퍼넌트 간의 임피던스 불일치 해결 거래 같은 다자 관계는 하나의 컴퍼넌트에서 해결할 수 없기 때문에 필연적으로 발생 개별 기능 단위로 엄밀하게 가용 조건을 통제 가능 단점 일반적인 설계에 비해 간접층이 늘어남 각각의 구현체가 단순해진 대신, 전체 흐름을 파악하기 위해서 알아야 하는 구조가 늘어남 트레이드 오프?

Slide 85

Slide 85

너무 간단해서 인생이 허무한 지경 Feature : IFeature 컴퍼넌트 레이어 지속 효과들 FunctionA : IFeatureContract IFeatureFunction RequestA() Use() ReplyA() = 0 Do() RequestB() ReplyB() = 0 ActionComponent Flag StatusComponent Flag FunctionB AbnormalCondition Component Use() Do() ActionLockComponent Flag

Slide 86

Slide 86

여러가지 심각한 문제를 해결하긴 했는데… 뭔가 아직도 해결이 미진한 부분이 많고… …결정적으로 새로운 문제들도 수면 위로 부상

Slide 87

Slide 87

의존성 금지와 사건 통지 프리젠테이션 액터 이터레이션 속도 해당 이미지는 DSP 엔터테인먼트의 자산입니다

Slide 88

Slide 88

해당 이미지는 구하라 본인의 자산입니다 1 | 의존성 금지와 사건 통지

Slide 89

Slide 89

불편한 탄생 과정 컴퍼넌트 간 의존성은 강력하게 금지되나 자신의 정합성은 유지해야 함 의존성이 객체만으로 프로그래밍을 한다는 건 불가능한 일 어쩔 수 없이 컴퍼넌트 프로시저 개념이 도출 그 외의 프로시저 코드는 피처의 기능으로 정리되었음 NDC2010 – M2 아키텍처 리뷰, 완벽한 MMO 클라이언트 설계에의 도전

Slide 90

Slide 90

이건 이것대로 해결해야 할 문제 중요한 처리 중 대부분을 컴퍼넌트 프로시저가 수행

Slide 91

Slide 91

상호 의존성을 갖지 못하기 때문에 필연적

Slide 92

Slide 92

프리젠테이션 의존성 금지를 트리거로 해결 많은 경우 프리젠테이션은 제네릭한 트리거를 받아서 해석, 처리

Slide 93

Slide 93

구현체를 보기만 해도 마음이 불편해짐

Slide 94

Slide 94

본질적으로 같은 문제 컴퍼넌트→다른 컴퍼넌트로 사건 전달 로직→프리젠테이션으로 사건 전달 해당 이미지는 구하라 본인의 자산…이었던가 좋은 방법이 없어 숙고 중 다른 시각에서 해결할 수 있지 않을까도 고민 중 eoi

Slide 95

Slide 95

해당 이미지는 박규리 본인의 자산입니다 2 | 프리젠테이션 액터

Slide 96

Slide 96

Slide 97

Slide 97

타입에 따라서 패스가 다른 경우가 보통 로직 프로그래머 입장에서는 수정하기가 어려운 경우가 많다

Slide 98

Slide 98

서버에서는 로직 액터의 생성까지만 관여 프리젠테이션 액터는 로직 액터의 정보를 바탕으로 자신을 구축 로직이 UI에 정보를 통지하지 않고, UI가 로직을 모니터링하는 것과 유사 CharacterTag 로직 프리젠테이션 Animator Inventory RenderActor EquipmentHolder Status AbnormalCondition 로직 생성 이후에 별도 과정으로 구축 SoundActor Particle ControllerBackLink

Slide 99

Slide 99

프리젠테이션 액터를 균일화 게임 디자이너나 아티스트가 ‘얘는 왜 이걸 할 수 없어요?’라고 놀랄 필요가 없음 게임 로직에서 특정한 프리젠테이션 처리가 가능한지 알 필요가 없음 프리젠테이션 쪽에서 게임 로직에 대해서 알 필요가 없음 게임 플레이의 프로토타이핑이나 연출을 시험할 때 좀 더 용이 CharacterTag 로직 Inventory 프리젠테이션 Animator RenderActor EquipmentHolder SoundActor Status AbnormalCondition Particle ControllerBackLink eoi

Slide 100

Slide 100

해당 이미지는 니콜 본인의 자산…아니 구하라던가;; 3 | 느린 이터레이션

Slide 101

Slide 101

프로토타이핑, 빠른 이터레이션의 중요성 프리젠테이션에 투자하면 팔 수 있던 시대가 지나버렸음 주류 (콘솔) 게임이 NDS와 소셜 게임이 가져온 “파괴적 혁신”에 패배 GDC2011 동향보고

Slide 102

Slide 102

라이브 시스템의 복잡도 기존 피처와 상호 작용하므로 독립적 프로토타이핑이 어려움 돌아가는 시스템 위에서 테스트하지 않으면 의미가 없는 경우가 많음

Slide 103

Slide 103

서버-클라이언트 메시징 변경에 재컴파일이 필요 필연적으로 이터레이션 속도의 감소가 동반 ServiceContract RequestA ReplyA Feature : IFeature FunctionA : IFeatureFunction MessageHandler IFeatureContract RequestA() 메시지 분배기 Use() 로직 처리 ReplyA() = 0 Do() 클라이언트 서버

Slide 104

Slide 104

스크립트로 작성된 피처에 전달하면 다운 없는 개발이 가능 Feature ServiceContract RequestA ReplyA : IFeature FunctionA : IFeatureFunction Use() Do() MessageHandler IFeatureContract 메시지 분배기 RequestA() 로직 처리 ReplyA() = 0 스크립트 라우터 스크립트 스크립트 스크립트 스크립트 라우터 클라이언트 서버 eoi

Slide 105

Slide 105

설계 원칙과 인지적 한계 기획자 무용론? 재활용에 대한 관점 설계 목표 재변경 해당 이미지는 DSP 엔터테인먼트의 자산입니다

Slide 106

Slide 106

사실, 프로시저와 피처의 논리적 구조는 동일 설계 원칙 측면에서는 큰 차이가 없으나 인지적 차이는 하늘과 땅 코드가 마음 속의 어떤 모델에 대응하는가 여부가 매우 중요함 분류 방식, 실제 구현 등에서 거의 차이가 없음

Slide 107

Slide 107

올바른 설계에는 인지적인 측면이 중요 설계 원칙으로 해결되지 않는 문제의 판단 기준은 인간의 인지 능력 OAOO를 지켜야 하는 이유가 곰곰히 생각해보면 인간의 인지 능력의 한계 때문 마인드 모델을 공유하기 위해서 노력이 필요 도메인 주도 설계에서 강조하는 것도 일맥상통 엔지니어링 리부트 OT

Slide 108

Slide 108

결론이 난 개념과 구조는 허탈할 정도로 간단 그럼에도 개념을 정제하고 게임 디자이너와 동기화하는데 어려움을 겪음 아니 게임 디자이너가 문제가 아니라 프로그래머들끼리도 힘들었음;;; Feature : IFeature 컴퍼넌트 레이어 지속 효과들 FunctionA : IFeatureContract IFeatureFunction RequestA() Use() ReplyA() = 0 Do() RequestB() ReplyB() = 0 ActionComponent Flag StatusComponent Flag FunctionB AbnormalCondition Component Use() Do() ActionLockComponent Flag

Slide 109

Slide 109

우리 스스로 무엇을 만들고 있는지 정확히 모르고 있기 때문? 합의된 모델을 구현하는 게 아니라 프로그래머가 원하는 대로 구현하는 게 보통 디자인과 불일치하는 구현체에 대해서 게임 디자이너가 통제를 할 방법이 없는 게 당연 게임 로직의 모델을 정식화하고 공유하는 노력이 필요 게임 디자인에 있어서도 팀 전체의 인지적인 한계가 똑같이 문제가 됨 게임 디자이너는 올바른 모델을 제시하기 위해 프로그래밍을 알아야 한다. 반대로, 프로그래머도 게임 디자이너의 모델을 성실하게 구현해야 한다.

Slide 110

Slide 110

목표는 게임 로직 코드를 재활용하는 것이었으나… 로직이 프리젠테이션에 암묵적 의존 관계를 형성하지 않을 수가 없다 그리고 프리젠테이션 의존성은 게임 로직 재활용에 가장 큰 걸림돌 하지만 프리젠테이션을 개선하지 않는다면 게임을 다시 만드는 의미가 없다! 꼭 그런 건 아니지만 많은 경우 그렇다

Slide 111

Slide 111

게임 디자인 도메인에서 개념의 재활용을 목표로 재활용 가능한 개념을 증류하려는 노력이 유효하다고 판단

Slide 112

Slide 112

원칙을 준수하는 설계의 추후 수익률은 높지 않을 전망 → 큰 문제는 해결, 완벽한 설계보다는 인지친화적인 설계가 더욱 중요 게임 디자인을 정확하게 반영하는 설계의 중요성 → 정확한 설계 많은 이터레이션과 게임의 성공 가능성 문제가 부각 → 기민한 설계

Slide 113

Slide 113

‘인지 친화적이고 / 정확하며 / 기민한 설계에의 도전’ ……중언부언이라 결국 파트 3에서도 ‘완벽한’이라고 줄여서 쓸 거 같긴 함 해당 이미지는 DSP 엔터테인먼트의 자산입니다

Slide 114

Slide 114

R e f e r e n c e s 에릭 에반스, 2003“도메인 주도 설계” 김주복, NDC2010“M2 아키텍처 리뷰: 완벽한 MMO 클라이언트 설계에의 도전” 이무림, NDC2011“고양이가 개발한다” 김주복, 2011“GDC2011 동향보고” 김주복, 2011“엔지니어링 리부트 OT” 김주복, 2011“엔지니어링 리부트: 복합액션 도입 계획” 김주복, 2011“엔지니어링 리부트: 스테이터스란 무엇인가” 김주복, 2011“엔지니어링 리부트: 메시지 라우팅 방식 변경” 김주복, 2011“엔지니어링 리부트: 탈출 처리 도입과 이후 진행” Special thanks to“카라 and DSP 미디어”

Slide 115

Slide 115

해당 이미지는 DSP 엔터테인먼트의 자산입니다 @eiaserinnys | beforu.egloos.com 감사합니다 챕터가 모자라서 그만… 미안합니다 지영양