콘텐츠 대표 이미지 - 모바일 앱 아키텍처 패턴: MVC, MVVM, MVI 완전 정복 가이드

모바일 앱 아키텍처 패턴: MVC, MVVM, MVI 완전 정복 가이드

스파게티 코드와 작별하고 클린 아키텍처의 세계로! 🍝➡️🏛️
친구가 설명해주듯 쉽고 재미있게 파헤쳐 보자고!

들어가며: 내 코드는 왜 항상 스파게티일까? 🤯

자, 솔직하게 가슴에 손을 얹고 말해봅시다.
야심 차게 시작한 내 앱 프로젝트, 처음엔 분명 깔끔했는데...
기능 하나 추가하고, 버그 하나 잡고, 또 새로운 화면을 만들다 보니 어느새 코드가 뒤죽박죽 엉켜버린 경험, 다들 한 번쯤 있지 않아? 🙋‍♂️

분명히 버튼 하나 눌렀을 때의 로직을 수정해야 하는데, 대체 어느 파일, 어느 줄에 그 코드가 있는지 한참을 헤매고...
하나를 고쳤더니 예상치도 못한 다른 곳에서 버그가 빵! 터지고...
이런 상황을 우리는 전문용어(?)로 '스파게티 코드'라고 부르지. 소스 코드가 마치 스파게티 면처럼 복잡하게 얽히고설켜서 어디가 시작이고 끝인지 알 수 없는 상태 말이야.

이런 대참사를 막기 위해 우리 선배 개발자들이 머리를 싸매고 만들어낸 '설계도'가 있어.
바로 '아키텍처 패턴(Architecture Pattern)'이라는 거야.
집을 지을 때 설계도 없이 기둥부터 세우고 벽부터 쌓으면 어떻게 될까? 아마 얼마 못 가 무너져 내리겠지.
앱 개발도 똑같아. 코드의 뼈대를 어떻게 세우고, 각 부분들이 어떤 역할을 하며, 서로 어떻게 소통할지 미리 약속하고 규칙을 정하는 것, 그게 바로 아키텍처 패턴이야.

오늘은 모바일 앱 개발 씬에서 가장 핫하고, 또 가장 많이 쓰이는 세 명의 주인공!
MVC, MVVM, MVI 이 세 가지 아키텍처 패턴에 대해 제대로 파헤쳐 볼 거야.
각각 어떤 철학을 가지고 태어났고, 어떤 장단점이 있으며, 어떤 상황에 누구를 선택해야 하는지!
이 글을 끝까지 읽고 나면, 더 이상 스파게티 코드를 보며 한숨 쉬는 일은 없을 거라고 장담해. 자, 그럼 시작해볼까? Let's go! 🚀

Chapter 1: 클래식은 영원하다? - MVC (Model-View-Controller)

가장 먼저 만나볼 친구는 MVC야. Model-View-Controller의 약자인데, 거의 모든 아키텍처 패턴의 시조새 격이라고 할 수 있어.
1970년대에 처음 등장했으니, 정말 오래됐지? 하지만 그만큼 기본에 충실하고 직관적이라서 여전히 많은 곳에서 쓰이고 있어.
특히 iOS나 안드로이드 프레임워크 자체가 이 MVC 패턴을 기반으로 설계된 부분이 많아서, 개발자라면 반드시 이해하고 넘어가야 할 기본 소양 같은 거야.

MVC, 그래서 넌 누구냐? 🤔

MVC는 앱의 구성 요소를 세 가지 역할로 명확하게 나누는 것에서 시작해.

1. 모델 (Model) 🧠:
앱의 '데이터'와 '비즈니스 로직'을 담당하는 녀석이야. 쉽게 말해 앱의 '두뇌'라고 할 수 있지.
사용자 정보, 게시글 내용 같은 데이터 자체와, 이 데이터를 어떻게 저장하고, 불러오고, 가공할지에 대한 규칙(로직)을 모두 가지고 있어.
중요한 건, 모델은 뷰(View)나 컨트롤러(Controller)가 어떻게 생겨 먹었는지 전혀 신경 쓰지 않아. 그냥 자기 할 일만 묵묵히 하는 순수한 존재야.

