React를 처음 공부할 때 "왜 React는 이렇게 설계되었을까?"라는 질문을 자연스럽게 갖게 된다. 그 답을 이해하려면 React 이전에 프론트엔드가 어떤 문제를 겪었는지 알아야 한다. MVC, MVVM, 관찰자 패턴 — 이 개념들은 모두 React가 단방향 데이터 흐름을 선택하게 된 맥락과 직결된다.
MVC란?
MVC는 Model, View, Controller 세 가지 역할로 코드를 나누는 아키텍처 패턴이다. 원래는 백엔드에서 많이 쓰이던 개념이다.
- Model: 데이터와 비즈니스 로직을 담당한다. DB에서 데이터를 가져오고 어떻게 가공할지 결정한다.
- View: 사용자가 직접 보는 화면, 즉 HTML과 UI 요소들을 담당한다.
- Controller: 중간 관리자 역할로, 사용자 입력을 받아 Model을 업데이트하고 View에 반영한다.
사용자 입력 → Controller → Model 업데이트 → View 갱신
문제는 앱이 커지면서 생긴다. View가 여러 Model을 참조하고, Model이 다른 Model을 업데이트하면서 의존성이 복잡하게 얽힌다. Facebook은 실제로 이 문제를 겪었는데, 대표적인 사례가 읽지 않은 메시지 숫자가 계속 틀리게 표시되는 버그였다. 어디서 상태가 바뀐 건지 추적하는 게 불가능해졌다.
MVVM과 양방향 데이터 바인딩
MVVM은 MVC의 복잡성을 줄이기 위해 등장한 패턴이다. Model, View, ViewModel로 구성되며, 핵심은 View와 ViewModel 사이의 양방향 데이터 바인딩이다. Vue와 Angular가 이 패턴을 사용한다.
Model ↔ ViewModel ↔ View
Vue의 v-model이 대표적인 예시다. input 값이 바뀌면 데이터가 자동으로 바뀌고, 데이터가 바뀌면 화면도 자동으로 업데이트된다.
<!-- Vue — 양방향 바인딩 -->
<input v-model="username" />
<!-- input 바꾸면 username 자동 변경, username 바꾸면 input 자동 변경 -->
<!-- React — 단방향 -->
<input value={username} onChange={(e) => setUsername(e.target.value)} />
<!-- 이벤트 → 상태 변경 → 리렌더링 순서를 직접 명시해야 한다 -->
양방향이라 개발이 편리하지만, 앱이 커지면 어디서 데이터가 변경되었는지 추적하기 어려워진다는 단점이 여전히 남아있다.
관찰자 패턴
관찰자(Observer Pattern) 패턴은 사실 이미 익숙하게 쓰고 있는 개념이다. 핵심은 이렇다.
특정 대상의 상태가 바뀌면, 그것을 구독하고 있는 대상들에게 자동으로 알려준다.
Subject(발행자) → 상태 변경 → Observer들에게 notify
addEventListener가 바로 관찰자 패턴이다.
button.addEventListener('click', handleClick)
// button = Subject
// handleClick = Observer
React에서는 State가 Subject다. State가 바뀌면 그것을 구독하고 있는 컴포넌트들이 자동으로 리렌더링된다. React의 핵심 동작 원리가 관찰자 패턴이다.
React의 단방향 데이터 흐름
React는 MVC와 MVVM의 복잡성 문제를 단방향 데이터 흐름으로 해결했다. 항상 이 방향만 존재한다.
State → View → 이벤트 발생 → State 변경 → 리렌더링
View가 직접 State를 건드리지 않는다. 이 덕분에 데이터가 어디서 왔는지 추적하기 쉽고, 같은 State면 항상 같은 화면이 나온다는 예측 가능성이 생긴다.
이 철학이 Flux 패턴으로 정립되었고, Redux와 Zustand 같은 상태관리 라이브러리도 이 연장선에 있다.
Action → Dispatcher → Store(State) → View
정리
| MVC | MVVM | React | |
| 데이터 흐름 | 양방향 (복잡) | 양방향 (바인딩) | 단방향 |
| 대표 사례 | Backbone.js | Vue, Angular | React |
| 장점 | 역할 분리 | 편리한 동기화 | 예측 가능성 |
| 단점 | 앱 커지면 복잡 | 추적 어려움 | 코드량 많아짐 |
'💻 STUDY > Frontend' 카테고리의 다른 글
| z-index 무한루프에서 벗어나기 — React Portal 제대로 이해하기 (0) | 2026.06.22 |
|---|---|
| Next.js App Router의 렌더링 방식 이해하기 (0) | 2026.06.11 |
| Next.js는 React의 어떤 문제를 해결할까? (0) | 2026.06.08 |
| React 클라이언트 전역 상태 관리 (0) | 2026.06.07 |
| Storybook이란? — props가 많아질수록 개발이 느려진다고 느꼈다면 (0) | 2026.06.01 |