편의상 고수분들 앞에서 반발 써도 이해해주실꺼죠?ㅋ


ASP.NET 서버 태그를 벗어나서 Razor 입문할 때 Classic ASP와 비슷한 느낌을 드는 부분이 아마 여러 부분 있을 것이다.

아니면 PHP를 해본 경우라면 아무래도 반복적인 템플릿을 입힐 때 while 문이나 for,foreach 문 등으로 반복하면서 서버 태그 닫고 HTML 작성하고 뭐 이렇게들 했을 것이다.

Razor도 마찬가지로 그런 식으로 해결하기도 한다.

  1. <table>
  2.     <tr>
  3.         <th>이름목록</th>
  4.     </tr>
  5.     <tr>
  6. @foreach(DataRow row in table.Rows){
  7.     @<td>@row["name"]</td>
  8. }
  9.     </tr>
  10. </table>

이렇게 하는게 편할 수도 있지만 여러 컬렉션을 다루는 면에서 조금 불편하지 않을까?

닷넷 컬렉션은 일반 배열이 필요없을 정도로 유연하며 강력해졌다. 특히 Linq 지원으로

다른 언어에까지 손을 뻗친 재밌는 기법이다. PHPLinq,JSLinq 등등.

그래서 IEnumerable<T> 인터페이스 기반 컬렉션에 익숙한 닷넷 개발자는

아마 이거 다루는게 엄청 편할 것이다.

그래서 준비했다. 쉽게 접근하여 가독성 있게 반복 템플릿을 작성하자.

초간단하다. 고급 지식 따위 필요없다.

StringBuilder로 문자열 만들어서 뿌려주면 땡이다.

왜 StringBuilder인가? 그 이유는 대량의 문자열을 넣고 출력할때 가장 빠른 성능을 나타내기 때문이다.

즉, 한번에 많은 문자열을 넣기보다, 조금씩 반복적으로 많은 문자열을 쏙쏙쏙 집어넣을 때,

일반 string보다 이 StringBuilder가 더 빠르다. 그 이유? 10000번 반복해서 속도 비교해보라.

귀찮다면 이 링크 참고 : String 클래스와 StringBuilder 클래스의 성능차이 - 예제

일단 소풍에 왔으면 돗자리를 깔아야 한다. 없으면 만들어야겠지만.

IEnumerable<T>를 이용하여 반복 템플릿을 작성하기 위한 Razor 친화적인 코드

  1.           public static IHtmlString Repeater<Tcol>(
    IEnumerable<Tcol> source,//컬렉션 원본을 여기에
    Func<Tcol, HelperResult> body//여기다가 템플릿을 작성함ㅋ
    )
    {
    StringBuilder builder = new StringBuilder();//버퍼 만들어 주시고
    foreach (Tcol o in source) builder.Append(body(o));//반복적으로 넣어주시고
    return new HtmlString(builder.ToString());//쏘세요~
    }

에게.. 이게 끝이다. 왜 제네릭 메서드를 만들었을까? 겪어보면 알겠지만 컬렉션이 한정되있는건 아니잖아.ㅋ

그럼 왜 HtmlString 일까? 그냥 string으로 출력해도 된다. 그다음 태그 그대로 출력했다고 필자에게 뭐라고 하지 마시길.ㅋㅋ

필자는 이 소스를 ListHelper 클래스에 쑤셔박아서 사용한다. 원하는 클래스명으로 메서드명으로 바꿔도 상관 없다.

 

이제 이걸 Razor에다 써먹을 시간. 어떻게 합니까요? 풀HD 버전 예제를 통해 쓸만한 구석을 찾아보겠다.

