전통적 MPA(Multi Page App)의 구조와 한계
웹의 시작: 문서를 주고받는 시스템
섹션 제목: “웹의 시작: 문서를 주고받는 시스템”2005년 이전의 웹은 기본적으로 문서 배달 시스템 이었다. 브라우저가 URL을 요청하면, 서버가 HTML 문서를 만들어 응답하고, 브라우저는 그것을 화면에 표시한다. 그게 전부였다.
이 시기의 표준 아키텍처는 다음과 같다.
[브라우저] [웹 서버] [DB] │ │ │ │── GET /products ──────────>│ │ │ │── SELECT * FROM ──>│ │ │<── rows ───────────│ │ │ (템플릿에 데이터 │ │ │ 삽입 후 HTML 생성)│ │<── 200 OK (완성된 HTML) ───│ │ │ (브라우저 전체 화면 갱신) │ │링크를 클릭할 때마다, 폼을 제출할 때마다 이 사이클 전체가 반복된다. 매번 서버가 새 HTML을 생성하고, 브라우저는 화면 전체를 다시 그린다.
서버 사이드 템플릿 렌더링
섹션 제목: “서버 사이드 템플릿 렌더링”PHP, Java Server Pages(JSP), Django, Rails — 이 모두는 서버에서 HTML을 완성 해 클라이언트에 내려보내는 방식이다.
Django 템플릿 예시:
def product_list(request): products = Product.objects.all() return render(request, 'products/list.html', {'products': products}){# products/list.html #}<ul> {% for product in products %} <li>{{ product.name }} — {{ product.price }}원</li> {% endfor %}</ul>서버가 데이터를 DB에서 읽고, 템플릿에 주입하고, 완성된 HTML 문자열을 응답으로 돌려준다. 브라우저는 그 HTML을 파싱해 화면을 그린다.
PHP의 경우:
<?php$result = $db->query("SELECT name, price FROM products");?><ul><?php while ($row = $result->fetch_assoc()): ?> <li><?= $row['name'] ?> — <?= $row['price'] ?>원</li><?php endwhile; ?></ul>로직과 HTML이 한 파일에 뒤섞이는 형태였다. 간단하지만, 규모가 커질수록 유지보수가 어려워졌다.
폼 제출과 전체 페이지 리로드
섹션 제목: “폼 제출과 전체 페이지 리로드”쇼핑 카트에 상품을 추가하는 단순한 동작을 생각해보자.
<form method="POST" action="/cart/add"> <input type="hidden" name="product_id" value="42"> <button type="submit">장바구니에 추가</button></form>버튼을 누르면:
- 브라우저가
POST /cart/add요청을 보낸다 - 서버가 DB를 업데이트한다
- 서버가
302 Redirect로/cart페이지로 보낸다 - 브라우저가
GET /cart요청을 다시 보낸다 - 서버가 장바구니 HTML 전체를 새로 생성한다
- 브라우저가 화면 전체를 갱신한다 — 스크롤 위치 초기화, 깜빡임 발생
이 “깜빡임”이 사용자 경험(UX)의 핵심 문제였다.
왜 2005년까지는 충분했나
섹션 제목: “왜 2005년까지는 충분했나”| 특성 | 설명 |
|---|---|
| 단순성 | 서버 한 곳에서 모든 로직을 처리 |
| SEO 친화적 | 완성된 HTML이 내려오므로 검색엔진 크롤링 용이 |
| 보안 | 비즈니스 로직이 서버에만 존재 |
| 기술 스택 단일화 | Python/Java/PHP 하나만 알면 전체 개발 가능 |
2005년의 웹 사용 패턴은 주로 정보 탐색 이었다. 뉴스를 읽고, 상품을 검색하고, 이메일을 확인한다. 페이지 전환이 잦아도 사용자들은 그것을 당연하게 여겼다.
MPA의 한계 — 왜 변화가 필요했나
섹션 제목: “MPA의 한계 — 왜 변화가 필요했나”인터넷 속도가 빨라지고 웹 앱이 복잡해지면서 문제가 드러났다.
| 한계 | 구체적 문제 |
|---|---|
| 전체 페이지 리로드 | 헤더/네비게이션 등 변하지 않는 영역도 매번 다시 전송·렌더링 |
| 서버 부하 집중 | 모든 렌더링을 서버가 처리하므로 트래픽 급증 시 병목 |
| 반응성 한계 | 드래그&드롭, 실시간 편집 등 앱 수준의 인터랙션 구현 어려움 |
| 대역폭 낭비 | 내용 일부만 바뀌어도 전체 HTML을 다시 전송 |
| 상태 관리 불가 | 페이지 이동 시 클라이언트 상태(스크롤, 입력값 등) 초기화 |
2004년 Gmail 등장이 전환점이었다. 이메일을 클릭했는데 페이지 전체가 깜빡이지 않는다. 답장을 쓰면서 다른 이메일을 탐색할 수 있다. 이것은 MPA 구조로는 불가능했다.
핵심 정리
섹션 제목: “핵심 정리”- MPA(Multi Page Application)는 서버가 매 요청마다 완성된 HTML을 생성해 응답하는 구조다
- PHP/JSP/Django 등 서버 사이드 템플릿 엔진이 이 방식의 핵심 기술이다
- 모든 인터랙션이 전체 페이지 리로드를 유발해 앱 수준의 UX 구현에 한계가 있다
- 2004~2005년 Gmail, Google Maps 등장으로 “웹도 앱처럼 동작할 수 있다”는 기대가 생겼고, 이것이 JavaScript 기반 동적 웹의 출발점이 되었다