센로그

6. View 본문

게임/ASP.NET Core

6. View

seeyoun 2024. 4. 15. 23:15

◆ View

View는 MVC의 V로, 유저에게 보여줄 뷰(UI)를 의미한다.

 

요청이 들어오면 Action에서 데이터를 전달받아서 서비스를 통해 처리하고, 다시 돌려받은 데이터를 View로 전달할 것.

그리고 View에서 HTML을 생성해서 응답으로 돌려줄 것임.

 

이때 View가 어떻게 동작하는지 살펴보겟음.

 

현재 코드(기본 MVC 프로젝트)에서 View는 어디서 처리하고 있을까?

 

Index.cshtml을 보면 아래와 같이 작성되어있다

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

이렇듯 C# 과 HTML 을 섞은 것처럼 생긴 포맷을 Razor View Page 라고 함. (.cshtml)

 

 

Razoe Page 라는 템플릿을 사용해서 만들거나, .cshtml 확장자를 붙여주면 된다.

 

 

 

근데, HTML이랑 비슷한 것 같은데, 왜 굳이 cshtml을 사용하는걸까? 하는 의문점이 들 수 있다.

이는 HTML의 치명적 단점 -동적 처리가 애매함- 을 극복하기 위함이다!

  • if else와 같은 분기문 처리라거나,
  • 특정 리스트 개수에 따라서 HTML 태그의 개수가 유동적으로 변해야 하는 상황에서 처리가 애매해짐.

따라서 기본적으로는 HTML을 사용하되, C#을 이용해서 동적인 처리를 하겠다! 하는 게 cstml이다.

 

 

물론 처리는 이렇게 해도 최종 결과물은 HTML형태로 보내준다. 

  • 우리가 Razor Template을 만들면, Razor Template Engine이 이를 분석해서 최종 HTML 결과물을 동적으로 생성해줌.

 


Action - View(.cshtml) 매핑 방법

예제의 Action 함수들을 보면 View()를 반환해주곤 한다.

이때 다 똑같이 return View()를 쓰던데, 나랑 연결된 View를 어떻게 고를까?

 

View()를 호출하면, 기본적으로 다음 경로의 뷰를 반환한다.

Views/Controller/Action이름.cshtml

 

 

즉 Test 액션에서는 다음 뷰를 반환할 것!

 

 

 

굳이 사용할 일은 없겠지만, 다른 뷰를 호출할 수도 있다.

  • View("뷰이름") 을 호출하면 뷰이름에 해당하는 뷰를 반환한다. (상대경로)
  • 직접 경로 적어넣어도 됨. (절대경로)

 

예시 코드를 살펴보자.

다음은 Test.cshtml 코드이다.

@* 주석 *@
@* C# 코드가 시작한다는 의미로도 @를 이용함 *@
@* C# 코드는 공백을 만나면 끝난다. (공백이 포함된 코드면 괄호( )로 감싸야 함) *@
@* C#코드 영역은 { }로 감싸면 됨 *@

@{
    List<string> names = new List<string> { "Seeyoun", "Hoochu" };
}

<h1>Hello Razor Template</h1>
<h2>DateTime.Now</h2>
<h2>@DateTime.Now</h2>

@{
    if(names.Count < 5){
        <h1>데이터가 @names.Count 개 있어.</h1>
    }
    else{
        <h1>데이터가 5개 초과야!</h1>
    }
}

<ul>
    @for (int i = 0; i < names.Count; i++)
    {
        <li>@names[i]</li>
    }    
</ul>

 

 

실행해서 Test 뷰를 띄우면!!

 


Action -> View(.cshtml) 데이터 전달

그럼 액션에서 레이저 템플릿 파일(.cshtml)로 데이터를 넘겨줄 때는 어떻게 넘겨줄까?

 

여러 가지 방법이 있다.

  • ViewModel 사용 (BEST)
    • 데이터를 클래스로 만들어서 넘겨주는 방식.
    • 그냥 클래스일 뿐, 뭔가 특별한 것은 아님.
  • ViewData 사용
    • Dictionary<string, object> 형태인 ViewData를 사용해 key/value를 넘겨줄 수 있음
    • 간단한 데이터를 넘길 때 사용
    • ViewData["Message"] = "Data From Test"; 
      • key가 Message이고 value가 "Data From Test"
  • ViewBag
    • ViewData와 유사한데, Dictionary가 아니라 dynamic 문법을 사용하는 것
    • 굳이 쓸 일은^^ 없을듯

 


Action -> View(.cshtml) 데이터 전달 - ViewModel 사용

ViewModel을 사용하는 방법을 알아보자.

이걸 젤 많이 씀.

 

일단 데이터를 담을 클래스를 정의한다.

public class TestViewModel
{
    public List<string> Names { get; set; }
}

 

 

그리고 이 클래스를 통해 데이터를 넘겨주는 코드를 액션에다 작성해보자.

public IActionResult Test()
{
    TestViewModel testViewModel = new TestViewModel()
    {
        Names = new List<string>()
        {
            "Seeyoun", "Hoochu"
        }
    };

    return View(testViewModel);
}

 

 

레이저 템플릿 파일에서 ViewModel을 사용하려면, 넘어온 데이터가 어떤 형식인지 알려줘야 한다!

 

이를 위해 우선 다음 내용을 .cshtml 파일에 적어줘야 함

  • @model 데이터타입
    • @model TestViewModel

 

그러면 이제 코드에서 'Model' 프로퍼티를 이용해서 데이터에 접근할 수 있다.

 

 

ex) 

Test.cshtml에서 아까 작성했던 코드를 넘겨받은 데이터로 실행하는 코드로 바꿔보자.