2. 뷰 (View) 👀:
사용자에게 보여지는 화면, 즉 UI(User Interface) 그 자체야. 앱의 '얼굴' 담당이지.
버튼, 텍스트 필드, 이미지 등 사용자가 직접 보고 터치하는 모든 것들이 뷰에 속해.
뷰는 모델에 데이터가 뭐가 있는지 알지만, 그 데이터를 어떻게 처리해야 하는지에 대한 로직은 전혀 몰라. 그저 모델이 주는 데이터를 화면에 예쁘게 뿌려주고, 사용자가 버튼을 누르면 "어이, 컨트롤러! 유저가 버튼 눌렀어!" 하고 알려주는 역할만 할 뿐이야.

3. 컨트롤러 (Controller) 👮:
모델과 뷰 사이를 이어주는 '중간 관리자' 또는 '교통경찰'이야.
사용자가 뷰를 통해 어떤 행동(예: 로그인 버튼 클릭)을 하면, 뷰는 이걸 컨트롤러에게 알려줘.
그럼 컨트롤러는 "아, 로그인하려는구나!" 하고 파악한 뒤, 모델에게 "야, 모델! 이 아이디랑 비밀번호 맞는지 확인 좀 해줘!" 하고 일을 시키지.
모델이 "응, 맞아. 로그인 성공!"이라는 결과를 돌려주면, 컨트롤러는 다시 뷰에게 "자, 이제 메인 화면 보여줘!" 하고 지시하는 역할을 해.

🎮 Controller 중간 관리자 / 교통 경찰 👀 View 사용자 인터페이스 (UI) 🧠 Model 데이터 & 비즈니스 로직 1. 유저 입력 (터치, 클릭) 2. 이벤트 알림 3. 데이터 업데이트 요청 4. 데이터 변경 알림 (KVO, Notification) 5. 뷰 업데이트 지시 MVC 패턴의 기본 흐름

모바일 세계에서의 MVC: 어딘가 좀 다른데? 🤔

이론적으로는 정말 완벽해 보이지? 각자 역할이 명확하고, 서로의 일에 간섭하지 않고...
하지만 이 MVC 패턴이 모바일, 특히 iOS 개발로 넘어오면서 살짝 변형이 일어나.
애플이 만든 UIKit 프레임워크에서 `UIViewController`라는 게 있는데, 이름부터가 '뷰'와 '컨트롤러'가 합쳐진 느낌이지?
맞아. 실제로 iOS에서는 뷰와 컨트롤러가 거의 한 몸처럼 끈끈하게 붙어있어. 뷰의 생명주기(Life Cycle)를 컨트롤러가 관리하기 때문에 분리하기가 거의 불가능에 가까워.

그래서 뷰에서 발생한 이벤트는 컨트롤러가 바로 알아채고, 컨트롤러는 모델에게 데이터를 요청한 뒤, 그 결과를 받아서 *직접* 뷰를 업데이트해.
위 다이어그램에서 4번(Model -> View) 흐름이 약해지고, 5번(Controller -> View) 흐름이 훨씬 더 강해지는 거지.
이런 구조 때문에 모바일 MVC는 종종 'Massive View Controller', 우리말로 하면 '거대 비만 컨트롤러'라는 치명적인 문제에 봉착하게 돼. 😱

🚨 재앙의 시작: Massive View Controller (MVC의 함정)

컨트롤러가 모델과 뷰의 모든 소통을 책임지다 보니, 앱의 기능이 복잡해질수록 컨트롤러의 코드가 기하급수적으로 늘어나.
사용자 입력 처리, 데이터 가공, 네트워크 통신, 에러 처리, 화면 전환, 뷰의 세세한 UI 업데이트 로직까지...
모든 코드가 컨트롤러 하나에 집중되는 거야. 파일 하나가 수천, 수만 줄이 되는 건 시간문제지.
이렇게 되면 코드를 이해하기도, 수정하기도, 테스트하기도 극도로 어려워져. 바로 우리가 피하고 싶었던 '스파게티 코드'의 완성이야.

