본문 바로가기
개발/게임 디자인 패턴

게임 디자인 패턴 10. 컴포넌트 패턴 (Component Pattern)

by 석시 2023. 11. 3.



컴포넌트 패턴이다.

사실 유니티를 조금이라도 다뤄봤다면 모를 수가 없다.

유니티의 핵심 프레임워크인 GameObject가 전적으로 컴포넌트 방식에 맞춰 설계되었기 때문이다.

그래서 이번 시간에는 컴포넌트끼리 어떻게 구성해야하는지를 위주로 다뤄보겠다.


디자인 요소 1. 객체는 컴포넌트를 어떻게 얻는가?

객체가 컴포넌트를 어떻게 얻는지를 두 가지로 결정할 수 있겠다.

객체가 필요한 컴포넌트를 알아서 생성할 지 vs 외부 코드로부터 받을지

유지보수 측면에서는 외부로부터 받는 것이 더 낫다.

하지만 이 때 잘못된 컴포넌트를 넘겨줄 위험성이 존재하기 때문에, 객체가 필요한 컴포넌트를 생성하게 하는 선택지 또한 존재하는 것이다.

따라서 유연하고 디커플링된 컴포넌트를 구현하고 싶다면 외부로부터 받는 방식을, 객체를 변경하기 어려운 대신 반드시 해당 컴포넌트를 보장 받고 싶은 경우는 직접 생성하는 방식을 택하면 좋다.


디자인 요소 2. 컴포넌트들끼리 어떻게 통신할 것인가?

컴포넌트들은 기본적으로 한 객체 안에 들어있게 되기 때문에, 서로 간의 참조가 필요하거나 하는 등의 상황이 필요할 것이다.

세 가지 방식을 소개하고자 하는데, 중요한 것은 한 방법을 사용한다고 나머지를 사용 못하는 것이 아니다라는 것이다.

상황에 따라 컴포넌트들과 통신 방식을 적절히 선택하도록 하자.

방법 1) 컨테이너 객체의 상태를 변경하는 변경하는 방식

다음 방식의 특징은 다음과 같다.

  1. 컴포넌트들은 서로 디커플링 상태를 유지한다.

    아무래도 최대 장점이 아닌가 싶다.

    각 컴포넌트들이 서로를 몰라도 된다!

  1. 컴포넌트들이 공유하는 정보컨테이너 객체에 전부 넣어야 한다.

    당연하게도 해당 통신을 구현하기 위해서는 서로 공유하는 정보가 모두 컨테이너에 들어있어야 한다.

    따라서 추천하는 것은 많은 컴포넌트들에서 필요로 하는 정보는 컨테이너에 넣고 그렇지 않고 일부 컴포넌트에서만 사용한다면 뒤에서 언급하는 방법2로 연결하는 것을 추천한다.

  1. 컴포넌트끼리 암시적으로 통신하다 보니 컴포넌트 실행 순서에 의존하게 된다.

    예를 들어 위치를 업데이트하고 그래픽 컴포넌트를 업데이트하지 않고 그래픽 컴포넌트를 먼저 업데이트하는 상황이 일어난다면, 그래픽은 항상 1프레임 전의 위치를 보여주는 상황이 일어나는 것이나 마찬가지이다!

방법 2) 컴포넌트가 서로 참조하는 방식

특징은 다음과 같다.

  1. 간단하고 빠르다.

    참조하는 컴포넌트의 public으로 열어준 모든 것을 사용할 수 있다.

  1. 두 컴포넌트가 강하게 결합된다.

    최대 단점 중 하나이다.

    커플링이 너무 심해진다.

    따라서 방법2를 쓰기 가장 좋은 방식은 컴포넌트의 많은 기능이 필요한데, 해당 컴포넌트가 참조되는 곳이 많지 않은 경우가 아닐까 싶다.

방법 3) 메시지를 전달하는 방식

컨테이너 객체에 간단한 메시징 시스템을 만든 뒤에, 각 컴포넌트들이 서로에게 정보를 뿌리게 하는 것이다.

구현이 복잡하지만, C#에서는 상위 컨테이너에 event를 선언하는 방식으로 쉽게 구현할 수 있다.

특징은 다음과 같다.

  1. 하위 컴포넌트들은 디커플링된다.

    컴포넌트들은 메세지 값과 커플링될 뿐이지 컴포넌트끼리는 디커플링 상태를 유지하는 것이다.

    이처럼 둘 이상의 객체가 중간 객체를 통해서 메세지를 간접적으로 전달해 통신하는 방식을 GoF에서는 중재자(Mediator) 패턴이라고 한다.

  1. 컨테이너 객체는 단순하다.

    컴포넌트들이 공유하는 변수를 어떻게 사용하는 지를 알아야할 필요 없이 메세지만 냅다 전달하면 된다.


Uploaded by N2T