login register Sysop! about ME  
qrcode
    최초 작성일 :    2014년 01월 10일
  최종 수정일 :    2014년 01월 10일
  작성자 :    Jake
  편집자 :    Jake (류 지형)
  읽음수 :    32,120

강좌 목록으로 돌아가기

필자의 잡담~

이번 강좌는 Jake(류지형)님이 번역해 주신 ASP.NET MVC 5 시리즈의 3번째 강좌입니다. 원문 강좌는 다음과 같습니다.

http://www.asp.net/mvc/tutorials/mvc-5/introduction/adding-a-view
컨트롤러에서 뷰를 호출하고 데이터를 넘기는 방법에 대해 알아봅니다. 컨트롤러의 액션에서 뷰를 지정하는 가장 간단한 방법은 View() 메서드를 사용하는 겁니다. 이 메서드는 컨트롤러 이름과 같은 폴더를 Views 라는 솔루션 폴더에서 찾고 액션 이름과 같은 뷰 파일을 찾아서 ViewResult를 반환합니다.

ASP.NET MVC 는 Convention over configuration 라는 개발 패러다임에 맞추어 명명규칙에 의해 자동으로 해결되는 것들이 많이 있습니다.

이번 자습서에서는 HelloWorldController 클래스를 뷰 템플릿을 사용하도록 수정합니다. 뷰 템플릿을 사용하여 HTML 응답을 생성하는 과정을 깔끔하게 캡슐화할 것입니다.

Razor 뷰 엔진을 사용하여 뷰 템플릿을 생성하는데, Razor 기반의 뷰 템플릿은 .cshtml 라는 확장자를 갖는 파일로서 C#을 이용하여 HTML 결과를 생성하는 우아한 방법을 제공합니다. Razor 문법은 뷰 템플릿 작성에 필요한 키 입력과 문자수를 최소화하여 빠르고 끊이지 않는 자연스러운 코딩을 가능하게 합니다.

현재, Index 메서드는 컨트롤러 클래스에서 하드 코딩된 문자열을 반환하고 있습니다. Index 메서드를 아래 코드와 같이 View 객체를 반환하도록 변경합니다.

public ActionResult Index() 
{ 
    return View(); 
}

위의 Index 메서드는 브라우저에 돌려줄 HTML 응답을 생성하기 위해 뷰 템플릿을 사용합니다. 액션 메서드라고도 알려진 컨트롤러 메서드는 일반적으로 ActionResult 를 반환합니다. ActionResult를 상속하는 클래스를 반환하기도 합니다만 문자열과같은 기본적인 데이터 형식을 반환하지는 않습니다.

Views\HelloWorld 폴더를 우클릭하고 Add 를 선택해서 MVC 5 View Page with Layout (Razor) 를 추가합니다.


 

Specify Name for Item 다이얼로그 창에서 Index 를 입력하고, OK 를 클릭합니다.



Select a Layout Page 다이얼로그 창에서 기본 값인 _Layout.cshtml 을 선택하고 OK 버튼을 클릭합니다.



위의 다이얼로그 창의 왼쪽 패널에서 Views\Shared 폴더가 선택되었습니다. 여러분이 정의한 레이아웃 파일이 다른 폴더에 있다면 그것을 선택할 수도 있습니다. 레이아웃 파일은 이 자습서의 뒷부분에서 다시 알아보겠습니다.

이렇게 해서 MvcMovie\Views\HelloWorld\Index.cshtml 파일이 생성되었습니다.

아래에 하일라이트로 강조된 마크업을 뷰에 추가합니다.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>

Index.cshtml 파일을 우클릭하고 View in Browser 를 선택합니다.

PI

Index.cshtml 파일을 우클릭해서 View in Page Inspector 를 선택할 수도 있습니다. 자세한 내용은 Page Inspector tutorial 을 참고하세요.