MVC, 넌 어떨 때 쓰는 게 좋을까?

👍 장점 (Pros):

1. 배우기 쉽고 직관적이다: 구조가 단순해서 초보 개발자도 금방 이해하고 적용할 수 있어.
2. 개발 속도가 빠르다: 간단한 앱이나 프로토타입을 만들 때, 복잡한 설정 없이 빠르게 개발을 시작할 수 있다는 장점이 있어.
3. 검증된 패턴이다: 오랜 역사만큼이나 수많은 자료와 예제가 있어서 문제 해결에 참고할 자료가 많아.

👎 단점 (Cons):

1. Massive View Controller: 위에서 말했듯이, 프로젝트 규모가 커지면 컨트롤러가 모든 책임을 떠안고 비대해지기 쉬워.
2. 낮은 테스트 용이성: 컨트롤러가 뷰와 너무 밀접하게 연결되어 있어서, UI 프레임워크에 의존하지 않는 순수한 로직 단위 테스트가 어려워.
3. 강한 결합도 (Tight Coupling): 뷰와 컨트롤러가 거의 한 몸처럼 움직이기 때문에, 나중에 UI를 바꾸거나 로직을 재사용하기가 까다로워.

💡 MVC 사용 설명서

MVC는 이제 구시대의 유물일까? 절대 아니야!
- 화면이 한두 개뿐인 아주 작은 프로젝트
- 기능 검증을 위한 빠른 프로토타입 개발
- 아키텍처 패턴을 처음 공부하는 입문자
이런 경우에는 MVC가 여전히 훌륭한 선택지가 될 수 있어. 모든 문제에 망치를 들 필요는 없으니까! 🛠️

Chapter 2: 구원투수의 등장! - MVVM (Model-View-ViewModel)

MVC의 'Massive View Controller'라는 고질병에 개발자들이 신음하고 있을 때, 혜성처럼 등장한 구원투수가 있었으니...
바로 MVVM (Model-View-ViewModel)이야.
MVVM은 마이크로소프트에서 자사의 기술(WPF, Silverlight)을 위해 처음 고안한 패턴인데, 이게 모바일 개발 환경의 문제점을 해결하는 데 기가 막히게 들어맞았던 거지.

MVVM의 핵심 철학은 딱 두 가지야.
1. 뷰(View)와 뷰의 '상태' 및 '로직'을 완벽하게 분리하자.
2. 이 둘 사이의 소통은 '데이터 바인딩'이라는 마법에게 맡기자.

MVVM, 넌 또 누구냐? 🧐

MVVM은 MVC의 C(Controller)를 VM(ViewModel)으로 바꾼 형태야. 각 구성원을 다시 한번 살펴보자.

1. 모델 (Model) 🧠:
MVC의 모델과 완전히 똑같아. 앱의 데이터와 비즈니스 로직을 담당하는 순수한 녀석. 여전히 뷰나 뷰모델에 대해 아무것도 몰라.

2. 뷰 (View) 👀:
MVC의 뷰보다 훨씬 더 '멍청해졌어'. 이게 바로 핵심이야!
MVVM의 뷰는 화면에 무엇을 어떻게 그릴지에 대한 정보만 가지고 있고, '왜' 그렇게 그려야 하는지에 대한 로직은 전혀 없어.
그저 뷰모델이 "지금 이름은 '홍길동'이야", "로딩 상태는 true야" 라고 알려주는 데이터를 화면에 보여줄 뿐이야.
그리고 사용자가 버튼을 누르면 "어이, 뷰모델! 유저가 저장 버튼 눌렀어!" 하고 알려주는 역할만 충실히 수행해.

