MVC(Model-View-Controller) 패턴은 웹 응용 프로그램의 구성 요소를 모델, 뷰, 컨트롤러 3가지 구성요소로 분리하는 아키텍처 설계 원칙이다.
분리된 각 부분에 대해서 개발, 수정, 테스트를 보다 쉽게 할 수 있도록 하기 위함이라고 보면 되며
System.Web.Mvc 어셈블리에 정의되어 있다.
ASP.NET의 MVC는 ASP.NET 프레임워크의 일부로
제공이 되는데, ASP.NET MVC3를 설치하면(VisualStudio 2010을 설치하면 MVC2까지 밖에 없다.)
ASP.NET의 Web Form 대신 ASP.NET MVC 응용 프로그램을 개발할 수 있다.
하지만 이 MVC라는것이 Razor등 View Engine의 종류가 많긴하지만 Web Form 자체를 대체하는 목적은 아닐것이다.
Routing Engine만 쓰고, Web Form을 쓰는것이 편하긴 하던데....입맛에 맞게 골랐쓰도록 하자.
Web Form과 MVC
Web Form | MVC |
---|
Server-Based Form을 이용하기 때문에 MVC보다는 나름 적은 코딩양으로 구현 | Model, View, Controller로 나뉘어 있어, 비교적 관리 편함 |
HTTP State를 컨트롤 가능, 이벤트를 통해서 보다 세부적으로 컨트롤 가능 | View, State등을 몰라도 되므로, 나름 편함 |
Page에 컨트롤(Server-Based Form)을 추가하므로써 기능을 추가(페이지 컨트롤러 패턴) | Controller와 함께 URL Routing 이용가능(프런트 컨트롤러 패턴) |
MVC 프레임워크의 기능
- .NET Framework와 호환되는 모든 단위 테스트 프레임워크를 사용할 수 있습니다.
- 기능 확장 또는 기능 추가 용이.(View 엔진을 바꾼다던지, 라우팅 정책을 바꾼다던지 하는 것이 용이, DI(Dependency Injection) 및 IOC(Inversion of Control) 컨테이너 모델의 사용가능)
DI, IOC같은 패턴은 Enterprise Library를 보면 됨.
- 쉽게 URL Routing기능 지원( SEO(Search Engine Optimization) 및 REST(Representational State Transfer) 주소 지정 방식에 적합한 URL 이름 지정 가능)
- 기존 ASP.NET에서 제공하는 기능은 MVC에서도 사용가능
MVC 3 프로젝트를 생성하기 위해서는 Framework를 다운받아 설치해야 하는데,
설치하고 나면 아래와 같이 메뉴가 생성되어 있음을 볼 수 있다.
이렇게 생성된 구조는 아래와 같다.
기본적으로 생성된 폴더 구조를 살펴보면, ASP.NET과 같이, Script, Content와 같은 폴더도 있지만,
MVC에서 말하는 Model, View, Controller라는 단어에 s가 붙어있는 폴더들이 있음을 볼수 있는데, 여기에 소스를 만들게 된다.
각 기능들에 수동으로 추가해 줄 수도 있겠지만, 추가하고 싶은 기능에 마우스 오른쪽 버튼을 누르면 쉽게 추가 가능하다.
폴더 | 설명 |
---|
Content | CSS, image등 컨텐츠 파일 폴더 |
Scripts | Script 파일 폴더. ASP.NET AJAX Foundation 및 jQuery 라이브러리가 포함되어 있다. |
Models | DB등과 같은 데이터 모델을 나타내는 클래스관련 폴더, Entity및 DB와 관계된 코드를 포함함. |
Views | 뷰
에서 사용하는 ViewPage(.aspx), ViewUserControl(.ascx), ViewMasterPage(.master)
파일등과 같이 뷰 렌더링에 관련된 파일 폴더. 컨트롤러에서 View를 통하지 않고 직접 리턴하는 경우가 아니라면 여기에는 각
컨트롤러에 대응하는 폴더가 하나씩 있고 해당 컨트롤러 이름은 각 폴더 이름에서 접두사로 사용된다. HomeController라는 컨트롤러가 있으면 Views 폴더에 Home이라는 폴더가 포함된다. |
Controllers | MVC 프레임워크에서 모든 컨트롤러의 이름은 HomeController, LoginController 등과 같이 "Controller"로 끝나야 한다. |
App_Data | 생성되어 있지는 않지만 Web Form 페이지를 사용하는 ASP.NET 웹 사이트에서와 동일(웹폼을 이용할때 필요할 때가 있다.) |
기타 | - Global.asax 파일 : URL Route기본 코드 구성 - Web.config 파일 : 프로그램 환경설정 관련 코드 구성 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
routes.MapRoute(
"Default" ,
"{controller}/{action}/{id}" ,
new { controller = "Home" , action = "Index" , id = "" }
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
|
- 라우트 등록을 RegisterRoutes라는 함수로 왜 뺏느냐 하면..
- IIS에서 웹사이트를 만들때, Application Pool이 겹치는 경우가 있더라..->.NET4를 설치한다던지 해서, aspnet_regiis를 통해 iis에 등록해버렸더니 이미 꼬여있었음. 이럴경우 내사이트가 뻑난다고, 내가 잘못만들었나?라고 생각하기 전에, 내 사이트 말고, 다른 사이트의 Application Pool이 우리사이트의 Application pool로 바뀌어있나 함 물어볼것..
ASP.NET
MVC 기반에서 Request시 UrlRoutingModule(HTTP Module, Route Class참조:RouteBase
Class구현) 개체를 통해서, 시작하게 되는데 Request를 분석하고 그에 따른 Path를 선택한다.
- 일치하는 Path가 있을경우 Path 개체를 리턴해 주지만, 없을경우 아무런 작업도 수행하지 않음.
UrlRoutingModule object는 선택한 Route object(IRouteHandler)를 리턴하는데, MvcRouteHandler class의 인스턴스이다.
MvcRouteHandler(IHttpHandler 인터페이스를 구현) 인스턴스는 MvcHandler 개체를 만든다.
마지막으로 MvcHandler 개체는 요청을 최종적으로 처리할 컨트롤러를 선택한다.
- Request 처리 순서
1단계. 라우팅
UrlRoutingModule은 RouteTable에서 일치하는 Route object를 사용해 RouteData object를 만든다.
- RouteData는 RequestContext object를 만드는데 사용됨
2단계. MVC Request Hanlder 생성
MvcRouteHandler는 MvcHandler 클래스의 인스턴스를 만들고 RequestContext 인스턴스를 처리기에 전달.
3단계. 컨트롤러 생성
MvcHandler는 컨트롤러 인스턴스를 만드는 데 사용할 IControllerFactory object를 식별하는 데 RequestContext 인스턴스를 사용.
4단계. 컨트롤러 실행
MvcHandler 인스턴스는 해당 컨트롤러의 Execute 메서드를 호출.
5단계. 작업 호출
ControllerBase 클래스에서 상속한 컨트롤러의 경우 해당 컨트롤러에 연결된 ControllerActionInvoker 개체가 컨트롤러 클래스의 작업 메서드 중 호출할 메서드를 결정하고 해당 메서드를 호출.
6. 결과 실행
작업 메서드는 사용자 입력을 받아 적절한 응답 데이터를 준비한 후 결과 형식을 반환하여 결과를 실행.
ViewResult, RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult, EmptyResult중 하나를 사용하여 결과 표현.
- 당근! 반드시! 꼭! Global.asax 파일에 Route object가 RouteTable object에 추가되어 있어야 한다.
- 난 뷰는 필요없고, 그냥 처리만 하고 바로 끝낼래요 라고 한다면, ViewResult대신 JsonResult와 같은 결과형식으로 리턴해버려도 됨.
등록된 라우트를 통하지 않고, Virtual Directory로 설정된 경우, 직접 파일을 요청받았다면? 어떻게 될까 했더니,,
일단 파일을 아무 이상없이 잘 받아지지만, Application_Error() 핸들러에서, Exception을 처리를 해두었더니,
파일을 요청받아 처리한 족족 에러를 내뱉고 있었다. 모든 액션마다 꼼꼼하게 에러처리를 하고 있지만서도 혹시 모르니
Application_Error()는 살려두는게 좋을 것이기 때문에, 나는 파일요청에 따른 액션을 추가해주고 처리하고 있다.