login register Sysop! about ME  
qrcode
    최초 작성일 :    2012년 06월 13일
  최종 수정일 :    2012년 06월 13일
  작성자 :    songgun
  편집자 :    songgun (송 원석)
  읽음수 :    38,280

강좌 목록으로 돌아가기

필자의 잡담~

본문에서는 지난 강좌에서 만들었던 기초적인 ASP.NET MVC 4 응용 프로그램에 뷰 템플릿과 간단한 모델 클래스를 추가해보고, 레이아웃의 개념을 살펴봅니다.

또한, 컨트롤러에서 뷰로 데이터를 전달하기 위한 ViewBag 개체도 사용해봅니다. 그리고, 마지막으로 Web.config 파일에 데이터베이스 연결 문자열을 설정해봅니다.

뷰 추가하기
이번에는 HelloWorldController 클래스를 변경해서, 클라이언트에 응답할 HTML의 생성 과정을 간결하게 감춰주는 뷰 템플릿을 적용해 보겠습니다.

그리고, 뷰 템플릿 파일은 ASP.NET MVC 3에서 처음 도입된 Razor 뷰 엔진을 사용해서 작성해 볼 것입니다. Razor 기반의 뷰 템플릿은 .cshtml 이라는 파일 확장자를 갖고 있으며, C#을 이용한 우아한 HTML 출력 생성 방식을 제공해줍니다. Razor를 이용하면 뷰 템플릿 작성을 위해 필요한 글자수와 키입력을 최소화할 수 있으며, 빠르고 자연스러운 코딩이 가능해집니다.

먼저, HelloWorldController 클래스의 Index 메서드에 대한 뷰 템플릿부터 만들어 보겠습니다. 현재 Index 메서드는 그저 단순히 컨트롤러 클래스 자체에 하드코딩 되어 있는 문자열 메시지를 반환만 해줄 뿐입니다. 따라서, 다음과 코드와 같이 View 메서드를 호출하여 ActionResult 개체를 반환하도록 Index 메서드의 코드를 변경합니다:
public ActionResult Index() {
    return View();
}
이렇게 변경된 Index 메서드는 브라우저에 응답할 HTML을 생성하기 위해서 뷰 템플릿을 사용하게 됩니다. 일반적으로 컨트롤러의 메서드(액션 메서드)는, 이 Index 메서드처럼 문자열 같은 기본 형식 대신, ActionResultActionResult로부터 파생된 클래스를 반환하는 것이 보통입니다.

이제 프로젝트에 Index 메서드에 대한 뷰 템플릿을 추가하겠습니다. Index 메서드의 내부를 마우스 오른쪽 버튼으로 클릭하고 Add View를 선택합니다.


그러면, Add View 대화 상자가 나타나는데, 기본값을 그대로 남겨두고 Add 버튼을 클릭합니다:


그러면, MvcMovie\Views\HelloWorld 폴더와 MvcMovie\Views\HelloWorld\Index.cshtml 파일이 만들어집니다. 이 폴더와 파일을 Solution Explorer에서 확인해보십시요:


다음 그림에는 생성된 Index.cshtml 파일의 내용이 나타나 있습니다:


다음의 HTML을 <h2> 태그 아래에 추가합니다.
<p>Hello from our View Template!</p>
여기까지 작업을 마치고 나면 MvcMovie\Views\HelloWorld\Index.cshtml 파일의 내용은 다음과 비슷한 모습이 될 것입니다.
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>
만들어진 페이지를 살펴보고 보다 상세하게 분석해보고 싶다면, Solution Explorer에서 Index.cshtml 파일을 마우스 오른쪽 버튼으로 클릭한 다음, View in Page Inspector를 선택합니다.


이 새로운 도구에 관한 보다 자세한 정보는 Page Inspector tutorial을 참고하시기 바랍니다.

물론, 간단히 응용 프로그램을 실행한 다음, 브라우저에서 HelloWorld 컨트롤러로 이동해도 무방합니다. 이 컨트롤러의 Index 메서드는 그다지 많은 작업을 수행하지는 않습니다. 이 메서드는 단지 return View() 구문만 실행하는데, 이 구문은 브라우저에 응답을 렌더할 때, 뷰 템플릿을 사용하도록 지시합니다. 그리고, 사용해야 할 뷰 템플릿의 파일명을 명시적으로 지정하지 않았으므로, ASP.NET MVC가 자동으로 \Views\HelloWorld 폴더의 Index.cshtml 뷰 파일을 사용하게 됩니다. 다음 그림은 컨트롤러가 아닌, 뷰에 하드코딩 된 문자열이 출력된 화면을 보여주고 있습니다.


