HTML5 달력 및 jQuery UI 날짜선택 팝업 달력 사용하기 - 파트 4

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

본 자습서에서는 편집 템플릿(Editor Templates)이나 출력 템플릿(Display Templates) 기능을 활용해서 ASP.NET MVC 웹 응용 프로그램에서 jQuery UI 날짜선택 팝업 달력을 사용하는 기본적인 방법을 살펴봅니다.

날짜 편집을 위한 템플릿 추가하기

이번 절에서는 ASP.NET MVC가 Date 열거형 DataType 어트리뷰트로 지정된 모델 속성 편집을 위한 UI를 출력할 때 적용되는 날짜 편집 템플릿을 작성해보겠습니다. 이 템플릿은 날짜만 렌더하고 시간은 출력하지 않을 것입니다. 더불어, 날짜 편집 방식의 한 가지로 jQuery UI 날짜선택 팝업 달력을 제공할 것입니다.

먼저 Movie.cs 파일을 열고, 다음 코드처럼 ReleaseDate 속성에 Date 열거형이 지정된 DataType 어트리뷰트를 추가합니다:

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

이렇게 코드를 변경하면 ReleaseDate 필드는 출력 템플릿과 편집 템플릿 양쪽 모두에서 시간 부분이 제거된 상태로 출력됩니다. 또한, 응용 프로그램의 Views\Shared\EditorTemplates 폴더나 Views\Movies\EditorTemplates 폴더에 date.cshtml이라는 이름의 템플릿이 존재한다면, DateTime 형식의 속성이 편집되는 모든 경우에 해당 템플릿이 사용될 것입니다. 반면, 해당 템플릿이 존재하지 않는 경우에는 내장 ASP.NET 템플릿 시스템에 의해 날짜만 출력될 것입니다.

컨트롤+F5 키를 눌러서 응용 프로그램을 실행한 다음, Edit 링크를 클릭해서 살펴보면 ReleaseDate 입력 필드에 날짜 부분만 나타나는 것을 확인할 수 있습니다.

편집 템플릿을 추가하려면 솔루션 탐색기에서 Views 폴더 하위의 Shared 폴더를 열고, Views\Shared\EditorTemplates 폴더를 마우스 오른쪽 버튼으로 클릭합니다. (역주: EditorTemplates 폴더가 존재하지 않으면 새로 추가합니다.)

컨텍스트 메뉴에서 추가(Add)를 클릭한 다음, 뷰(View)를 클릭하면, 뷰 추가(Add View) 대화 상자가 나타납니다.

뷰 이름(View name) 입력란에는 "Date"라고 입력합니다. 그리고, 부분 뷰로 만들기(Create as a partial view) 체크 박스를 선택합니다. 반면, 레이아웃 또는 마스터 페이지 사용(Use a layout or master page) 체크 박스와 강력한 형식의 뷰 만들기(Create a strongly-typed view) 체크 박스는 선택하지 말아야 합니다.

마지막으로 추가(Add) 버튼을 클릭합니다. 그러면, Views\Shared\EditorTemplates\Date.cshtml 템플릿이 생성될 것입니다.

다음의 코드를 방금 생성한 Views\Shared\EditorTemplates\Date.cshtml 템플릿에 추가합니다.

@model DateTime
Using Date Template
@Html.TextBox("", String.Format("{0:d}", Model.ToShortDateString()),
    new { @class = "datefield", type = "date" })

이 코드의 첫 번째 줄은 모델의 형식이 DateTime라는 것을 선언합니다. 편집 템플릿이나 출력 템플릿에서 반드시 이런 식으로 모델 형식을 선언할 필요는 없지만, 이처럼 모델 형식을 선언하면 컴파일 타임에 뷰에 전달되는 모델을 검사할 수 있으므로 유용합니다. (또한 Visual Studio에서 뷰 모델에 대한 인텔리센스 지원을 받을 수 있다는 또 다른 장점도 있습니다.) 모델의 형식이 선언되지 않은 경우, ASP.NET MVC는 모델을 dynamic 형식으로 간주하며, 이 때에는 컴파일 타임 형식 검사가 수행되지 않습니다. 이렇게 모델을 DateTime 형식으로 선언하면, 뷰가 강력한 형식이 됩니다.

