Design Pattern / Game Programming

[게임 프로그래밍 패턴] Component

상속 대신 기능을 작은 단위로 쪼개 조합해 엔티티를 구성하는 패턴입니다.

  • Design Pattern
  • Game Programming
목차

패턴 한 줄 설명

상속 대신 기능을 작은 단위로 쪼개 조합해 엔티티를 구성하는 패턴입니다.

Unity에서 쓰는 대표 상황

  • 캐릭터 기능을 유연하게 조합해야 할 때
  • 런타임에 기능을 켜고 끄는 설계가 필요할 때

구성 요소 (역할)

  • Entity: 컴포넌트 컨테이너
  • Component: 독립 기능 단위
  • Composer: 초기 조합 설정

Unity 예시 (C#)

아래 코드는 위에서 설명한 대표 상황을 Unity 프로젝트 맥락으로 단순화한 예시입니다.

using System.Collections.Generic;
using UnityEngine;

public interface IGameComponent
{
    void Tick(float deltaTime);
}

public sealed class MovementComponent : IGameComponent
{
    private readonly Transform targetTransform;
    private readonly float moveSpeed;

    public MovementComponent(Transform targetTransform, float moveSpeed)
    {
        this.targetTransform = targetTransform;
        this.moveSpeed = moveSpeed;
    }

    public void Tick(float deltaTime)
    {
        targetTransform.position += Vector3.forward * moveSpeed * deltaTime;
    }
}

public sealed class CharacterControllerRoot : MonoBehaviour
{
    private readonly List<IGameComponent> components = new();

    private void Awake()
    {
        components.Add(new MovementComponent(transform, 5f));
    }
}

장점

  • 기능을 조립식으로 나눠 캐릭터/오브젝트 변형을 빠르게 만들 수 있습니다.
  • 특정 컴포넌트만 테스트/교체할 수 있어 회귀 범위를 줄입니다.

주의할 점

  • 컴포넌트 간 의존성이 커지면 결국 또 다른 결합이 생깁니다.
  • Update 루프가 컴포넌트마다 분산되면 호출 비용과 디버깅 난도가 올라갑니다.

동작 다이어그램

엔티티가 여러 컴포넌트를 조합해 최종 상태를 만드는 흐름입니다.

flowchart LR

  game_loop["Game Loop"]
  entity["Player Entity"]
  result["Transform / State 반영"]

  subgraph components["Components"]
    movement["Movement"]
    health["Health"]
    inventory["Inventory"]
  end

  game_loop -- "Tick()" --> entity
  entity -->|update| movement
  entity -->|update| health
  entity -->|update| inventory
  movement --> result
  health --> result
  inventory --> result

댓글