편집 메서드 및 편집 보기 검사(VB)

작성자: Rick Anderson

이 자습서에서는 Microsoft Visual Studio의 무료 버전인 Microsoft Visual Web Developer 2010 Express Service Pack 1을 사용하여 ASP.NET MVC 웹 애플리케이션을 빌드하는 기본 사항을 설명합니다. 시작하기 전에 아래에 나열된 필수 구성 요소를 설치했는지 확인합니다. 웹 플랫폼 설치 관리자 링크를 클릭하여 모두 설치할 수 있습니다. 또는 다음 링크를 사용하여 필수 구성 요소를 개별적으로 설치할 수 있습니다.

Visual Web Developer 2010 대신 Visual Studio 2010을 사용하는 경우 Visual Studio 2010 필수 구성 요소 링크를 클릭하여 필수 구성 요소를 설치합니다.

VB.NET 소스 코드가 있는 Visual Web Developer 프로젝트는 이 항목과 함께 사용할 수 있습니다. VB.NET 버전을 다운로드합니다. C#을 선호하는 경우 이 자습서의 C# 버전 으로 전환합니다.

이 섹션에서는 영화 컨트롤러에 대해 생성된 작업 메서드 및 뷰를 살펴봅니다. 그런 다음 사용자 지정 검색 페이지를 추가합니다.

애플리케이션을 실행하고 브라우저의 Movies 주소 표시줄에 URL에 /Movies 를 추가하여 컨트롤러로 이동합니다. 마우스 포인터를 편집 링크 위에 놓으면 링크가 연결되는 URL을 볼 수 있습니다.

스크린샷은 선택한 영화 중 하나에 대한 편집 링크가 있는 MVC 이동 앱을 보여줍니다.

편집 링크는 Views\Movies\Index.vbhtml 뷰의 메서드에 의해 Html.ActionLink 생성되었습니다.

@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |

코드 편집기에서 Html.ActionLink를 보여 주는 스크린샷

Html 개체는 기본 클래스의 속성을 WebViewPage 사용하여 노출되는 도우미입니다. ActionLink 도우미의 메서드를 사용하면 컨트롤러의 작업 메서드에 연결되는 HTML 하이퍼링크를 쉽게 생성할 수 있습니다. 메서드의 ActionLink 첫 번째 인수는 렌더링할 링크 텍스트(예: <a>Edit Me</a>)입니다. 두 번째 인수는 호출할 작업 메서드의 이름입니다. 마지막 인수는 경로 데이터를 생성하는 익명 개체 입니다(이 경우 ID는 4).

이전 이미지에 표시된 생성된 링크는 입니다 http://localhost:xxxxx/Movies/Edit/4. 기본 경로는 URL 패턴을 {controller}/{action}/{id}사용합니다. 따라서 ASP.NET 매개 변수 ID 가 4인 컨트롤러의 Movies 작업 메서드에 대한 요청 Edit 으로 변환 http://localhost:xxxxx/Movies/Edit/4 됩니다.

쿼리 문자열을 사용하여 작업 메서드 매개 변수를 전달할 수도 있습니다. 예를 들어 URL http://localhost:xxxxx/Movies/Edit?ID=4 은 4의 매개 변수 ID 를 컨트롤러의 Edit 작업 메서드에 전달합니다 Movies .

EditQueryString

컨트롤러를 Movies 엽니다. 아래에는 두 가지 Edit 작업 메서드가 나와 있습니다.

'
' GET: /Movies/Edit/5

Function Edit(id As Integer) As ViewResult
    Dim movie As Movie = db.Movies.Find(id)
    Return View(movie)
End Function

'
' POST: /Movies/Edit/5

<HttpPost()>
Function Edit(movie As Movie) As ActionResult
    If ModelState.IsValid Then
        db.Entry(movie).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    Return View(movie)
End Function

두 번째 Edit 작업 메서드 앞에 HttpPost 특성이 지정되어 있는 것에 유의하세요. 이 특성은 POST 요청에 대해서만 메서드의 Edit 오버로드를 호출할 수 있도록 지정합니다. 첫 번째 편집 메서드에 HttpGet 특성을 적용할 수 있지만 기본값이므로 필요하지 않습니다. (특성을 메서드로 HttpGet 암시적으로 할당된 작업 메서드를 HttpGet 참조합니다.)

