프로그래밍 디자인 패턴은 소프트웨어 개발에서 자주 발생하는 문제를 해결하기 위한 재사용 가능한 설계 솔루션입니다.
쉽게 말해, 세상 수많은 프로그래머 선배분들이 각자의 프로그래밍을 해오다가 공통되게 나타난 비슷한 설계 구조들이 있는데, 그 중 이런 설계 구조에 이름을 붙여서 설계 원칙으로 만든 것 입니다.
- 디자인 패턴은 게임뿐만이 아니라, 다양한 모든 프로그래밍 분야에서 활용 가능한 가이드라인입니다.
- 디자인 패턴은 구체적인 코드를 제공하지 않으며, 일반적인 구조와 상호작용을 설명하는 템플릿으로 이해할 수 있습니다.
- 예를 들어, 세상 다양한 프로그래머들이 제작하던 코드 중, "수많은 객체를 동시에 인스턴스화 시켜 한 곳에 담아두고, 사용이 끝난 후 메모리가 해제" 방식이 프로그래밍 언어나 구현 방식만 차이가 있을 뿐 마치 공통된 무늬와 같이 여러 코드에서 발견되었다고 가정하겠습니다.
- 영향력이나 이름이 있는 프로그래머가, 혹은 상용엔진을 만드는 회사가 이러한 방식을 보고 A패턴이라고 이름을 붙여서 널리 알려지게 되면, 추후 다른 개발자들이 비슷한 내용을 구현해아 할 상황에 편하게 A패턴이란 이름으로 정보를 구하고 적용할 수 있게 되는것 입니다.
- 하나의 예시를 들자면, 본인이 만들고자 하는 음악플레이어라는 기능이 프로그램 상에 하나만 존재하여야 하고 어느곳에서도 음악을 재생할 수 있게끔, 전역적으로 접근 가능할 수 있게 구현해야 하는 상황이라고 가정하겠습니다.
- 잘 알려진 디자인 패턴 중, '프로그램에서 유일한 인스턴스를 보장하고 전역적인 접근을 제공' 하는 개념의 싱글톤 패턴이라는 것이 있는데, 이러한 디자인 패턴 개념을 활용하여 본인이 원하는 코드를 해당 개념에 맞추어 작성하면 손쉽게 작성할 수 있는것 입니다.
- 수많은 디자인 패턴들이 존재하는데 일부는 확장성에 초점을 맞추기도, 일부는 최적화 및 재활용성에 초점을 맞추기도 합니다.
- 게임의 경우, 퍼포먼스가 중요하기에 최적화와 직결되는 디자인 패턴들의 선호도가 높습니다.
- 개요에서 설명이 나왔던 싱글톤 패턴은 게임에서 유일한 인스턴스를 보장하고, 전역적인 접근이 필요한 경우에 사용되는 패턴입니다.
- 싱글톤 패턴은 클래스의 인스턴스가 하나만 생성되도록 보장하고, 어디서든 동일한 인스턴스에 접근할 수 있게 합니다.
- 예를 들어, 게임 매니저, 자원 관리자 등에서 활용됩니다.
- 게임에서 오브젝트의 동작이 상태에 따라 달라지는 경우 사용되는 패턴입니다.
- 상태 패턴은 각 상태를 클래스로 구현하고, 상태에 따라 다른 동작을 수행합니다.
- 예를 들어, 캐릭터의 이동 상태, 공격 상태, 대기 상태 등을 다루는 데 유용합니다.
- 캐릭터의 상태를 객체로 구현하게 되면, 추후 새로운 상태가 추가 되어도 이 상태를 사용하는 캐릭터 클래스의 코드를 대폭 수정할 필요 없이 유연하게 대처가 가능합니다.
- 게임에서 반복적으로 생성되고 소멸되는 객체들을 효율적으로 관리하기 위한 패턴입니다.
- 객체 풀 패턴은 미리 생성된 객체들을 풀에 저장해두고, 필요할 때마다 객체를 재사용하여 생성 및 소멸의 오버헤드를 줄입니다.
- 게임에서 객체는 정말 많은데, 이 객체들을 필요한 상황마다 생성하여 사용하거나, 사용이 종료되는 순간순간 없애는 작업이 반복된다면 꽤 큰 부하가 걸릴것입니다.
- 미리 큰 메모리 공간을 확보해 둔 후에, 객체의 사용이 끝나도 객체를 지우는 것이 아닌, 잠시 비활성화 해 두었다가 재활용하는 방법으로 사용하면 성능상 큰 이득을 볼 수 있습니다.
- 게임 오브젝트의 동작과 기능을 구현하는 데 사용되는 패턴입니다.
- 각각의 게임 오브젝트는 여러 개의 컴포넌트로 구성되며, 컴포넌트는 독립적으로 동작하고 상호작용합니다.
- 다시 말해, 자동차라는 객체가 있을 경우, 이 객체를 만드는 방법으로 엔진객체, 휠 객체, 미션 객체, 브레이크 객체 등 세분화 된 객체들을 조립하여 하나의 객체를 구성해 나가는 패턴입니다.
- Unity 엔진에서 만들어내는 객체들이 컴포넌트 패턴의 예시라고 볼 수 있습니다.
- 캐릭터를 하나 만들고, 거기에 필요에 따라 물리가 필요하면 물리 객체, 네트워킹이 필요하면 네트워크관련 객체등을 붙여나가며 원하는 객체를 만들어 냅니다.
- 이 패턴은 객체 간의 일대다 관계를 구성하여, 한 객체의 상태 변화에 따라 다른 객체들이 자동으로 업데이트되도록 하는 것을 목적으로 합니다.
- 옵저버 패턴은 주제(Subject)와 옵저버(Observer)라는 두 가지 주요 요소로 구성됩니다.
- 주제는 상태를 가지며, 상태가 변경될 때 옵저버에게 알립니다.
- 옵저버는 주제를 구독하고, 주제의 상태가 변경되면 업데이트를 수신하여 필요한 동작을 수행합니다.
- 플레이어의 정보를 표시하는 UI가 있다고 가정 시, 이 UI가 플레이어의 정보를 항시 받아 출력하는 형태는 비효율적일것입니다.
- 변동사항이 있을때만, 변동사항이 있다는 것을 관련된 객체들에게 전달시키는 방식을 채용하게 되면 객체간의 결합도를 낮추고, 유연성 및 확장성을 제공할 수 있습니다. 이럴때 옵저버 패턴을 고려할 수 있습니다.
이외에도 컬렉션 객체를 유용하게 관리하게 도와주는 이터레이터 패턴, 많은 수의 유사한 객체를 관리하기 위한 플라이웨이트 패턴, 플레이어 입력 자체를 캡슐화 하여 상호작용 및 제어 흐름에 도움을 주는 커맨드 패턴, 게임 내에서 객체를 새로 만들어 내는 과정을 단일 지점에 집중시켜 코드 단순화를 이루어낼 수 있는 팩토리 패턴 등 유용한 패턴들이 상당히 많습니다.
게임의 종류가 다양하듯, 적용시킬 수 있는 디자인 패턴도 상황에 따라 다릅니다. 만들고자 하는 게임에 따라 어울리지 않는 디자인 패턴을 무리하여 적용시키거나, 무리하게 많은 디자인패턴을 적용시켜버리면 구현 시간보다 설계시간이 반대로 더욱 길어져서 자칫 옳지 못한 결과로 이어질 수도 있습니다. 다양한 디자인 패턴 중, 충분히 본인 프로젝트에 어울리는지 판단한 후에 적용시킬지 여부를 결정하는 것이 좋습니다.