3. 뷰모델 (ViewModel) 🧑‍🎨:
MVVM의 새로운 주인공이자 가장 중요한 역할이야. '뷰를 위한 모델'이라는 이름처럼, 뷰에 표시되어야 할 데이터와 상태, 그리고 뷰에서 실행되어야 할 명령어(로직)들을 가지고 있어.
컨트롤러와 다른 점은, 뷰모델은 뷰가 어떻게 생겼는지(버튼이 파란색인지, 텍스트가 몇 포인트인지 등) 전혀 모른다는 거야. 뷰에 대한 어떠한 참조도 가지고 있지 않아.
뷰모델은 그저 "현재 유저 이름은 '홍길동'입니다" 라는 `userName`이라는 데이터와, "저장 버튼을 누르면 이 함수를 실행하세요" 라는 `saveButtonTapped()` 라는 로직만 가지고 있을 뿐이야.

마법의 연결고리: 데이터 바인딩 (Data Binding) ✨

"아니, 뷰모델이 뷰를 모르는데 어떻게 뷰를 업데이트해?" 라는 의문이 들 거야.
바로 여기서 MVVM의 핵심 기술인 '데이터 바인딩'이 등장해.
데이터 바인딩은 뷰의 특정 UI 요소를 뷰모델의 데이터에 '연결' 또는 '구독' 시켜놓는 기술이야.

예를 들어, 뷰에 있는 '이름'을 보여주는 텍스트 라벨을 뷰모델의 `userName`이라는 데이터에 바인딩해놓는 거지.
그러면 뷰모델에서 `userName`의 값이 '홍길동'에서 '김철수'로 바뀌는 순간! 뷰는 이 변화를 자동으로 감지하고, 별도의 명령 없이도 화면의 텍스트 라벨을 '김철수'로 스스로 업데이트해.
마치 유튜브 채널을 구독하면 새 영상이 올라올 때마다 알림이 오는 것과 같은 원리야. 뷰가 뷰모델의 데이터를 구독하고 있는 거지.

이 데이터 바인딩 덕분에, MVC에서 컨트롤러가 뷰의 UI 요소를 하나하나 잡아서 "너는 이 값으로 바뀌어!" 라고 지시하던 지저분한 코드가 사라지게 돼.

👀 View UI, 사용자 입력 감지 🧑‍🎨 ViewModel View의 상태, 로직 🧠 Model 데이터, 비즈니스 로직 1. 유저 입력 (터치, 클릭) 2. 명령어 호출 5. 상태 변경 알림 3. 데이터 요청/수정 4. 데이터 반환 ✨ 데이터 바인딩 ✨ (View가 ViewModel의 데이터를 '구독'하고, 변경 시 자동으로 UI 업데이트) MVVM 패턴의 흐름 (feat. 데이터 바인딩)

MVVM, 넌 뭐가 그렇게 좋은데?

👍 장점 (Pros):

1. 완벽한 테스트 용이성 (Testability): 뷰모델은 뷰에 대한 의존성이 전혀 없어. 즉, 안드로이드나 iOS 프레임워크를 몰라도 되는 순수한 코드 덩어리라는 뜻이야. 그래서 뷰모델의 로직을 단위 테스트(Unit Test)하기가 정말 정말 쉬워. 이건 유지보수 측면에서 엄청난 장점이야. 🏆
2. 역할의 명확한 분리 (Separation of Concerns): MVC의 비만 컨트롤러 문제가 해결됐어. 뷰는 오직 화면을 그리는 책임만, 뷰모델은 상태와 로직을 처리하는 책임만, 모델은 데이터를 관리하는 책임만 지게 돼. 각자 자기 일에만 집중하니 코드가 훨씬 깔끔해지지.
3. 재사용성 증가: 뷰와 뷰모델이 분리되어 있기 때문에, 같은 뷰모델에 다른 뷰를 붙이는 것도 가능해. 예를 들어, 모바일 뷰와 태블릿 뷰를 같은 뷰모델에 연결할 수 있다는 거지.
4. 보일러플레이트 코드 감소: 데이터 바인딩을 사용하면, 데이터가 바뀔 때마다 UI 요소를 일일이 찾아 업데이트해주던 코드가 사라져서 전체적인 코드 양이 줄어들어.