메서드는 HttpGetEdit 동영상 ID 매개 변수를 사용하고 Entity Framework Find 메서드를 사용하여 동영상을 조회한 다음 선택한 동영상을 편집 보기로 반환합니다. 스캐폴딩 시스템은 Edit 보기를 만들 때 Movie 클래스를 검토하고 클래스의 각 속성에 대해 <label><input> 요소를 렌더링하기 위한 코드를 만들었습니다. 다음 예제에서는 생성된 편집 보기를 보여줍니다.

@ModelType MvcMovie.Movie

@Code
    ViewData("Title") = "Edit"
End Code

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@Using Html.BeginForm()
    @Html.ValidationSummary(True)
    @<fieldset>
        <legend>Movie</legend>

        @Html.HiddenFor(Function(model) model.ID)

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Title)
            @Html.ValidationMessageFor(Function(model) model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ReleaseDate)
            @Html.ValidationMessageFor(Function(model) model.ReleaseDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Genre)
            @Html.ValidationMessageFor(Function(model) model.Genre)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Price)
            @Html.ValidationMessageFor(Function(model) model.Price)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
End Using

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

뷰 템플릿 @ModelType MvcMovie.Models.Movie 에 파일 맨 위에 문이 있는 방식을 확인합니다. 이렇게 하면 뷰 템플릿에 대한 모델이 형식 Movie이 될 것으로 예상됩니다.

스캐폴드된 코드는 여러 도우미 메서드 를 사용하여 HTML 태그를 간소화합니다. 도우미는 Html.LabelFor 필드의 이름("Title", "ReleaseDate", "Genre" 또는 "Price")을 표시합니다. 도우미는 Html.EditorFor HTML <input> 요소를 표시합니다. 도우미는 Html.ValidationMessageFor 해당 속성과 연결된 유효성 검사 메시지를 표시합니다.

애플리케이션을 실행하고 /Movies URL로 이동합니다. Edit 링크를 클릭합니다. 브라우저에서 페이지의 소스를 봅니다. 페이지의 HTML은 다음 예제와 같습니다. (명확성을 위해 메뉴 태그가 제외되었습니다.)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Edit</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
    <script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>MVC Movie App</h1>
            </div>
           ...
        </header>
        <section id="main">

<h2>Edit</h2>

<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

<form action="/Movies/Edit/4" method="post">    <fieldset>
        <legend>Movie</legend>

        <input data-val="true" data-val-number="The field ID must be a number." 
    data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

        <div class="editor-label">
            <label for="Title">Title</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
            <span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="ReleaseDate">ReleaseDate</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required." 
    id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
            <span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Genre">Genre</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
            <span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Price">Price</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." 
    data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" />
            <span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
</form>
<div>
    <a href="/Movies">Back to List</a>
</div>

        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

요소는 <input> 특성이 action/Movies/Edit URL에 게시되도록 설정된 HTML <form> 요소에 있습니다. 편집 단추를 클릭하면 양식 데이터가 서버에 게시됩니다.

POST 요청 처리

다음 목록은 Edit 작업 메서드의 HttpPost 버전을 보여줍니다.

'
' POST: /Movies/Edit/5

<HttpPost()>
Function Edit(movie As Movie) As ActionResult
    If ModelState.IsValid Then
        db.Entry(movie).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    Return View(movie)
End Function

ASP.NET 프레임워크 모델 바인더는 게시된 양식 값을 사용하고 매개 변수로 전달되는 개체를 movie 만듭니다Movie. ModelState.IsValid 코드의 검사 양식에 제출된 데이터를 사용하여 개체를 수정 Movie 할 수 있음을 확인합니다. 데이터가 유효한 경우 코드는 영화 데이터를 Movies instance 컬렉션에 MovieDBContext 저장합니다. 그런 다음, 코드는 데이터베이스에 대한 변경 내용을 유지하는 의 MovieDBContext메서드를 SaveChanges 호출하여 새 동영상 데이터를 데이터베이스에 저장합니다. 데이터를 저장한 후 코드는 사용자를 클래스의 MoviesController 작업 메서드로 Index 리디렉션하여 업데이트된 동영상이 영화 목록에 표시되도록 합니다.

