[ASP.NET CORE] 무료 템플릿으로 만드는 ASP.NET Core MVC WebSite #5: Layout

이번 글에서는 “Medcare” HTML 무료 Template 기반의 MVC Web Application에서 WebSite의 공통 Layout 요소인 _Layout.cshtml 파일을 제작하는 방법을 통해 코드의 효율성과 유지보수성을 높이는 과정을 자세히 설명합니다.

“Medcare” template을 이용한 MVC Web Application 구축, 다섯 번째 입니다. 지난 4편에서는 각 메뉴의 기본적인 뼈대인 Controller와 해당 controller 의 index ActionMethod 에 대응하는index.cshtml View 파일을 만드는 과정을 살펴봤습니다. 이제 웹사이트의 기본적인 구조를 갖추었으니, 이번 편에서는 모든 페이지에 공통으로 적용될 Layout 을 template 에서 어떻게 가져와서 _Layout.cshtml 파일을 구성하는지 살펴보겠습니다.

1. 공통 부분 :

MVC Web Application에서는 일반적으로 _Layout.cshtml이라는 파일을 사용하여 웹사이트의 공통 Layout 을 정의합니다. 이 파일은 Web page의 전체적인 구조를 담고 있으며, 각 페이지의 내용이 삽입될 영역을 지정하는 역할을 합니다. 필요에 따라서 여러 Layout page 를 만들어 놓고 각 View 마다 다르게 설정할 수도 있습니다.

  • Views 폴더 아래 Shared 폴더를 확인하거나 없다면 생성합니다.
  • Shared 폴더에 Razor View Page (_Layout.cshtml)를 확인합니다. 없으면 생성합니다.

제가 생성한 Project 에는 이미 Shared 폴더에 _Layout.cshtml 파일이 있으므로 더블클릭으로 파일을 엽니다.Source 가 길어 복잡해 보이지만 Editor 화면의 Line Number 우측의 화살표를 클릭하면 축소되어 내용을 감출 수가 있습니다. 그럼 아래와 같이 간략하게 보기 쉽게 됩니다.

크게 head tag 와 body tag 로 나뉘고, 다시 body tag 내에는 header, div, footer 이렇게 세부분으로 나뉩니다. 이 부분이 핵심입니다.

잘 기억해 두세요.

이 번에는 “Medcare” 의 HTML Source 를 살펴보겠습니다.

Source 를 편하게 보기 위해서 Visual Studio Code 로 열어서 보겠습니다. Download 받아 압축을 푼 폴더를 마우스 오른쪽 클릭을 하면 나타나는 Context menu 에서 “Code(으)로 열기” 메뉴를 클릭합니다.

아래와 같이 VS Code 가 열리고 해당 폴더 내의 파일 구조가 표시됩니다.

index.html  이 첫 페이지지만 너무 길어서 보기가 어려울 수 있으니 about-us.html 파일을 열어보겠습니다. menu 의 about 에 해당하는 페이지 입니다.

페이지 내용은 아래와 같습니다.

보기 편하도록  Visual Studio 2022 에서와 같이 Line Number 오론쪽의 화살표를 클릭하여 내용을 축소해 봅니다.

어떻습니까? 구조가 익숙하죠?

다시 Visual Studio 2022 의 모습을 보죠.

Header 와 Footer 그리고 그 사이에 내용이 배치되어 유사한 구조라는 걸 알 수 있습니다. 다른 메뉴의 화면들은 어떤지 살펴볼까요?

Department.html
Docters.htmlContact.html

모두 같은 구조를 가지고 있습니다.

사각형의 내의 Source 내용을 제외한 부분들이 거의 대부분 동일하다는 말은 WebSite 에서 공통적으로 사용할 _Layout.cshtml 에 넣으면 모든 Page 에서 재 사용할 수 있다는 의미입니다. 그리고 Source 적용 후에 header 와 footer 를 별도의 코드로 분리하여 관리할 수 있습니다.

2. 각 화면의 영역 :

이제 공통 부분을 찾았으니 차이가 나는 각 화면의 부분을 어떻게 적용하는지에 대해서 살펴보겠습니다.

html source 에서 사각형의 내용들을 어떻게 처리하느냐를 이야기하는 건데요. Rendering  된다라고 이야기합니다.

_Layout.cshtml 파일에서 각 페이지의 내용이 Rendering될 위치를 지정해야 합니다. 이는 @RenderBody() 라는 Helper Method를 사용하여 간단하게 처리할 수 있습니다. 이 Method는 각 View page의 HTML 콘텐츠를 해당 위치에 삽입해 줍니다.