그리 나빠보이지는 않지만, 브라우저의 타이틀바에는 "Index My ASP.NET A..."라는 텍스트가 나타나 있고, 페이지 상단에는 "your logo here."라는 보기 싫은 커다란 링크가 자리잡고 있습니다. 그리고, "your logo here." 링크의 아래쪽에는 등록과 로그인과 관련된 링크가 있고, 다시 그 아래쪽에는 Home과 About, 그리고 Contact 페이지에 대한 링크가 자리잡고 있습니다. 자, 그러면 지금부터 이 부분들을 조금 변경해보도록 하겠습니다.


뷰와 레이아웃 페이지 변경하기
먼저, 페이지 상단의 "your logo here." 링크 텍스트부터 바꿔보겠습니다. 이 텍스트는 모든 페이지에 공통으로 나타나는 문구로, 실제로는 프로젝트 전체에서 단 한 곳에만 작성되어 있지만, 응용 프로그램에 존재하는 모든 페이지에 나타납니다. Solution Explorer에서 /Views/Shared 폴더에 위치한 _Layout.cshtml 파일을 열어봅니다. 이 페이지를 레이아웃 페이지라고 부르며, 응용 프로그램의 다른 모든 페이지들이 공유하는 기본적인 "구조"를 담고 있습니다.


이와 같은 레이아웃 템플릿을 사용하면, 사이트의 HTML 컨테이너로 사용될 레이아웃을 한 곳에서 지정한 다음, 사이트의 모든 페이지에 해당 레이아웃을 적용할 수 있습니다. 이 파일의 내용 중, @RenderBody() 라인을 살펴보시기 바랍니다. 이 RenderBody 메서드는 레이아웃 페이지 상에서 여러분이 작성한 뷰-전용 페이지들이 나타나게 될 위치를 지정합니다. 가령, About 링크를 클릭해보면, 이 RenderBody 메서드의 위치에 Views\Home\About.cshtml 뷰의 내용이 나타나는 것을 확인할 수 있습니다.

먼저, 레이아웃 템플릿에서 링크의 텍스트를 "your logo here."에서 다음과 같이 "MVC Movie"로 변경합니다.
<div class="float-left">
    <p class="site-title">@Html.ActionLink("MVC Movie", "Index", "Home")</p>
</div>
그리고, title 요소도 그 내용을 다음의 마크업으로 변경합니다:
<title>@ViewBag.Title - Movie App</title>
이제 다시 응용 프로그램을 실행시켜보면, 로고 링크의 텍스트가 "MVC Movie"로 변경된 것을 확인할 수 있을 것입니다. 또한, About 링크를 클릭해보면, 이 페이지의 로고 링크 텍스트도 역시 "MVC Movie"로 변경된 것을 확인할 수 있습니다. 비록, 레이아웃 템플릿에서 단 한 번의 변경 작업만 수행했지만, 사이트의 모든 페이지에 새로운 링크 텍스트가 반영된 것입니다.


작업이 마무리 된, 완전한 _Layout.cshtml 파일의 내용은 다음과 같습니다:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - Movie App</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
        <link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")" rel="stylesheet" type="text/css" />
        <script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>
        <meta name="viewport" content="width=device-width" />
    </head>
    <body>
        <header>
            <div class="content-wrapper">
            <div class="float-left">
<p class="site-title">@Html.ActionLink("MVC Movie", "Index", "Home")</p>
            </div>
<div class="float-right">
    <section id="login">
        @Html.Partial("_LoginPartial")
    </section>
    <nav>
        <ul id="menu">
            <li>@Html.ActionLink("Home", "Index", "Home")</li>
            <li>@Html.ActionLink("About", "About", "Home")</li>
            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
        </ul>
    </nav>
</div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
@RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
<div class="float-left">
    <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
</div>
<div class="float-right">
    <ul id="social">
        <li><a href="http://facebook.com" class="facebook">Facebook</a></li>
        <li><a href="http://twitter.com" class="twitter">Twitter</a></li>
    </ul>
</div>
            </div>
        </footer>
    </body>
</html>
그러면, 이번에는 Index 뷰의 브라우저 타이틀을 변경해보도록 하겠습니다.

