MVC2 패턴으로 심리 테스트 웹사이트 설계하기
확장 가능하고 유지보수가 쉬운 웹 애플리케이션을 만들기 위한 아키텍처 설계
1. 왜 MVC2 패턴인가?
심리 테스트 웹사이트를 개발하면서 가장 먼저 고민했던 부분은 "어떻게 하면 나중에 쉽게 확장하고 유지보수할 수 있을까?"였습니다. 처음에는 모든 코드를 한 파일에 작성하는 것이 빠를 수 있지만, 프로젝트가 커질수록 관리가 어려워집니다.
MVC2 패턴을 선택한 이유는 다음과 같습니다:
- 명확한 책임 분리: 데이터(Model), 화면(View), 제어(Controller)가 각자의 역할에만 집중합니다.
- 재사용성: View를 변경해도 Model은 그대로 사용할 수 있습니다.
- 테스트 용이성: 각 레이어를 독립적으로 테스트할 수 있습니다.
- 협업 효율성: 디자이너는 View에, 개발자는 Model과 Controller에 집중할 수 있습니다.
- 확장성: 새로운 테스트를 추가할 때 기존 코드를 수정하지 않아도 됩니다.
2. 프로젝트 구조 설계
프로젝트를 시작하기 전에 명확한 디렉토리 구조를 설계했습니다. 각 레이어를 별도의 폴더로 분리하여 코드의 위치를 직관적으로 파악할 수 있도록 했습니다.
SimpleTest/
├── index.html
├── css/
│ └── styles.css
└── js/
├── app.js # 진입점
├── models/ # 데이터 레이어
│ └── TestModel.js
├── views/ # 화면 레이어
│ ├── CardView.js
│ └── ModalView.js
└── controllers/ # 제어 레이어
└── TestController.js
이러한 구조는 다음과 같은 장점을 제공합니다:
- 새로운 팀원이 프로젝트에 투입되어도 빠르게 구조를 이해할 수 있습니다.
- 특정 기능을 찾을 때 어디를 봐야 할지 명확합니다.
- 코드 리뷰 시 변경사항의 영향 범위를 쉽게 파악할 수 있습니다.
3. Model 레이어 구현
Model은 애플리케이션의 데이터와 비즈니스 로직을 담당합니다.
저는 TestModel.js에 8개의 심리 테스트 데이터를 관리하는 클래스를 만들었습니다.
Model의 핵심 원칙은 다음과 같습니다:
- 순수성: DOM이나 UI와 전혀 관련이 없어야 합니다.
- 재사용성: 어떤 View에서도 사용할 수 있어야 합니다.
- 검증: 데이터의 무결성을 보장해야 합니다.
export class TestModel {
constructor() {
this.tests = [
{
id: 1,
priority: "01",
name: "초정밀 MBTI 검사",
icon: "🧬",
category: "메인",
description: "90문항으로 분석하는 내 안의 진짜 성격 유형",
effect: "유입 및 바이럴 핵심",
color: "from-purple-500 to-indigo-600",
bgColor: "bg-gradient-to-br from-purple-50 to-indigo-50",
status: "coming-soon"
},
// ... 더 많은 테스트 데이터
];
}
getAllTests() {
return this.tests;
}
getTestById(id) {
return this.tests.find(test => test.id === id);
}
addTest(testData) {
const newTest = {
id: this.tests.length + 1,
...testData
};
this.tests.push(newTest);
return newTest;
}
}
이렇게 구현하면 나중에 데이터베이스를 연동할 때도 Model만 수정하면 됩니다. View와 Controller는 전혀 수정할 필요가 없습니다.
4. View 레이어 구현
View는 오직 화면 렌더링에만 집중합니다.
저는 CardView.js와 ModalView.js 두 개의 View를 만들었습니다.
View의 핵심 원칙:
- 비즈니스 로직 금지: 어떤 계산이나 판단도 하지 않습니다.
- 데이터 독립성: 받은 데이터를 그대로 표시만 합니다.
- 재사용성: 다양한 Controller에서 사용할 수 있어야 합니다.
export class CardView {
constructor(containerId) {
this.container = document.getElementById(containerId);
}
render(tests, onCardClick) {
this.container.innerHTML = '';
tests.forEach(test => {
const card = this.createCard(test);
card.addEventListener('click', () => onCardClick(test));
this.container.appendChild(card);
});
}
createCard(test) {
const card = document.createElement('div');
card.className = 'test-card bg-white rounded-2xl shadow-lg...';
card.innerHTML = `
${test.name}
${test.description}
`;
return card;
}
}
View는 콜백 함수를 통해 사용자 이벤트를 Controller에게 전달합니다. 이를 통해 View는 이벤트가 발생했다는 사실만 알리고, 실제 처리는 Controller가 담당합니다.
5. Controller 레이어 구현
Controller는 Model과 View를 연결하는 다리 역할을 합니다. 사용자의 액션을 받아 Model을 업데이트하고, 그 결과를 View에 반영합니다.
import { TestModel } from '../models/TestModel.js';
import { CardView } from '../views/CardView.js';
import { ModalView } from '../views/ModalView.js';
export class TestController {
constructor() {
this.testModel = new TestModel();
this.cardView = new CardView('test-cards-container');
this.modalView = new ModalView('modal-container');
}
init() {
const tests = this.testModel.getAllTests();
this.cardView.render(tests, this.handleCardClick.bind(this));
}
handleCardClick(test) {
if (test.status === 'coming-soon') {
this.modalView.showComingSoonModal(test.name);
} else if (test.status === 'active') {
this.startTest(test);
}
}
startTest(test) {
console.log('Starting test:', test.name);
// 테스트 시작 로직
}
}
Controller의 역할:
- 애플리케이션 초기화
- 사용자 이벤트 처리
- Model과 View 간의 데이터 흐름 관리
- 애플리케이션 전체 흐름 제어
6. 얻게 된 이점들
MVC2 패턴을 적용하고 나서 다음과 같은 실질적인 이점들을 체감했습니다:
확장성
새로운 심리 테스트를 추가할 때 TestModel.js의 배열에 객체 하나만 추가하면 됩니다.
View와 Controller는 자동으로 새로운 테스트를 처리합니다.
실제로 8개의 테스트를 추가하는데 10분도 걸리지 않았습니다.
유지보수성
디자인을 변경하고 싶을 때는 View만 수정하면 됩니다. 데이터 구조를 변경하고 싶을 때는 Model만 수정하면 됩니다. 각 레이어가 독립적이어서 수정의 영향 범위가 명확합니다.
디버깅 효율성
버그가 발생했을 때 어디를 봐야 할지 명확합니다. 화면이 이상하면 View를, 데이터가 이상하면 Model을, 동작이 이상하면 Controller를 확인하면 됩니다.
코드 재사용성
나중에 모바일 앱을 만들거나 다른 프로젝트를 진행할 때 Model을 그대로 재사용할 수 있습니다. View만 플랫폼에 맞게 새로 만들면 됩니다.
"좋은 아키텍처는 코드를 적게 쓰는 것이 아니라, 미래의 변경을 쉽게 만드는 것입니다."
프로젝트 초기에 시간을 투자해서 MVC2 패턴을 제대로 구현한 덕분에, 이후 기능 추가와 수정이 매우 수월해졌습니다. 여러분의 프로젝트에도 적용해보시길 추천드립니다!
💡 핵심 요약
- MVC2 패턴은 Model, View, Controller를 완전히 분리합니다
- 각 레이어는 명확한 책임을 가지고 독립적으로 동작합니다
- 확장성과 유지보수성이 크게 향상됩니다
- 초기 설계에 시간을 투자하면 장기적으로 큰 이득을 얻습니다