M-V-C가 서로의 영역을 전혀 침범하지 않고 개발하는 것이 과연 가능한가?

myPassion의 이미지

얼마전부터 디자인 패턴을 공부하고 있는 PHP개발자 입니다.

MVC패턴이라는것이 있고 이것이 수도없이 날아드는 디자인 변경요구에 대해 개발자의 삶을 정말 편하게 만들어줄 만한 패턴이라는 이야기를 들었습니다.

하지만 MVC패턴을 처음으로 접해본 저로서는 몇가지 궁금한 사항이 생겼는데요..

그중 하나는 Model과 View, 그리고 Controller가 서로의 영역을 전혀 침범하지 않고 개발하는 것이 과연 가능한가? 입니다.

달력(table)을 이용한 일정관리 프로그램을 예로 들어보면,

우선 달력이므로 table태그를 사용하기로 하고,

<table>

</table>

한달은 4~5주 이니깐
<tr></tr>이 테이블 사이에 들어갈 것이고,

한 주는 7일이므로 7개의 <td></td>가 tr사이에 들어갈 겁니다.

그리고 td사이에는 1~31까지의 날짜와 일정등이 들어가게 되겠지요.

그렇다면, td안의 내용을 불러와 채워주는 것은 모델의 몫일 것이고, <table><tr><td>를 그려주는 것은 뷰의 몫일 겁니다.

두가지 정도의 방법을 생각하고 있는데,

첫번째는 table을 열고 닫는 것까지 모델에서 string으로 저장시켜 컨트롤러를 거쳐 뷰에 까지 보내주는 방법과

두번째는 뷰에서 모델의 일정을 불러주는 메소드 호출을 하는 방법입니다;

첫번째 방법은 뷰와 모델의 기능적인 충돌이 일어나고, string이 모델->컨트롤러->뷰를 거쳐가면서 퍼포먼스가 떨어지게 될겁니다.

두번째 방법은 뷰가 모델을 알고 있는것은(레퍼런스를 가진다는 것은) MVC원칙에 위배되지 않나 하는 것이 제 생각입니다.

위 두가지 방법을 한번에 날려버릴만한 세번째 방법이라는게 과연 있을지, 아니면 다른 분들은 첫번째와 두번째 사이에서 어떤 방법을 택하실지 궁금합니다.

요즘 뷰와 모델의 싸움 사이에서 객체지향원칙을 지키지 못하고 있다는 양심의 가책을 많이 느끼고 있습니다. 좋은 답변을 기다립니다.

(원래 그렇게 해요! 라는 답변이라도 주신다면; 제 양심에 조금은 덜 찔릴것 같네요;;)

그리고 MVP패턴이라는 것도 있다는 것 같고, MODEL2라는 패턴도 있다는 것 같은데, 좋은 한글 Article이 있다면 소개해 주시면 감사하겠습니다.
예제코드는 자바여도 상관 없습니다. ^^;

긴글 읽어주셔서 감사합니다.

1day1의 이미지

뷰에서 날짜,일정등의 처리된 값(모델)을 받아서 처리하도록 하면 되지 않을까요?

모델에서 이미 처리된값이므로, 뷰와 모델이 서로 충돌하지는 않을 것 같네요.

F/OSS 가 함께하길.. (F/OSS서포터즈,F/OSS서포터즈그룹)

F/OSS 가 함께하길..

myPassion의 이미지

그렇겠네요;

지금까지 쉽게 스트링을 만들어내는 방법만 생각해냈는데.. 대신 오브젝트를 처리하는 부분을 추가해서 돌려주면 되겠군요 ^^

감사합니다 ^^;

--------------------------------
http://www.elegantcoder.com

semmal의 이미지

뷰가 모델을 알고 있으면 MVC모델에서는 잘못된 것이 맞습니다.

그리고, 설계는 원래 퍼포먼스보다 유연성에 중점을 둬야 하는걸로 알고있습니다.
완성된 모양이 나오기 전까지는 마음대로 만질정도의 유연성이 갖춰지고,
모양이 갖춰진 다음에 퍼포먼스에 신경쓰는 것이 맞을겝니다.

