다음을 통해 공유


(6) Razor 강좌 - 레이아웃 페이지 구조 처리

안녕하세요. 김대우 입니다.

코난이와 함께하는 Razor & WebMatrix 시리즈 강좌리스트

(1) WebMatrix와 Razor! 이제 시작합니다.

(2) WebMatrix 설치부터 Hello World까지

(3) Razor 강좌 - 기본 구문 및 주석 처리

(4) Razor 강좌 - 코드 블록과 POST 처리

(5) Razor 강좌 - 재사용 가능한 코드 생성

(6) Razor 강좌 - 레이아웃 페이지 구조 처리 - (지금 보고 계신 내용)

(7) Razor 강좌 - 파일처리

(8) Razor 강좌 - 데이터베이스 처리

(9) Razor 강좌 - Helper 소개(이미지, 비디오)

(10) Razor 강좌 - 디버깅

(11) Razor 강좌 - 캐시 처리

지난 시간에는 “(5) Razor 강좌 - 재사용 가능한 코드 생성” 강좌를 진행 했습니다.

이번 시간에는 바로 이어서 여섯번째 강좌, “Razor 강좌 - 레이아웃 페이지 구조 처리” 강좌를 진행 하도록 하겠습니다.
이 녀석도 실제 구조만 이해하시면 어렵지 않은 내용이에요. 꼬옥 아래 처음으로 보여 드리는 처리 구조를 잘 살펴 보시고 이해하시면 아래의 내용은 모두 껌처럼 보이실 겁니다.
왜 Layout을 이용하는가?
이전 강좌에서는 RenderPage를 이용해 페이지의 특정 위치에 원하는 내용을 삽입하는 처리를 진행해 보았습니다. 하지만, 개발자의 입장에서 볼 때, 재사용성을 극대화하고 좀더 구조적으로 페이지의 디자인과 레이아웃을 살릴 수 있는 과정이 필요하게 됩니다. 이 경우에 이용 가능한 처리가 바로 레이아웃 페이지(Layout page) 방식입니다. 먼저 아래 그림을 통해 처리 방식을 반드시 먼저 이해 하시는 게 아주 중요합니다.
layout

처리 방식은 이렇습니다. 꼭 이해하셔야 아래 나머지 강좌 내용이 수월 하실 거에요.
1) 사용자가 Content Page를 요청합니다.
2) Content Page는 레이아웃 페이지의 링크를 담고 있습니다.
3) 레이아웃 페이지가 호출되며 레이아웃 페이지 내부에서 Content Page가 렌더링 됩니다.
4) 레이아웃 페이지에서 다른 페이지 역시 호출해(include) 재사용 가능합니다.
5) 사용자에게 모든 렌더링된 레이아웃 페이지가 전달됩니다.
어떠세요? 조금 감이 잡히시는지요?
레이아웃 페이지는 마치 HTML 파일처럼 콘텐트 정보를 제외한 모든 처리를 넣을 수 있습니다.

HTML페이지와 다른점은 오직 콘텐트 페이지의 정보를 담기 위한 RenderBody나 RenderPage가 호출된다는 점 뿐이지요.
몇 가지 더 경험적인 Tip을 말씀 드리자면, 앞의 강좌의 재사용을 위한 RenderPage 방식보다 이런 레이아웃 방식을 대규모의, 디자인과 협업이 더 많이 필요할 경우에 주로 사용하게 됩니다. 정보와 디자인을 쉽게 분리해 개발자와 디자이너간 협업을 증대시키며 구조적으로 정보를 개발자의 조건에 따라 레이아웃 페이지에 삽입 여부 등도 제어가 가능하기 때문에 더욱 동적이고 개발자와 디자이너 협업이 가능한 처리를 이용 가능하기 때문입니다.
자, 이제 처리 방식이 조금 이해 되셨다면, 저와 같이 코드를 직접 실행해 보시지요.
앞의 강좌에서 “Reuse”라는 폴더를 만들어 두었습니다. 아래처럼 파일들을 이 폴더에 생성해 볼께요.

<!DOCTYPE html> 
  <head> 
    <title> 레이아웃 콘텐트를 만들어요 </title> 
    <link href="@Href("Styles/Site.css")" rel="stylesheet" type="text/css" /> 
  </head> 
  <body> 
    @RenderPage("_Header2.cshtml")  
    <div id="main"> 
      @RenderBody()  
    </div> 
    <div id="footer"> 
      &copy; 2010 SQLER의 Razor와 WebMatrix 강좌. 
    </div> 
  </body> 
</html>

“_layout1.cshtml” 파일로 저장합니다.

@{
LayoutPage = "_Layout1.cshtml";
}
 