게시된 값이 유효하지 않으면 양식에서 다시 표시됩니다. Edit.vbhtml 뷰 템플릿의 도우미는 Html.ValidationMessageFor 적절한 오류 메시지를 표시합니다.

abcNotValid

로캘에 대한 참고 사항 일반적으로 영어 이외의 로캘로 작업하는 경우 영어 이외의 로 캘을 사용하여 MVC 3 유효성 검사 ASP.NET 지원을 참조하세요.

Edit 메서드를 보다 강력하게 만들기

스캐폴딩 시스템에서 생성된 메서드는 HttpGetEdit 전달된 ID가 유효한지 검사 않습니다. 사용자가 URL(http://localhost:xxxxx/Movies/Edit)에서 ID 세그먼트를 제거하면 다음 오류가 표시됩니다.

Null_ID

사용자는 데이터베이스에 없는 ID(예: http://localhost:xxxxx/Movies/Edit/1234)를 전달할 수도 있습니다. 이 제한을 해결하기 위해 작업 메서드를 HttpGetEdit 두 가지 변경하면 됩니다. 먼저 ID가 ID 명시적으로 전달되지 않으면 매개 변수를 기본값 0으로 변경합니다. 동영상 개체를 보기 템플릿으로 반환하기 전에 메서드가 Find 실제로 동영상을 찾았는지 검사 수도 있습니다. 업데이트 Edit 된 메서드는 다음과 같습니다.

Public Function Edit(Optional ByVal id As Integer = 0) As ActionResult
    Dim movie As Movie = db.Movies.Find(id)
    If movie Is Nothing Then
        Return HttpNotFound()
    End If
    Return View(movie)
End Function

동영상을 찾을 수 없으면 메서드가 HttpNotFound 호출됩니다.

모든 메서드는 HttpGet 비슷한 패턴을 따릅니다. 영화 개체(또는 의 경우 Index개체 목록)를 가져와서 뷰에 모델을 전달합니다. 메서드는 Create 빈 동영상 개체를 만들기 뷰에 전달합니다. 생성, 편집, 삭제 또는 어떤 식으로든 데이터를 수정하는 모든 메서드는 메서드의 HttpPost 오버로드에서 해당 작업을 수행합니다. HTTP GET 메서드에서 데이터를 수정하는 것은 보안 위험입니다. 블로그 게시물 항목 ASP.NET MVC 팁 #46 – 보안 허점을 만들기 때문에 링크 삭제를 사용하지 마세요. GET 메서드에서 데이터를 수정하면 HTTP 모범 사례 및 아키텍처 REST 패턴도 위반됩니다. 이 패턴은 GET 요청이 애플리케이션의 상태를 변경하지 않도록 지정합니다. 즉, GET 작업을 수행하는 것은 부작용이 없는 안전한 작업이어야 합니다.

검색 방법 및 검색 보기 추가

이 섹션에서는 장르 또는 이름으로 영화를 검색할 수 있는 작업 메서드를 추가 SearchIndex 합니다. /Movies/SearchIndex URL을 사용하여 사용할 수 있습니다. 요청에는 사용자가 동영상을 검색하기 위해 입력할 수 있는 입력 요소가 포함된 HTML 양식이 표시됩니다. 사용자가 양식을 제출하면 작업 메서드는 사용자가 게시한 검색 값을 가져오고 값을 사용하여 데이터베이스를 검색합니다.

SearchIndx_SM

SearchIndex 양식 표시

먼저 기존 MoviesController 클래스에 SearchIndex 작업 메서드를 추가합니다. 메서드는 HTML 양식이 포함된 뷰를 반환합니다. 코드는 다음과 같습니다.

Public Function SearchIndex(ByVal searchString As String) As ActionResult
    Dim movies = From m In db.Movies
                 Select m 

    If Not String.IsNullOrEmpty(searchString) Then 
        movies = movies.Where(Function(s) s.Title.Contains(searchString)) 
    End If
    Return View(movies) 
End Function

메서드의 SearchIndex 첫 번째 줄은 다음 LINQ 쿼리를 만들어 영화를 선택합니다.

Dim movies = From m In db.Movies    Select m

쿼리는 이 시점에서 정의되지만 아직 데이터 저장소에 대해 실행되지 않았습니다.

매개 변수에 searchString 문자열이 포함된 경우 영화 쿼리는 다음 코드를 사용하여 검색 문자열 값을 필터링하도록 수정됩니다.

String.IsNullOrEmpty(searchString)가 아닌 경우
movies = movies. Where(function)s.Title.Contains(searchString))
End If

LINQ 쿼리는 정의되거나 또는 OrderBy와 같은 Where 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 즉, 실현된 값이 실제로 반복되거나 ToList 메서드가 호출될 때까지 식의 평가가 지연됩니다. 샘플에서 SearchIndex 쿼리는 SearchIndex 보기에서 실행됩니다. 지연된 쿼리 실행에 대한 자세한 내용은 쿼리 실행을 참조하세요.

이제 사용자에게 양식을 표시할 뷰를 구현 SearchIndex 할 수 있습니다. 메서드 내부를 마우스 오른쪽 단추로 SearchIndex 클릭한 다음 보기 추가를 클릭합니다. 보기 추가 대화 상자에서 개체를 모델 클래스로 뷰 템플릿에 전달 Movie 하도록 지정합니다. 스캐폴드 템플릿 목록에서 목록을 선택한 다음 추가를 클릭합니다.

AddSearchView

추가 단추를 클릭하면 Views\Movies\SearchIndex.vbhtml 보기 템플릿이 만들어집니다. 스캐폴드 템플릿 목록에서 목록을 선택했기 때문에 Visual Web Developer는 보기에서 일부 기본 콘텐츠를 자동으로 생성(스캐폴드)합니다. 스캐폴딩에서 HTML 양식을 만들었습니다. 클래스를 검사하고 클래스의 Movie 각 속성에 대한 요소를 렌더링 <label> 하는 코드를 만들었습니다. 아래 목록에서는 생성된 만들기 뷰를 보여 줍니다.

@ModelType IEnumerable(Of MvcMovie.Movie)

@Code
    ViewData("Title") = "SearchIndex"
End Code

<h2>SearchIndex</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Title
        </th>
        <th>
            ReleaseDate
        </th>
        <th>
            Genre
        </th>
        <th>
            Price
        </th>
        <th></th>
    </tr>

@For Each item In Model
    Dim currentItem = item
    @<tr>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Title)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Genre)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
        </td>
    </tr>