굳은 찰흙으로는 맘대로 만들기는 아무래도 힘들겠지요.
물렁한 찰흙으로 만들고 굳히는 편이 더 좋다고 봅니다.

------------------------------
How many legs does a dog have?

kall의 이미지

로직과 뷰의 분리는 템플릿을 사용하면 쉽게 익히실 수 있습니다.

----
자신을 이길 수 있는자는
무슨짓이든 할수있다..
즉..무서운 넘이란 말이지 -_-
나? 아직 멀었지 ㅠㅠ

----
자신을 이길 수 있는자는
무슨짓이든 할수있다..
즉..무서운 넘이란 말이지 ^-_-^
나? 아직 멀었지 ㅠㅠ

myPassion의 이미지

템플릿 사용은 하고 있는데..
템플릿 사용하면서 새로운 고민이 생겼어요.
제로보드 스킨과 같은 유연성(?.. 하드코딩)을 포기하고 설계에 비중이 높아지다보니
지긋지긋한 그놈의 '요구사항' 변동에 따라 상당히 힘들게 왔다갔다 하는 중입니다.

애자일이나 XP를 좀 더 공부해야 하는데.. 개발자의 길은 너무 험난해요.

--------------------------------
http://www.elegantcoder.com

7339989b62a014c4ce6e31b3540bc7b5f06455024f22753f6235c935e8e5의 이미지

PHP를 쓴다면 PHP 자체가 이미 하나의 '템플릿 엔진' 이기 때문에, 따로 템플릿 엔진이 필요하다고 생각하지는 않습니다.

sh.의 이미지

그런 점을 지적하시는 분도 많기는 합니다만
템플릿으로서의 기능만 있는게 아니라
html 사이사이에 코드를 넣다보면
해서는 안될 일도 자꾸 하게되고 그렇지요...

사실 smarty같은 컴파일형 템플릿 엔진들은
템플릿 코드를 php코드로 변환을 합니다.

narusas의 이미지

잘 이해가 안가시면 아래처럼 생각하시면 조금더 쉬워 지실겁니다.

C - Input
M - Caculation
V - Output

예를 들어 달력을 만드신다면
사용자의 입력을 받아 Model을 건드리는 부분이 Controller
실제 데이터를 관리하는 부분이 Model
Model을 HTML로 만들어 내는 부분이 View
이니까

DiaryController.php
DiaryView.php
Diary.php (model)

정도로 구분하시면 됩니다.

처음부터 객체지향으로 생각하시는것보다는 역활(Role)적으로만 확실한 분리를 해주는게 더 이해하기 쉬우실겁니다.

narusas의 이미지

대충 짠겁니다.

Model

class Diary {
String name;
Date time;
}