👎 단점 (Cons):

1. 높은 학습 곡선: MVC에 비해 구조가 복잡하고, 데이터 바인딩과 '반응형 프로그래밍(Reactive Programming)'이라는 개념을 이해해야 해서 처음 배울 때 조금 어려울 수 있어.
2. 과도한 설계 (Overkill): 아주 간단한 화면에 MVVM을 적용하면, 오히려 배보다 배꼽이 더 커지는 경우가 생길 수 있어. 간단한 기능인데도 뷰, 뷰모델 파일을 따로 만들고 데이터 바인딩을 설정하는 게 불필요한 작업이 될 수 있다는 거지.
3. 디버깅의 어려움: 데이터 바인딩은 편리하지만, 문제가 생겼을 때 데이터의 흐름을 추적하기가 까다로울 수 있어. "대체 이 값이 어디서 바뀐 거지?" 하고 헤맬 때가 종종 생겨.

🤔 요즘 대세는 MVVM!

MVVM은 현재 모바일 앱 개발의 '표준' 아키텍처라고 불릴 만큼 널리 사용되고 있어.
구글에서는 안드로이드 Jetpack 라이브러리를 통해 `ViewModel`, `LiveData`, `Data Binding` 등 MVVM을 구현하기 위한 도구를 공식적으로 지원하고 있고,
애플 역시 SwiftUI 프레임워크를 발표하면서 데이터 바인딩을 기본으로 하는 선언형 UI 방식을 채택했기 때문에 MVVM 패턴과 찰떡궁합을 자랑해.
웬만한 규모의 상용 앱을 만든다면, MVVM은 가장 먼저 고려해야 할 안정적이고 강력한 선택지야.

Chapter 3: 가장 진화한 형태 - MVI (Model-View-Intent)

MVC가 질서를 만들고, MVVM이 역할을 분리했다면, MVI는 여기에 '예측 가능성'과 '단방향 데이터 흐름'이라는 강력한 무기를 더한, 가장 현대적인 아키텍처 패턴이야.
MVI는 Model-View-Intent의 약자인데, 이름에서부터 뭔가 '의도'가 중요해 보이지? 😉

MVI의 핵심 철학은 이거야.
"앱의 상태(State)는 오직 한 곳에서만 관리하고(Single Source of Truth), 상태는 오직 하나의 방향으로만 흐른다(Unidirectional Data Flow)."
이게 무슨 말이냐고? 쉽게 말해, 데이터가 앱 안에서 제멋대로 돌아다니며 상태를 바꾸는 걸 원천 차단하고, 정해진 고속도로로만 다니게 해서 교통사고(버그)를 막겠다는 강력한 의지야.

MVI, 너의 정체는? 🤖

MVI는 기존 패턴들과 용어의 의미가 조금씩 달라서 집중해야 해.

1. 모델 (Model) or 상태 (State) 📦:
MVI에서 모델은 '데이터'가 아니라, '뷰의 현재 상태' 전체를 나타내는 단 하나의 객체(Single State Object)를 의미해.
예를 들어, 로그인 화면의 상태라면 `isLoading(로딩 중인지)`, `userName(사용자 이름)`, `password(비밀번호)`, `errorMessage(에러 메시지)` 같은 모든 정보를 담고 있는 하나의 데이터 클래스인 거지.
가장 중요한 특징은 이 상태 객체는 '불변(Immutable)'이라는 거야. 즉, 한번 만들어지면 절대 내부의 값을 바꿀 수 없어. 상태를 바꾸려면, 기존 상태 객체를 복사해서 바꿀 부분만 수정한 '새로운' 상태 객체를 만들어야 해.