또 다른 방법으로, 어플리케이션을 실행해서 HelloWorld 컨트롤러 (http://localhost:xxxx/HelloWorld) 를 브라우징해도 됩니다. 여기서 Index 메서드는 그렇게 많을 일을 하지는 않았습니다. 단순히 return View() 라는 문장을 실행했습니다만, 이 문장은 브라우저에 대한 응답을 렌더링하기 위해 뷰 템플릿을 사용해야 한다고 명시한 것과 같습니다. 여러분이 명시적으로 뷰 템플릿의 이름을 지정하지 않았기 때문에 ASP.NET MVC는 기본적으로 컨트롤러와 대응하는 \Views\HelloWorld 폴더에서 메서드명과 대응하는 Index.cshtml 라는 뷰 파일을 사용했습니다. 아래의 그림은 뷰에 하드 코딩된 "Hello from our View Template!" 라는 문자열을 보여주고 있습니다.

간단한 작업으로 볼만한 화면이 완성되었습니다. 그러나 몇 가지 아쉬운 부분이 있습니다. 브라우저의 타이틀 바를 보면 "Index - My ASP.NET Appli" 라고 되어 있고, 페이지 상단에는 "Application name" 이라고 커다란 링크가 있습니다.
브라우저 창의 크기가 얼만큼 작은가에 따라 Home, About, Contact, Register, Log in 메뉴를 보기 위해 우상단의 세줄 아이콘을 클릭해야 할수도 있습니다.

뷰, 레이아웃 페이지 변경하기

먼저, 페이지 상단의 "Application name" 링크를 변경하고자 합니다. 이 텍스트는 모든 페이지에서 공통으로 보입니다. 이 텍스트가 어플리케이션의 모든 페이지에서 보이지만 사실은 프로젝트의 한 곳에 구현되어 있습니다. Solution Explorer 에서 /Views/Shared 폴더로 가서 _Layout.cshtml 페이지를 엽니다. 이 파일은 레이아웃 페이지라고 불리며 다른 모든 페이지들이 사용하는 공유 폴더에 있습니다.

_LayoutCshtml

레이아웃 템플릿들은 사이트의 HTML 컨테이너 레이아웃을 한 군데에 지정해 두고 사이트내의 여러 페이지에 적용할 수 있도록 해줍니다. @RenderBody() 행을 찾아보세요. RenderBody 는 뷰 페이지가 나타나 레이아웃에 포함되는 자리를 지정하고 있습니다. 예를 들어, About 링크를 선택하면 Views\Home\About.cshtml 뷰가 RenderBody 메서드의 위치에 렌더링됩니다.

타이틀 태그의 내용을 수정합니다. 레이아웃 템플릿에서 ActionLink 를 "Application name" 에서 "MVC Movie" 로, 컨트롤러를 Home 에서 Movies 로 변경합니다. 수정 후의 레이아웃 파일은 아래와 같습니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Movie App</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("MVC Movie", "Index", "Movies", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

어플리케이션을 실행하면 이제 "MVC Movie" 라고 보이는걸 확인할 수 있습니다. About 링크를 선택해도 페이지는 여전히 "MVC Movie" 라고 나옵니다. 우리는 레이아웃 템플릿에서 한번 수정했지만 사이트의 전체 페이지에서 새로운 타이틀을 반영하게 되었습니다.

우리가 처음 Views\HelloWorld\Index.cshtml 파일을 생성했을 때, 다음의 코드가 포함되어 있었습니다.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

위의 Razor 코드는 레이아웃 페이지에 대한 명시적인 설정입니다. Views\_ViewStart.cshtml 파일을 조사해 보면 똑같은 Razor 코드가 있는 걸 확인할 수 있습니다. Views\_ViewStart.cshtml 파일은 모든 뷰가 사용하는 공통의 레이아웃을 정의합니다. 그러므로 여러분이 Views\HelloWorld\Index.cshtml 파일로부터 이 코드를 주석 처리하거나 삭제해도 됩니다. (역자 주; 삭제해도 Views\_ViewStart.cshtml 파일에 정의된 레이아웃이 적용되므로 뷰 내에서 같은 레이아웃을 다시 지정할 필요가 없습니다)

@*@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}*@
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>

여러분은 Layout 속성에 다른 레이아웃 뷰를 지정하거나 null 로 설정하여 레이아웃을 사용하지 않도록 지정할 수 있습니다.

자, 이제 Index 뷰의 페이지 타이틀을 변경해 봅시다.

MvcMovie\Views\HelloWorld\Index.cshtml 파일을 엽니다. 두 군데 수정할 곳이 있는데, 첫번째로 브라우저의 타이블에 있는 텍스트를, 두번째로 <h2> 에 정의된 헤더입니다. 살짝 바꿔볼텐데 어떤 코드가, App의 어떤 부분을 변경하는지 보게 될겁니다.

@{
    ViewBag.Title = "Movie List";
}
<h2>My Movie List</h2>
<p>Hello from our View Template!</p>

HTML 페이지의 타이틀을 보여주기 위해 위의 코드는 Index.cshtml 뷰 템플릿 내에서 ViewBag 객체의 Title 속성을 설정했습니다. 주목할 부분은 우리가 이전에 수정했던 레이아웃 파일 (Views\Shared\_Layout.cshtml) 에서, <head> 섹션의 일부인 <title> 에 이 값을 사용한다는 것입니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Movie App</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>

ViewBag 을 이용한 접근법은 템플릿과 레이아웃 파일간에 파라미터 전송을 쉽게 해줍니다.

어플리케이션을 실행합니다. 변경된 브라우저 타이틀, 주 제목 (MVC Movie), 보조 제목 (My Movie List)이 눈에 띕니다. (만약 변경된 정보가 보이지 않는다면 페이지가 캐시 되었기 때문일겁니다. 이 경우에는, Ctrl+F5 버튼을 사용하여 새로고침 하세요.) 브라우저 타이틀은 Index.cshtml 뷰 템플릿에서 ViewBag.Title 을 이용하여 정의하였고 뒤에 붙은 "- Movie App" 은 레이아웃 파일에서 추가되었습니다.

Index.cshtml 뷰 템플릿의 내용은 _Layout.cshtml 뷰 템플릿과 합쳐져서 브라우저로 보내지는 단일 HTML 응답이 되었습니다. 레이아웃 템플릿은 어플리케이션 모든 페이지에 걸쳐 필요한 변경이 있을때, 이를 쉽게 할수 있도록 해줍니다.

우리의 아주 작은 데이터 (이 예제에서 "Hello from our View Template!" 메세지) 가 하드코딩 되긴 했습니다. 데이타와 직접 연관있는 "M" (Model) 은 아직 다루지 않았지만 이 MVC 어플리케이션 예제에서 "V" (View), "C" (Controller) 를 살펴 봤습니다. 이제 어떻게 데이터베이스를 생성하고 모델 데이터를 조회하는지 알아보겠습니다.

컨트롤러에서 뷰로 데이터 전송하기

먼저 데이터베이스와 모델에 대해 언급하기 전에 정보를 컨트롤러에서 뷰로 어떻게 보내는지 얘기해 봅시다. 컨트롤러 클래스는 입력 URL 요청에 대한 응답으로 실행됩니다. 컨트롤러 클래스는 이런 브라우저 요청을 받아서 데이터베이스로부터 데이터를 조회하고 마지막에는 브라우저에 어떤 종류의 응답을 돌려줄지 결정합니다. 뷰 템플릿은 컨트롤러에 의해 지정되어 HTML 응답을 생성하고 형식을 잘 정리하는데 사용됩니다.

컨트롤러는 뷰 템플릿이 브라우저에 돌려줄 응답을 생성하는데 사용할 데이터 또는 객체를 제공할 책임이 있습니다. 뷰에 대한 모범적인 사용법은, "뷰에서는 비즈니스 로직을 절대로 수행하지 않고 데이터베이스와도 직접적으로 상호작용하지 않는다" 라는 것입니다. 그 대신, 뷰 템플릿은 컨트롤러에 의해 주어진 데이터만 사용하여 작업합니다. MVC 패턴이 고수하는 디자인 원칙, "separation of concerns" (역자 주: 가독성이 높고 깨끗한 코딩을 하고자 중요한 부분을 별도로 분리하여 부분간의 간섭을 최소화하는 프로세스 또는 개념. 그 결과로 테스트와 유지보수가 용이해짐.) 을 유지하는 것은 여러분의 코드를 깨끗하게 관리하고 테스트와 유지보수를 더욱 쉽게 해줍니다.

현재, HelloWorldController 컨트롤러의 Welcome 액션 메서드는 namenumTimes 파라미터를 받아서 브라우저에 직접 값들을 출력하고 있습니다. 컨트롤러가 이 응답을 문자열로 렌더링하는 것보다는 뷰 템플릿을 사용하도록 변경해 봅시다. 뷰 템플릿은 동적인 응답을 생성할 겁니다. 그러기 위해서, 컨트롤러는 적당한 데이터를 뷰 템플릿으로 전달해야 합니다. 어떻게 할까요? 뷰 템플릿이 액세스할 수 있는 ViewBag 객체에 동적 파라미터를 만들어 값을 전달하면 됩니다.

HelloWorldController.cs 파일로 돌아가서 Welcome 메서드에 MessageNumTimes 값을 ViewBag 객체에 추가합니다. ViewBag 은 동적 객체입니다. 여러분이 무엇인가를 넣기 전까지는 정해진 속성도 없기 때문에 어떤 것이든 집어 넣을수 있습니다. ASP.NET MVC 모델 바인딩 시스템 은 쿼리스트링에 주어진 파라미터의 이름을 이용해서 자동으로 메서드의 파라미터와 매핑해 줍니다. 수정이 완료된 HelloWorldController.cs 파일은 아래와 같습니다.

using System.Web;
using System.Web.Mvc;
namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult Welcome(string name, int numTimes = 1)
        {
            ViewBag.Message = "Hello " + name;
            ViewBag.NumTimes = numTimes;
            return View();
        }
    }
}