다시 MvcMovie\Views\HelloWorld\Index.cshtml 파일을 엽니다. 이 파일에서 변경하게 될 부분은 모두 두 곳으로, 브라우저 타이틀에 나타나는 텍스트와 페이지 상의 2차 헤더 제목(<h2> 요소) 텍스트가 바로 그것입니다. 변경되는 부분이 극히 일부분이기 때문에, 어떤 코드가 응용 프로그램의 어떤 부분을 변경하는지 쉽게 이해할 수 있을 것입니다.
@{ 
    ViewBag.Title = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>
변경된 Index.cshtml 뷰 템플릿에서는 HTML의 타이틀 출력을 지정하기 위해서, ViewBag 개체의 Title 속성을 설정하고 있습니다. 앞에서 살펴봤던 레이아웃 템플릿의 내용을 다시 살펴보면, HTML <head> 영역 하위의 <title> 요소에서 이 값이 사용되고 있다는 사실을 확인할 수 있을 것입니다. 이처럼 ViewBag 접근 방식을 사용하면 뷰 템플릿과 레이아웃 페이지 간에 매개변수를 손쉽게 전달할 수 있습니다.

응용 프로그램을 다시 시작한 다음, 브라우저에서 http://localhost:xxxx/HelloWorld로 이동합니다. 브라우저의 타이틀과 로고 링크의 텍스트, 그리고 2차 헤더의 제목이 변경된 것을 확인할 수 있을 것입니다. (만약, 브라우저에 변경된 내용들이 반영되지 않는다면, 아마도 캐시된 내용 때문일 것입니다. 브라우저에서 Ctrl+F5를 눌러서 강제로 서버로부터 받은 응답을 로드해보시기 바랍니다.) 이 브라우저의 타이틀은 Index.cshtml 뷰 템플릿에서 설정한 ViewBag.Title의 값과 레이아웃 파일에 추가된 " - Movie App"가 결합되어 만들어진 결과입니다.

또한, 어떻게 Index.cshtml 뷰 템플릿의 내용과 _Layout.cshtml 뷰 템플릿이 결합되어 단일 HTML 응답으로 브라우저에 전송되는지도 주의해서 살펴보시기 바랍니다. 이처럼 레이아웃 템플릿을 활용하면 응용 프로그램의 모든 페이지에 공통적으로 적용되는 부분들을 정말 손쉽게 수정할 수 있습니다.


그런데, 이번 예제에 사용된 "데이터"(즉, "Hello from our View Template!" 메시지)는 여전히 하드코딩되어 있는 데이터에 불과합니다. 결국, 이 예제 MVC 응용 프로그램에는 "V" (뷰) 와 "C" (컨트롤러)는 존재하지만, 여전히 "M" (모델)은 존재하지 않는 상태나 마찮가지인 것입니다. 잠시 뒤에, 데이터베이스를 생성하고 데이터베이스로부터 모델 데이터를 가져오는 방법을 살펴보게 될 것입니다.


컨트롤러에서 뷰로 데이터 전달하기
데이터베이스와 모델에 관해서 살펴보기 전에, 먼저 컨트롤러에서 뷰로 정보를 전달하는 방법부터 살펴보도록 하겠습니다. 컨트롤러 클래스는 전달된 URL 요청에 대한 응답 과정 중 호출됩니다. 컨트롤러 클래스는 전달된 브라우저 요청을 처리하고, 데이터베이스에서 데이터를 가져온 다음, 최종적으로 어떤 형식의 응답을 브라우저에 전송할 것인지를 결정하는 코드들이 작성되는 위치입니다. 그리고, 그 이후에야 브라우저로 전달될 HTML 응답을 생성하고 형식화하기 위해 컨트롤러에 의해 뷰 템플릿이 사용됩니다.

컨트롤러는 뷰 템플릿이 브라우저에 응답을 렌더할 때 필요한 모든 데이터와 개체를 제공해야 할 책임을 갖고 있습니다. 그리고, 뷰 템플릿은 어떠한 경우에도 업무 로직을 수행하거나 데이터베이스와 직접 연결돼서는 안됩니다. 그 대신, 컨트롤러로부터 제공 받은 데이터만을 사용해서 모든 작업들을 수행해야 합니다. 이처럼 "관심의 분리(Separation of Concerns)"를 지키면 깔끔하고, 테스트 가능하며, 유지보수가 용이한 코드를 유지할 수 있습니다.

현재 HelloWorldController 클래스의 Welcome 액션 메서드는 namenumTimes이라는 이름의 매개변수를 받은 다음, 그 값들을 브라우저로 직접 출력하도록 구현되어 있습니다. 이 메서드를 문자열 대신, 뷰 템플릿을 사용하여 응답을 렌더하도록 변경해 보겠습니다. 그리고, 이 뷰 템플릿을 통해서 동적 응답을 생성해보려고 하는데, 결국 이 말은 응답을 생성하기 위해 필요한 데이터를 컨트롤러에서 뷰로 전달해줘야 한다는 뜻입니다. 이를 위해서 뷰 템플릿에 필요한 동적 데이터를 (매개변수들을) 컨트롤러 내부에서 ViewBag 개체에 설정한 다음, 이를 뷰 템플릿에서 접근해볼 것입니다.

다시 HelloWorldController.cs 파일로 돌아가서, MessageNumTimes의 값을 ViewBag 개체에 설정하도록 Welcome 메서드를 변경합니다. ViewBag은 동적 개체로, 여러분이 원하는 것은 무엇이든지 이 개체에 설정할 수 있습니다. 여러분이 ViewBag 개체에 무언가를 설정하기 전까지는, 이 개체에 어떠한 속성도 정의되어 있지 않습니다. 그리고, ASP.NET MVC의 모델 바인딩 시스템은 자동으로 브라우저 주소 표시줄의 쿼리스트링에 포함된 명명된 매개변수들을 (namenumTimes) 액션 메서드의 매개별수들과 맵핑시켜줍니다. 변경 작업이 마무리된 완전한 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 뷰 템플릿이 필요합니다. 다만, 먼저 Debug 메뉴에서 Build MvcMovie를 선택해서 프로젝트를 컴파일합니다.


그런 다음, Welcome 메서드의 내부를 마우스 오른쪽 버튼으로 클릭하고, Add View를 선택합니다.


다음 그림은 Add View 대화 상자에 설정된 내용들을 보여주고 있습니다:


마지막으로 Add를 클릭한 다음, 새로 만들어진 Welcome.cshtml 파일의 <h2> 요소 아래에 다음과 같이 코드를 추가합니다. 이 코드는 지정한 횟수만큼 지정한 사용자에게 "Hello"를 출력하는 루프문입니다. 완전한 Welcome.cshtml 파일은 다음과 같습니다.
@{
    ViewBag.Title = "Welcome";
}

<h2>Welcome</h2>

<ul> 
    @for (int i=0; i < ViewBag.NumTimes; i++) { 
        <li>@ViewBag.Message</li>
    }
</ul>
다시 응용 프로그램을 실행한 다음, 브라우저에서 다음 URL로 이동합니다:

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

그러면, URL로부터 얻어진 데이터가 모델 바인더에 의해서 컨트롤러로 전달됩니다. 그리고, 컨트롤러는 이 데이터를 ViewBag 개체에 정리해서 집어 넣은 다음, 이 개체를 다시 뷰로 전달합니다. 마지막으로 뷰는 해당 데이터를 HTML로 출력하고, 이를 사용자에게 전달하게 됩니다.


물론 이번 예제에 사용된 데이터도 일종의 "M", 즉 모델로 볼 수는 있겠지만, 아직도 데이터베이스가 사용되지는 않았습니다. 다음에는 바로 이 문제에 관해 살펴보고 영화 정보를 저장할 데이터베이스도 생성해보도록 하겠습니다.


모델 추가하기
이번에는 데이터베이스의 영화 정보 관리를 위한 클래스들을 추가해 보겠습니다. 이 클래스들은 ASP.NET MVC 응용 프로그램의 "모델(Model)" 부분을 담당하게 될 것입니다.

그리고, Entity Framework라는 이름으로 알려져 있는 .NET 프레임워크 데이터-접근 기술을 이용해서 이 모델 클래스들을 정의하고 사용해 볼 것입니다. Entity Framework는 (EF라고도 합니다) Code First라는 개발 패러다임을 지원해줍니다. 이 Code First 기법을 사용하면 간단한 클래스를 작성해서 모델 개체를 생성할 수 있습니다. (이런 클래스들을 POCO 클래스라고도 하는데, 이는 "Plain-Old CLR objects"의 약자입니다.) 그런 다음, 실시간으로 여러분이 작성한 클래스로부터 데이터베이스를 생성하게 되는데, 매우 깔끔하고 신속한 개발 워크플로우를 가능하게 해줍니다.


모델 클래스 추가하기
먼저, Solution Explorer에서 Models 폴더를 마우스 오른쪽 버튼으로 클릭한 다음, Add > New Item을 선택합니다.


그러면, Add New Item 대화 상자가 나타나는데, 좌측 트리뷰에서 Code를 클릭한 다음, Class를 선택하고 이 클래스의 이름을 "Movie"로 지정합니다.


그리고, Add를 클릭하면, Movie 클래스가 만들어집니다.


만들어진 Movie 클래스에 다음과 같이 다섯 개의 속성들을 추가합니다:
public class Movie 
{ 
    public int ID { get; set; } 
    public string Title { get; set; } 
    public DateTime ReleaseDate { get; set; } 
    public string Genre { get; set; } 
    public decimal Price { get; set; } 
}
Movie 클래스는 데이터베이스의 영화 정보를 나타내기 위해서 사용됩니다. 각각의 Movie 개체 인스턴스는 데이터베이스 테이블의 로우에 해당하고, Movie 클래스의 각 속성들은 테이블의 컬럼과 맵핑됩니다.

동일한 파일에, 다음과 같이 MovieDBContext 클래스를 추가합니다:
public class MovieDBContext : DbContext { 
    public DbSet<Movie> Movies { get; set; } 
}
MovieDBContext 클래스는 데이터베이스에서 Movie 클래스의 인스턴스를 가져오고, 저장하고, 갱신하는 작업을 처리하는 Entity Framework 영화 데이터베이스 컨텍스트의 역할을 수행합니다. 이 MovieDBContext 클래스는 Entity Framework로부터 제공되는 DbContext 기본 클래스를 상속받습니다. DbContextDbSet에 관한 보다 자세한 정보는 Productivity Improvements for the Entity Framework를 참고하시기 바랍니다.

DbContextDbSet을 참조하려면, 파일 상단에 다음과 같은 using 문을 추가해야 합니다:
using System.Data.Entity;
모든 작업이 마무리된 완전한 Movie.cs 파일은 다음과 같습니다. (불필요한 몇 가지 using 문은 제거되었습니다.)
using System;
using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }        
        public DateTime ReleaseDate { get; set; }        
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