<h1> 구조화된 콘텐트  </h1> 
<p>

택시기사가 나를 보통 녀석이 아닌데?라고 생각하게 만드는 방법 (1/3)

1 왼쪽 문을 열고 타자마자 오른쪽 문을 열고 내린다.
4 요금이 오를 때마다 비명을 지른다.
7 어느새 내가 운전한다.
18 U턴 해서 반대 차선에 내려 주세요.
21 택시에 타자마자 페브리즈를 마구 뿌린다.
28 재개발 지구나 새 건물이 들어 선 거리를 지날 때 한숨을 쉬며 「하나도 안 변했네··· 여기」라고 중얼거린다.
번역 : 행복한 마조히스트(sweetpjy.tistory.com)
<p>

“Content1.cshtml” 파일로 저장합니다.

<div id="header">  
  구조화된 콘텐트를 만들어 보세요~

</div>

“_header2.cshtml” 파일로 저장합니다.

Reuse 폴더 하위에 “Styles” 폴더를 만들어 주세요.

h1 { 
    border-bottom: 3px solid #cc9900; 
    font: 2.75em/1.75em Georgia, serif; 
    color: #996600; 

ul { 
    list-style-type: none; 

body { 
    margin: 0; 
    padding: 1em; 
    background-color: #ffffff; 
    font: 75%/1.75em "Trebuchet MS", Verdana, sans-serif; 
    color: #006600; 

#list { 
    margin: 1em 0 7em -3em; 
    padding: 1em 0 0 0; 
    background-color: #ffffff; 
    color: #996600; 
    width: 25%; 
    float: left; 

#header, #footer { 
    margin: 0; 
    padding: 0; 
    color: #996600; 
}

이 파일은 Styles 폴더 하위에 “Site.css” 파일로 만들어 주세요.

이제 실행을 해 볼까요? WebMatrix에서 Content1.cshtml을 선택하시고 F12를 눌러 실행해 주세요.
조금 파일들이 많으시지요? 걱정 마세요. 이해만 하시면 아주 쉽습니다.

이 강좌 맨 위의 처리 흐름을 생각 하시면서 설명 드릴께요.
1) 사용자의 요청으로 Content1.cshtml 파일이 실행되면 Layout1.cshtml 페이지를 호출합니다.
2) Layout 페이지에서 Header 영역을 불러와 include 시키고 바로 아래에서 Content 페이지의 내용을 RenderBody로 호출합니다.
3) 만들어진 콘텐트가 담긴 레이아웃 페이지가 사용자에게 CSS 디자인 파일과 함께 전달됩니다.
콘텐트 페이지의 특정 영역을 레이아웃 페이지 특정 영역에 표시

쿨럭. 쓰고 나니 제목이 더 복잡하네요. 의도한 바는 아닙니다만, 아래 도표를 보시면 바로 감이 오실 겁니다. 먼저, 아래 도표를 보시지요.
layout2

1) 사용자의 요청이 콘텐트 페이지에 도착하면 레이아웃 페이지가 호출됩니다.
2) 레이아웃 페이지의 RenderSection은 콘텐트 페이지의 지정된 Section을 쏙쏙 가져와 표시합니다.
3) RenderBody와 혼용도 가능합니다.
4) 사용자에게 콘텐트가 입혀진 레이아웃 페이지가 전달됩니다.
자 그럼 마찬가지로, 예제를 통해 이해해 보도록 하겠습니다.

<!DOCTYPE html> 
<html> 
    <head>
      <title>섹션이 존재하는 콘텐트 파일</title> 
      <link href="@Href("Styles/Site.css")" rel="stylesheet" type="text/css" /> 
    </head> 
    <body> 
      <div id="header"> 
        @RenderSection("header")
      </div> 
      <div id="list"> 
        @RenderSection("list")  
      </div> 
      <div id="main"> 
        @RenderBody()  
      </div> 
      <div id="footer"> 
        &copy; 2010 SQLER의 Razor와 WebMatrix 강좌 
      </div> 
    </body> 
</html>

”_Layout2.cshtml” 파일로 저장합니다.