2. 뷰 (View) 🖼️:
MVVM의 뷰보다도 더더욱 멍청해졌어. MVI의 뷰가 하는 일은 딱 두 가지야.
- 상태를 화면에 그리기 (Render State): MVI 코어(비즈니스 로직)가 "현재 상태는 이거야!" 하고 상태 객체를 던져주면, 뷰는 그 상태를 보고 화면을 그리기만 해. 로직? 고민? 전혀 없어. 그냥 기계처럼 그릴 뿐.
- 사용자의 의도를 전달하기 (Emit Intent): 사용자가 화면을 터치하거나 텍스트를 입력하면, 뷰는 "유저가 로그인을 '의도'하고 있어!", "유저가 아이디를 '입력하려는 의도'가 있어!" 와 같이 사용자의 행동을 '의도(Intent)'라는 객체로 만들어서 MVI 코어로 전달해.

3. 인텐트 (Intent) ✉️:
안드로이드 개발자들이 아는 그 `startActivity`의 인텐트가 아니야! 여기서 인텐트는 '사용자의 행동에 대한 의도'를 나타내는 객체야.
`LoginButtonClickIntent`, `EmailInputChangedIntent` 처럼, 사용자가 무엇을 하려고 하는지를 명확하게 표현하는 명령어 객체라고 생각하면 돼.

멈추지 않는 수레바퀴: MVI의 단방향 데이터 흐름 🔄

MVI는 아래와 같은 끝없는 순환 고리로 동작해.

(1) 사용자가 뷰에서 어떤 행동을 한다. (예: '새로고침' 버튼 클릭)
(2) 뷰는 이 행동을 `RefreshIntent` 라는 '인텐트' 객체로 변환해서 MVI의 비즈니스 로직 부분으로 보낸다.
(3) 비즈니스 로직(ViewModel, Presenter, Reducer 등 다양한 이름으로 불림)은 이 인텐트를 받아서 처리한다. (예: 서버에 데이터 요청)
(4) 로직 처리 결과에 따라, 현재 상태를 기반으로 '새로운 상태(State)' 객체를 만든다. (예: `isLoading`을 `true`로 바꾼 새 상태 객체 생성)
(5) 이 새로운 상태 객체를 뷰에게 전달한다.
(6) 뷰는 새로운 상태 객체를 받아서 화면을 다시 그린다. (예: 로딩 스피너를 보여준다)
(7) 그리고 다시 (1)번으로 돌아가 다음 사용자 입력을 기다린다.

이 흐름을 보면 데이터가 [View → Intent → Model(State) → View] 라는 한 방향으로만 계속 순환하는 걸 볼 수 있어. 데이터가 옆길로 새거나 역주행하는 일이 절대 없지. 이게 바로 MVI의 핵심인 '단방향 데이터 흐름(Unidirectional Data Flow)'이야.

MVI 패턴의 단방향 데이터 흐름 (Unidirectional Data Flow) 🖼️ View 상태를 렌더링 ✉️ Intent 사용자 의도 📦 Model (State) ⚙️ Logic (ViewModel/Reducer) 2. Intent 생성 3. Intent 처리 4. 새 State 생성 5. View 렌더링 1. 사용자 액션

MVI, 너의 필살기는 뭐야?

👍 장점 (Pros):

1. 예측 가능성과 디버깅 용이성: 상태는 오직 하나의 원인(Intent)에 의해, 하나의 로직을 거쳐서만 변경돼. 그래서 버그가 발생했을 때, 어떤 인텐트가 들어와서 어떤 상태 변화를 일으켰는지 로그를 추적하는 것만으로도 원인을 찾기가 매우 쉬워. '타임 트래블 디버깅(Time-travel debugging)'이라고 해서, 상태 변화의 역사를 되돌려보며 버그를 잡는 것도 가능해. 🕵️‍♂️
2. 상태 관리의 단순함 (Single Source of Truth): 앱의 모든 상태가 단 하나의 객체에 담겨있기 때문에, 더 이상 "이 데이터는 저기서 가져오고, 저 데이터는 여기서 가져와야지" 같은 복잡한 고민을 할 필요가 없어. 뷰는 그냥 최신 상태 객체 하나만 바라보면 돼.
3. 스레드 안전성 (Thread Safety): 상태가 불변(Immutable)이기 때문에, 여러 스레드에서 동시에 상태에 접근해도 데이터가 꼬일 걱정이 없어. 복잡한 동시성 처리가 필요한 앱에서 매우 강력한 장점이야.
4. 선언형 UI와의 완벽한 조화: Jetpack Compose나 SwiftUI처럼, 상태가 바뀌면 UI가 알아서 다시 그려지는 '선언형 UI 프레임워크'와 MVI의 철학은 완벽하게 일치해. 그래서 최신 기술 스택을 사용하는 프로젝트에서 MVI가 특히 각광받고 있어.