연결 문자열 생성하기 및 SQL 서버 LocalDB 작업하기
방금 작성한 MovieDBContext 클래스는 데이터베이스 연결 작업과 Movie 개체와 데이터베이스 레코드 간의 맵핑 작업을 처리합니다. 그렇다면 이제 아마 여러분은 연결할 데이터베이스를 지정하는 방법이 궁금할 것입니다. 응용 프로그램의 Web.config 파일에 연결 정보를 추가해보겠습니다.

응용 프로그램의 루트에 위치한 Web.config 파일을 엽니다. (Views 폴더에 있는 Web.config 파일이 아닙니다.) 다음 그림에서 빨간색으로 표시된 Web.config 파일을 열어야 합니다.


Web.config 파일의 <connectionStrings> 요소에 다음의 연결 문자열을 추가합니다.
<add name="MovieDBContext" 
   connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" 
   providerName="System.Data.SqlClient" 
/>
다음 예제는 새로운 연결 문자열이 추가된 Web.config 파일의 일부를 보여주고 있습니다:
<connectionStrings>
  <add name="DefaultConnection" 
       connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcMovie-2012213181139;Integrated Security=true" 
       providerName="System.Data.SqlClient" 
  />    
  <add name="MovieDBContext" 
    connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" 
    providerName="System.Data.SqlClient" 
  />
</connectionStrings>
지금까지 살펴본 얼마 안되는 코드와 XML이 데이터베이스에 존재하는 영화 데이터를 나타내거나 저장하기 위해서 작성해야 할 코드의 전부입니다.

다음 단계에서는, 영화 데이터를 출력하는데 사용되고, 사용자들이 새로운 영화 정보를 생성할 수 있게 해주는, 새로운 MoviesController 클래스를 작성해 보겠습니다.


다음 강좌에서 계속 이어집니다...


authored by

  quamdiu
  2013-01-06(10:24)
캐릭 이미지
감사합니다.
  sisyphus2020
  2013-08-02(15:16)
캐릭 이미지
잘 봤습니다.
  cogoree
  2013-08-07(14:01)
캐릭 이미지
감사합니당.
  romanticiiz
  2013-11-16(15:19)
캐릭 이미지
MVC에 대해서 프로젝트를 진행하게 되어서 보고있는데
잘봤습니다..^^ 감사합니다 ㅎ


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

로딩 중입니다...

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