@{  
    LayoutPage = "_Layout2.cshtml";  

   @section list {  
    <ul> 
        <li>김대우</li> 
        <li>박중석</li> 
        <li>황리건</li> 
        <li>조성우</li> 
        <li>김영욱</li> 
        <li>김재우</li> 
        <li>서진호</li> 
    </ul> 

@section header {  
    <div id="header">  
        레이아웃 페이지 제작 
    </div> 

<h1>여러개의 섹션이 있는 콘텐트</h1> 
<p>

택시기사가 나를 보통 녀석이 아닌데?라고 생각하게 만드는 방법 (2/3)

39 내릴 때 레드 카펫을 깐다.
45 비 내리는 밤에 택시를 타고 「저기, 요즘에 이 근처에서 뭐가 나온다는 소문이 돌잖아요~」
49 「오늘은 여기에 한 번 둬 볼까……… 」 라고 말하며 계기판 위에 물이 든 종이컵을 내려놓는다.
59 행선지를 물어보면「몰라요···!!」하고 운다.
70 들고 있던 비상등을 차 위에 올리고「빨리 갑시다, 신호는 무시하세요!」
95 차멀미가 심하니까 잘 부탁드려요. 이러면 운전을 정말 조심스럽게 해준다.
99 타자마자 「교통 불편 신고 엽서」를 집어 든다.
104 땀을 뻘뻘 흘리면서 항문을 손으로 틀어막고 조심조심 탄다.
번역 : 행복한 마조히스트(sweetpjy.tistory.com)
</p>

”Content2.cshtml” 파일로 저장합니다.

보시는 것처럼, 레이아웃 페이지에서 RenderSection을 통해 영역을 구별해 두게 됩니다.

이어서 콘텐트 페이지에서 @section 을 이용해 콘텐트를 분리해 처리하게 되지요.
그럼, WebMatrix에서 Content2.cshtml 파일을 선택하시고 F12를 눌러 실행해 보세요.
레이아웃 페이지는 구조와 영역에 대한 처리가 사실상 전부 입니다. 잊지 마시고, 꼭 페이지가 어떻게 렌더링 되어 사용자에게 표시되는지, 그 흐름을 고민하면서 진행해 보시길 바랍니다.
Section이 존재하지 않을 경우 처리
위의 콘텐트 페이지에 각 Section 정보를 담고 있습니다. 레이아웃 페이지에는 이 Section을 표시하라고 명시되어 있는데, 몇몇 콘텐트 페이지만 이런 Section이 빠져 있다면 어떻게 될까요? – Section 여부에 따른 분기 처리가 가능합니다. 아래 내용을 참고 하세요.
Content2.cshtml 페이지에서 아래 섹션을 제거해 보세요.

@section header { 
    <div id="header">  
        레이아웃 페이지 제작  
    </div> 

네, 바로 header 섹션을 없애 버리는 겁니다. 저장 하시고, Content2.cshtml 파일을 WebMatrix에서 실행해 보시면. 뚜시꿍~ 에러가 떨어집니다.
layout3
이럴 경우를 위해 간단히 Layout 페이지를 살짝 손보면 됩니다.

_Layout2.cshtml 파일을 열고

    @RenderSection("header")

항목을 아래로 변경합니다.
@RenderSection("header", optional: true)
또는, 아래처럼 if 분기로도 처리가 가능합니다.

@if (IsSectionDefined("header") {
    @RenderSection("header")
}

Section이 없더라도 걱정하실 필요 없지요? ^_^

끝으로, 데이터를 레이아웃 페이지로 넘기는 방법에 대해서 말씀 드리도록 하겠습니다.
콘텐트 페이지의 데이터를 레이아웃 페이지로 전달
콘텐트 페이지에서 사용자의 로그인 상태를 레이아웃 페이지에 전달해 그에 맞게 페이지를 렌더링 하고자 할 경우에 반드시 콘텐트 페이지에서 데이터를 레이아웃 페이지에 전달해 적절한 처리가 이루어지도록 구성할 필요가 있습니다. 이럴 경우를 생각해 보시면 좋을 거에요. 어렵지 않습니다. 이럴 경우 값을 전달할 경우에는 Request 처리와 비슷하게 “PageData” 속성을 이용하시면 됩니다.
예제를 돌려 보도록 할께요.
흐름은 간단히, PageData 조건을 검사해 메뉴 아이템들을 표시할지 말지 여부를 결정하는 간단한 예제라고 보시면 됩니다.

@{  
    LayoutPage = "_Layout3.cshtml"; 
    PageData["Title"] = "데이터 전달";
PageData["ShowList"] = true;
 
    if (IsPost) { 
        if (Request["list"] == "off") { 
            PageData["ShowList"] = false;  
        } 
    } 

@section header { 
    <div id="header">  
        레이아웃 페이지 만들기  
    </div> 

<h1>@PageData["Title"]</h1>  
<p>

택시기사가 나를 보통 녀석이 아닌데?라고 생각하게 만드는 방법 (3/3)

106 룸미러 너머로 운전기사의 얼굴을 심각하게 응시.
135 혼자 탄 다음에 아무도 없는 조수석 쪽에 계속 말을 건다.
144 조수석 앞에 붙은 기사증을 소리 내서 읽는다.
157 경찰차가 지나가면 몸을 숙인다.
161 준비한 애니메이션 CD를 카오디오에 넣고 튼다.
172 뒷자석으로 타서 조수석으로 옮겨 앉는다.
223 타자마자 「트렁크가 열려있는데요? 」 한다. 운전기사가 확인하러 간 사이에 운전석에 앉는다. 그대로 출발.
번역 : 행복한 마조히스트(sweetpjy.tistory.com)

</p> 
@if (PageData["ShowList"] == true) {  
    <form method="post" action=""> 
      <input type="hidden" name="list" value="off" /> 
      <input type="submit" value="Hide List" /> 
    </form> 

else { 
    <form method="post" action=""> 
      <input type="hidden" name="list" value="on" /> 
      <input type="submit" value="Show List" /> 
    </form> 

<br />

Content3.cshtml 파일로 저장합니다.

<!DOCTYPE html> 
<html> 
    <head> 
      <title>@PageData["Title"]</title>  
      <link href="@Href("Styles/Site.css")" rel="stylesheet" type="text/css" /> 
    </head> 
    <body> 
      <div id="header"> 
        @RenderSection("header") 
      </div> 
      @if (PageData["ShowList"] == true) {  
          <div id="list"> 
            @RenderPage("/Reuse/_List.cshtml") 
          </div> 
      } 
      <div id="main"> 
        @RenderBody() 
      </div> 
      <div id="footer"> 
        &copy; 2010 SQLER의 Razor와 WebMatrix 강좌  
      </div> 
    </body> 
</html>

”_Layout3.cshtml” 파일로 저장합니다.

<ul> 
        <li>김대우</li> 
        <li>박중석</li> 
        <li>황리건</li> 
        <li>조성우</li> 
        <li>김영욱</li> 
        <li>김재우</li> 
        <li>서진호</li> 
</ul>

_List.cshtml 파일로 저장합니다.

흐름은 간단히, PageData 조건을 검사해 메뉴 아이템들을 표시할지 말지 여부를 결정하는 예제라고 보시면 됩니다.
완료 하셨다면, Content3.cshtml 파일을 실행해 보세요. 아래의 “Hide List” 버튼을 클릭하시면 Post 여부에 따라 넘겨받은 PageData로 레이아웃이 변화합니다.

어떠세요? 어렵지 않으시지요?
자~ 이렇게 해서 지난 시간의 RenderPage에 이어 레이아웃을 이용한 처리 역시 알아 보았습니다.

사실, 맨 처음에 말씀 드린 것처럼,  콘텐트 페이지와 레이아웃 페이지가 어떻게 서로 지지고 볶으면서 영역들을 렌더링 하는지 여부만 이해하시면 조금은 쉬운 내용셨을 거라고 생각되네요.
레이아웃 처리를 이용할 경우는...
1) 개발자의 입장에서 레이아웃의 재사용성을 극대화하고
2) 디자이너와 협업을 통해 구조적으로 페이지의 디자인과 레이아웃을 살릴 수 있는 과정이며
3) 레이아웃과 콘텐츠 페이지간 데이터 전달 및 상호작용이 가능한 처리 방식입니다.
자~ 그럼 레이아웃 강좌를 마무리 하도록 하겠습니다.
다음 강좌인 "(7) Razor 강좌 - 파일처리" 에서 뵙도록 하겠습니다. ^_^
감사합니다.~
PS.
cshtml 파일 앞에 “_”가 붙은 녀석은 사용자의 요청에 의해 실행 불가한 파일입니다. 다른 콘텐트 페이지 같은 “_”가 없는 녀석들에 의해 참조되어 호출만 가능한 녀석이지요. 레이아웃 페이지나 항상 참조 되는 header, footer 페이지에 쓰면 유용하겠지요? 참고 하시길 바랍니다.

참고자료 :

(1) WebMatrix와 Razor! 이제 시작합니다.
(2) WebMatrix 설치부터 Hello World까지
(3) Razor 강좌 - 기본 구문 및 주석 처리
(4) Razor 강좌 - 코드 블록과 POST 처리
(5) Razor 강좌 - 재사용 가능한 코드 생성
[동영상 강좌] (1) WebMatrix 첫 실행 & Hello World까지 달려요~
[동영상 강좌] (2) WebMatrix 5분 리뷰~
[동영상 강좌] (3) Razor 강좌 - 기본 구문 및 주석 처리
[동영상 강좌] (4) Razor 강좌 - 코드 블록과 POST 처리
ASP.NET 사이트의 Razor Tutorial 내용 3 - Creating a Consistent Look