@model TestViewModel	//넘어온 데이터는 TestViewMOdel 형태임을 알려줌


<h1>Hello Razor Template</h1>
<h2>DateTime.Now</h2>
<h2>@DateTime.Now</h2>

@{
    if (Model.Names.Count < 5)		//Model 프로퍼티를 통해 데이터에 접근 가능
    {
        <h1>데이터가 @Model.Names.Count 개 있어.</h1>
    }
    else{
        <h1>데이터가 5개 초과야!</h1>
    }
}

<ul>
    @for (int i = 0; i < Model.Names.Count; i++)
    {
        <li>@Model.Names[i]</li>
    }    
</ul>

 

 

잘 실행된다.

 

 


Layout

 

웹사이트에는 보통 공통적으로 등장하는 UI가 많다. (보통 Header, Footer 에 있는 UI들)

만약 이런 잘 변하지 않는 뷰들을 매번 새로 집어넣어서 보내주도록 하면 관리하기가 어려워질 것임.

  • 변경이 생기면 해당 뷰가 사용된 모든 곳을 고쳐야 하기 때문

따라서 이런 공통적인 UI들을 따로 빼서 관리하는 기능이 Layout이다.

 

 

기본 프로젝트에는 _Layout.cshtml 이라는 이름의 레이아웃이 있다.

 

Views/Shared/_Layout.cshtml을 보자.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - AspNetCoreMVC</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/AspNetCoreMVC.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">AspNetCoreMVC</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()	//필수 포함!!!
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - AspNetCoreMVC - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

 

  • Layout도 일반적인 Razor Template과 크게 다르진 않다는 걸 알 수 있다.
  • 다만 한가지 규칙이 있는데, 무조건 @RenderBody()를 포함해야 한다는 것.
    • 이는 ChildView(이번에 보여줄 뷰)의 위치를 지정하는 것임.
      • 실제 ChildView의 HTMl들이 해당 위치에 복붙됨

 

 

그러면 만약, 1개의 위치가 아닌 여러 위치에 ChildView를 보여주고싶다면?

  • RenderSection을 이용해 다른 이름으로 넣어주면 됨
    • 우선 여러번 보여주고 싶은 렌더 섹션을 먼저 정의하고
      @section Hoochu {
          <h1>I am Hoochu Section. </h1>
      }
    • Layout에서 보여주고싶은 위치에다가 RenderSection 코드를 넣어주면 됨
      @RenderSection("Hoochu", required:false)​
       
      • required: true인 경우, 뷰에 해당 섹션이 정의되어있지 않으면 오류 남.

 


ViewStart, ViewImports

레이아웃을 설정했다고 해서 바로 모든 뷰에 적용되는 것은 아니다.

레이아웃을 적용하겠다! 라는 설정을 해줘야 한다.

  • 직접 뷰마다 레이아웃 사용 설정을 해줄 수도 있는데, 만약 모든 뷰가 다 같은 레이아웃을 사용한다면?
    • 뷰마다 레이아웃 설정을 할 경우 코드 중복이 심하다.
  • 이때 사용하는 것이 _ViewStart.cshtml

 

 

_ViewStart.cshtml이나 _ViewImports.cshtml은 일괄 설정에 관련된 것이다. 

 

뷰들의 공통적인 부분(레이아웃 or 코드)을 일괄적으로 넣어줄 때 사용하는 것이다.
(해당 폴더 내부의 모든 View에 일괄 적용)

  • _ViewStart : 레이아웃을 전체 뷰에 적용
    • 대부분의 뷰가 공통된 레이아웃을 쓰는데, 각 뷰마다 어떤 레이아웃을 적용할지 일일이 코드를 넣어주긴 귀찮다.
      • _ViewStart.cshtml에다 공통적으로 사용되는 레이아웃이 무엇인지 정의해주면 뷰마다 일일이 안 적어줘도 됨
        @{
            Layout = "_Layout";  //모든 뷰에서 _Layout.cshtml 레이아웃을 사용하겠다.
        }
  • _ViewImports : 코드를 전체 뷰에 적용
    • 전체 뷰에서 Import할 코드를 작성. 
    • 보통 using 같은 게 포함됨  
      @using AspNetCoreMVC
      @using AspNetCoreMVC.Models
      @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers​

 

ex) 

다음 폴더 구조를 보자.

  • 이 경우 _ViewImports와 _ViewStart의 내용들은 'Views' 폴더 내부의 모든 뷰에 일괄 적용된다.
    • 당연히 Views 폴더 밖에 있는 뷰들에는 적용 안됨.

 


PartialView

반복적으로 등장하는 View의 경우 재사용할 수 있게 만들 수 있다. (부품 용도로)

  • 단, 이런 뷰를 작성할 때는 이름 앞에 _를 붙여야 함.
  • _가 붙은 경우, _ViewStart가 적용되지 않는다

 

예를들어 PartialView인 _ValidationScriptsPatial.cshtml 을 보자.

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
  • 이건 그냥 부품 용도로 다른 뷰에 끼워넣을 목적으로 만든 것임. (재사용)
  • 그러므로 만약 얘한테 레이아웃이 적용돼서, 괜히 RenderBody에다가 붙어버리면 낭패임! 
  • 따라서 이런 뷰를 만들 때는 이름 앞에 _를 붙여준다.

 

'게임 > ASP.NET Core' 카테고리의 다른 글

8. WebAPI (+Routing Attributes)  (0) 2024.04.15
7. TagHelper  (0) 2024.04.15
5. Model Binding (+Validation)  (0) 2024.04.15
4. Routing  (0) 2024.04.15
3. MVC 철학  (0) 2024.04.15
Comments