아래 처럼 _Layout.cshtml 파일을 보면 사각형 내의 @RenderBody() 를 보실 수 있습니다.

<div> tag 내에 다시 <main> tag 가 있지만 “Medcare” Source  에는 <main> tag 가 없으므로 아래와 같이 간단히 구성하도록 하겠습니다.

<body>
    <header>
    </header>

    <div class="container">
        @RenderBody()
    </div>

    <footer>
    </footer>
</body>

3. _Layout.cshtml(공통 레이아웃) 파일:

위 내용을 바탕으로 _Layout.cshtml 파일을 수정해 보도록 하겠습니다. 여러 html page 중에서 어떤 파일을 선택해도 좋지만 제일 간단하다고 생각되는 about-us.html 파일을 가지고 진행하겠습니다.

사각형 내의 내용을 제외한 내용을 _Layout.cshtml 에 복사해 넣고 사각형 부분의 내용은 아래 코드로 대치하겠습니다.

    <div class="container">
        @RenderBody()
    </div>

그럼 아래와 같습니다.

Code Snippet
  1. <!doctype html>
  2. <html lang=”en”>
  3. <head>
  4.     <!– Required meta tags –>
  5.     <meta charset=”utf-8″>
  6.     <meta name=”viewport” content=”width=device-width, initial-scale=1, shrink-to-fit=no”>
  7.     <link rel=”icon” href=”img/favicon.png” type=”image/png”>
  8.     <title>Medcare Medical</title>
  9.     <!– Bootstrap CSS –>
  10.     <link rel=”stylesheet” href=”css/bootstrap.css”>
  11.     <link rel=”stylesheet” href=”css/themify-icons.css”>
  12.     <link rel=”stylesheet” href=”css/flaticon.css”>
  13.     <link rel=”stylesheet” href=”vendors/fontawesome/css/all.min.css”>
  14.     <link rel=”stylesheet” href=”vendors/owl-carousel/owl.carousel.min.css”>
  15.     <link rel=”stylesheet” href=”vendors/animate-css/animate.css”>
  16.     <!– main css –>
  17.     <link rel=”stylesheet” href=”css/style.css”>
  18.     <link rel=”stylesheet” href=”css/responsive.css”>
  19. </head>
  20. <body>
  21.  
  22.     <!–================Header Menu Area =================–>
  23.     <header class=”header_area”>
  24.         <div class=”top_menu row m0″>
  25.             <div class=”container”>
  26.                 <div class=”float-left”>
  27.                     <a class=”dn_btn” href=”mailto:medical@example.com”><i class=”ti-email”></i>medical@example.com</a>
  28.                     <span class=”dn_btn”> <i class=”ti-location-pin”></i>Find our Location</span>
  29.                 </div>
  30.                 <div class=”float-right”>
  31.                     <ul class=”list header_social”>
  32.                         <li><a href=”#”><i class=”ti-facebook”></i></a></li>
  33.                         <li><a href=”#”><i class=”ti-twitter-alt”></i></a></li>
  34.                         <li><a href=”#”><i class=”ti-linkedin”></i></a></li>
  35.                         <li><a href=”#”><i class=”ti-skype”></i></a></li>
  36.                         <li><a href=”#”><i class=”ti-vimeo-alt”></i></a></li>
  37.                     </ul>
  38.                 </div>
  39.             </div>
  40.         </div>
  41.         <div class=”main_menu”>
  42.             <nav class=”navbar navbar-expand-lg navbar-light”>
  43.                 <div class=”container”>
  44.                     <!– Brand and toggle get grouped for better mobile display –>
  45.                     <a class=”navbar-brand logo_h” href=”index.html”><img src=”img/logo.png” alt=””></a>
  46.                     <button class=”navbar-toggler” type=”button” data-toggle=”collapsedata-target=”#navbarSupportedContentaria-controls=”navbarSupportedContent” aria-expanded=”false” aria-label=”Toggle navigation”>
  47.                         <span class=”icon-bar”></span>
  48.                         <span class=”icon-bar”></span>
  49.                         <span class=”icon-bar”></span>
  50.                     </button>
  51.                     <!– Collect the nav links, forms, and other content for toggling –>
  52.                     <div class=”collapse navbar-collapse offset” id=”navbarSupportedContent”>
  53.                         <ul class=”nav navbar-nav menu_nav ml-auto”>
  54.                             <li class=”nav-item”><a class=”nav-link” href=”index.html”>Home</a></li>
  55.                             <li class=”nav-item”><a class=”nav-link” href=”about-us.html”>About</a></li>
  56.                             <li class=”nav-item”><a class=”nav-link” href=”department.html”>Department</a></li>
  57.                             <li class=”nav-item”><a class=”nav-link” href=”doctors.html”>Doctors</a></li>
  58.                             <li class=”nav-item submenu dropdown”>
  59.                                 <a href=”#” class=”nav-link dropdown-toggle” data-toggle=”dropdownrole=”button” aria-haspopup=”true” aria-expanded=”false”>Blog</a>
  60.                                 <ul class=”dropdown-menu”>
  61.                                     <li class=”nav-item”><a class=”nav-link” href=”blog.html”>Blog</a></li>
  62.                                     <li class=”nav-item”><a class=”nav-link” href=”single-blog.html”>Blog Details</a></li>
  63.                                     <li class=”nav-item”><a class=”nav-link” href=”element.html”>element</a></li>
  64.                                 </ul>
  65.                             </li>
  66.                             <li class=”nav-item”><a class=”nav-link” href=”contact.html”>Contact</a></li>
  67.                         </ul>
  68.                     </div>
  69.                 </div>
  70.             </nav>
  71.         </div>
  72.     </header>
  73.     <!–================Header Menu Area =================–>
  74.  
  75.  
  76.     <div class=”container”>
  77.         @RenderBody()
  78.     </div>
  79.  
  80.     <!– start footer Area –>
  81.     <footer class=”footer-area area-padding-top”>
  82.         <div class=”container”>
  83.             <div class=”row”>
  84.                 <div class=”col-lg-2 col-sm-6 single-footer-widget”>
  85.                     <h4>Top Products</h4>
  86.                     <ul>
  87.                         <li><a href=”#”>Managed Website</a></li>
  88.                         <li><a href=”#”>Manage Reputation</a></li>
  89.                         <li><a href=”#”>Power Tools</a></li>
  90.                         <li><a href=”#”>Marketing Service</a></li>
  91.                     </ul>
  92.                 </div>
  93.                 <div class=”col-lg-2 col-sm-6 single-footer-widget”>
  94.                     <h4>Quick Links</h4>
  95.                     <ul>
  96.                         <li><a href=”#”>Jobs</a></li>
  97.                         <li><a href=”#”>Brand Assets</a></li>
  98.                         <li><a href=”#”>Investor Relations</a></li>
  99.                         <li><a href=”#”>Terms of Service</a></li>
  100.                     </ul>
  101.                 </div>
  102.                 <div class=”col-lg-2 col-sm-6 single-footer-widget”>
  103.                     <h4>Features</h4>
  104.                     <ul>
  105.                         <li><a href=”#”>Jobs</a></li>
  106.                         <li><a href=”#”>Brand Assets</a></li>
  107.                         <li><a href=”#”>Investor Relations</a></li>
  108.                         <li><a href=”#”>Terms of Service</a></li>
  109.                     </ul>
  110.                 </div>
  111.                 <div class=”col-lg-2 col-sm-6 single-footer-widget”>
  112.                     <h4>Resources</h4>
  113.                     <ul>
  114.                         <li><a href=”#”>Guides</a></li>
  115.                         <li><a href=”#”>Research</a></li>
  116.                         <li><a href=”#”>Experts</a></li>
  117.                         <li><a href=”#”>Agencies</a></li>
  118.                     </ul>
  119.                 </div>
  120.                 <div class=”col-lg-4 col-md-6 single-footer-widget”>
  121.                     <h4>Newsletter</h4>
  122.                     <p>You can trust us. we only send promo offers,</p>
  123.                     <div class=”form-wrap” id=”mc_embed_signup”>
  124.                         <form target=”_blank” action=”https://spondonit.us12.list-manage.com/subscribe/post?u=1462626880ade1ac87bd9c93a&amp;id=92a4423d01″
  125.                               method=”get” class=”form-inline”>
  126.                             <input class=”form-control” name=”EMAIL” placeholder=”Your Email Address” onfocus=”this.placeholder = ”” onblur=”this.placeholder = ‘Your Email Address'”
  127.                                    required=”” type=”email” />
  128.                             <button class=”click-btn btn btn-default”>
  129.                                 <i class=”ti-arrow-right”></i>
  130.                             </button>
  131.                             <div style=”position: absolute; left: -5000px;”>
  132.                                 <input name=”b_36c4fd991d266f23781ded980_aefe40901a” tabindex=”-1″ value=”” type=”text” />
  133.                             </div>
  134.  
  135.                             <div class=”info”></div>
  136.                         </form>
  137.                     </div>
  138.                 </div>
  139.             </div>
  140.             <div class=”row footer-bottom d-flex justify-content-between”>
  141.                 <p class=”col-lg-8 col-sm-12 footer-text m-0″>
  142.                     <!– Link back to Colorlib can’t be removed. Template is licensed under CC BY 3.0. –>
  143.                     Copyright &copy;<script>document.write(new Date().getFullYear());</script> All rights reserved | This template is made with <i class=”fa fa-heart” aria-hidden=”true”></i> by <a href=”https://colorlib.com” target=”_blank”>Colorlib</a>
  144.                     <!– Link back to Colorlib can’t be removed. Template is licensed under CC BY 3.0. –>
  145.                 </p>
  146.                 <div class=”col-lg-4 col-sm-12 footer-social”>
  147.                     <a href=”#”><i class=”fab fa-facebook-f”></i></a>
  148.                     <a href=”#”><i class=”fab fa-twitter”></i></a>
  149.                     <a href=”#”><i class=”fab fa-dribbble”></i></a>
  150.                     <a href=”#”><i class=”fab fa-linkedin”></i></a>
  151.                 </div>
  152.             </div>
  153.         </div>
  154.     </footer>
  155.     <!– End footer Area –>
  156.  
  157.     <!– Optional JavaScript –>
  158.     <!– jQuery first, then Popper.js, then Bootstrap JS –>
  159.     <script src=”js/jquery-2.2.4.min.js”></script>
  160.     <script src=”js/popper.js”></script>
  161.     <script src=”js/bootstrap.min.js”></script>
  162.     <script src=”js/stellar.js”></script>
  163.     <script src=”vendors/owl-carousel/owl.carousel.min.js”></script>
  164.     <script src=”js/jquery.ajaxchimp.min.js”></script>
  165.     <script src=”js/waypoints.min.js”></script>
  166.     <script src=”js/mail-script.js”></script>
  167.     <script src=”js/contact.js”></script>
  168.     <script src=”js/jquery.form.js”></script>
  169.     <script src=”js/jquery.validate.min.js”></script>
  170.     <script src=”js/mail-script.js”></script>
  171.     <script src=”js/theme.js”></script>
  172. </body>
  173. </html>