자, 이제 ViewBag 객체는 뷰 템플릿에 전달될 데이터를 포함하게 되었습니다. 다음에는 Welcome 뷰가 필요하겠죠! Build 메뉴에서 Build Solution 를 선택해서 (또는 Ctrl+Shift+B 단축키로) 프로젝트를 컴파일하십시오. Views\HelloWorld 폴더에서 우클릭하고 Add를 선택하여 MVC 5 View Page with (Layout Razor) 를 추가합니다.


 

Specify Name for Item 다이얼로그 창에서 Welcome 이라고 입력하고 OK 를 클릭합니다..

Select a Layout Page 다이얼로그 창에서 _Layout.cshtml 을 선택하고 OK 를 클릭합니다.

   

MvcMovie\Views\HelloWorld\Welcome.cshtml 파일이 생성되었습니다.

Welcome.cshtml 파일의 내용을 아래 코드로 대치합니다. 이 코드는 지정된 횟수만큼 Hello를 출력할 겁니다.

@{
    ViewBag.Title = "Welcome";
}
<h2>Welcome</h2>
<ul>
    @for (int i = 0; i < ViewBag.NumTimes; i++)
    {
        <li>@ViewBag.Message</li>
    }
</ul>

어플리케이션을 실행하고 아래 URL의 포트를 환경에 맞게 수정해서 브라우징해 봅니다.

http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4

URL의 데이터가 모델 바인더 를 통해 컨트롤러로 전달되었습니다. 컨트롤러는 그 데이터를 ViewBag 객체로 포장해서 뷰로 넘겼고, 뷰는 그것을 HTML로 사용자에게 보여줍니다.

위의 예제에서 우리는 ViewBag 객체를 통해 컨트롤러에서 뷰로 데이터를 넘겨줬습니다. 이 자습서 시리즈의 뒷편에서는 같은 일을 하기 위해 뷰 모델을 사용할 것입니다. 뷰 모델을 사용하는 접근법이 ViewBag 을 을 사용하는 방식보다 훨씬 선호됩니다. 자세한 정보는 Dynamic V Strongly Typed Views 블로그 포스팅을 참조하세요.

여기까지 모델과 관련된 "M"을 알아보았습니다. 그럼, 지금까지 배운것을 가지고 Movies 데이터베이스를 만들어 봅시다.


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})