MVC 구조 안에서 Observer와 Strategy가 하는 일
MVC 패턴에서 Model-View 동기화는 Observer가, 변하는 행위의 캡슐화는 Strategy가 맡는 구조적 관계와 적용 절차를 실무 관점에서 정리한다.
2026-08-13 · 최초 발행 2025-10-14
MVC 패턴은 대규모 UI·웹 애플리케이션에서 관심사 분리로 유지보수성과 확장성을 확보하는 아키텍처로 자리잡았다. 그런데 MVC라는 이름 자체는 세 영역을 나누는 것 이상을 설명하지 않는다 — Model과 View를 실제로 동기화하는 메커니즘, Controller·View·Model 내부에서 바뀌는 행위를 다루는 방식은 별도로 정의해야 한다. 실무에서는 전자를 Observer 패턴이, 후자를 Strategy 패턴이 맡는 조합이 표준으로 정착했다.
MVC, Observer, Strategy가 각각 정의하는 것
MVC는 Model-View-Controller의 약어로, 도메인 상태(Model)와 표현(View), 입력 제어(Controller)를 분리하는 구조다. 데이터 변경은 Model에서 일어나고 View는 이를 표시하며, Controller는 사용자 입력을 Model 또는 View로 전달한다. 목표는 관심사 분리, 테스트 용이성, 변경 영향 최소화다.
Observer는 주체(Subject)가 상태 변화 시 관찰자(Observer)에게 알림을 발행하는 이벤트 기반 패턴이다. MVC에서는 Model을 Subject로, View를 Observer로 두어 데이터 변경 시 자동 갱신 메커니즘을 구성한다. 목표는 느슨한 결합, 푸시 기반 업데이트, 다중 구독자로의 확장이다.
Strategy는 알고리즘(행위)을 캡슐화해 런타임에 교체 가능한 정책으로 주입하는 패턴이다. Controller의 라우팅·검증·바인딩 정책, View의 렌더링 정책, Model의 도메인 규칙 계산 등에 적용한다. 목표는 조건 분기 축소, 확장 지점의 명시화, 테스트 격리다.
세 패턴을 합치면 관계가 드러난다. MVC의 Model-View 동기화는 Observer로 실현하고, Controller·View·Model 내부의 변하는 행위는 Strategy로 캡슐화하는 조합이 일반적이다. 의존성 방향은 View→Model(조회), Model→View(이벤트 알림), Controller→Model/Strategy(조작·정책 위임)로 고정된다. 그 결과 결합도가 줄고 이벤트 중심 흐름이 만들어지며, 정책 교체만으로 기능을 확장할 수 있게 된다.
구성 요소가 실제로 하는 일
이벤트 동기화 메커니즘에서는 Model 상태 변경 시 Observer 알림을 통해 View 일관성을 확보한다. 새로운 View를 추가할 때도 Model 수정 없이 Observer 등록만으로 확장할 수 있다. 동기·비동기 알림, 배치 알림, 디바운스 등 이벤트 전략을 상황에 맞게 선택할 수 있다.
정책 교체 지점은 명시적으로 드러나야 한다. 입력 검증, 포맷팅, 라우팅, 렌더링, 도메인 계산을 Strategy로 분리하고, Feature flag나 구성 기반 전략 선택, DI·팩토리 적용으로 운영 유연성을 확보한다.
의존성 방향은 테스트성과 직결된다. View는 Model 인터페이스만 의존하고 Model은 View의 구체 타입에 의존하지 않는다. Controller는 Strategy 인터페이스를 목킹해 단위 테스트를 분리할 수 있다.
동시성과 트랜잭션 경계도 고려 대상이다. Model 변경은 트랜잭션 경계 내에서 처리하고, 알림은 커밋 이후에 발행하는 것이 권장된다. Observer 안에서 Model을 재변경하는 것은 금지해야 하며, UI 스레드나 이벤트 루프의 규칙을 준수해야 한다.
요청 하나가 화면에 반영되기까지
입력부터 출력까지는 다섯 단계를 거친다. 사용자 이벤트나 HTTP 요청이 Controller에 도달하면, Controller는 Strategy로 검증·바인딩·행위를 선택하고, Controller가 Model을 업데이트한다(트랜잭션 시작 → 도메인 규칙 → 커밋). Model은 Observer인 View에게 변경 이벤트를 발행하고, View는 Model을 조회해 UI를 갱신하거나 템플릿을 렌더링한다.
오류가 나면 흐름이 갈라진다. Strategy 실행이 실패하면 오류 전략을 실행하거나 에러 View를 선택한다. Model 업데이트가 실패하면 롤백하고 알림은 발행하지 않은 채 에러 응답을 반환한다. 비동기 알림에서는 재시도·백오프·중복 억제 정책을 적용한다.
어디에서 이 조합을 볼 수 있는가
웹 MVC 프레임워크가 가장 흔한 예다. Spring MVC는 HandlerMapping·HandlerAdapter·ViewResolver 등을 Strategy 구성 요소로 두고, Model 변경 후 View를 렌더링한다. ASP.NET Core MVC도 ModelBinder·Formatter·ResultExecutor를 Strategy로 교체할 수 있게 열어둔다.
데스크톱·모바일 UI에서는 Cocoa의 KVO, Android의 LiveData·Flow가 Observer 기반 상태 전파를 담당한다. View 렌더러나 레이아웃 쪽에서는 Strategy로 테마·플랫폼별 동작을 분리한다.
프론트엔드 상태 관리에서는 Redux, Signals, Observer 유사 store 구독으로 View를 갱신하고, 포맷팅·리스트 정렬·필터링 정책은 Strategy로 주입한다.
도메인 서비스에서는 가격·할인·라우팅·추천 엔진의 알고리즘을 Strategy로 구성해 A/B 테스트나 리전별 정책 교체에 쓴다. 정책 교체형 Strategy를 도입한 프로젝트에서는 기능 실험 속도가 1.5~3배 개선된 사례가 있다.
패턴별 성능·확장성·운영 특성
| 패턴 | 성능 | 확장성 | 일관성 | 안정성 | 운영 편의 |
|---|---|---|---|---|---|
| MVC | 간접적, 렌더·도메인 분리로 핫패스 최적화 용이 | 수평 확장 시 역할별 스케일링 용이 | 흐름 명확화로 프로세스 일관성 향상 | 책임 분리로 회복 탄력성 증대 | 디버깅·로깅 지점 명확 |
| Observer | 동기 알림 과다 시 비용 증가 가능 | 구독자 증대에 따라 선형 확장 | 커밋 이후 알림으로 데이터 일관성 유지 | 구독자 실패 전파 주의 필요 | 이벤트 라우팅/필터로 운용 용이 |
| Strategy | 호출 오버헤드는 미미 | 정책 추가가 O(1) 수준 | 정책 표준화로 처리 일관성 확보 | 잘못된 선택 시 행위 불일치 위험 | DI/구성으로 실시간 교체 용이 |
모범사례와 트레이드오프
Model은 순수 도메인 규칙과 이벤트 발행에 집중시키고, View는 렌더만 담당하게 하며, Controller는 오케스트레이션 역할을 최소화하는 것이 기본 원칙이다. Observer 알림은 커밋 후 발행하고 예외는 격리 처리하며, 비동기라면 큐와 배압을 적용한다. Strategy 선택은 구성·피처 플래그·DI로 외부화하고, 공통 인터페이스와 계약 테스트를 유지한다. 이렇게 관심사를 분리하면 변경 영향 범위가 줄어 코드 변경 라인수가 프로젝트 성숙도에 따라 약 20~40% 감소하는 경향을 보이고, UI·도메인 테스트가 분리돼 결함 유입률도 낮아진다.
물론 대가도 있다. 추상화가 과하면 간접층이 늘고 이해 비용이 올라간다 — 단순한 시나리오에서는 과도 설계가 될 수 있다. 동기 Observer는 UI 프리즈·지연 위험이 있어 비동기로 전환할 때는 순서 보장 정책이 필요하다. Strategy가 난립하면 정책 충돌과 우선순위 혼선이 생기므로 중앙 레지스트리와 해석 규칙을 정의해둬야 한다. 이벤트 배치·디바운스·재시도 전략을 갖추면 트래픽 스파이크를 완화하고, 트랜잭션 경계를 지키면 데이터 일관성도 함께 지켜진다.