Introduction
어떤 practice가 보편화되어있고 그것을 보조하는 툴이나 생각의 장치들이 잘 만들어져있다면, 오히려 그 practice의 장점이 무엇인지 파악하는 데에는 방해가 되기도 한다. 어떻게 보면, 생산성을 높히고자 하는 우리의 노력이 때로는, 각 개인의 능력을 키우는 데에는 방해가 될 수도 있는 것이다.
예를 들어, 잘 만들어진 소프트웨어 프로세스 환경에만 익숙한 개발자는, 그러한 프로세스가필요없다고 주장하는 사람에게, 그것이 왜 필요한지 제대로 설명하지 못할 것이다.현대의 특정 프로그래밍 언어에만 익숙한 사람은, 자신이 활용하고 있는 수많은 언어적 장치들의 이점을 제대로 이해하고 있지 못할 가능성이 높다.
마찬가지로, 잘 만들어진 Model-View-Controller(이하 MVC) 프레임워크에만 익숙한 사람이라면, 그 패턴이 가지고 있는 유용성이나 의미를 발견하지 못할 가능성이 높다. 대부분의 웹어플리케이션 개발자들은, 프리젠테이션과 로직이 뒤섞인 기존의 웹어플리케이션에만 익숙하거나, MVC 프레임워크 웹어플리케이션에만 익숙하다. 기존의 웹어플리케이션이 MVC를 사용함으로써 어떤 점에서 좋아질 수 있는지는 전자나 후자의 프로그래머들 모두 알지못할 가능성이 높다.
이 글의 목적은 기존의 웹어플리케이션에 MVC 패턴을 적용하면서 리팩토링하는 과정을 보임으로써, MVC 패턴의 유용성을 재발견하는데 있다.
Refactoring Galaxy admin part
Galaxy Iteration 3에서는 그동안 자잘하면서도 중요한 기능들을 계속 추가해왔는데, 어느 정도 완료가 되었다고 생각되어, Galaxy의 admin part를 refactoring 하기 시작했다. Galaxy의 주 페이지는 정보를 보여주고 기껏해야 filtering하는 정도의 기능밖에 가지지 않았기 때문에, 단순했지만, admin part에 해당하는 admin 페이지는 수많은 기능들을 가지고 있고, 여러가지 정보를 보여주어야 하기 때문에 비교적 복잡한(적어도 이 글의 목적에 부합할만큼) web application 이라고 볼 수 있다.
Iteration 3까지 기능들을 추가해오면서, admin part은 admin.rb라는 하나의 파일에 담기게 되었다. CS 학부생이 심심해서 만들어보는 전형적인 CGI 페이지의 형태로 구현되어있다. 다음의 pseudo code를 보면 약간 감이 올지 모르겠다.
case cgi[‘mode’]
when “add_subscription”
add subscription
when “remove_subscription”
remove subscription
when “add_category”
add category
when “update_feeds”
update feed
when “set_category”
set category
end
render form to add subscription
render subscription list & forms to change category for each subscription
render form to add category
render forms to update feeds
여러가지 정보를 보여주기 위한 코드들과 그 정보들을 수정하기 위한 html form들이 주를 이루고, 코드의 위쪽에서는 그 form들로부터 POST된 operation들을 처리하기 위한 코드들이 위치하고 있다.
Extracting Views
이러한 상황에서, 일단 내가 필요로 하는 admin 페이지를 디자인 했다. 기존의 페이지는 모든 정보들이 한 페이지에 담겨 있는 형식이었지만, 새로운 인터페이스에서는 보여주는 정보들의 종류와 그것을 다루는 인터페이스(form)을 한데 묶음으로써, 좀 더 사용성을 높혔다. 설명의 이해를 위해서 디자인들을 비교해 보이고 싶으나, 종이에 디자인을 한 관계로, 생략하겠다.
이 디자인을 통해서, 5가지의 페이지 형태가 나오게 되었는데, 다음과 같다.
- Galaxy의 전체 설정 리스팅과 이를 수정할 수 있는 인터페이스
- Subscription을 추가하는 인터페이스와 Subscription의 리스트, 각 Subscription에 대한 수정 페이지로의 링크
- Category를 추가하는 인터페이스와 Category의 리스트, 각 Category에 대한 수정 페이지로의 링크
- 모든 Feed를 업데이트하기 위한 인터페이스
- 특정 Subscription의 정보를 리스팅하고 이를 수정할 수 있는 인터페이스
- 특정 Category의 정보를 리스팅하고 이를 수정할 수 있는 인터페이스
이들 페이지는 서로 충분히 독립적이다. admin 페이지의 디자인이 정보의 분리를 원칙으로 했기 때문이다. 따라서, 각 페이지를 그리는 코드를 각각의 module로 만드는 것이 당연해 보인다. 사실, admin.rb는 적절한 decomposition이 이루어지지 않은 너무나 거대한 module이었던 것이다.
바로 이 때, MVC pattern이 개입한다. 각 페이지를 그리는 코드는 각각 하나의 View에 해당한다. MVC pattern에서 설명하는 View의 역할을 적어보면,
- Renders the models
- Requests updates from models
- Sends user gestures to controller
- Allows controller to select view
과 같다. 각 페이지들이 하는 역할이 바로 Subscription이나 Category와 같은 entity들(Model)을 그리거나, 사용자의 의도를 (인터페이스를 통해) 이를 처리하는 다른 코드(Controller)에 전달하는 역할 아닌가!
자, 각각의 View를 SubscriptionListView, SubscriptionView, CategoryListView, CategoryView, UpdateFeedView와 같은 class로 구현하였다.
모든 View class들은 render method를 가지고, SomeView.new.render를 수행하면, 해당 View를 그리는 코드가 수행된다. 차후에 render method를 가지는 View의 abstraction을 추가할 수 있을 것이다.
class SubscriptionListView
def render
…
end
end
특히, View를 그리기 위해서 추가적인 정보가 필요한 경우가 있는데, 이를 위해서 render에 parameter를 추가하기 보다는 다음과 같이 생성 메서드 initialize를 따로 구현해준다.
class SubscriptionView
def initialize(subscriptionID)
@subscriptionID = subscriptionID
end
def render
…
end
end
View는 sub-View들과의 hierarchy를 유지하면서, sub-View들을 그리는 것에도 책임이 있는데, 지금은 이러한 것들은 무시하자. 현재의 디자인에서 아직은 sub-View의 필요가 충분히 드러나지 않았다.
(Will be continued…)
분리의 미학 (1) MVC 패턴과 Rails
이 글에서는 Rails의 근간을 이루는 MVC 패턴을 소개하고 Rails에 어떻게 적용되었는지 살펴봄으로써 Rails 어플리케이션이 구동되는 원리를 살…..