MVC, 사실 클라이언트 측에서 출발한 아키텍처였다

date
Apr 24, 2025
slug
mvc-client-side-history
author
status
Public
tags
Architecture
summary
type
Post
thumbnail
preview.jpg
category
updatedAt
Apr 28, 2025 03:46 AM
 

MVC, 그 시작과 현대적 해석: 디자인 패턴의 기초

최근 GoF 디자인 패턴 북스터디를 진행하면서, 문득 이런 생각이 들었습니다.
"GoF 패턴을 공부하는 것도 좋지만, 그보다 더 오래되고, 더 본질적인 개념부터 다시 짚어보는 건 어떨까?"
그래서 이번 글에서는, 소프트웨어 아키텍처의 기초이자, 지금까지도 강한 영향을 끼치고 있는
MVC(Model-View-Controller) 패턴을 프론트엔드 개발자의 시선에서 다시 들여다보려 합니다.
 
이번 글에서는
  • MVC가 어떻게 등장했는지
  • 그리고 현대 프론트엔드 개발에서는 어떻게 재해석되고 있는지
살펴보겠습니다.
 

MVC의 기원: 서버가 아니라, 클라이언트에서 시작됐다

흔히 MVC를 서버 아키텍처의 일부로 생각하곤 합니다. 하지만, MVC는 사실 클라이언트 측 GUI 애플리케이션을 위해 탄생했습니다.
때는 1979년, Xerox PARC — 컴퓨터 역사상 가장 전설적인 연구소 중 하나 — 에서 트리그베 린스카우그(Trygve Reenskaug)는 고민에 빠졌습니다.
"점점 복잡해지는 사용자 인터페이스를, 어떻게 깔끔하게 관리할 수 있을까?"
그 고민 끝에 탄생한 것이 바로 MVC 패턴이었습니다.
 

Smalltalk: MVC를 탄생시킨 혁신적인 언어

MVC가 태어난 배경에는 Smalltalk라는 프로그래밍 언어가 있었습니다.
Smalltalk는 1970년대 초 Xerox PARC에서 개발된 언어로, 객체 지향 프로그래밍(OOP) 개념을 완성도 있게 구현한 시스템입니다. 👉 Smalltalk 맛보기
  • 모든 것이 객체였고,
  • 객체들은 메시지를 주고받으며 상호작용했으며,
  • 실시간으로 코드를 수정하고 테스트할 수 있는 내장된 통합 개발 환경(IDE)을 제공했습니다.
또한 Smalltalk는 세계 최초로 그래픽 사용자 인터페이스(GUI)를 도입한 언어이기도 합니다.
창, 버튼, 입력 필드 같은 다양한 컴포넌트를 다루는 복잡한 사용자 인터페이스 환경 속에서, 구조적이고 체계적인
복잡한 UI를 체계적으로 관리할 필요성 속에서, 자연스럽게 MVC 아키텍처가 등장하게 된 것이죠.
 

왜 클라이언트 애플리케이션에 MVC가 필요했을까?

당시 클라이언트 애플리케이션은 급격히 복잡해지고 있었습니다.
  • 사용자의 클릭이나 키 입력에 실시간으로 반응해야 했고,
  • 다양한 컴포넌트들이 서로 의존하거나 상호작용해야 했습니다.
 
하지만 초기 프로그램 구조는 여전히 데이터 처리, 입력 처리, 화면 출력이 뒤엉킨 스파게티 코드였습니다. 🍝
  • 기능 추가나 수정이 대공사였고,
  • 버그 수정조차 끔찍할 정도로 어렵고 위험했습니다.
 
린스카우그는 이를 해결하기 위해 "관심사의 분리" 원칙을 도입합니다.
  • Model은 데이터와 비즈니스 로직을 담당하고,
  • View는 사용자 인터페이스를 그리며,
  • Controller는 사용자 입력을 해석해 Model에 전달합니다.
이렇게 각자의 역할을 명확히 분리한 덕분에, UI는 훨씬 구조적이고 유지보수하기 쉬운 형태로 발전할 수 있었습니다.
 

MVC란 무엇인가: 사용자의 행동을 따라가는 구조

notion image
  • Model: 애플리케이션의 데이터와 비즈니스 로직을 관리합니다.
  • View: 사용자에게 보이는 화면을 담당합니다.
  • Controller: 사용자 입력을 받아 적절한 동작을 Model에 요청합니다.
MVC의 핵심은 "각자의 역할을 명확히 나누어 복잡성을 줄이는 것"이었습니다.
 

서버로 넘어온 MVC: 웹 개발의 뼈대를 만들다

시대가 흐르면서, MVC는 서버 사이드에서도 큰 인기를 끌었습니다.
특히, Ruby on Rails, Spring MVC, ASP.NET MVC 같은 프레임워크들은 MVC를 기반으로 웹 애플리케이션을 설계하는 표준이 되었습니다.
 