초간단 RSS 리더 되시겠다. 스누피님 감사합니다. http://snoopybox.co.kr/

  1.           @using System.IO;
    @using System.Xml.Linq;
    @{Layout = "~/Shared/_SiteContent.cshtml";}
    @section CssSection{
    <style type="text/css">
    div,p,table,blockquote{font:9pt 'malgun gothic',dotum,sans-serif;}
    img{border:0;}
    h1,h3{color:White;}
    h3 a{color:White;}
    </style>
    }
    <h1>Snoopy RSS</h1>
    <ul>
    @{ // 스누피 블로그에 랜덤으로 RSS 뿌리기
    Random r = new Random(DateTime.Now.Millisecond);//랜덤임.
    XDocument feedoc = XDocument.Load("http://snoopybox.co.kr/rss");//스누피 RSS 소스 불러오기
    @ListHelper.Repeater(feedoc.Document.Descendants("item").Where(o => { return r.Next(0, 2) == 1; }),
    @<li style="padding-right:3em;">
    <h3><a class="rss-title" href="@item.Element("link").Value">@item.Element("title").Value</a></h3>
    <div class="rss-cont" style="display:none;">@(new HtmlString(item.Element("description").Value))</div>@{/*그냥 출력시키면 태그가 그냥 나오므로 HtmlString 으로 만들어야 함.*/}
    </li>); //랜덤으로 뽑은 후 HTML 불러오긔.
    }
    </ul>
    @section ScriptSection{
    <script type="text/javascript">
    $('a.rss-title').click(function () {
    $('div.rss-cont').hide();
    var $_t = $(this).parent().next().toggle();
    return false;
    });
    </script>
    }

레이아웃 섹션이 있다고 쫄지마라. Razor 하다보면 꼭 거쳐가야 하는게 ASP.NET의 마스터페이지 개념인 Razor 레이아웃이다.

미안하다. 레이아웃 소스는 공개 못하겠다. 레이아웃 부분 없애고 제이쿼리 추가하면 열나게 잘나온다.

XML Linq를 좀 해본 사람이라면 이해가 가겠지만, XML 요소의 컬렉션을 IEnumerable<XElement>로 관리한다. 그래서 Linq 메서드 Where로 필터링이 가능한 것이다.

그래서 요녀석이 희생양 되시겠다. RSS 구조를 모른다면 스누피 블로그 가서 RSS 버튼 클릭한 후, 소스를 보면 이해 가시겠다. 우리가 불러올 요소는 item 뿐이다. 그 안에 본문이 있기 때문이지.

ListHelper는 아까 말한 클래스명이다. 정적 클래스에 정적 메서드니 편안하게 불러오 주시면 된다. Descendants 메서드는 해당 XElement 안에 있는 하위에 하위에... 부모가 아들뿐만 아니라 손자도 찾겠다는 메서드 되시겠다.

그걸 컬렉션으로 반환하는 기능을 해주시는 분이시니 잘 알아두시도록.

Where에 랜덤으로 뿌려주겠다고 했으니 RSS 전체 내용 중 일부분만 몇개 삐져나온다. 만약 다 뿌리고 싶다면 Where 메서드를 지워주시면 된다.

그리고, @<태그> 해 주시면 런타임이 알아서 HelperResult 로 만들어서 뿌려준다. 어자피 HTML 문자열이니 너무 어렵게 생각할 건 없고.

여기서 눈에 띄는게 item 변수이다. 기본적으로 Razor 에서는 item 이라는 예약 변수를 지정했는데. Razor가 그렇게 만들었으므로 필자에게 나무라지는 마시길.

어쨌든 대리자로 하나의 인자와 HelperResult 라는 반환값을 받을 때 이렇게 약속을 해둔 것이다. 그럼 인자가 2개 이상이거나 없을 경우라면? 없을 경우는 그냥 HelperResult 만 쓰면 되지만.. 2개 이상은 아직 실험 안해봤다.

이 과정에서 변수를 받을 수 있도록 예약 변수 item을 만들어서 그걸 써먹으면 된다. 그 item의 타입은 당연히 대리자가 지정한 타입으로 가며, int 일 경우 int로 다루면 되고 그런거다.

이렇게 해서 HTML로 감싸면 반복 필요없이 개발자와 디자이너 좋은 가독성을 보여줄 수 있을 것이다.

 

그럼 힘쎄고 강한 Razor 코딩 하시길.





profile
20대 언제나 쿨한 개발(犬足)자.