👎 단점 (Cons):

1. 많은 보일러플레이트 코드: 모든 사용자 행동을 인텐트로, 모든 화면 상태를 상태 객체로 만들어야 해. 간단한 기능 하나를 추가하더라도 만들어야 할 클래스와 코드가 많아서, 초기 개발 속도가 더딜 수 있어.
2. 가장 높은 학습 곡선: 단방향 데이터 흐름, 불변성, 반응형 프로그래밍 등 이해해야 할 개념이 가장 많아. 특히 함수형 프로그래밍에 익숙하지 않은 개발자에게는 꽤 어렵게 느껴질 수 있어.
3. 상태 객체의 복잡성: 화면이 매우 복잡해지면, 모든 상태를 담고 있는 단 하나의 상태 객체가 너무 거대해지고 관리하기 어려워질 수 있어.

💡 MVI 사용 설명서

MVI는 강력하지만 아무 때나 쓰는 만병통치약은 아니야.
- 사용자의 인터랙션이 많고, 실시간으로 변하는 복잡한 상태를 가진 화면 (예: 주식 거래 앱, 실시간 채팅 앱)
- 버그 발생 시 원인 추적이 매우 중요하고, 높은 안정성이 요구되는 앱
- Jetpack Compose, SwiftUI 등 선언형 UI 프레임워크를 사용하는 프로젝트
- 반응형 프로그래밍에 익숙한 팀
이런 경우에 MVI는 그 어떤 패턴보다 강력한 무기가 될 거야. ⚔️

Chapter 4: 그래서 뭘 써야 할까? - MVC vs MVVM vs MVI 최종 비교

자, 지금까지 세 명의 주인공 MVC, MVVM, MVI에 대해 자세히 알아봤어.
각자 태어난 배경도, 철학도, 장단점도 모두 다르지.
"그래서 결론이 뭔데? 내 프로젝트에는 뭘 써야 해?" 라는 질문이 머릿속에 맴돌 거야.
정답은 없어. '최고의 아키텍처'는 존재하지 않아. 오직 '상황에 맞는 최적의 아키텍처'만 있을 뿐이야.
마지막으로 세 패턴을 한눈에 비교하고, 어떤 상황에 어떤 패턴을 선택하면 좋을지 가이드를 제시해 줄게.

한눈에 보는 비교 테이블 📊

항목🏛️ MVC🎨 MVVM🔄 MVI
학습 곡선낮음 (가장 쉬움)중간 (데이터 바인딩 개념 필요)높음 (반응형/함수형 개념 필요)
데이터 흐름양방향 (복잡)양방향 (데이터 바인딩)단방향 (예측 가능)
상태 관리분산됨 (컨트롤러, 뷰 등)ViewModel에 집중단일 불변 상태 객체
테스트 용이성낮음 (View와 Controller 결합)높음 (ViewModel 단위 테스트 용이)매우 높음 (순수 함수 로직)
코드량 (보일러플레이트)적음중간많음
주요 특징직관적, 빠른 개발역할 분리, 테스트 용이성예측 가능, 단방향 흐름
추천 프로젝트소규모, 프로토타입대부분의 상용 앱 (표준)복잡한 상태 관리, 높은 안정성 요구