간단한 Express.js 예제를 볼까요?
// routes/user.js const express = require('express'); const router = express.Router(); const UserModel = require('../models/user'); router.get('/users', async (req, res) => { const users = await UserModel.getAllUsers(); // Model 호출 res.render('users', { users }); // View로 데이터 전달 }); module.exports = router;
여기서도 똑같이
  • Model이 데이터베이스와 대화하고,
  • Controller가 요청을 받아 처리하며,
  • View가 사용자에게 결과를 보여줍니다.
MVC를 통해 서버 코드 역시 구조적이고 명확하게 유지할 수 있었습니다.
 

복잡한 웹에서의 MVC의 한계

시간이 흐르면서 웹은 단순한 정보 제공용 페이지를 넘어, 상호작용이 핵심인 복잡하고 역동적인 애플리케이션으로 진화했습니다.
  • 지도에 핀을 찍고,
  • 메일을 읽고 보내고,
  • 쇼핑몰에서 상품을 검색하고 주문하는 것처럼,
웹은 점점 데스크톱 애플리케이션에 가까워지고 있었습니다. 하지만 이 변화는 기존 서버 중심의 MVC 아키텍처로는 대응하기 어려운 문제를 낳았습니다.
 

구체적인 문제

  • 매번 입력할 때마다 전체 페이지를 새로고침해야 했습니다.
  • 서버와 클라이언트 간 역할 분담이 모호해졌습니다.
  • 클라이언트 컴포넌트 간 데이터 흐름이 복잡해졌습니다.
결국, 복잡한 프론트엔드 애플리케이션을 다루기에는 기존 MVC만으로는 부족해졌습니다.
MVC 구조는 결국, 규모가 커지고 복잡해진 프론트엔드 애플리케이션을 제대로 다루기에는 한계가 있었습니다.
 

SPA의 등장: 컴포넌트 중심으로

이런 한계를 극복하기 위해 등장한 것이 바로 SPA(Single Page Application) 아키텍처입니다.
한 번의 페이지 로딩 이후, 사용자 입력에 따라 클라이언트에서 필요한 부분만 동적으로 갱신하는 방식이죠.
하지만 SPA 시대가 열리면서, 웹 애플리케이션은 이제 "페이지 단위"가 아니라 "컴포넌트 단위" 로 동작하고,
컴포넌트 간 상태 관리가 새로운 과제로 떠올랐습니다. 이를 해결하기 위한 새로운 접근이 필요해졌습니다.
 

MVVM의 등장: View와 상태를 더 똑똑하게 나누자

notion image
MVVM(Model-View-ViewModel)은 컴포넌트 기반 SPA에서 발생하는 복잡성을 해결하려는 시도였습니다.
  • Model: 도메인 데이터
  • ViewModel: View의 상태를 추상화
  • View: 화면을 렌더링
특징은 View와 ViewModel 간의 양방향 바인딩입니다. (Angular, Vue 2.x)
하지만 앱이 커지면서 양방향 바인딩이 오히려 복잡성을 증가시키는 부작용이 나타났습니다.
 

Flux의 탄생: 단방향 흐름이라는 혁신

Flux란 무엇인가?

Flux는 단순한 상태 관리 패턴이 아니라, 앱의 데이터 흐름 자체를 명확하게 규정한 아키텍처입니다.
핵심 아이디어: "데이터는 항상 한 방향으로만 흐른다."
구조는 다음과 같습니다.
 
View → Action → Dispatcher → Store → View
notion image
 

Flux의 특징

  • 단방향 데이터 흐름: 상태 변경이 항상 예측 가능하다.
  • Store 분리: 관심사에 따라 상태를 나눌 수 있다.
  • Action: 상태 변경을 명확히 표현하는 단순한 객체.
단방향 흐름 덕분에 상태 추적이 쉬워지고, 버그를 줄이고, 복잡한 앱도 구조적으로 관리 할 수 있게 되었습니다.
 

Flux가 가져온 이점

  • 상태 변경이 예측 가능해졌다.
  • 데이터 흐름이 명확해져 디버깅이 쉬워졌다.
  • 복잡한 앱도 구조적으로 관리할 수 있게 되었다.
이전까지는 "어디서 뭐가 바뀌었는지" 알기 어려웠지만,
Flux에서는 상태가 바뀌는 경로가 항상 Action → Dispatcher → Store 순서로만 진행되기 때문에, 앱의 동작을 추적하고 이해하는 게 수월해졌습니다.
 

MVC는 아직도 살아있다

요즘은 React 같은 라이브러리를 보면,
  • 컴포넌트가 View를 렌더링할 뿐만 아니라,
  • 내부 상태를 관리하고 사용자 입력을 처리하는 등
