Subject : 옵저버를 등록/해제/알림하는 역할
Observer : Subject의 변경을 받는 인터페이스 (일반적으로 update 메서드)
Subject는 상태가 바뀔 때 등록된 모든 Observer의 update를 호출
보통 Push 방식(변경된 데이터 함께 전달) /
Pull 방식(Observer가 Subject에서 필요한 데이터 조회)로 나뉨
Subject { attach(Observer), detach(Observer), notify() }
Observer { update(data?) }
느슨한 결합: Subject는 Observer의 구체적 타입 모름(인터페이스만 알면 됨).
확장성: 옵저버 추가/제거가 쉽다.
메모리 누수: 등록만 하고 해제 안 하면 레퍼런스 남아 GC 못함
(특히 이벤트/델리게이트 사용 시).
성능: 옵저버 수가 많거나 notify할 때 비용이 큼.
순환/의존성 문제: A가 B를, B가 A를 옵저빙하면 복잡해짐.
동시성: 멀티스레드 환경에서 안전성 확보 필요.
U- I 업데이트는 주로 pull 방식보다 push 방식이 편리.
Model : 상태와 그 상태를 변경하는 메서드 (게임 데이터, 저장소 등)
View : Model을 사용자에게 보여주고, 사용자 입력을 Controller나 Model에 전달
Controller : 사용자의 입력을 해석해 Model을 변경하거나 View를 업데이트
Model : PlayerData (레벨, 경험치, 인벤토리)
View : HUD / 인벤토리 창 (화면에 보여주는 것만 담당)
Controller : 버튼 클릭 처리 (아이템 사용, 레벨 업 로직 호출)
관심사 분리(SoC) : UI·비즈니스 로직 분리로 유지보수, 테스트 용이.
팀 작업에 유리 : 아트/UI 개발자와 시스템 개발자가 덜 충돌.
작은 프로젝트에선 오히려 오버헤드(복잡성 증가).
Controller가 비대해지는 경향 (로직이 Controller에 몰릴 수 있음).
플랫폼/프레임워크에 따라 MVC 해석이 달라 혼란스러움 (웹 MVC vs 데스크탑/게임).
UI 화면(메뉴, 인벤토리)은 MVC 또는 MVVM 스타일로 만드는 게 유지보수에 좋음.
게임플레이 로직은 pure Model로 두고, 입력/상호작용은 Controller에서 처리.
Model → View 알림은 옵저버(이벤트)로 구현하고,
옵저버 해제(OnDisable/Dispose)를 철저히 관리해 메모리 누수 방지.