2025. 11. 12. 19:20ㆍTIL
디자인 패턴과 EventBus 남용 반성, 그리고 MeshCollider 최적화
1. 디자인 패턴 사용의 함정
"망치를 들면 모든 것이 못으로 보인다"
오늘 특강에서 가장 와닿았던 부분:
- 디자인 패턴을 배웠다고 해서 무조건 적용하려고 하면 안 된다
- 기본기(알고리즘, 자료구조, 베스트 프랙티스)가 먼저
- 패턴을 봤을 때 "새롭지 않다"고 느껴질 때 사용해도 된다
- 즉, 이미 비슷한 구조로 짜본 적이 있을 때
내 EventBus 패턴 남용 사례 반성
문제점 분석
// 나쁜 예: 1:1 관계인데 이벤트 사용
public static Action OnPlayerJumpRequested;
public static Action<bool> OnPlayerSprintRequested;
왜 문제인가?
- PlayerFSM → PlayerController로 직접 호출 가능한 1:1 관계
- 여러 곳에서 참조하지 않는데도 이벤트로 구현
- "EventBus 패턴을 사용해보자!"는 강박으로 무분별하게 남발
실제로 겪은 문제들
- 디버깅 지옥
- 이벤트 호출 추적이 매우 어려움
- 구독자가 어디 있는지 찾기 힘듦
- 코드 복잡도 증가
- 단순한 호출을 이벤트로 감싸서 오히려 복잡해짐
- 코드 찾는 데 시간이 오래 걸림
- 유지보수 어려움
- 이벤트 구독/해제 관리 필요
- 메모리 누수 위험 (Subject에 등록된 걸 해제 안 하면 GC 대상이 안 될 수 있음)
앞으로의 Event 패턴 사용 기준
Event를 사용해야 할 때 (1:N 관계)
/// <summary>
/// 플레이어 사망 시 발생 (UI, 적AI, 사운드, 카메라 등 여러 시스템에서 반응 필요)
/// 구독자: GameManager, UIManager, EnemyAI, AudioManager, CameraController...
/// </summary>
public static Action OnPlayerDead;
/// <summary>
/// 인벤토리 요청 시 발생
/// - 인벤토리 UI 로드
/// - 플레이어 골드 업데이트
/// - 추후 확장 가능성 높음 (퀘스트 시스템, 상점 시스템 등)
/// </summary>
public static Action OnInventoryRequested;
사용 기준:
- 여러 시스템이 동시에 반응해야 할 때
- 확장 가능성이 높을 때
- Observer들이 Subject의 로직을 몰라도 될 때
Direct Call을 사용해야 할 때 (1:1 관계)
// 좋은 예: 직접 호출
public class PlayerFSM
{
private PlayerController controller;
private void HandleJumpInput()
{
if (Input.GetKeyDown(KeyCode.Space))
{
controller.Jump(); // 직접 호출!
}
}
}
```
사용 기준:
- 1:1 관계일 때
- 한 곳에서만 반응하면 될 때
- 직접 참조해도 결합도가 크게 높아지지 않을 때
다음 팀 프로젝트 개선 방향
Event 사용 전 체크리스트
□ 이 이벤트를 여러 시스템이 구독하는가?
□ 확장 가능성이 있는가?
□ 직접 호출하면 결합도가 너무 높아지는가?
모두 Yes → Event 사용
하나라도 No → Direct Call 고려
2. Event 주석 작성 규칙
/// <summary>
/// [이벤트 설명]
/// 구독자: [구독하는 클래스들 나열]
/// </summary>
public static Action OnEventName;
3. Event 카테고리 분리
[Header("플레이어 상태 이벤트 (1:N)")]
public static Action OnPlayerDead;
public static Action OnPlayerLevelUp;
[Header("UI 업데이트 이벤트 (데이터→UI)")]
public static Action OnSpChanged;
public static Action OnHpChanged;
MeshCollider 최적화
문제 상황
- MeshCollider를 오브젝트에 사용
- Unity Stats에서 Batches 수가 증가
해결 방법
기본 Collider 조합


// 나쁜 예
gameObject.AddComponent<MeshCollider>();
// 좋은 예
// BoxCollider와 CapsuleCollider를 조합해서 복잡한 형태
BoxCollider box1 = gameObject.AddComponent<BoxCollider>();
BoxCollider box2 = child1.AddComponent<BoxCollider>();
CapsuleCollider capsule = child2.AddComponent<CapsuleCollider>();
이유:
- MeshCollider는 연산 비용이 매우 높음
- BoxCollider, SphereCollider, CapsuleCollider 조합으로도 대부분 커버 가능
- Batches 증가 방지 → 성능 향상
결론
배운 교훈
- "필요악"으로서의 디자인 패턴
- Event는 필요할 때만 사용
- 무분별한 추상화는 독이 됨
- 기본기가 우선
- 패턴보다 코드를 정확히 이해하는 게 먼저
- 패턴이 "새롭지 않을 때" 사용
- 다음 프로젝트에서는
- "꼭 필요한가?" 고민하고 적용
- 1:1 관계는 직접 호출
- 1:N 관계만 Event 사용
특강에서의 한 마디
"디자인 패턴을 배웠다고 바로 적용하려 하지 말자.
프로젝트하면서 적용해보고 연습하는 건 OK,
취업해서 기존 코드에 디자인 패턴 적용해보려는 건 X"
이번 개인 과제에서 EventBus 패턴을 강박적으로 사용했던 게 정말 반성된다...
다음엔 더 신중하게 판단해서 적용해야겠다!
+오늘 싱글턴 패턴 수업을 들으며 하승우 튜터님께 했던 질문
이전 팀플에서 사용했던 ManagerRoot
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ManagerRoot : Singleton<ManagerRoot>
{
[Header("직접 참조")]
[SerializeField] private GameManager gameManager;
[SerializeField] private UIManager uiManager;
[SerializeField] private SceneController sceneController;
[SerializeField] private AudioManager audioManager;
public static GameManager GameManager { get; private set; }
public static UIManager UIManager { get; private set; }
public static SceneController SceneController { get; private set; }
public static AudioManager AudioManager { get; private set; }
protected override void Init()
{
GameManager = gameManager;
UIManager = uiManager;
SceneController = sceneController;
AudioManager = audioManager;
Screen.SetResolution(1920, 1080, true);
}
}
매니저들을 한곳에서 관리하겠다는 목표는 OK 그러나, 매니저들의 초기화 순서를 수동으로 지정하겠다!는 No.
각 매니저의 Awake,Start등의 유니티 콜백함수를 모두 지우고 RootManger의Init클래스에서 각 매니저들의 Init함수를 호출 해 값들을 초기화하거나
하위 클래스들의 MonoBehaviour를 지우고 유니티에서 쓰는 방식의 싱글턴이 아닌 c#에서 사용하는 방식의 싱글턴을 사용해 싱글턴 구현 후 동적 할당(eventSystem이나 Canvas이 때 동적 생성)
예시로 UIManager에서 UIPrefab을 불러올 때 ResroucesManager에서 프리팹들 동적으로 할당,생성 해줌
'TIL' 카테고리의 다른 글
| [2025_11_14]3d 러닝 게임 팀프로젝트 시작 (0) | 2025.11.14 |
|---|---|
| [2025_11_13]유니티 심화 개인과제 마감 (0) | 2025.11.13 |
| [2025_11_11]EventBus패턴 (0) | 2025.11.11 |
| [2025_11_10]플레이어 물리 버그 해결 (0) | 2025.11.07 |
| [2025_11_06]객제지향 프로그래밍(OOP)와 SOLID원칙 (0) | 2025.11.06 |