_Layout.cshtml 파일을 수정했지만 WebSite 에서 사용하는 javascript, StyleSheet, Image 파일들을 복사하고 경로를 잡아주는 과정이 진행되어야 합니다.

4. Image, Javascript, StyleSheet :

“Medcare” Template Source 에서 아래 그림과 같이 “css, fonts, img, js, vendors” 폴더를 복사합니다.

그리고 Visual Studio 2022 의 Solution Explorer (솔루션 탐색기)에서 wwwroot를  오른쪽 click  하여  “Open  Folder  in  File  Explorer(파일탐색기에서  폴더열기)” 를 cliek  합니다.File Explorer (파일탐색기)가 열리면  wwwroot 폴더에 복사한 파일을 붙여 넣습니다.결과는 다음과 같습니다.

5. 실행 :

지금까지 작업이 잘 되었는지 확인해 보겠습니다. 

Debugging Button 을 Click 하거나 F5 Button 을 눌러 실행시켜 봅니다.

잘 실행되십니까? index page 도 잘 표시되고 favicon 도 표시되네요. 메뉴를 Click 하시고 싶겠지만 메뉴의 link 를 수정하지 않아 표시할 수 없다는 오류가 나올겁니다. 지난 시간에 확인했던 것 처럼 주소창에 “https://localhost:7154/About” 를 입력하시면 해당 메뉴로 이동할 겁니다.

마무리

이번 편에서는 “Medcare” template 기반의 MVC Web Application에 공통 Layout인 _Layout.cshtml 파일을 수정하여 Layout 을 적용하는 과정을 살펴봤습니다. 깊이 살펴보아야 할 기본 내용은 많습니만 진행과정을 단순하게 하여 WebSite 제작에 쉽게 접근하도록 구성해 봤습니다. 내용이 길어 Header와 Footer를 적용하고, CSS와 JavaScript 파일을 분리하는 과정은 다음 편에서 살펴보겠습니다. 

Happy GoSu ~

WooGong ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\