Controller 역할까지 함께 수행하는 경우가 많습니다.
또한, 전역 상태를 관리하는 Redux, Zustand 같은 라이브러리들은 자연스럽게 Model 역할을 담당합니다.
프레임워크와 기술은 변했지만, 변하지 않은 원칙이 있습니다. 바로 "관심사의 분리" 입니다.
 

MVC는 여전히 살아있는 사고의 틀이다

현대 프론트엔드 프레임워크들은 더 이상 고전적인 MVC 구조를 그대로 따르진 않습니다.
하지만 여전히 소프트웨어 아키텍처의 핵심 원칙인 "관심사의 분리""구조적 설계" 는 살아 숨 쉬고 있습니다.
예를 들어,
  • React 컴포넌트는 View를 렌더링하지만, 내부 상태 관리(useState)나 사용자 입력 처리(onClick, onChange)까지 담당하면서 Controller 역할까지 수행합니다.
  • Redux, Zustand, Recoil 같은 상태 관리 라이브러리는 애플리케이션 전체의 상태를 책임지는 Model 역할을 담당합니다.
  • React Query, SWR과 같은 서버 상태 관리 라이브러리는 API 통신 결과를 캐시하고 관리하며, 서버 사이드 Model처럼 동작합니다.
  • Form Libraries (React Hook Form, Formik)은 사용자 입력 처리를 별도로 모듈화하여, Controller와 View의 역할을 명확히 나누려는 시도입니다.
이처럼 현대의 프레임워크와 라이브러리들은 모두 "관심사의 분리"를 다양한 방식으로 구현하고 있고,
결국 현대의 다양한 프레임워크들도, 모두 MVC 철학을 현대적으로 재해석한 결과물입니다.
 

지금도 MVC를 이해해야 할까?

MVC는 단순히 과거의 유물이 아닙니다. 오늘날처럼 복잡하고 역동적인 UI를 설계할 때, 여전히 "구조적으로 사고하는 틀" 이 되어줍니다.
현대 프론트엔드 개발에서 흔히 사용하는 아키텍처 패턴들 - Flux, MVVM, 상태 관리 라이브러리들은 MVC의 철학을 현대적으로 재해석한 결과물입니다.
따라서 MVC를 이해하는 것은 단순히 옛 개념을 공부하는 것이 아닙니다. 더 나은 설계, 더 견고한 시스템, 더 명확한 역할 분담을 위해 프론트엔드 개발자로서 반드시 갖춰야 할 사고방식을 익히는 과정입니다.
MVC를 제대로 이해하고 있다면, 어떤 새로운 기술이 등장하더라도 그 기반이 되는 원칙을 꿰뚫어보고 현명하게 선택하고 설계할 수 있게 될 것입니다.
 
 

부록 - Smalltalk


Smalltalk이란?

  • 개발 시기: 1970년대 초반, Xerox PARC에서 개발됨
  • 주요 설계자: 앨런 케이(Alan Kay), 댄 잉글스(Dan Ingalls), 트리그베 린스카우그(Trygve Reenskaug) 등
  • 객체 지향 개념을 구현하기 위한 시범 언어 - OOP의 발전에 영향을 끼친 역사적인 언어
  • 최초로 GUI를 도입한 언어
  • MVC 패턴을 처음 정의한 언어

특징

  1. 모든 것이 객체 (Everything is an object)
      • 숫자, 문자열, 함수, 클래스까지도 전부 객체
      • 객체들은 메시지를 주고받으며 상호작용함
  1. 메시지 기반 구조
      • 메소드를 호출하는 것이 아니라 객체에 "메시지를 보낸다"
      • 3 + 4는 사실 3 객체에 + 메시지를 보내 4라는 인자를 전달하는 것
  1. 동적 타입 & 런타임 환경
      • 매우 유연한 동적 언어
      • 코드 작성, 실행, 디버깅까지 모두 런타임에서 가능
  1. 완전한 IDE 포함
      • Smalltalk 환경은 단순한 언어가 아니라, 전체 개발 환경(IDE)을 통합한 시스템
      • 클래스를 수정하고 곧바로 반영할 수 있는 라이브 코딩 환경 제공

Smalltalk 맛보기 (실습)

1. PharO IDE 설치
notion image
설치하고 실행해보면, 복고풍이지만 강력한 Smalltalk 환경을 직접 체험할 수 있습니다.
(엄청난 GUI가 저를 압도했어요!)
  1. Playgroud 창을 열기
    1. notion image
    2. 코드 작성해보기 'Hello from Smalltalk!' printNl.
      1. 부분
        의미
        'Hello, Pharo!'
        문자열 객체. 이 자체가 String 클래스의 인스턴스
        printNl
        출력 및 줄바꿈 처리
        notion image