Priv's Blog
3. Design patterns for game development 본문
3. Design patterns for game development
Priv 2023. 10. 5. 19:28
1. 게임 개발자를 위한 디자인 패턴
SOLID 원칙에 대해 이해하셨다면, 이제 디자인 패턴에 대해 좀 더 깊게 파 보고 싶으실 겁니다.
디자인 패턴은 소프트웨어를 개발하면서 매일 같이 발생하는 문제들을 보편적인 해결책들을 통해 효과적으로 해결할 수 있게 해줍니다. 그러나 디자인 패턴은 규격화된 라이브러리 또는 프레임워크가 아닙니다. 특정 결과를 달성하기 위한 단계들을 묶어둔 알고리즘 또한 아니죠.
그 대신, 디자인 패턴은 청사진처럼 생각해야 합니다. 실제로 어떻게 구축할 것인지는 여러분에게 맡기는 일반적인 계획이죠. 두 개의 프로그램이 동일한 디자인 패턴을 따를 수 있으나, 매우 다른 코드를 가질 수 있습니다.
수많은 개발자분이 현업에서 동일한 문제를 마주치면, 필연적으로 서로 비슷한 해결책을 내놓게 됩니다. 그렇게 만들어진 해결책이 여러 차례 반복적으로 쓰이기 시작하면, 누군가가 그 해결책에서 패턴을 “발견”하고 공식적인 이름이 붙게 됩니다.
2. 디자인 패턴의 사인방 (The Gang of Four)
오늘날 쓰이는 대부분의 소프트웨어 디자인 패턴은 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides분들이 쓴 유명한 저서인 Design Patterns: Elements of Reusable Object-Oriented Software에서 유래되었습니다. 이 저서에서는 다양한 일상적인 애플리케이션에서 발견된 23가지 종류의 디자인 패턴을 소개하고 있습니다.
해당 저서의 작가분들은 일반적으로 “사인방”(GoF: Gang of Four)으로 잘 알려져 있습니다. 여러분들도 GoF 디자인 패턴이라고 불리는 본래의 디자인 패턴들에 대해 들어보셨을 겁니다. 해당 책에 등장한 예제들은 대부분 C++(와 Smalltalk)로 작성된 코드들이지만, C#처럼 객체 지향 프로그래밍 언어라면 얼마든지 GoF 디자인 패턴을 적용할 수 있습니다.
1994년에 GOF 디자인 패턴이 처음 등장했던 Design Patterns 저서가 출판된 이후, 개발자분들은 다양한 분야에서 수십 개 이상의 객체 지향 디자인 패턴을 더 발견했습니다. 게임 개발 분야도 다르지 않았죠.
3. 디자인 패턴 학습하기
디자인 패턴을 학습하지 않아도 게임 프로그래머로 일할 수 있습니다. 디자인 패턴을 학습하는 것은 더 나은 개발자가 되는 데 도움을 줄 뿐입니다. 결국, 디자인 패턴이란 잘 알려진 문제들을 해결하는 일반적인 해결책에 라벨을 붙인 것이기 때문입니다.
소프트웨어 엔지니어들은 일반적인 개발 과정 전체에 거쳐서 디자인 패턴을 재발견했습니다. 여러분들도 이미 자신도 모르는 사이에 몇 가지 디자인 패턴을 구현해 본 적이 있으셨을 겁니다.
디자인 패턴을 인지할 수 있도록 스스로를 훈련해 보세요. 아래의 항목들이 도움이 될 것입니다:
- 객체 지향 프로그래밍 학습하기: 디자인 패턴은 스택 오버플로우에 게시된 난해한 글 속에 숨겨진 비밀스러운 존재가 아닙니다. 개발하는 과정에서 매일 마주하게 되는 일반적인 문제들을 극복하는 방법들일 뿐이죠. 디자인 패턴은 수많은 다른 개발자분들이 여러분이 지금 겪고 있는 동일한 문제에 대해 어떻게 접근했는지에 대한 정보를 제공해 줄 수 있습니다. 명심하세요, 만약 여러분이 디자인 패턴을 사용하지 않는다 하더라도, 다른 누군가는 사용한다는 겁니다.
- 다른 개발자들과 소통하기: 디자인 패턴은 팀원들과 소통할 때 약어로 사용될 수도 있습니다. “커맨드 패턴(Command pattern)” 또는 “오브젝트 풀(Object pool)”이라고 언급하면 경험이 있는 Unity 개발자분들은 정확하게 여러분이 어떤 것을 구현하고자 하는지 이해할 수 있을 것입니다.
- 새로운 프레임워크 탐색하기: 내장된 패키지를 추가하거나 에셋 스토어에서 내려받은 신규 패키지를 추가할 때, 필연적으로 여러분은 이 책에서 언급된 디자인 패턴 중 최소 한 가지 이상을 마주하게 될 것입니다. 디자인 패턴을 인지하면 어떻게 새로운 프레임워크가 동작하는지를 이해하고 그 프레임워크가 제작된 복잡한 과정 속의 사고방식을 이해하는 데 도움이 될 수 있습니다.
물론, 모든 디자인 패턴이 모든 게임 애플리케이션에 적용되지는 않습니다. 디자인 패턴을 매슬로의 망치로 바라보면 안 됩니다. 만약 그렇게 된다면 여러분은 그저 망치로 내려칠 못만 찾아 헤매게 될 것입니다.
다른 도구와 마찬가지로 디자인 패턴의 유용함은 상황에 달려 있습니다. 각각의 디자인 패턴은 해당하는 상황에 맞춰 이점을 제공하며 그와 동시에 단점도 지니고 있습니다. 소프트웨어 개발에서 모든 결정은 타협에서 비롯됩니다.
하늘을 나는 수많은 게임 오브젝트를 생성하셨나요? 그 오브젝트들이 성능에 영향을 미치고 있나요? 여러분의 코드를 수정함으로써 이 문제를 해결할 수 있나요?
문맥에 맞는 디자인 패턴들을 기억해 두고, 때가 되었을 때 여러분의 게임 개발용 도구 상자에서 꺼내어 마주한 문제를 해결하는 데 사용해 보세요.
더 나아가기
앞에서 언급했던 사인방(the Gang of Four)의 Design Patterns: Elements of Reusable Object-Oriented Software 저서와 더불어 Robert Nystrom 분이 쓰신 Game Programming Patterns라는 저서도 유명합니다. 다양한 소프트웨어 디자인 패턴들을 상세하지만 간결하고 명확하게 잘 설명해주는 책입니다. 해당 저서는 gameprogrammingpatterns.com에서 무료로 웹 버전을 읽어보실 수 있습니다.
4. Unity 내부의 디자인 패턴
Unity 엔진은 이미 몇 가지 성립된 게임 개발 패턴들을 구현해 두었기 때문에 여러분이 직접 이를 구현할 필요가 없습니다. Unity 엔진에 포함된 패턴으로는 다음과 같습니다:
- 게임 루프(Game loop): 모든 게임의 핵심 부분에는 클록 속도와 독립적으로 동작해야 하는 무한 루프가 존재합니다. 이는 게임 애플리케이션을 구동시키는 하드웨어의 성능이 크게 다를 수 있기 때문입니다. 컴퓨터들의 서로 다른 속도를 고려하기 위해 게임 개발자분들은 일반적으로 고정된 시간 단위(초당 프레임 수)와 가변적인 시간 단위를 사용합니다. 엔진은 이전 프레임에서 시간이 얼마나 지났는지를 측정하죠. Unity 엔진이 이러한 작업을 전부 처리하므로, 여러분이 직접 이를 구현할 필요는 없습니다. 여러분은 단지 Update, LateUpdate, FixedUpdate와 같은 MonoBehaviour 메서드를 사용하여 게임 플레이를 관리하기만 하면 됩니다.
- 업데이트(Update): 여러분의 게임 애플리케이션 내에서 여러분은 종종 프레임 단위로 각각의 오브젝트들의 동작을 업데이트할 것입니다. 여러분이 해당 기능을 Unity 엔진 내에서 직접 구현하실 수도 있지만, MonoBehaviour 클래스가 똑같은 작업을 이미 자동으로 수행하고 있습니다. 단순하게 Update, LateUpdate 또는 FixedUpdate 중에서 적합한 메서드를 사용하여 여러분의 게임 오브젝트와 컴포넌트가 게임 속 시간 단위에 맞춰지도록 조정하면 됩니다.
- 프로토타입(Prototype): 종종 원본에 영향을 미치지 않고 오브젝트를 복사해야 할 일이 생길 것입니다. 이 생성 패턴은 오브젝트 복제 및 클론 생성 과정에서 원본과 유사한 다른 오브젝트들을 만들어 내는 문제를 해결해 줍니다. 이러한 방법은 여러분의 게임 내에서 모든 유형의 객체를 생성하는 별도의 클래스를 정의하는 것을 막을 수 있습니다.
Unity 엔진의 프리팹(Prefab) 시스템은 게임 오브젝트의 프로토타이핑 형식을 구현합니다. 이는 컴포넌트를 온전하게 포함하고 있는 오브젝트 템플릿을 복제할 수 있게 해줍니다. 특정 속성을 재정의하여 변형된 프리팹(Prefab Variants)을 생성하거나 다른 프리팹 내부에 중첩된 프리팹(Nest Prefabs)을 추가하여 계층 구조를 형성할 수도 있습니다. 특수한 프리팹 수정 모드(Prefab editing mode)를 사용하여 프리팹을 독립적 또는 상황에 맞춰 수정할 수 있습니다.
- 컴포넌트(Component): Unity 엔진을 다루는 대부분 사람은 해당 패턴을 이미 잘 알고 있습니다. 여러 책임을 지는 거대한 클래스들을 생성하는 것 대신, 하나의 책임만 지는 작은 컴포넌트들을 여러 개 만드는 겁니다.
만약 여러분이 컴포넌트를 고르고 선택하기 위해서 컴포지션을 사용한다면, 여러분은 복잡한 동작을 구현하기 위해 이를 결합할 것입니다. 물리 구현을 위해 Rigidbody 컴포넌트와 Collider 컴포넌트를 추가하는 식이죠. 3차원 지오메트리를 위해 MeshFilter 컴포넌트와 MeshRenderer 컴포넌트를 추가할 수도 있습니다. 각각의 게임 오브젝트는 포함하고 있는 컴포넌트에 따라서 풍부하고 독특해집니다.
물론, Unity 엔진은 여러분에게 필요한 모든 것을 제공할 수는 없습니다. 필연적으로 여러분은 Unity 엔진에 내장되어 있지 않은 다른 패턴들을 사용해야 할 것입니다. 그럼, 이제 다음 장에서 그러한 패턴 중 몇 가지를 살펴보도록 하겠습니다.
수고하셨습니다!
'Unity Learn > Game Programming Patterns' 카테고리의 다른 글
6. Singleton pattern (0) | 2023.10.31 |
---|---|
5. Object pool (0) | 2023.10.23 |
4. Factory pattern (0) | 2023.10.11 |
2. The SOLID principles (0) | 2023.10.01 |
1. Introducing design patterns (0) | 2023.09.07 |