나의 선택은? 상황별 추천 가이드 🧭

Scenario 1: "해커톤에 참가해서 2일 안에 앱을 만들어야 해요!"
➡️ MVC를 추천해. 지금은 복잡한 구조를 고민할 때가 아니야. 가장 익숙하고 빠르게 결과물을 만들어낼 수 있는 패턴이 최고야. 일단 완성하고, 나중에 리팩토링을 고민해도 늦지 않아.

Scenario 2: "취업을 준비 중인데, 포트폴리오용 앱을 만들고 싶어요."
➡️ MVVM이 정답에 가까워. 현재 업계 표준으로 가장 널리 쓰이는 패턴이기 때문에, MVVM으로 프로젝트를 구성했다는 것만으로도 '요즘 트렌드를 아는 개발자'라는 인상을 줄 수 있어. 테스트 코드까지 작성한다면 금상첨화!

Scenario 3: "팀 프로젝트로, 앞으로 2년 이상 꾸준히 업데이트해야 할 서비스를 만들어요."
➡️ MVVM 또는 MVI를 진지하게 고민해봐야 해. 팀원들의 숙련도와 프로젝트의 특성을 고려해야 해.
- 팀원들이 반응형 프로그래밍에 익숙하고, 앱의 핵심 기능이 복잡한 상태 변화를 다룬다면 MVI가 장기적으로 유지보수에 큰 도움이 될 거야.
- 그렇지 않다면, 가장 안정적이고 자료도 풍부한 MVVM이 좋은 선택이야. MVVM으로도 충분히 확장성 있고 유지보수하기 좋은 앱을 만들 수 있어.

결국 아키텍처를 선택하는 것은 기술적인 결정이면서 동시에 팀과 프로젝트의 미래를 위한 투자야.
혼자서 결정하기 어렵다면, 팀원들과 충분히 상의하고 각 패턴의 장단점을 공유하는 과정이 필수적이야.
만약 주변에 조언을 구할 전문가가 없다면, 재능넷 같은 플랫폼에서 경험 많은 시니어 개발자에게 코드 리뷰나 멘토링을 받아보는 것도 좋은 방법이 될 수 있어. 때로는 외부 전문가의 객관적인 시선이 막힌 길을 뚫어주기도 하거든.

마치며: 아키텍처는 목적이 아닌 도구다 🛠️

오늘 우리는 MVC라는 고전부터 MVVM이라는 표준, 그리고 MVI라는 최신 트렌드까지, 모바일 앱 아키텍처의 세계를 함께 여행했어.
어때? 이제 스파게티 코드를 마주했을 때, 어디서부터 어떻게 풀어가야 할지 감이 좀 잡히는 것 같아?

기억해야 할 가장 중요한 사실은, 이 패턴들은 우리를 괴롭히기 위해 존재하는 게 아니라는 거야.
오히려 복잡한 문제들을 더 쉽고, 체계적으로 해결할 수 있도록 도와주는 든든한 '도구'이자 '가이드'지.
어떤 패턴이 무조건 좋고 나쁘다는 흑백논리에 빠지지 말고, 내가 만들고자 하는 앱의 특성과 규모, 그리고 함께하는 팀의 역량을 고려해서 가장 적합한 도구를 선택하는 지혜가 필요해.

처음에는 새로운 패턴을 배우고 적용하는 게 어색하고 어려울 수 있어.
하지만 이 고비를 넘고 나면, 훨씬 더 안정적이고, 확장 가능하며, 동료들과 협업하기 좋은 코드를 작성하는 '클린 코더'로 성장한 자신을 발견하게 될 거야.
두려워하지 말고, 작은 토이 프로젝트부터 하나씩 적용해보는 건 어떨까?

자, 이제 당신의 손에 멋진 설계도들이 쥐어졌어.
이 설계도를 바탕으로 세상에 없던 멋진 집을 지어보길 바라! 🚀

댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0
댓글을 불러오는 중입니다.

아직 댓글이 없습니다.