파트 2: 컨트롤러 추가하기

등록일시: 2015-04-20 08:00,  수정일시: 2015-04-20 08:00
조회수: 21,817
이 문서는 ASP.NET MVC 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.

MVC는 모델-뷰-컨트롤러(Model-View-Controller)를 뜻하는 약자로, 검증이 가능하고 관리가 용이한 구조적인 응용 프로그램 개발 패턴입니다. MVC 기반의 응용 프로그램들은 다음과 같은 요소들로 구성됩니다:

  • 모델(Models): 응용 프로그램의 데이터를 표현하는 클래스들입니다. 이 클래스들은 데이터에 업무 규칙을 적용하기 위한 유효성 검사 로직이 수행되는 곳이기도 합니다.
  • 뷰(Views): 응용 프로그램이 HTML 응답을 동적으로 생성하기 위해서 사용하는 템플릿 파일들입니다.
  • 컨트롤러(Controllers): 브라우저로부터 전달된 요청을 처리하고, 모델 데이터를 가져온 뒤, 브라우저로 응답을 반환할 뷰 템플릿을 지정하는 클래스들입니다.

본 자습서의 일련의 시리즈에서는 이 개념들을 모두 살펴보고, 응용 프로그램을 구축하기 위해서 이 요소들을 활용하는 방법에 관해서 살펴봅니다.

그러면 컨트롤러 클래스부터 생성해보겠습니다. 솔루션 탐색기(Solution Explorer)에서 마우스 오른쪽 버튼으로 Controllers 폴더를 클릭한 다음, 추가(Add) > 컨트롤러(Controller)를 선택합니다.

스캐폴드 추가(Add Scaffold) 대화 상자가 나타나면 MVC 5 컨트롤러 - 비어 있음(MVC 5 Controller - Empty)을 선택하고 추가(Add) 버튼을 클릭합니다.

그러면 다시 컨트롤러 추가(Controller Add) 대화 상자가 나타나는데, 새 컨트롤러의 이름을 "HelloWorldController"라고 지정하고 추가(Add) 버튼을 클릭합니다.

이제 솔루션 탐색기(Solution Explorer)를 살펴보면 HelloWorldController.cs라는 이름의 파일과 Views\HelloWorld 폴더가 새로 생성된 것을 확인할 수 있습니다. 또한 새로 생성된 컨트롤러 파일이 자동으로 통합 개발 환경에 열립니다.

이 파일의 내용을 다음 코드로 대체합니다.

using System.Web;
using System.Web.Mvc;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        // 
        // GET: /HelloWorld/ 
        public string Index()
        {
            return "This is my <b>default</b> action...";
        }

        // 
        // GET: /HelloWorld/Welcome/ 
        public string Welcome()
        {
            return "This is the Welcome action method...";
        }
    }
}

이 컨트롤러의 메서드들은 HTML 문자열을 반환하고 있습니다. 컨트롤러의 이름은 HelloWorldController이며 두 메서드들 중 첫번째 메서드의 이름은 Index입니다. 바로 이 메서드를 브라우저를 통해서 호출해보겠습니다. 먼저 F5 키나 Ctrl+F5 키를 눌러서 응용 프로그램을 실행합니다. 그런 다음, 브라우저의 주소 표시줄에 나타난 URL 뒤에 "HelloWorld"라는 문자열을 추가합니다. (예를 들어서, 아래 그림의 경우 http://localhost:1234/HelloWorld 라고 입력된 것을 볼 수 있습니다.) 그러면, 브라우저에 아래 그림과 비슷한 모습의 페이지가 출력될 것입니다. 이 예제 메서드의 코드는 문자열을 직접 반환하고 있는데, 이는 MVC 프레임워크에게 일련의 HTML을 직접 반환하도록 지시한 셈이며, 실제로도 그렇게 동작한 것입니다!

이처럼 ASP.NET MVC는 전달된 URL을 기반으로 선택된 컨트롤러 클래스(와 그 클래스에 존재하는 선택된 메서드)를 호출합니다. 그리고 ASP.NET MVC가 사용하는 기본 URL 라우팅 로직은 다음과 같은 형태의 URL을 사용해서 호출할 컨트롤러와 메서드를 결정합니다:

/[Controller]/[ActionName]/[Parameters]

이 라우팅 형식은 App_Start/RouteConfig.cs 파일에 다음과 같이 지정되어 있습니다.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

만약 응용 프로그램을 실행하고 아무런 URL 세그먼트도 지정하지 않는다면, 기본적으로 이 코드의 defaults 섹션에 지정된 "Home" 컨트롤러의 "Index" 액션 메서드가 호출됩니다.

이 기본 라우트 형식에서 전달된 URL의 첫번째 세그먼트는 실행할 컨트롤러 클래스를 결정합니다. 따라서 위의 예제에서 지정했던 /HelloWorld 라는 URL은 HelloWorldController 클래스에 매핑됩니다. URL의 두번째 세그먼트는 실행할 컨트롤러의 액션 메서드를 결정합니다. 따라서 /HelloWorld/Index 라는 URL은 HelloWorldController 클래스의 Index 메서드를 실행하게 됩니다. 그런데 이번 예제에서 /HelloWorld 로 이동했는데도 자동으로 Index 메서드가 호출되었다는 점을 주목하시기 바랍니다. 그 이유는 명시적으로 메서드가 지정되지 않은 경우, 컨트롤러에 존재하는 Index라는 이름의 메서드가 호출되도록 기본값이 구성되어 있기 때문입니다. 마지막으로 Parameters라는 URL 세그먼트의 세번째 부분은 라우트 데이터를 위한 것으로, 라우트 데이터에 대해서는 본 자습서의 뒷 부분에서 살펴보도록 하겠습니다.

이번에는 http://localhost:xxxx/HelloWorld/Welcome 으로 이동해봅니다. 그러면, Welcome 메서드가 실행되어 "This is the Welcome action method..."라는 문자열이 반환될 것입니다. 이는 MVC의 기본 라우트 매핑이 /[Controller]/[ActionName]/[Parameters]이기 때문인데, 즉 컨트롤러로는 HelloWorld가 선택되고 액션 메서드로는 Welcome이 선택된 것입니다. 다만 URL의 [Parameters] 세그먼트 부분은 여전히 사용되지 않고 있습니다.

그러면 이번에는 예제를 조금 수정해서 URL을 통해서 매개변수 정보를 컨트롤러에 전달해보도록 하겠습니다 (예, /HelloWorld/Welcome?name=Scott&numtimes=4). 다음 코드처럼 두 개의 매개변수를 전달받도록 Welcome 메서드를 수정합니다. 이때 C#의 선택적 매개변수 기능을 이용해서 numTimes 매개변수에 아무 값도 전달되지 않은 경우, 기본 값인 1을 전달하도록 지정한 부분을 눈여겨 보시기 바랍니다.

public string Welcome(string name, int numTimes = 1) {
    return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes);
}