Next

</table>

애플리케이션을 실행하고 /Movies/SearchIndex로 이동합니다. 쿼리 문자열(예: ?searchString=ghost)을 URL에 추가합니다. 필터링된 영화가 표시됩니다.

SearchQryStr

라는 매개 변수를 갖도록 메서드의 SearchIndex 서명을 변경하는 경우 매개 변수 ididGlobal.asax 파일에 설정된 기본 경로의 자리 표시자와 일치 {id} 합니다.

{controller}/{action}/{id}

수정된 SearchIndex 메서드는 다음과 같습니다.

Public Function SearchIndex(ByVal id As String) As ActionResult
Dim searchString As String = id
Dim movies = From m In db.Movies
             Select m

If Not String.IsNullOrEmpty(searchString) Then
    movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If

Return View(movies)
End Function

이제 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 검색 제목을 전달할 수 있습니다.

SearchRouteData

그러나 사용자가 영화를 검색하려고 할 때마다 URL을 수정하리라고 기대하지는 않을 것입니다. 이제 영화를 필터링하는 데 도움이 되는 UI를 추가합니다. 경로 바인딩된 ID 매개 변수를 전달하는 방법을 테스트하기 위해 메서드의 SearchIndex 서명을 변경한 경우 메서드가 SearchIndex 라는 searchString문자열 매개 변수를 사용하도록 다시 변경합니다.

Views\Movies\SearchIndex.vbhtml 파일을 열고 바로 다음에 @Html.ActionLink("Create New", "Create")다음을 추가합니다.

@Code
    ViewData("Title") = "SearchIndex"
    Using (Html.BeginForm())
         @<p> Title: @Html.TextBox("SearchString") 
         <input type="submit" value="Filter" /></p>
        End Using
End Code

도우미는 여 <form>Html.BeginForm 태그를 만듭니다. 도우미는 Html.BeginForm 사용자가 필터 단추를 클릭하여 양식을 제출할 때 양식이 자체에 게시되도록 합니다.