두 번째 코드 줄은 단지 날짜 필드 앞에 "Using Date Template"라고 출력하기 위한 리터럴 HTML 마크업입니다. 이 마크업은 정상적으로 date 템플릿이 사용되고 있는지를 확인하기 위한 용도로 사용되는 임시적인 표시일 뿐입니다.

마지막 줄은 텍스트 박스로 렌더될 input 필드를 출력하기 위한 Html.TextBox 도우미 메서드입니다. 이 메서드의 세 번째 매개변수는 익명 형식을 사용해서 텍스트 박스의 class 어트리뷰트를 datefield로, type 어트리뷰트를 date로 설정하기 위한 매개변수입니다. (class는 C#의 예약어이므로, C# 파서에서 class 어트리뷰트를 사용하려면 @ 문자를 지정해야만 합니다.)

여기서 type 어트리뷰트에 지정된 date 형식은 HTML5의 입력 형식 중 하나로, HTML5를 인식하는 브라우저에서 HTML5 달력 컨트롤을 렌더하도록 해줍니다. 잠시 뒤에는 datefield CSS 클래스를 이용해서 jQuery 날짜선택 팝업과 Html.TextBox 요소를 결합시키는 자바스크립트를 추가해볼 것입니다.

다시 컨트롤+F5 키를 눌러서 응용 프로그램을 실행합니다. 그러면, 다음 이미지와 같이 ReleaseDate 텍스트 입력 박스의 바로 앞 부분에 템플릿이 출력하는 "Using Date Template" 문구가 나타나 있는 것을 확인할 수 있으며, 이 결과를 통해서 편집 뷰의 ReleaseDate 속성이 편집 템플릿을 통해서 출력되고 있다는 사실을 알 수 있습니다:

이번에는 브라우저 자체의 기능을 이용해서 페이지의 소스를 살펴보시기 바랍니다. (가령, 인터넷 익스플로러에서는 페이지를 마우스 오른쪽 버튼으로 클릭한 다음, 소스 보기(View source)를 선택합니다.) 다음 마크업은 그렇게 살펴본 페이지의 마크업 중 일부로, 렌더된 HTML의 class 어트리뷰트와 type 어트리뷰트를 보여주고 있습니다.

<input class="datefield" data-val="true" data-val-required="Date is required"
       id="ReleaseDate" name="ReleaseDate" type="date" value="1/11/1989" />  

다시 Views\Shared\EditorTemplates\Date.cshtml 템플릿으로 돌아와서 "Using Date Template" 마크업을 제거합니다. 템플릿의 새로운 전체 코드는 다음과 같습니다:

@model DateTime
@Html.TextBox("", String.Format("{0:d}", Model.ToShortDateString()),
    new { @class = "datefield", type = "date" })

NuGet을 이용하여 jQuery UI 날짜선택 팝업 달력 추가하기

이번 절에서는 date-편집 템플릿에 jQuery UI 날짜선택 팝업 달력을 추가해보겠습니다. jQuery UI 라이브러리는 jQuery 자바스크립트 라이브러리를 기반으로 구현되었으며, 에니메이션, 고급 효과, 사용자 정의 위젯 등의 지원을 제공해줍니다. 날짜선택 팝업 달력은 문자열을 직접 입력하는 대신 달력을 사용해서 쉽고 자연스럽게 날짜를 입력할 수 있게 해줄 뿐만 아니라, 유효한 날짜만 입력할 수 있도록 도와줍니다. 일반적인 텍스트 입력으로는 2/33/1999 (1999년 2월 33일) 등과 같은 이상한 날짜를 입력할 수도 있지만, jQuery UI 날짜선택 팝업 달력은 이를 허용하지 않습니다. (역주: 텍스트 입력 자체를 막지는 않습니다. 달력 팝업을 사용할 때의 이점을 설명하는 것 뿐입니다.)

먼저 jQuery UI 라이브러리를 설치해야 합니다. 이를 위해서 Visual Studio 2010 및 Visual Web Developer의 SP1 버전에 포함된 패키지 관리자인 NuGet을 이용해보도록 하겠습니다. 만약, Visual Web Developer를 사용하고 있다면 도구(Tools) 메뉴의 라이브러리 패키지 관리자(Library Package Manager)에서 NuGet 패키지 관리(Manage NuGet Packages)를 선택합니다.

노트: 도구(Tools) 메뉴에 라이브러리 패키지 관리자(Library Package Manager) 하위 메뉴가 나타나지 않는다면, NuGet 웹사이트의 Installing NuGet 페이지의 지시에 따라 NuGet을 설치합니다. 만약, Visual Web Developer 대신 Visual Studio를 사용하고 있다면 도구(Tools) 메뉴에서 라이브러리 패키지 관리자(Library Package Manager)를 선택한 다음, 라이브러리 패키지 참조 추가(Add Library Package Reference)를 선택합니다.

그러면, [프로젝트명] - NuGet 패키지 관리(MVCMovie - Manage NuGet Packages) 대화 상자가 나타나는데, 좌측의 온라인(Online) 탭을 선택한 다음, 검색 박스에 "jQuery.UI"라고 검색어를 입력합니다. 그리고, 잠시 후 나타나는 검색 결과에서 jQuery UI WIdgets:Datepicker를 선택하고 설치(Install) 버튼을 클릭합니다.

그러면, NuGet이 자동으로 다음과 같은 jQuery UI 코어와 jQuery UI 날짜 선택기의 디버그 버전과 축소 버전을 프로젝트에 추가해줍니다:

  • jquery.ui.core.js
  • jquery.ui.core.min.js
  • jquery.ui.datepicker.js
  • jquery.ui.datepicker.min.js
노트: 디버그 버전(확장자가 .min.js가 아닌 파일들)은 디버그 시 유용하긴 하지만, 운영 사이트에는 축소 버전만 포함시켜야 합니다.

편집 템플릿에서 실제로 jQuery 날짜 선택기를 사용하려면, 달력 위젯과 편집 템플릿을 결합시켜주기 위한 jQuery 스크립트를 작성해야 합니다. 솔루션 탐색기에서 Scripts 폴더를 마우스 오른쪽 버튼으로 클릭한 다음, 추가(Add), 새 항목(New Item)을 차례대로 선택합니다. 그런 다음, 새 항목 추가(Add New Item) 대화 상자에서 JScript 파일(JScript File)을 선택하고 파일 이름을 DatePickerReady.js라는 지정해서 새로운 파일을 생성합니다.

그리고, 다음 코드를 DatePickerReady.js 파일에 추가합니다:

$(function () {
    $(".datefield").datepicker();
});

여러분이 jQuery에 익숙하지 않을 수도 있으므로 이 코드를 간단히 설명하도록 하겠습니다. 첫 번째 줄은 "jQuery ready" 함수로, 페이지에 존재하는 모든 DOM 요소들이 로드된 직후에 호출됩니다. 두 번째 줄은 class 어트리뷰트의 이름이 datefield인 모든 DOM 요소들을 선택한 다음, 그 모든 요소들을 대상으로 datepicker 함수를 각각 한 번씩 호출합니다. (본 자습서의 앞 부분에서 Views\Shared\EditorTemplates\Date.cshtml 템플릿에 datefield class 어트리뷰트를 추가했었다는 점을 기억하시기 바랍니다.)

이제 Views\Shared\_Layout.cshtml 파일을 열고, 날짜 선택기를 사용하기 위해 필요한 다음 파일들에 대한 참조를 추가해야 합니다:

  • Content/themes/base/jquery.ui.core.css
  • Content/themes/base/jquery.ui.datepicker.css
  • Content/themes/base/jquery.ui.theme.css
  • jquery.ui.core.min.js
  • jquery.ui.datepicker.min.js
  • DatePickerReady.js

다음은 Views\Shared\_Layout.cshtml 파일의 head 요소 하단에 추가해야 할 실제 코드를 보여주고 있습니다.

    <link href="@Url.Content("~/Content/themes/base/jquery.ui.core.css")"
        rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.datepicker.css")"
        rel="stylesheet"  type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.theme.css")"
        rel="stylesheet" type="text/css" />
  
    <script src="@Url.Content("~/Scripts/jquery.ui.core.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.datepicker.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/DatePickerReady.js")"
        type="text/javascript"></script>

이 작업을 마치고 나면, Views\Shared\_Layout.cshtml 파일의 head 섹션은 다음과 같은 모습일 것입니다:

<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
        rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
        type="text/javascript"></script>
  
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.core.css")"
        rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.datepicker.css")"
        rel="stylesheet"  type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.theme.css")"
        rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery.ui.core.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.datepicker.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/DatePickerReady.js")"
        type="text/javascript"></script>
</head>

이 코드에 사용된 URL content 도우미 메서드는 리소스의 경로를 절대 경로로 변환해줍니다. 응용 프로그램이 IIS에서 실행될 때, 리소스들을 올바르게 참조되려면 반드시 @URL.Content 메서드를 사용해야 합니다.

컨트롤+F5 키를 눌러서 응용 프로그램을 실행시킵니다. 그리고, Edit 링크를 선택한 다음 입력 캐럿을 ReleaseDate 필드에 위치시켜보면, 다음과 같이 jQuery UI 팝업 달력이 나타날 것입니다.

대부분의 jQuery 컨트롤들처럼 날짜 선택기도 많은 부분을 사용자 정의할 수 있습니다. 이에 대한 더 많은 정보는 jQuery UI 사이트의 Visual customization: Designing a jQuery UI theme를 참고하시기 바랍니다.

HTML5 날짜 입력 컨트롤 지원하기

점차 더 많은 브라우저들이 HTML5를 지원하게 됨에 따라, 여러분은 jQuery UI 달력 대신 date 입력 요소 등의 브라우저 자체의 HTML5 입력 사용을 선호하게 될 것입니다. 응용 프로그램에 약간의 로직을 추가해서 브라우저가 HTML5 컨트롤을 지원하는 경우에는 자동으로 해당 기능을 사용하도록 만들 수 있습니다. DatePickerReady.js 파일의 내용을 다음과 같이 수정합니다:

if (!Modernizr.inputtypes.date) {
    $(function () {
        $(".datefield").datepicker();
    });
}

이 스크립트에서 첫 번째 줄은 HTML5의 날짜 입력 지원 여부를 확인하기 위해서 Modernizr를 사용하고 있습니다. 만약, 지원이 되지 않는다면, 대신 jQuery UI 날짜 선택기가 결합됩니다. (Modernizr는 HTML5 및 CSS3의 네이티브 구현이 사용 가능한지 여부를 감지하기 위한, 오픈 소스 자바스크립트 라이브러리입니다. Modernizr는 여러분이 생성하는 모든 ASP.NET MVC 프로젝트에 자동으로 포함됩니다.)

변경을 마치고나면, 오페라 11 등과 같은 HTML5를 지원하는 브라우저를 사용해서 테스트를 할 수 있습니다. HTML5 지원 브라우저를 사용해서 응용 프로그램을 실행한 다음, 특정 영화 항목을 편집해봅니다. 그러면, jQuery UI 팝업 달력 대신 브라우저 자체의 HTML5 날짜 컨트롤이 나타날 것입니다:

다양한 브라우저의 새로운 버전들이 지속적으로 HTML5를 구현해나가고 있으므로, 지금과 같은 시점에서는 HTML5를 지원하기 위한 폭넓은 코드들을 웹사이트에 적절히 추가해놓는 것이 바람직할 것입니다. 가령, HTML5 날짜 컨트롤을 부분적으로만 지원하는 브라우저들에 대응하기 위한 보다 개선된 DatePickerReady.js 스크립트는 다음과 같습니다.

if (!Modernizr.inputtypes.date) {
    $(function () {
        $("input[type='date']")
                    .datepicker()
                    .get(0)
                    .setAttribute("type", "text");
    })
}

이 스크립트는 우선 HTML5 날짜 컨트롤을 완벽하게 지원하지 않는 date 형식의 HTML5 input 요소들을 선택합니다. 그런 다음, 해당 요소들을 대상으로 jQuery UI 팝업 달력을 결합시키고 type 어트리뷰트의 값을 date에서 text로 변경합니다. 이런 방식으로 type 어트리뷰트를 date에서 text로 변경하고 나면 부분적인 HTML5 날짜 지원 기능이 제거됩니다. 이 예제 스크립트보다 훨씬 더 정교한 DatePickerReady.js 스크립트는 JSFIDDLE에서 찾아볼 수 있습니다.

템플릿에 Nullable 날짜 지원 추가하기

만약, 지금까지 살펴본 날짜 템플릿들 중 하나를 사용할 때, 날짜를 null로 전달한다면 런타임 오류가 발생할 것입입니다. 날짜 템플릿을 보다 견고하게 만들기 위해서는 null 값도 정상적으로 처리할 수 있도록 변경해야 합니다. Nullable 날짜를 지원하려면, Views\Shared\DisplayTemplates\DateTime.cshtml 파일의 코드를 다음과 같이 변경합니다:

@model Nullable<DateTime>
@(Model != null ? string.Format("{0:d}", Model) : string.Empty)

이 코드는 모델이 null인 경우 빈 문자열을 반환합니다.

그리고, Views\Shared\EditorTemplates\Date.cshtml 파일의 코드도 다음과 같이 변경합니다:

@model Nullable<DateTime>
@{
    DateTime dt = DateTime.Now;
    if (Model != null)
    {
       dt = (System.DateTime) Model;
    }
 
    @Html.TextBox(
        "", 
        String.Format("{0:d}", dt.ToShortDateString()), 
        new { @class = "datefield", type = "date" }
    )
}

이 코드는 모델이 null이 아닌 경우에는 모델의 DateTime 값을 사용하고, null인 경우에는 현재 날짜를 대신 사용합니다.

마무리

본 자습서에서는 ASP.NET 템플릿 도우미에 대한 기본적인 내용들을 살펴보고, ASP.NET MVC 응용 프로그램에서 jQuery UI 날짜선택 달력 팝업을 사용하는 방법을 살펴봤습니다. 더 많은 정보들은 다음의 자료들을 참고하시기 바랍니다:

  1. ASP.NET MVC에서 jQuery UI 날짜선택 달력 팝업을 사용하는 방법에 대한 더 자세한 정보는 Rajeesh의 JQueryUI Datepicker in ASP.Net MVC 블로그 문서를 참고하시기 바랍니다.
  2. jQuery UI에 관한 더 많은 정보들은 jQuery UI를 참고하시기 바랍니다.
  3. 날짜선택 컨트롤을 지역화하는 방법에 관해서는 UI/Datepicker/Localization을 참고하시기 바랍니다.
  4. ASP.NET MVC 템플릿에 관한 더 많은 정보는 Brad Wilson의 ASP.NET MVC 2 Templates 블로그 시리즈들을 참고하시기 바랍니다. 비록 이 시리즈들은 ASP.NET MVC 2를 대상으로 작성되었지만, 그 내용들은 ASP.NET MVC의 현재 버전에서도 아직 유효합니다.