보안 노트: 이번 예제 코드에서는 악의적인 사용자의 입력으로부터 (다시 말하자면 JavaScript로부터) 응용 프로그램을 보호하기 위해서 HttpServerUtility.HtmlEncode 메서드를 사용하고 있습니다. 이에 대한 보다 자세한 정보는 How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings 문서를 참고하시기 바랍니다.

계속해서 응용 프로그램을 다시 실행하고 브라우저에서 다음 예제 URL로 이동해봅니다 (http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numtimes=4). 그런 다음 URL의 name이나 numtimes에 다른 값들을 지정해서 이리 저리 테스트 해보시기 바랍니다. 그러면 ASP.NET MVC의 모델 바인딩 시스템이 주소 표시줄의 쿼리 문자열에 포함된 명명된 매개변수들을 자동으로 메서드의 매개변수들과 매핑시켜준다는 점을 확인할 수 있을 것입니다.

이번 예제에서는 매개변수 값을 전달하기 위해서 URL 세그먼트를 사용하는 대신, 쿼리 문자열name 매개변수와 numTimes 매개변수를 전달하고 있습니다. 이 예제의 URL에서 물음표(?)는 구분자 역할을 하는데, 이 물음표 뒤에 나타나는 문자열들이 바로 쿼리 문자열들입니다. 그리고 다시 앰퍼샌드(&) 문자는 각각의 쿼리 문자열들을 서로 구분해주는 역할을 합니다.

이번에는 Welcome 메서드를 다음의 코드로 대체합니다:

public string Welcome(string name, int ID = 1)
{
    return HttpUtility.HtmlEncode("Hello " + name + ", ID: " + ID);
}

그리고 응용 프로그램을 실행한 다음, 다시 다음의 URL을 입력합니다: http://localhost:xxx/HelloWorld/Welcome/3?name=Rick

이번에는 URL의 세번째 세그먼트가 ID 라우트 매개변수와 매치됩니다. 더불어 Welcome 액션 메서드 역시 RegisterRoutes 메서드에 지정된 URL 사양과 일치하는 동일한 이름의 ID라는 매개변수를 갖고 있습니다.

public static void RegisterRoutes(RouteCollection routes)
{
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

     routes.MapRoute(
          name: "Default",
          url: "{controller}/{action}/{id}",
          defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );
}

이처럼 ASP.NET MVC 응용 프로그램에서는 쿼리 문자열을 통해서 매개변수를 전달하는 방식보다는 라우트 데이터의 형태로 매개변수를 전달하는 방식이 더 일반적입니다 (이번 예제의 ID 매개변수처럼). 또한 namenumtimes 모두가 URL을 통해서 라우트 데이터의 형태로 매개변수에 전달될 수 있도록 라우트 자체를 추가할 수도 있습니다. 가령 다음과 같이 App_Start\RouteConfig.cs 파일에 "Hello"라는 이름의 라우트를 추가할 수도 있을 것입니다:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Hello",
            url: "{controller}/{action}/{name}/{id}"
        );
    }
}

그런 다음, 응용 프로그램을 실행하고 /localhost:XXX/HelloWorld/Welcome/Scott/3로 이동해보면 그 결과는 다음과 같습니다.

대부분의 MVC 응용 프로그램에서는 기본 라우트만 사용해도 충분합니다. 본 자습서의 뒷 부분에서는 굳이 기본 라우트를 변경하지 않고도 모델 바인더를 이용해서 데이터를 전달하는 방법을 살펴봅니다.

본문에서 살펴본 예제들에서는 컨트롤러가 MVC 중 "VC"의 역할을, 즉 뷰와 컨트롤러의 역할을 모두 수행하고 있습니다. 다시 말해서 컨트롤러가 HTML을 직접 반환하고 있는 것입니다. 그러나 일반적인 경우 컨트롤러가 HTML을 직접 반환해서는 안되는데, 그렇게 되면 코드가 매우 길고 복잡해지기 때문입니다. 대신 HTML 응답을 생성하기 위한 별도의 뷰 템플릿을 사용하는 것이 보다 일반적인 방법입니다. 그러면, 이제 바로 그 방법을 살펴보도록 하겠습니다.

이 기사는 2013년 10월 17일에 최초 작성되었습니다.