애플리케이션을 실행하고 영화를 검색해 봅니다.

SearchIndxIE9_title

메서드의 오버로드가 SearchIndex 없습니다HttpPost. 메서드가 애플리케이션의 상태를 변경하지 않고 데이터를 필터링하기 때문에 필요하지 않습니다. 다음 HttpPostSearchIndex 메서드를 추가한 경우 작업 호출자는 메서드와 일치SearchIndexHttpPost하고 메서드는 HttpPostSearchIndex 아래 이미지와 같이 실행됩니다.

<HttpPost()>
 Public Function SearchIndex(ByVal fc As FormCollection, ByVal searchString As String) As String
     Return "<h3> From [HttpPost]SearchIndex: " & searchString & "</h3>"
 End Function

SearchPostGhost

장르별 검색 추가

메서드 버전을 추가한 HttpPostSearchIndex 경우 지금 삭제합니다.

다음으로 사용자가 장르별로 영화를 검색할 수 있도록 하는 기능을 추가합니다. SearchIndex 메서드를 다음 코드로 바꿉니다.

Public Function SearchIndex(ByVal movieGenre As String, ByVal searchString As String) As ActionResult
    Dim GenreLst = New List(Of String)()

    Dim GenreQry = From d In db.Movies
                   Order By d.Genre
                   Select d.Genre
    GenreLst.AddRange(GenreQry.Distinct())
    ViewBag.movieGenre = New SelectList(GenreLst)

    Dim movies = From m In db.Movies
                 Select m

    If Not String.IsNullOrEmpty(searchString) Then
        movies = movies.Where(Function(s) s.Title.Contains(searchString))
    End If

    If String.IsNullOrEmpty(movieGenre) Then
        Return View(movies)
    Else
        Return View(movies.Where(Function(x) x.Genre = movieGenre))
    End If

End Function

이 버전의 메서드는 SearchIndex 추가 매개 변수, 즉 movieGenre를 사용합니다. 처음 몇 줄의 코드는 데이터베이스에서 영화 장르를 저장할 개체를 만듭니 List 다.

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

Dim GenreQry = From d In db.Movies
                   Order By d.Genre
                   Select d.Genre

코드는 제네릭 List 컬렉션의 메서드를 사용하여 AddRange 목록에 모든 고유 장르를 추가합니다. (한정자가 없으면 Distinct 중복 장르가 추가됩니다. 예를 들어 코미디는 샘플에서 두 번 추가됩니다.) 그런 다음, 코드는 장르 목록을 개체에 ViewBag 저장합니다.

다음 코드는 매개 변수를 검사 movieGenre 방법을 보여줍니다. 비어 있지 않은 경우 코드는 선택한 영화를 지정된 장르로 제한하도록 영화 쿼리를 추가로 제한합니다.

If String.IsNullOrEmpty(movieGenre) Then
        Return View(movies)
    Else
        Return View(movies.Where(Function(x) x.Genre = movieGenre))
    End If

장르별 검색을 지원하기 위해 SearchIndex 보기에 태그 추가

Html.DropDownList 도우미 바로 앞에 Views\Movies\SearchIndex.vbhtml 파일에 도우미를 TextBox 추가합니다. 완료된 태그는 다음과 같습니다.

<p>
    @Html.ActionLink("Create New", "Create")
    @Code
    ViewData("Title") = "SearchIndex"
    Using (Html.BeginForm())
         @<p> Genre: @Html.DropDownList("movieGenre", "All")
         Title: @Html.TextBox("SearchString") 
         <input type="submit" value="Filter" /></p>
        End Using
End Code
</p>

애플리케이션을 실행하고 /Movies/SearchIndex로 이동합니다. 장르, 영화 이름 및 두 기준별로 검색을 시도합니다.

이 섹션에서는 프레임워크에서 생성한 CRUD 작업 메서드 및 뷰를 검사했습니다. 사용자가 영화 제목 및 장르별로 검색할 수 있도록 하는 검색 작업 방법 및 보기를 만들었습니다. 다음 섹션에서는 모델에 속성을 Movie 추가하는 방법과 테스트 데이터베이스를 자동으로 만드는 이니셜라이저를 추가하는 방법을 살펴보겠습니다.