class DiaryFacade {
public void addDiary(Diary diary) { //DB에 추가..... }
public void removeDiary(Diary diary) { //DB에 제거..... }

public Diary[] getDiaries() {// DB에 있는 Diary 몽땅 얻어오기 ....}
public Diary getDiary(Date time) {{ // DB에서 해당 날짜의 Diary얻어오기 ...}
}

Controller (/diaryController로 등록됨...)

class DiaryController extends HttpServlet {
DiaryFacade facade;
public void doPost(HttpServletRequest req, HttpServletResponse) {
if ("WRITE".equasl(req.getParameter("COMMAND")) {
Diary d = createDiary(req);
facade.addDiary(diary);
}
else if ("DELETE".equasl(req.getParameter("COMMAND")) {
Diary d = createDiary(req);
facade.removeDiary(diary);
}
getDispatcher().forward(req.getParameter("comeback"));
}

/** Request를 기반으로 Diary 객체 생성 */
Diary createDiary(HttpServletRequest req) {....}
}

View

diary.jsp

무슨 이유인지..제대로 코드가 않나오네요..
아무튼 controller serlvet을 먼저 호출한 이후에, 사용자의 요청에 맞는 diary를 HTML Rendering하는 JSP 코드였습니다.

cleol의 이미지

Quote:

뷰가 모델을 알고 있으면 MVC모델에서는 잘못된 것이 맞습니다.

제가 알고 있는 것이 맞다면 모델이 뷰를 몰라야지 뷰가 모델을 모를 수는 없습니다.
뷰가 모델에 대한 레퍼런스를 가지고 있지 않으면 어디서 어떻게 데이터를 가져와서 화면에 뿌려줄까요?
프리젠테이션 모델과 도메인 모델을 분리할 경우에도 뷰가 도메인 모델을 모르는 것은 맞지만 프리젠테이션 모델을 알고 있어야 합니다.

그리고 사실 모델 역시 뷰를 전혀 모를 수는 없습니다. 다만 "내가 가진 데이터에 관심 있는 녀석" 이라는 개념으로만 알고 있는 것이지요.
모델에서 데이터 변경 같은 이벤트가 일어났을 경우 이벤트에 관심 있는 녀석들에게 알려주기 위해서는 역시 그 녀석들의 레퍼런스를 가지고 있어야만 합니다.
데스크탑 GUI라면 이를 위해 옵저버 패턴을 사용하겠지만 웹에서는 뷰와 모델 사이에 옵저버 패턴을 구현하기가 어렵기 때문에
보통 모델은 뷰를 전혀 모르고 컨트롤러가 대신 모델과 뷰를 연결해 줍니다.

저는 웹에서는 굳이 Model, View, Controller 라는 개념보다는
"프론트 엔드", "비지니스 로직", "프리젠테이션 로직", "템플릿" 개념을 가지고 생각하는게 좋다고 봅니다.

전체적인 제어 흐름은 프론트 엔드가 담당합니다. 프론트 엔드는

1. 웹의 특성과 관련된 처리를 한 다음(URL 파싱, 세션 관리 등등)
2. 비지니스 로직을 호출한 후(DB 업데이트, 기타 등등)
3. 프리젠테이션 로직을 호출하고 (DB 에 select 질의, 데이터 가공)
4. 프리젠테이션 로직이 반환한 데이터를 템플릿에 전달합니다.(html 생성)

프론트 엔드가 전체적인 흐름을 조절하므로 예외나 에러는 항상 프론트 엔드로 전달되어야하고, 예외/에러의 최종적인 처리는 프론트 엔드가 합니다.
프론트 엔드가 커맨드 패턴을 구현하면 좋습니다. 커맨드는 2,3,4 에 사용될 구체적인 구현체들을 엮어주는 역할을 합니다.

자바라면, 프론트 엔드로 하나의 서블릿을 사용하고 커맨드는 하나 하나가 별도의 클래스로 작성될 겁니다.
비지니스 로직은 별도의 라이브러리나 패키지로 분리하고 가능하다면 커맨드가 비지니스 로직의 상세한 부분을 최대한 모르도록 퍼서드를 사용하는 것이 좋습니다.
(비지니스 로직이 복잡하지 않고, 오로지 웹을 통해서만 사용자 인터페이스가 제공되는 것이 확실할 경우에는 비지니스 로직을 분리 구현하지 않고 그냥 커맨드에서 로직을 구현하는 것도 나쁘지 않다고 생각합니다.)
템플릿은 jsp, velocity 등을 사용하면 됩니다.

다즐링의 이미지

http://en.wikipedia.org/wiki/Model-view-controller

MVC 패턴에서는

Controller 가 모든걸 제어합니다. ( view , model )

View 는 이벤트 트리거일뿐입니다.

View 가 Model 을 안다면 OOP 디자인에 맞지 않습니다.

정확하게 다시 말한다면.. MVC1 에서는 뷰가 모델을 아는게 맞습니다.

그런데 MVC2 에서는 분리가 확실하게 되어야합니다.

스트러츠에서는 1,2 둘다 쓸수가 있습니다.

PHP 에서 2를 제대로 구현하려면 php5가 되어야 될것 같군요.

(링크를 확인해보니 저기 있는건 MVC1 인거 같군요 -_-;; )

------------------------------------------------------------------------------------------------
Life is in 다즐링

죠커의 이미지

Quote:
View 가 Model 을 안다면 OOP 디자인에 맞지 않습니다.

정확하게 다시 말한다면.. MVC1 에서는 뷰가 모델을 아는게 맞습니다.

그런데 MVC2 에서는 분리가 확실하게 되어야합니다.

스트러츠에서는 1,2 둘다 쓸수가 있습니다.

PHP 에서 2를 제대로 구현하려면 php5가 되어야 될것 같군요.

엄밀하게 말한다면 MVC 1, MVC 2가 아니라 자바 진영의 Model 1, Model 2겠지요. Model 2역시 View가 Model을 알고 있습니다.

javaworld의 도해을 보시면 Model2는 일반적으로 Servlet 등을 중간에 도입해서 Controller로 맡기는 것을 볼 수 있습니다. (Controller 제작이 자바에서는 상대적으로 overhead가 많기 때문에 많은 프레임워크를 나온 것으로 판단됩니다.) 그리고 영속적인 객체를 이용하여 Model을 전달하고 View는 그것을 이용하고 있습니다. 따라서 View가 Model을 모른다는 것은 사실이라고 보긴 힘듭니다.

웹 어플리케이션의 View가 Model을 아는 것이 옳다고 생각합니다. Model이 제공하는 데이터를 어떻게 가공하느냐는 전적으로 View의 몫이니 모르는게 이상한 것이라고 생각합니다.

PHP는 영속적인 객체를 생성할 수 없으니 include, require등을 사용해서 콘트롤러가 바로 model과 view를 불러와야겠지요. 이 부분만 유의하면서 JSP Model2를 참고하시면 도움이 되실 겁니다.

- CN의 낙서장 / HanIRC:#CN

bichi의 이미지

사실상 MVC 정답은 없지 않을까 생각합니다.
모델이 broadcast하며 같이보낸 정보만 활용해서 view가 구성될 수 있고
broadcast 한 Model 찾아가서 Model을 알고 정보를 빼갈 수도 있는 것.
정보를 일일이 보낸다면 조금더 자원을 쓰겠지만 독립적이 겠고.
view가 정보를 빼간다면 자원들 아끼겠지만 독립적이지 못하겠지요 ...

항상 패턴이 옳다고 한다는 것은 발전에 뒤쳐지는 것이 아닐까 ... 생각합니다..

semmal의 이미지

요즘 괜히 다굴 맞는다는 기분이 드는군요.

------------------------------
How many legs does a dog have?

------------------------------
How many legs does a dog have?

AnonymousOS의 이미지

xml(데이터) + xslt(표현) 를 사용하세요

익명 사용자의 이미지

어렵게 생각하지 말고, 앱의 요소가 3 구룹이 있는데 각 이름하여
C, M, V인데 M은 공장역이고 V는 영업장역인 거라, 사실 C는 부로커라
M과 V는 존재조차 서로 알면 안되는거라.왜냐하면 M,V가 서로 결탁하여
C를 물먹이면 안되니까. 그래서 C와 V는 단독으로 거래하고, C와 M
도 단독 거래하는 것이라. V가 상품을 요구하면 C에 오더하고, C는 M에
오더하고 그 생산물을 M또는 M의 하청공장(core의 기본 db I/O)에 두고
C에 열쇠를 넘기면, (모든것이 pointer)
AJAX인 경우 출하시켜 C에서 json스트링으로 가공(json_encode)하여 보내고
dynamic방식),
PHP view에서 사용시는 M에서 받은 열쇠를 V것이라고 전달($this->view->{열쇠})
하면 view의 내용에서 직접 access($this->{열쇠}) 하는 식으로 render
하여 그 결과가 응답 html을 타고 사용자 부라우저에 전달.
심지어 AJAX request의 요구마져 URL->접수계->라우터->C->M 흐름으로 진행.
느려진다는 의미는 필수불가결한 경로가 있으니까 아주 쪼금..가능성 유.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.