들어가며
MVC 패턴을 적용해야 할 일이 생겼다. MVC에 대해서 아주 얕게만 알고 있었기 때문에 일단 정확히 개념을 잡고 개발하고 싶어서 구글링을 했는데, 뭔가 나오는 자료들이 묘하게 조금씩 다르다는 것을 알게 되었다. 객관적인 자료를 찾아보고 싶어서 좋아하는 전공책인 ‘헤드퍼스트 디자인패턴’ 책을 폈는데 또 책의 내용도 조금 다르더라. 그래서 어떤 것이 진짜 MVC 패턴인지를 찾기 위해서 여러 자료들을 찾아보고 의문들을 해결한 것들을 정리해보았다.
MVC 패턴
MVC 패턴은 1978-79년에 Smalltalk 관련 일을 하던 Trygve Reenskaug에 의해 고안된 패턴이다. Smalltalk-80에 MVC 패턴을 적용하는 방법을 설명한 논문이 아카이빙 되어있었다.
How to use Model-View-Controller (MVC)
모델, 뷰, 컨트롤러의 역할과 관계를 그림으로 그려보면 아래와 같다.
뷰는 모델을 필터링해서 사용자에게 보여주는 창이다.
컨트롤러에서는 사용자의 입력을 받아 해석하고 모델에게 상태 변경 요청을 하거나 (예 : “다음 곡을 재생해주세요.”) 또는 뷰에 모델 표시 방법 변경 요청을 한다. (예 : 페이지 스크롤을 내려주세요.)
모델이 관리하는 데이터의 상태가 변경되면 모델에서 뷰에게 그 사실을 알린다. 상태의 변경은 사용자의 요청에 의해서 발생할 수도 있고(예 : 다음 곡 재생 버튼을 누른 경우) 내부적인 변화로 인해서 발생할 수도 있다. (예 : 현재 곡 재생이 완료되어 다음곡이 재생됨.)
필요하다면 뷰에서 모델쪽으로 상태 정보를 요청할 수 있다. (예를 들면, 컨트롤러에서 뷰 변경을 요청했을 때 새로운 상태 정보가 필요한 경우, 모델로부터 받은 상태 변경 알림에 데이터 정보가 없는 경우, 등등)
MVC 패턴을 여러 개의 디자인 패턴이 합쳐진 컴파운드 패턴이라고 생각하면 3개의 각 컴포넌트가 어떤 책임을 가지고 있고 어떻게 연결되어 있는지 이해하기 쉽다.
뷰와 컨트롤러는 스트레티지 패턴으로 연결되어 있고 모델은 뷰와 컨트롤러 각각과 옵서버 패턴으로 연결되어 있다.
따라서 아래처럼 특징을 정리해 볼 수 있다.
- 뷰는 인터페이스에만 신경쓰고 컨트롤러에서 모든 비즈니스 로직을 처리한다.
뷰와 컨트롤러의 역할을 명확하게 분리하게 되면
- 뷰는 컨트롤러를 통해서만 모델에게 변경을 요청할 수 있으므로 뷰와 모델의 연결을 느슨하게 만들 수 있다. → 느슨한 연결은 유연하게 확장이 가능한 구조를 만든다!
- 비즈니스 로직을 분리할 수 있어 뷰의 코드를 보다 간결하게 만들 수 있다.
- 모델은 옵저버 패턴을 써서 다른 객체들에게 변경사항을 알린다. 따라서 모델은 뷰나 컨트롤러에 의존하지 않는다.
MVC 패턴 규칙 같은게 있을 줄 알았는데 공식적으로는 없는 것 같더라. 근데 종종 블로그 글에 “MVC 패턴 규칙” 이렇게 정리된 항목들이 등장하길래 출처를 찾아봤더니 아마 아래 링크한 테코톡 발표인 것 같다. (멋지다… 😲)
의문점과 해결
웹 프로그래밍에 MVC 패턴을 적용하면서 생긴 다른 방향의 해석들에 대해 조사하고, 나름대로 내린 결론들에 대한 이야기입니다.
객관적인 자료를 참고하려고 노력했지만 결론을 내린 사람은 초짜 개발자이기 때문에 (ㅜㅜ) 결론이 이상할 수 있음을 먼저 알립니다…
사용자는 view와 소통할 수 있다.
위에 설명했던 Smalltalk-80 MVC에서 사용자의 입력을 받는 주체는 컨트롤러였다. 뷰는 단순히 모델을 표현하는 역할만 하고 있었는데, 헤드퍼스트 디자인패턴 책을 비롯해서 몇몇 자료들(예: https://developer.mozilla.org/ko/docs/Glossary/MVC) 중에서는 뷰를 유저 인터페이스라고 소개하며 유저에게 닿는 입출력을 모두 뷰가 담당하는 것으로 나와 있는 것들도 많다.
이렇게 해석이 달라진 것은 MVC 패턴이 웹 어플리케이션에 적용되면서 데스크탑 어플리케이션에 적용되던 그대로 적용하기에 문제가 있었기 때문이라고 한다. 서버와 클라이언트가 나뉘었기 때문에 사용자의 입력을 서버 측에 있는 컨트롤러가 받기 힘들어진 것이다.
The problem with using the MVC design pattern to develop web-applications arises from the fact that web applications are intrinsically partitioned between the client and the server.
A. Leff and J. T. Rayfield, "Web-application development using the Model/View/Controller design pattern," Proceedings Fifth IEEE International Enterprise Distributed Object Computing Conference, Seattle, WA, USA, 2001, pp. 118-127
위키백과에서는 1996년에 출시된 자바 기반 서버 개발 프레임워크인 WebObjects 를 예로 들고 있다. Webview Overview 문서에서 뷰를 사용자 인터페이스로 설명하고 있긴 한데, 딱 이정도의 설명 뿐이라 또 다른 참고자료로 언급된 마틴 파울러의 Patterns of Enterprise Application Architecture 의 MVC 부분만 발췌해서 읽어보았는데 놀랍게도 거의 모든 Smalltalk가 실제로는 뷰와 컨트롤러를 거의 구분하지 않았다고 한다. (왠지 배신감..이 드네요…)
Indeed, the irony is that almost every version of Smalltalk didn't actually make a view/controller separation.
Fowler, Martin (2003). Patterns of Enterprise Application Architecture. Pearson Education
또 마틴 파울러에 의하면 MVC 패러다임의 분리된 관계들 중에서 중요한 것은 프레젠테이션과 모델을 분리하는 것에 있기 때문에,,, 개인적 입장으로는 MVC의 시작에서는 사용자 입력을 컨트롤러에서 받아 처리하도록 했지만 컨트롤러에서 받던 뷰에서 받던 더 유용한 방식을 택하면 되지 않을까 하는 생각이다.
As I think about MVC I see two principal separations: separating the presentation from the model and separating the controller from the view. Of these the separation of presentation from model is one of the most fundamental heuristics of good software design. This separation is important for several reasons.
Fowler, Martin (2003). Patterns of Enterprise Application Architecture. Pearson Education
컨트롤러는 모델과 뷰를 연결할수도 있다?
새삼스러운 말이긴 하지만 컨트롤러는 모델과 뷰 사이에 존재한다.
내가 의문을 품었던 부분은 모델의 변화를 뷰가 업데이트하는 과정이었는데, Smalltalk-80 MVC에서는 뷰가 모델의 변화를 감지해서 화면을 업데이트하지만 WebObjects의 MVC에서는 컨트롤러를 사이에 두고 모델과 뷰가 소통한다. 모델이 직접 뷰를 업데이트하는 과정이 없는 것인데, 이 역시도 웹 어플리케이션의 특성으로 설명이 가능할 것 같다. 클라이언트의 뷰가 서버에 있는 모델을 구독한다는 것이 구조적으로 어렵기 때문에 이 한계를 극복하기 위해서 컨트롤러를 둘 사이의 중재자로 만든 것이라고 한다. (이런 구조를 MVA 라고 한다네요!)
2.5.1 Model-View-Adapter (MVA, Mediated MVC, Model-Mediator-View) -
내 생각 정리
MVC 패턴 자체에는 엄격한 규칙이 없기 때문에 이 패러다임이 여러 곳에 적용되면서 다양한 파생 패턴들이 생겨난 것 같다. 어떤 것이 “진정한 MVC 패턴일까?”를 찾아보려고 이런저런 자료들을 읽어보다가 나름대로 내린 결론은 MVC 패턴의 목적은 어쨌거나 관심사를 분리하고 기능들을 모듈화해서 유지보수가 편리한 구조를 만들기 위한 것이기 때문에 프로그램을 특성을 반영하느라 변형이 좀 있어도 MVC의 3가지 요소들을 잘 활용해서 그 목적을 달성했다면 MVC 패턴을 잘 적용한게 아닐까… 하는 생각을 했다…
아직까지도 정답이 뭔지는 잘 모르겠지만 누군가 Model과 View 사이에 Controller를 두는 구조로 짠 다음에 MVC 패턴을 적용했다고 말했다고 해서 ‘이건 진정한 MVC 패턴이 아니다!!’ 하고 말하기에는
⬇️ 이것도 MVC 패러다임을 적용한 것이고
⬇️ 이것도 MVC 패러다임을 적용했다고 할 수 있으니까..?!
근데 아무리 생각해도 프론트엔드에서 MVC 패턴을 쓰기에는 좀,,, 안어울리는 것 같다는 느낌을 가지고 있었는데 유튜브 알고리즘에 딱 아래 영상이 뜨더라.
심지어 혹자는 죽었다고까지 표현한다…
나중에 실제로 프론트엔드에 디자인 패턴을 적용할 일이 생기면 그때 가서 또 깊은 생각을 해보게 되지 않을까 싶다.