<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Whiteship&#039;s Epril</title>
	<atom:link href="http://whiteship.me/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://whiteship.me</link>
	<description>I feel good.</description>
	<lastBuildDate>Thu, 17 May 2012 08:58:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
	<atom:link rel='hub' href='http://whiteship.me/?pushpress=hub'/>
		<item>
		<title>번역서가 나왔네. 오예&#8230;</title>
		<link>http://whiteship.me/?p=13588</link>
		<comments>http://whiteship.me/?p=13588#comments</comments>
		<pubDate>Thu, 17 May 2012 08:58:04 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Koreanization]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[번역]]></category>
		<category><![CDATA[실시간 웹]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13588</guid>
		<description><![CDATA[http://www.yes24.com/24/goods/7039531 실시간 사용자 경험 프로그래밍이라는 이름으로 재밌는 책이 나왔습니다. 제가 번역했어요. 캬캬캬. 번역 실력이 안좋아서 편집자분께서 너무 많은 고생을 하셨지요. 한빛출판사의 한동훈님께 이자리를 빌어 깊은 감사와 미안한 마음을 표현하고 싶습니다. 책이 나오면 제가 밥을 쏘기로 했으니 꼭.. 밥한끼 하시죠. 이 &#8230; <a href="http://whiteship.me/?p=13588">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.yes24.com/24/goods/7039531" target="_blank">http://www.yes24.com/24/goods/7039531</a></p>
<p>실시간 사용자 경험 프로그래밍이라는 이름으로 재밌는 책이 나왔습니다. 제가 번역했어요. 캬캬캬. 번역 실력이 안좋아서 편집자분께서 너무 많은 고생을 하셨지요. 한빛출판사의 한동훈님께 이자리를 빌어 깊은 감사와 미안한 마음을 표현하고 싶습니다. 책이 나오면 제가 밥을 쏘기로 했으니 꼭.. 밥한끼 하시죠.</p>
<p><img class="aligncenter size-full wp-image-13589" title="rtu" src="http://whiteship.me/wp-content/uploads/2012/05/rtu.jpeg" alt="" width="313" height="400" /></p>
<p>이 책은 특징상 소스 코드가 많고 다양한 언어를 사용하고 있어서 매우 재밌습니다. 특히 마지막 장에서 세균전과 비슷한 게임을 만드는 내용이 있지요. 이 책에 나온 모든 내용을 총 망라하는 그런 게임이 되겠습니다.</p>
<p>부디 즐겁게 읽어주시고 부족한 부분이 있다면 역자인 저 말고 저자분께 메일을 보내 따져주시길 기대하지만&#8230; 저에게 보내셔도.. 딱히 제가.. 음&#8230; 암튼 즐겁게 보시어요. ㅋㅋㅋ</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13588&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13588&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13588&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13588&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13588&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13588</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Thymeleaf] 스프링에 타임리프 연동하기</title>
		<link>http://whiteship.me/?p=13585</link>
		<comments>http://whiteship.me/?p=13585#comments</comments>
		<pubDate>Fri, 27 Apr 2012 08:36:06 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Good Tools]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Thymeleaf]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13585</guid>
		<description><![CDATA[매우 쉽습니다. ViewResolver만 바꿔주면 됩니다. 기존에 JSP뷰를 사용하고 있었다면 InternelResourceVewResolver를 사용해서 JSTL뷰를 설정한 다음 prefix와 suffix 정도를 설정해서 사용하고 있으실텐데요. ThymeleafViewResolver로 바꿔주시면 됩니다. 그리고 ThymeleafViewResolver가 필요로하는 빈도 몇개 등록해야되구요. 아.. 그전에 메이븐 의존성부터 추가하셔야겠군요. 저는 스프링 자바 설정을 사용했는데 코드 &#8230; <a href="http://whiteship.me/?p=13585">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>매우 쉽습니다. ViewResolver만 바꿔주면 됩니다. 기존에 JSP뷰를 사용하고 있었다면 InternelResourceVewResolver를 사용해서 JSTL뷰를 설정한 다음 prefix와 suffix 정도를 설정해서 사용하고 있으실텐데요.</p>
<p>ThymeleafViewResolver로 바꿔주시면 됩니다. 그리고 ThymeleafViewResolver가 필요로하는 빈도 몇개 등록해야되구요. 아.. 그전에 메이븐 의존성부터 추가하셔야겠군요. 저는 스프링 자바 설정을 사용했는데 코드 보시면 XML 설정으로도 쉽게 설정하실 수 있으실 겁니다.</p>
<div id="gist-2508457" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;!DOCTYPE html&gt;</span></div><div class='line' id='LC2'><span class="nt">&lt;html&gt;</span></div><div class='line' id='LC3'><span class="nt">&lt;head&gt;</span></div><div class='line' id='LC4'>	<span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;utf-8&quot;</span><span class="nt">/&gt;</span></div><div class='line' id='LC5'>	<span class="nt">&lt;title&gt;</span>Cantabille<span class="nt">&lt;/title&gt;</span></div><div class='line' id='LC6'><span class="nt">&lt;/head&gt;</span></div><div class='line' id='LC7'><span class="nt">&lt;body&gt;</span></div><div class='line' id='LC8'>	Init Cantabille</div><div class='line' id='LC9'><span class="nt">&lt;/body&gt;</span></div><div class='line' id='LC10'><span class="nt">&lt;/html&gt;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2508457/434a695cd2e6732e3356b922f17c85f25efc1c41/init.html" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2508457#file_init.html" style="float:right;margin-right:10px;color:#666">init.html</a>
            <a href="https://gist.github.com/2508457">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;dependency&gt;</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;groupId&gt;</span>org.thymeleaf<span class="nt">&lt;/groupId&gt;</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;artifactId&gt;</span>thymeleaf-spring3<span class="nt">&lt;/artifactId&gt;</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;version&gt;</span>2.0.5<span class="nt">&lt;/version&gt;</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;scope&gt;</span>compile<span class="nt">&lt;/scope&gt;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/dependency&gt;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2508457/3d30f24e4b0b93b75da6bf475c1d0082a8f60eb6/pom.xml" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2508457#file_pom.xml" style="float:right;margin-right:10px;color:#666">pom.xml</a>
            <a href="https://gist.github.com/2508457">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>	<span class="c1">// ****************************************************************</span></div><div class='line' id='LC2'>	<span class="c1">// ViewResolver for the Thymeleaf</span></div><div class='line' id='LC3'>	<span class="c1">// ****************************************************************</span></div><div class='line' id='LC4'>	<span class="nd">@Bean</span></div><div class='line' id='LC5'>	<span class="kd">public</span> <span class="n">ThymeleafViewResolver</span> <span class="nf">viewResolver</span><span class="o">(){</span></div><div class='line' id='LC6'>		<span class="n">ThymeleafViewResolver</span> <span class="n">viewResolver</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ThymeleafViewResolver</span><span class="o">();</span></div><div class='line' id='LC7'>		<span class="n">viewResolver</span><span class="o">.</span><span class="na">setTemplateEngine</span><span class="o">(</span><span class="n">thymeleafEngine</span><span class="o">());</span></div><div class='line' id='LC8'>		<span class="k">return</span> <span class="n">viewResolver</span><span class="o">;</span></div><div class='line' id='LC9'>	<span class="o">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>	<span class="nd">@Bean</span></div><div class='line' id='LC12'>	<span class="kd">public</span> <span class="n">SpringTemplateEngine</span> <span class="nf">thymeleafEngine</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC13'>		<span class="n">SpringTemplateEngine</span> <span class="n">thymeleafEngine</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SpringTemplateEngine</span><span class="o">();</span></div><div class='line' id='LC14'>		<span class="n">thymeleafEngine</span><span class="o">.</span><span class="na">setTemplateResolver</span><span class="o">(</span><span class="n">templateResolver</span><span class="o">());</span></div><div class='line' id='LC15'>		<span class="k">return</span> <span class="n">thymeleafEngine</span><span class="o">;</span></div><div class='line' id='LC16'>	<span class="o">}</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'>	<span class="nd">@Bean</span></div><div class='line' id='LC19'>	<span class="kd">public</span> <span class="n">ServletContextTemplateResolver</span> <span class="nf">templateResolver</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC20'>		<span class="n">ServletContextTemplateResolver</span> <span class="n">templateResolver</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ServletContextTemplateResolver</span><span class="o">();</span></div><div class='line' id='LC21'>		<span class="n">templateResolver</span><span class="o">.</span><span class="na">setPrefix</span><span class="o">(</span><span class="s">&quot;/WEB-INF/views&quot;</span><span class="o">);</span></div><div class='line' id='LC22'>		<span class="n">templateResolver</span><span class="o">.</span><span class="na">setSuffix</span><span class="o">(</span><span class="s">&quot;.html&quot;</span><span class="o">);</span></div><div class='line' id='LC23'>		<span class="n">templateResolver</span><span class="o">.</span><span class="na">setTemplateMode</span><span class="o">(</span><span class="s">&quot;HTML5&quot;</span><span class="o">);</span></div><div class='line' id='LC24'>		<span class="k">return</span> <span class="n">templateResolver</span><span class="o">;</span></div><div class='line' id='LC25'>	<span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2508457/87ea88df3094296bed5a2d97c3fdc5b13fd83702/WebConfig.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2508457#file_web_config.java" style="float:right;margin-right:10px;color:#666">WebConfig.java</a>
            <a href="https://gist.github.com/2508457">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>좋아~ 이제야 드뎌 서버 띄우지 않고 html만 작업하면서 뷰를 만든다음 서버 띄우고나서도 계속 사용할 수도 있겠군요.</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13585&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13585&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13585&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13585&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13585&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13585</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>아파치 httpd에 SSL 인증서 설치하기</title>
		<link>http://whiteship.me/?p=13580</link>
		<comments>http://whiteship.me/?p=13580#comments</comments>
		<pubDate>Mon, 23 Apr 2012 03:29:12 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[httpd]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[아파치]]></category>
		<category><![CDATA[인증서]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13580</guid>
		<description><![CDATA[먼저.. 준비물 abc.pem: 인증 기관에서 받은 인증서 파일 abc.key: 인증 기관에 줄 인증 파일 만들 때 생성한 키 파일 global-abc.pem: 글로벌 인증서 파일 암호: 키 파일 만들 때 사용한 암호 문구 mod_ssl.so: apache/modules에 들어있나 확인 1. mod_ssl 로딩 설정하기 apache/conf/httpd.conf &#8230; <a href="http://whiteship.me/?p=13580">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>먼저.. 준비물</p>
<ul>
<li>abc.pem: 인증 기관에서 받은 인증서 파일</li>
<li>abc.key: 인증 기관에 줄 인증 파일 만들 때 생성한 키 파일</li>
<li>global-abc.pem: 글로벌 인증서 파일</li>
<li>암호: 키 파일 만들 때 사용한 암호 문구</li>
<li>mod_ssl.so: apache/modules에 들어있나 확인</li>
</ul>
<h2>1. mod_ssl 로딩 설정하기</h2>
<p>apache/conf/httpd.conf 파일 열고 mod_ssl.so 검색.</p>
<p>vim에서 :/mod_ssl.so 쳐보면 됨.</p>
<p>mod_ssl.so 로딩하는 부분이 없으면 다음과 같은 설정 추가.</p>
<p>LoadModule ssl_module modules/mod_ssl.so</p>
<p>여기서 중간에 있는 ssl_module은 일종의 변수명 같은데&#8230; 그냥 이대로 쓰지 뭐.</p>
<h2>2. httpd.conf하고 apache/conf/extra/httd-ssl.conf 연결하기</h2>
<p>httpd.conf에서 ssl_module이라고 검색하면 방금 위에서 설정한 LoadModule말고 &lt;IfModule&gt; 이라는 부분이 있다.. 없으면 추가.</p>
<p>&lt;IfModule ssl_module&gt;<br />
SSLRandomSeed startup builtin<br />
SSLRandomSeed connect builtin<br />
<strong>Include conf/extra/httpd-ssl.conf</strong><br />
&lt;/IfModule&gt;</p>
<p>그 부분에 저렇게 httpd-ssl.conf 설정을 추가하도록 설정. 아마도 httpd.conf 설정이 너무 복잡해 질까봐 이러식으로 분리하는것 같은데&#8230; 이게 더 복잡한거 같에. @_@;;; 어쩌겠어.. 이렇게 하라는데.. 흠냐..</p>
<h2>3. httpd-ssl.conf 설정</h2>
<p>위에부터 쭉 보면 Listen 443이라고 SSL 적용할 포트 설정이 있고 기타 여러가지 설정이 있는데 이 중에서 다음 설정을 현재 디렉토리 기준으로 잘 맞춰준다.</p>
<p>SSLPassPhraseDialog exec:/apache/conf/ssl/ssl.pass</p>
<p>/apache/conf/ssl/ssl.pass라는 파일은 없다. 이 작업 끝나면 만들꺼임. 파일 경로를 꼭 저렇게 할 필요도 없고.. 단지 실행 가능한 파일이어야 한다. 즉 x 권한이 있어야 한다. 이렇게 설정하지 않으면 기본값이 builtin인데 그렇게 해두면 httpd 띄울때마다 직접 인증서 키 파일 만들 때 사용한 암호를 입력해줘야해서 매우 번거롭다.</p>
<p>ServerName 도메인</p>
<p>인증서 발급받을 때 사용한 도메인을 입력해준다. 이 설정부터는 &lt;VirtualHost&gt; 안에 들어간다.</p>
<p>SSLProtocol -all ====<br />
SSLCipherSuite ====</p>
<p>이건 인증서를 발금해준 인증 기관의 매뉴얼대로 설정해야 할 것 같다. 내가 받은 인증 파일 설명서엔 저렇게 되있던데&#8230; 흠.. 중요해 보이는 정보는 ====로 자막처리 했으니 상관없겠지.</p>
<p>SSLCertificateFile &#8220;abc.pem 파일 경로&#8221;</p>
<p>여기에 abc.pem 파일 경로를 풀로 적어준다.</p>
<p>SSLCertificateKeyFile &#8220;abc.key&#8221;</p>
<p>여기에 abc.key 파일 경로를 풀로 적어준다.</p>
<p>SSLCACertificateFile &#8220;global-abc.pem&#8221;</p>
<p>여기에 global-abc.pem 파일 경로를 풀로 적어준다.</p>
<p>나머지 설정은 그냥 기본값 그대로 둔다. 설마.. SSLEngine on이라는 설정이 off로 되어있진 않겠지..</p>
<h2>4. 암호 파일 만들기</h2>
<p>위에서 SSLPassPhraseDialog 설정을 추가했었는데 거기서 지정한 파일을 다음과 같이 만든다.</p>
<p>#!/bin/sh<br />
echo 암호</p>
<p>즉 이 파일을 실행하면 암호가 입력되도록 하는 것이다. 서버 실행할 때 마다 귀찮지 않게&#8230;</p>
<p>아. 그리고 이 파일 만든 다음에 꼭 실행 권한을 주도록 하자.. chmod 755 ./ssl.pass 같은 식으로.. 그래야 httpd가 이 파일을 실행해서 암호를 입력 받을 수 있지&#8230; 그렇지 않으면 httpd가 아에 안뜬다.</p>
<h2>5. 서버 띄우고 확인</h2>
<p>이제 apache/bin으로 가서 ./apachectl start 등으로 아파치를 실행하고 netstat -na | grep 443으로 443번 포트가 동작하는지 확인하고 웹 브라우저에서 https://도메인 입력해서 확인한다. 끝.</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13580&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13580&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13580&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13580&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13580&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13580</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thymeleaf 죽이네.</title>
		<link>http://whiteship.me/?p=13572</link>
		<comments>http://whiteship.me/?p=13572#comments</comments>
		<pubDate>Thu, 19 Apr 2012 08:10:28 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Good Tools]]></category>
		<category><![CDATA[Thymeleaf]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13572</guid>
		<description><![CDATA[&#8220;백리향 잎사귀&#8221; http://www.thymeleaf.org/doc/Natural%20Templating%20in%20Spring%20MVC%20with%20Thymeleaf%2020120217.pdf 뭔지 알고싶다면 위에 있는 발표자료를 쭉 훑어보시면 됩니다. 일단.. 저는 뷰 만들 때 프리마커나 벨로시티같은 템플릿 엔진을 쓰지 않습니다. 그냥 JSP + JSTL + Spring Tags를 사용합니다. 사이트매쉬나 타일즈같은 레이아웃 엔진도 쓰지 않습니다. 그냥 JSP 태그파일을 씁니다. &#8230; <a href="http://whiteship.me/?p=13572">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>&#8220;백리향 잎사귀&#8221;</p>
<p><a href="http://www.thymeleaf.org/doc/Natural%20Templating%20in%20Spring%20MVC%20with%20Thymeleaf%2020120217.pdf" target="_blank">http://www.thymeleaf.org/doc/Natural%20Templating%20in%20Spring%20MVC%20with%20Thymeleaf%2020120217.pdf</a></p>
<p>뭔지 알고싶다면 위에 있는 발표자료를 쭉 훑어보시면 됩니다.</p>
<p>일단.. 저는 뷰 만들 때 프리마커나 벨로시티같은 템플릿 엔진을 쓰지 않습니다. 그냥 JSP + JSTL + Spring Tags를 사용합니다. 사이트매쉬나 타일즈같은 레이아웃 엔진도 쓰지 않습니다. 그냥 JSP 태그파일을 씁니다. 랜더링 속도가 전체 앱 성능에 얼마나 영향을 준다고 그 불편한 문법과 설정을 적용하며 애플리케이션에 덕지 덕지 붙이지 싫습니다. 성능이 문제면 차라리 <a href="https://www.varnish-cache.org/" target="_blank">varnish</a> 같은걸 추가해서 캐싱을 하죠 뭐. 잡다구리한걸 잔뜩 붙이고 싶지 않아요.</p>
<p>그런데 진짜 괜찮은 템플릿 엔진이 있군요&#8230; 타임리프라.. 캬.. JSP 개발도 마찬가지고 프리마커나 벨로시티를 쓸때도 마찬가지인데.. 뭐냐면..</p>
<p>보통 뷰 만들 때 HTML로 프로토타입을 만들기 나름이죠. 이때는 편하게 HTML로 만들어서 서버를 띄우지 않고 브라우저에서 바로바로 확인하면서 HTML/CSS/JS 코딩을 합니다. 어느정도 됐다 싶으면 그걸 JSP로 변경합니다. 그럼 이제부턴 지옥입니다. 매번 서버를 실행해야지만 뷰를 변경할 수 있죠. 이게 아주 짜증입니다. 그런데 타임리프는 안그래요. 일단 파일을 변경할 필요없이 HTML 그대로 두면 되고 그 상태 그대로 서버를 띄우고 보면 템플릿이 적용되고, 서버를 띄우지 않고 웹 브라우저에서 그냥 열어도 작업이 가능한 HTML 그대로 보여줍니다. JSP나 프리마커 뷰로 바꾼뒤부터는 그렇게 안되기 때문에 거기에 비해서 타임리프 뷰는 개발이 훨씬 편하겠죠.</p>
<p>어떻게 그런지는 안갈쳐 드리죠. 위에 있는 PDF를 보세요. 이 기능을 이름하여 <strong>내츄럴 템플릿</strong>이라고 하더군요. 이름 참 잘 지었네요.</p>
<p>추가로..</p>
<ul>
<li>스프링 바인딩 지원</li>
<li>스프링 PE 지원</li>
<li>스프링 EL 지원</li>
</ul>
<div>등 스프링과 아주 합이 잘 맞는 템플릿 엔진인듯 합니다.</div>
<p>앞으론 이걸 한번 써봐야겠습니다.</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13572&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13572&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13572&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13572&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13572&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13572</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>[스프링 3.2] 비동기 서블릿 지원 맛보기</title>
		<link>http://whiteship.me/?p=13570</link>
		<comments>http://whiteship.me/?p=13570#comments</comments>
		<pubDate>Thu, 19 Apr 2012 05:58:09 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[3.2]]></category>
		<category><![CDATA[Async Servlet]]></category>
		<category><![CDATA[Servlet 3.1]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring 3.2]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13570</guid>
		<description><![CDATA[https://github.com/SpringSource/spring-framework/pull/69 https://github.com/rstoyanchev/spring-mvc-async-sample 흠냐.. 맨 위에껀 스프링 3.2에 작업중인 코딩 내역이고 아래 링크는 실제로 어떻게 사용할 수 있는 보여주는 예제 프로젝트입니다. 로센이 작업했네요. 멋쟁이. 예제 프로젝트를 받아서 돌려봤는데 매우 깔끔하게 동작합니다. 뷰를 Thymeleaf라는 것을 사용했는데&#8230; 흠.. JS랑 맛물리는 뭔가가 있는것 같기도 &#8230; <a href="http://whiteship.me/?p=13570">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/SpringSource/spring-framework/pull/69" target="_blank">https://github.com/SpringSource/spring-framework/pull/69</a></p>
<p><a href="https://github.com/rstoyanchev/spring-mvc-async-sample" target="_blank">https://github.com/rstoyanchev/spring-mvc-async-sample</a></p>
<p>흠냐.. 맨 위에껀 스프링 3.2에 작업중인 코딩 내역이고 아래 링크는 실제로 어떻게 사용할 수 있는 보여주는 예제 프로젝트입니다. 로센이 작업했네요. 멋쟁이.</p>
<p>예제 프로젝트를 받아서 돌려봤는데 매우 깔끔하게 동작합니다. 뷰를 Thymeleaf라는 것을 사용했는데&#8230; 흠.. JS랑 맛물리는 뭔가가 있는것 같기도 하고 첨보는거라 뷰가 어떻게 돌아가는지 몰겠네요. 어쨌든 HTML 파일 하나를 사용하고 있습니다.</p>
<p>자바스립트는 두개를 사용하는데 하나는 제이쿼리, 하나는 넉아웃.js 그리고 제이쿼리 플러그인으로 하나더 jquery-stream.js이라고 있기는 한데&#8230; 소스코드를 봐도.. 크롬 개발자 도구로 봐도.. 사용하진 않는것 같습니다.</p>
<p>스프링 설정은 자바 설정으로 만들었는데 굳이 설정 파일은 루트와 웹을 나눴으면서 애플리케이션 컨텍스트는 나눠서 등록하지 않는 모습이 이번에도 보이는데&#8230; 왜 CCL을 사용하지 않고 DS만 사용할꺼면서 빈 설정은 나누는지 잘 모르겠네요. 그럴꺼면 걍 웹용 설정 파일만 만들어도 될텐데 말이죠. web.xml도 없고 톰캣7 기능을 사용해서 자바 웹 설정으로 web.xml을 대신합니다.</p>
<p>서론이 길었군요. 스프링 3.2부터는 @RequestMapping이 붙은 메서드에서 리턴할 수 있는 타입이 두개가 더 생깁니다. 비동기 서블릿과 관련된 리터타입이죠.</p>
<ul>
<li>스프링에서 만들어 둔 DeferredResult</li>
<li>자바 컨커런시에 있는 Callable</li>
</ul>
<p>지금 데모용 프로젝트에서는 DeferredResult를 사용하고 있습니다. DR을 사용하는 부분만 보겠습니다.</p>
<div id="gist-2419701" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kd">function</span> <span class="nx">ChatViewModel</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'>	<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>	<span class="nx">that</span><span class="p">.</span><span class="nx">userName</span> <span class="o">=</span> <span class="nx">ko</span><span class="p">.</span><span class="nx">observable</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC6'>	<span class="nx">that</span><span class="p">.</span><span class="nx">chatContent</span> <span class="o">=</span> <span class="nx">ko</span><span class="p">.</span><span class="nx">observable</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC7'>	<span class="nx">that</span><span class="p">.</span><span class="nx">message</span> <span class="o">=</span> <span class="nx">ko</span><span class="p">.</span><span class="nx">observable</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC8'>	<span class="nx">that</span><span class="p">.</span><span class="nx">activePollingXhr</span> <span class="o">=</span> <span class="nx">ko</span><span class="p">.</span><span class="nx">observable</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>	<span class="kd">var</span> <span class="nx">keepPolling</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'>	<span class="nx">that</span><span class="p">.</span><span class="nx">joinChat</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC13'>		<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">userName</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC14'>			<span class="nx">that</span><span class="p">.</span><span class="nx">chatContent</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC15'>			<span class="nx">that</span><span class="p">.</span><span class="nx">message</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC16'>			<span class="nx">keepPolling</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span></div><div class='line' id='LC17'>			<span class="nx">pollForMessages</span><span class="p">();</span></div><div class='line' id='LC18'>		<span class="p">}</span></div><div class='line' id='LC19'>	<span class="p">}</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>	<span class="kd">function</span> <span class="nx">pollForMessages</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC22'>		<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">keepPolling</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC23'>			<span class="k">return</span><span class="p">;</span></div><div class='line' id='LC24'>		<span class="p">}</span></div><div class='line' id='LC25'>		<span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#joinChatForm&quot;</span><span class="p">);</span></div><div class='line' id='LC26'>		<span class="nx">that</span><span class="p">.</span><span class="nx">activePollingXhr</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span><span class="nx">url</span> <span class="o">:</span> <span class="nx">getChatUrl</span><span class="p">(</span><span class="nx">form</span><span class="p">),</span> <span class="nx">type</span> <span class="o">:</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nx">data</span> <span class="o">:</span> <span class="nx">form</span><span class="p">.</span><span class="nx">serialize</span><span class="p">(),</span></div><div class='line' id='LC27'>			<span class="nx">success</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC28'>				<span class="k">for</span> <span class="p">(</span> <span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">messages</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC29'>					<span class="nx">that</span><span class="p">.</span><span class="nx">chatContent</span><span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">chatContent</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot;[&quot;</span> <span class="o">+</span> <span class="nx">messages</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">user</span> <span class="o">+</span> <span class="s2">&quot;] &quot;</span> <span class="o">+</span> <span class="nx">messages</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">text</span> <span class="o">+</span> <span class="s2">&quot;\n&quot;</span><span class="p">);</span></div><div class='line' id='LC30'>				<span class="p">}</span></div><div class='line' id='LC31'>			<span class="p">},</span></div><div class='line' id='LC32'>			<span class="nx">error</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC33'>				<span class="nx">keepPolling</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC34'>				<span class="k">if</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">.</span><span class="nx">statusText</span> <span class="o">!=</span> <span class="s2">&quot;abort&quot;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC35'>					<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">&quot;Error getting chat messages: status=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="o">+</span> <span class="s2">&quot;, statusText=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">statusText</span><span class="p">);</span></div><div class='line' id='LC36'>				<span class="p">}</span></div><div class='line' id='LC37'>			<span class="p">},</span></div><div class='line' id='LC38'>			<span class="nx">complete</span> <span class="o">:</span> <span class="nx">pollForMessages</span></div><div class='line' id='LC39'>		<span class="p">}));</span></div><div class='line' id='LC40'>	<span class="p">}</span></div><div class='line' id='LC41'><br/></div><div class='line' id='LC42'>	<span class="kd">function</span> <span class="nx">getChatUrl</span><span class="p">(</span><span class="nx">form</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC43'>		<span class="k">return</span> <span class="nx">form</span><span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;action&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="nx">that</span><span class="p">.</span><span class="nx">userName</span><span class="p">();</span></div><div class='line' id='LC44'>	<span class="p">}</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'>	<span class="nx">that</span><span class="p">.</span><span class="nx">postMessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC47'>		<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">message</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC48'>			<span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#postMessageForm&quot;</span><span class="p">);</span></div><div class='line' id='LC49'>			<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span><span class="nx">url</span> <span class="o">:</span> <span class="nx">getChatUrl</span><span class="p">(</span><span class="nx">form</span><span class="p">),</span> <span class="nx">type</span> <span class="o">:</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span> <span class="nx">data</span> <span class="o">:</span> <span class="nx">form</span><span class="p">.</span><span class="nx">serialize</span><span class="p">(),</span></div><div class='line' id='LC50'>				<span class="nx">error</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC51'>					<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">&quot;Error posting chat message: status=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="o">+</span> <span class="s2">&quot;, statusText=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">statusText</span><span class="p">);</span></div><div class='line' id='LC52'>				<span class="p">}</span></div><div class='line' id='LC53'>			<span class="p">});</span></div><div class='line' id='LC54'>			<span class="nx">that</span><span class="p">.</span><span class="nx">message</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC55'>		<span class="p">}</span></div><div class='line' id='LC56'>	<span class="p">}</span></div><div class='line' id='LC57'><br/></div><div class='line' id='LC58'>	<span class="nx">that</span><span class="p">.</span><span class="nx">leaveChat</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC59'>		<span class="nx">keepPolling</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC60'>		<span class="nx">that</span><span class="p">.</span><span class="nx">activePollingXhr</span><span class="p">().</span><span class="nx">abort</span><span class="p">();</span></div><div class='line' id='LC61'>		<span class="nx">that</span><span class="p">.</span><span class="nx">activePollingXhr</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span></div><div class='line' id='LC62'>		<span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#leaveChatForm&quot;</span><span class="p">);</span></div><div class='line' id='LC63'>		<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span><span class="nx">url</span> <span class="o">:</span> <span class="nx">getChatUrl</span><span class="p">(</span><span class="nx">form</span><span class="p">),</span> <span class="nx">type</span> <span class="o">:</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span></div><div class='line' id='LC64'>			<span class="nx">error</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC65'>				<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">&quot;Error while leaving chat: status=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="o">+</span> <span class="s2">&quot;, statusText=&quot;</span> <span class="o">+</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">statusText</span><span class="p">);</span></div><div class='line' id='LC66'>			<span class="p">}</span></div><div class='line' id='LC67'>		<span class="p">});</span></div><div class='line' id='LC68'>		<span class="k">this</span><span class="p">.</span><span class="nx">userName</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span></div><div class='line' id='LC69'>	<span class="p">}</span></div><div class='line' id='LC70'><br/></div><div class='line' id='LC71'><span class="p">}</span></div><div class='line' id='LC72'><br/></div><div class='line' id='LC73'><span class="c1">//Activate knockout.js</span></div><div class='line' id='LC74'><span class="nx">ko</span><span class="p">.</span><span class="nx">applyBindings</span><span class="p">(</span><span class="k">new</span> <span class="nx">ChatViewModel</span><span class="p">());</span></div><div class='line' id='LC75'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2419701/45433addf729f02a96e340dfdc6a8564d7227b14/chat.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2419701#file_chat.js" style="float:right;margin-right:10px;color:#666">chat.js</a>
            <a href="https://gist.github.com/2419701">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><br/></div><div class='line' id='LC2'><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">springframework</span><span class="o">.</span><span class="na">samples</span><span class="o">.</span><span class="na">async</span><span class="o">.</span><span class="na">chat</span><span class="o">;</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span></div><div class='line' id='LC5'><span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span></div><div class='line' id='LC6'><span class="kn">import</span> <span class="nn">java.util.concurrent.ConcurrentHashMap</span><span class="o">;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="kn">import</span> <span class="nn">org.springframework.stereotype.Controller</span><span class="o">;</span></div><div class='line' id='LC9'><span class="kn">import</span> <span class="nn">org.springframework.web.bind.annotation.PathVariable</span><span class="o">;</span></div><div class='line' id='LC10'><span class="kn">import</span> <span class="nn">org.springframework.web.bind.annotation.RequestMapping</span><span class="o">;</span></div><div class='line' id='LC11'><span class="kn">import</span> <span class="nn">org.springframework.web.bind.annotation.RequestMethod</span><span class="o">;</span></div><div class='line' id='LC12'><span class="kn">import</span> <span class="nn">org.springframework.web.bind.annotation.ResponseBody</span><span class="o">;</span></div><div class='line' id='LC13'><span class="kn">import</span> <span class="nn">org.springframework.web.context.request.async.DeferredResult</span><span class="o">;</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'><span class="nd">@Controller</span></div><div class='line' id='LC16'><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">&quot;/mvc/chat/{topic}/{user}&quot;</span><span class="o">)</span></div><div class='line' id='LC17'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatController</span> <span class="o">{</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>	<span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">ChatParticipant</span><span class="o">&gt;</span> <span class="n">participants</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConcurrentHashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">ChatParticipant</span><span class="o">&gt;();</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>	<span class="cm">/**</span></div><div class='line' id='LC22'><span class="cm">	 * Get chat messages immediately if any are cached or later when they arrive.</span></div><div class='line' id='LC23'><span class="cm">	 */</span></div><div class='line' id='LC24'>	<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">method</span><span class="o">=</span><span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">,</span> <span class="n">produces</span><span class="o">=</span><span class="s">&quot;application/json&quot;</span><span class="o">)</span></div><div class='line' id='LC25'>	<span class="nd">@ResponseBody</span></div><div class='line' id='LC26'>	<span class="kd">public</span> <span class="n">Object</span> <span class="nf">getMessages</span><span class="o">(</span><span class="nd">@PathVariable</span> <span class="n">String</span> <span class="n">topic</span><span class="o">,</span> <span class="nd">@PathVariable</span> <span class="n">String</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC27'>		<span class="n">ChatParticipant</span> <span class="n">participant</span> <span class="o">=</span> <span class="n">getChatParticipant</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">topic</span><span class="o">);</span></div><div class='line' id='LC28'>		<span class="n">DeferredResult</span> <span class="n">deferredResult</span> <span class="o">=</span> <span class="k">new</span> <span class="n">DeferredResult</span><span class="o">();</span></div><div class='line' id='LC29'>		<span class="n">List</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;</span> <span class="n">messages</span> <span class="o">=</span> <span class="n">participant</span><span class="o">.</span><span class="na">getMessagesWhenAvailable</span><span class="o">(</span><span class="n">deferredResult</span><span class="o">);</span></div><div class='line' id='LC30'>		<span class="k">return</span> <span class="o">(</span><span class="n">messages</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">?</span> <span class="n">messages</span> <span class="o">:</span> <span class="n">deferredResult</span><span class="o">;</span></div><div class='line' id='LC31'>	<span class="o">}</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'>	<span class="cm">/**</span></div><div class='line' id='LC34'><span class="cm">	 * Post a message to chat participants.</span></div><div class='line' id='LC35'><span class="cm">	 */</span></div><div class='line' id='LC36'>	<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">method</span><span class="o">=</span><span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">)</span></div><div class='line' id='LC37'>	<span class="nd">@ResponseBody</span></div><div class='line' id='LC38'>	<span class="kd">public</span> <span class="kt">void</span> <span class="nf">postMessage</span><span class="o">(</span><span class="n">ChatMessage</span> <span class="n">message</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC39'>		<span class="k">for</span> <span class="o">(</span><span class="n">ChatParticipant</span> <span class="n">participant</span> <span class="o">:</span> <span class="k">this</span><span class="o">.</span><span class="na">participants</span><span class="o">.</span><span class="na">values</span><span class="o">())</span> <span class="o">{</span></div><div class='line' id='LC40'>			<span class="k">if</span> <span class="o">(</span><span class="n">message</span><span class="o">.</span><span class="na">getTopic</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">participant</span><span class="o">.</span><span class="na">getTopic</span><span class="o">()))</span> <span class="o">{</span></div><div class='line' id='LC41'>				<span class="n">participant</span><span class="o">.</span><span class="na">processMessage</span><span class="o">(</span><span class="n">message</span><span class="o">);</span></div><div class='line' id='LC42'>			<span class="o">}</span></div><div class='line' id='LC43'>		<span class="o">}</span></div><div class='line' id='LC44'>	<span class="o">}</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'>	<span class="cm">/**</span></div><div class='line' id='LC47'><span class="cm">	 * Remove a chat participant.</span></div><div class='line' id='LC48'><span class="cm">	 */</span></div><div class='line' id='LC49'>	<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">method</span><span class="o">=</span><span class="n">RequestMethod</span><span class="o">.</span><span class="na">DELETE</span><span class="o">)</span></div><div class='line' id='LC50'>	<span class="nd">@ResponseBody</span></div><div class='line' id='LC51'>	<span class="kd">public</span> <span class="kt">void</span> <span class="nf">removeParticipant</span><span class="o">(</span><span class="nd">@PathVariable</span> <span class="n">String</span> <span class="n">topic</span><span class="o">,</span> <span class="nd">@PathVariable</span> <span class="n">String</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC52'>		<span class="n">removeChatParticipant</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">topic</span><span class="o">);</span></div><div class='line' id='LC53'>	<span class="o">}</span></div><div class='line' id='LC54'><br/></div><div class='line' id='LC55'><br/></div><div class='line' id='LC56'>	<span class="kd">private</span> <span class="n">ChatParticipant</span> <span class="nf">getChatParticipant</span><span class="o">(</span><span class="n">String</span> <span class="n">user</span><span class="o">,</span> <span class="n">String</span> <span class="n">topic</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC57'>		<span class="n">String</span> <span class="n">key</span> <span class="o">=</span> <span class="n">getKey</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">topic</span><span class="o">);</span></div><div class='line' id='LC58'>		<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">participants</span><span class="o">.</span><span class="na">containsKey</span><span class="o">(</span><span class="n">key</span><span class="o">))</span> <span class="o">{</span></div><div class='line' id='LC59'>			<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">participants</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">key</span><span class="o">);</span></div><div class='line' id='LC60'>		<span class="o">}</span></div><div class='line' id='LC61'>		<span class="k">else</span> <span class="o">{</span></div><div class='line' id='LC62'>			<span class="n">ChatParticipant</span> <span class="n">participant</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ChatParticipant</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">topic</span><span class="o">);</span></div><div class='line' id='LC63'>			<span class="k">this</span><span class="o">.</span><span class="na">participants</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">key</span><span class="o">,</span> <span class="n">participant</span><span class="o">);</span></div><div class='line' id='LC64'>			<span class="k">return</span> <span class="n">participant</span><span class="o">;</span></div><div class='line' id='LC65'>		<span class="o">}</span></div><div class='line' id='LC66'>	<span class="o">}</span></div><div class='line' id='LC67'><br/></div><div class='line' id='LC68'>	<span class="kd">private</span> <span class="kt">void</span> <span class="nf">removeChatParticipant</span><span class="o">(</span><span class="n">String</span> <span class="n">user</span><span class="o">,</span> <span class="n">String</span> <span class="n">topic</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC69'>		<span class="k">this</span><span class="o">.</span><span class="na">participants</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="n">getKey</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">topic</span><span class="o">));</span></div><div class='line' id='LC70'>	<span class="o">}</span></div><div class='line' id='LC71'><br/></div><div class='line' id='LC72'>	<span class="kd">private</span> <span class="n">String</span> <span class="nf">getKey</span><span class="o">(</span><span class="n">String</span> <span class="n">user</span><span class="o">,</span> <span class="n">String</span> <span class="n">topic</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC73'>		<span class="k">return</span> <span class="n">user</span> <span class="o">+</span> <span class="s">&quot;:&quot;</span> <span class="o">+</span> <span class="n">topic</span><span class="o">;</span></div><div class='line' id='LC74'>	<span class="o">}</span></div><div class='line' id='LC75'><br/></div><div class='line' id='LC76'><span class="o">}</span></div><div class='line' id='LC77'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2419701/9944a6ca21c8abb0533b24c4384d92bf03d00804/ChatController.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2419701#file_chat_controller.java" style="float:right;margin-right:10px;color:#666">ChatController.java</a>
            <a href="https://gist.github.com/2419701">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/*</span></div><div class='line' id='LC2'><span class="cm"> * Copyright 2002-2012 the original author or authors.</span></div><div class='line' id='LC3'><span class="cm"> *</span></div><div class='line' id='LC4'><span class="cm"> * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></div><div class='line' id='LC5'><span class="cm"> * you may not use this file except in compliance with the License.</span></div><div class='line' id='LC6'><span class="cm"> * You may obtain a copy of the License at</span></div><div class='line' id='LC7'><span class="cm"> *</span></div><div class='line' id='LC8'><span class="cm"> *      http://www.apache.org/licenses/LICENSE-2.0</span></div><div class='line' id='LC9'><span class="cm"> *</span></div><div class='line' id='LC10'><span class="cm"> * Unless required by applicable law or agreed to in writing, software</span></div><div class='line' id='LC11'><span class="cm"> * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></div><div class='line' id='LC12'><span class="cm"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class='line' id='LC13'><span class="cm"> * See the License for the specific language governing permissions and</span></div><div class='line' id='LC14'><span class="cm"> * limitations under the License.</span></div><div class='line' id='LC15'><span class="cm"> */</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'><span class="kn">package</span> <span class="n">org</span><span class="o">.</span><span class="na">springframework</span><span class="o">.</span><span class="na">samples</span><span class="o">.</span><span class="na">async</span><span class="o">.</span><span class="na">chat</span><span class="o">;</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'><span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span></div><div class='line' id='LC20'><span class="kn">import</span> <span class="nn">java.util.Arrays</span><span class="o">;</span></div><div class='line' id='LC21'><span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span></div><div class='line' id='LC22'><br/></div><div class='line' id='LC23'><span class="kn">import</span> <span class="nn">org.springframework.web.context.request.async.DeferredResult</span><span class="o">;</span></div><div class='line' id='LC24'><span class="kn">import</span> <span class="nn">org.springframework.web.context.request.async.StaleAsyncWebRequestException</span><span class="o">;</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'><span class="cm">/**</span></div><div class='line' id='LC27'><span class="cm"> * A ChatParticipant represents a user participating in a chat on a specific topic.</span></div><div class='line' id='LC28'><span class="cm"> *</span></div><div class='line' id='LC29'><span class="cm"> * &lt;p&gt;A participant in a chat makes polling requests continuously and waits until</span></div><div class='line' id='LC30'><span class="cm"> * a message arrives or the request times out. At the start of each polling</span></div><div class='line' id='LC31'><span class="cm"> * request a DeferredResult is created which can be used to process a chat message</span></div><div class='line' id='LC32'><span class="cm"> * as soon as it arrives (see {@link #processMessage(ChatMessage)}. In addition,</span></div><div class='line' id='LC33'><span class="cm"> * an internal cache is used to save messages that arrive after one polling</span></div><div class='line' id='LC34'><span class="cm"> * request ends and before the next one arrives.</span></div><div class='line' id='LC35'><span class="cm"> */</span></div><div class='line' id='LC36'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatParticipant</span> <span class="o">{</span></div><div class='line' id='LC37'><br/></div><div class='line' id='LC38'>	<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">user</span><span class="o">;</span></div><div class='line' id='LC39'><br/></div><div class='line' id='LC40'>	<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">topic</span><span class="o">;</span></div><div class='line' id='LC41'><br/></div><div class='line' id='LC42'>	<span class="kd">private</span> <span class="kd">final</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;</span> <span class="n">messageCache</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;();</span></div><div class='line' id='LC43'><br/></div><div class='line' id='LC44'>	<span class="kd">private</span> <span class="n">DeferredResult</span> <span class="n">deferredResult</span><span class="o">;</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'>	<span class="kd">private</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">lock</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Object</span><span class="o">();</span></div><div class='line' id='LC47'><br/></div><div class='line' id='LC48'>	<span class="cm">/**</span></div><div class='line' id='LC49'><span class="cm">	 * Create a ChatParticipant instance.</span></div><div class='line' id='LC50'><span class="cm">	 */</span></div><div class='line' id='LC51'>	<span class="kd">public</span> <span class="nf">ChatParticipant</span><span class="o">(</span><span class="n">String</span> <span class="n">user</span><span class="o">,</span> <span class="n">String</span> <span class="n">topic</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC52'>		<span class="k">this</span><span class="o">.</span><span class="na">user</span> <span class="o">=</span> <span class="n">user</span><span class="o">;</span></div><div class='line' id='LC53'>		<span class="k">this</span><span class="o">.</span><span class="na">topic</span> <span class="o">=</span> <span class="n">topic</span><span class="o">;</span></div><div class='line' id='LC54'>	<span class="o">}</span></div><div class='line' id='LC55'><br/></div><div class='line' id='LC56'>	<span class="kd">public</span> <span class="n">String</span> <span class="nf">getUser</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC57'>		<span class="k">return</span> <span class="n">user</span><span class="o">;</span></div><div class='line' id='LC58'>	<span class="o">}</span></div><div class='line' id='LC59'><br/></div><div class='line' id='LC60'>	<span class="kd">public</span> <span class="n">String</span> <span class="nf">getTopic</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC61'>		<span class="k">return</span> <span class="n">topic</span><span class="o">;</span></div><div class='line' id='LC62'>	<span class="o">}</span></div><div class='line' id='LC63'><br/></div><div class='line' id='LC64'>	<span class="cm">/**</span></div><div class='line' id='LC65'><span class="cm">	 * Process the message by setting the DeferredResult or if a DeferredResult</span></div><div class='line' id='LC66'><span class="cm">	 * is not available (between polling requests?), save the message.</span></div><div class='line' id='LC67'><span class="cm">	 *</span></div><div class='line' id='LC68'><span class="cm">	 * &lt;p&gt;Note: this method is thread-safe since some threads may poll for new</span></div><div class='line' id='LC69'><span class="cm">	 * messages while other threads post messages.</span></div><div class='line' id='LC70'><span class="cm">	 */</span></div><div class='line' id='LC71'>	<span class="kd">public</span> <span class="kt">void</span> <span class="nf">processMessage</span><span class="o">(</span><span class="n">ChatMessage</span> <span class="n">message</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC72'>		<span class="kd">synchronized</span> <span class="o">(</span><span class="n">lock</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC73'>			<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">deferredResult</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC74'>				<span class="k">try</span> <span class="o">{</span></div><div class='line' id='LC75'>					<span class="k">this</span><span class="o">.</span><span class="na">deferredResult</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">Arrays</span><span class="o">.</span><span class="na">asList</span><span class="o">(</span><span class="n">message</span><span class="o">));</span></div><div class='line' id='LC76'>					<span class="k">return</span><span class="o">;</span></div><div class='line' id='LC77'>				<span class="o">}</span></div><div class='line' id='LC78'>				<span class="k">catch</span> <span class="o">(</span><span class="n">StaleAsyncWebRequestException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC79'>					<span class="c1">// fall through and save message</span></div><div class='line' id='LC80'>					<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&quot;times out&quot;</span><span class="o">);</span></div><div class='line' id='LC81'>				<span class="o">}</span></div><div class='line' id='LC82'>				<span class="k">finally</span> <span class="o">{</span></div><div class='line' id='LC83'>					<span class="k">this</span><span class="o">.</span><span class="na">deferredResult</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span></div><div class='line' id='LC84'>				<span class="o">}</span></div><div class='line' id='LC85'>			<span class="o">}</span></div><div class='line' id='LC86'>			<span class="k">this</span><span class="o">.</span><span class="na">messageCache</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">message</span><span class="o">);</span></div><div class='line' id='LC87'>		<span class="o">}</span></div><div class='line' id='LC88'>	<span class="o">}</span></div><div class='line' id='LC89'><br/></div><div class='line' id='LC90'>	<span class="cm">/**</span></div><div class='line' id='LC91'><span class="cm">	 * Return saved messages or if none are available return {@code null} and save</span></div><div class='line' id='LC92'><span class="cm">	 * the DeferredResult to process the messages when they become available.</span></div><div class='line' id='LC93'><span class="cm">	 *</span></div><div class='line' id='LC94'><span class="cm">	 * &lt;p&gt;Note: this method is thread-safe since some threads may poll for new</span></div><div class='line' id='LC95'><span class="cm">	 * messages while other threads post messages.</span></div><div class='line' id='LC96'><span class="cm">	 */</span></div><div class='line' id='LC97'>	<span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;</span> <span class="n">getMessagesWhenAvailable</span><span class="o">(</span><span class="n">DeferredResult</span> <span class="n">deferredResult</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC98'>		<span class="kd">synchronized</span><span class="o">(</span><span class="n">lock</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC99'>			<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">messageCache</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span> <span class="o">{</span></div><div class='line' id='LC100'>				<span class="k">this</span><span class="o">.</span><span class="na">deferredResult</span> <span class="o">=</span> <span class="n">deferredResult</span><span class="o">;</span></div><div class='line' id='LC101'>				<span class="k">return</span> <span class="kc">null</span><span class="o">;</span></div><div class='line' id='LC102'>			<span class="o">}</span></div><div class='line' id='LC103'>			<span class="k">else</span> <span class="o">{</span></div><div class='line' id='LC104'>				<span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">ChatMessage</span><span class="o">&gt;(</span><span class="k">this</span><span class="o">.</span><span class="na">messageCache</span><span class="o">);</span></div><div class='line' id='LC105'>				<span class="k">this</span><span class="o">.</span><span class="na">messageCache</span><span class="o">.</span><span class="na">clear</span><span class="o">();</span></div><div class='line' id='LC106'>				<span class="k">return</span> <span class="n">result</span><span class="o">;</span></div><div class='line' id='LC107'>			<span class="o">}</span></div><div class='line' id='LC108'>		<span class="o">}</span></div><div class='line' id='LC109'>	<span class="o">}</span></div><div class='line' id='LC110'><br/></div><div class='line' id='LC111'>	<span class="nd">@Override</span></div><div class='line' id='LC112'>	<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC113'>		<span class="k">return</span> <span class="s">&quot;ChatParticipant [user=&quot;</span> <span class="o">+</span> <span class="n">user</span> <span class="o">+</span> <span class="s">&quot;, topic=&quot;</span> <span class="o">+</span> <span class="n">topic</span> <span class="o">+</span> <span class="s">&quot;]&quot;</span><span class="o">;</span></div><div class='line' id='LC114'>	<span class="o">}</span></div><div class='line' id='LC115'><br/></div><div class='line' id='LC116'><span class="o">}</span></div><div class='line' id='LC117'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2419701/e7c423a7a5273d9beab1f8995f72c9231a87a99b/ChatParticipant.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2419701#file_chat_participant.java" style="float:right;margin-right:10px;color:#666">ChatParticipant.java</a>
            <a href="https://gist.github.com/2419701">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p style="text-align:center;"><a href="http://whiteship.me/?p=13570&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13570&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13570&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13570&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13570&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13570</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[클파: 인사이드] 어떻게 만들었나?</title>
		<link>http://whiteship.me/?p=13565</link>
		<comments>http://whiteship.me/?p=13565#comments</comments>
		<pubDate>Tue, 17 Apr 2012 14:44:28 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Cloud Foundry]]></category>
		<category><![CDATA[클파]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13565</guid>
		<description><![CDATA[http://www.slideshare.net/derekcollison/design-of-cloud-foundry http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine 몇몇 핵심 요소들이 있는데&#8230; 커널 (CloudFoundry OSS): 핵심 PaaS 시스템 커널과 오케스트레이터(Orchestrator) 쉘: IaaS 상단의 레이어 오케스트레이터: IaaS 생성, 관리 및 관장(?) 커널이라고 부르는건 VCAP이라는 이름으로 오픈소스로 공개한 핵심 패스 시스템을 말하는 것 같고.. 오케스트레이터 쉘은 뭔지 잘 &#8230; <a href="http://whiteship.me/?p=13565">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.slideshare.net/derekcollison/design-of-cloud-foundry" target="_blank">http://www.slideshare.net/derekcollison/design-of-cloud-foundry</a></p>
<p><a href="http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine" target="_blank">http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine</a></p>
<p>몇몇 핵심 요소들이 있는데&#8230;</p>
<ul>
<li>커널 (CloudFoundry OSS): 핵심 PaaS 시스템</li>
<li>커널과 오케스트레이터(Orchestrator) 쉘: IaaS 상단의 레이어</li>
<li><strong>오케스트레이터: IaaS 생성, 관리 및 관장(?)</strong></li>
</ul>
<p>커널이라고 부르는건 VCAP이라는 이름으로 오픈소스로 공개한 핵심 패스 시스템을 말하는 것 같고.. 오케스트레이터 쉘은 뭔지 잘 몰겠넹;; 설명도 좀 짧고. 나중에 여러 계층과 어떻게 소통하는지 자세히 설명하겠다는군요.</p>
<p>오케스트레이터는 라이프사이클 관장으로 이 부분이 꽤 어려운 문제를 해결하는 부분이라고 합니다. 멀티 노드 설치 스크립트 등을 만들고 사용하는건 그리 어려운 부분이 아니라네요. 그런 부분보다는 &#8220;동작중인 시스템&#8221;을 만드는 것입니다. 즉.. 애플리케이션은 계속 돌면서도 그 밑단의 시스템이 죽었는지.. 전부 새로 껐다 켰는지 알 수 없게 만드는거라고 얼핏 이해했는데&#8230; 흠냐.. 맞겠지?.. 그렇게 하는게 어려운거라고 하고.. 이걸 어떻게 할 수 있게 했는지 설명하겠다고 하네요.</p>
<p><a href="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-1.45.17.png"><img class="aligncenter size-full wp-image-13566" title="cf" src="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-1.45.17.png" alt="" width="874" height="743" /></a></p>
<p>하드웨어 하드웨어고, IaaS 대충 알겠고, 오케스트레이터가 매우 중요하고 어려운 부분인데. 아마도 여기에 nats가 매우 중요한 역할을 하고 있을 것 같고.. CF Kernel이라는게 vcap일꺼고.. clients는 뭐.. http over json으로 통신하는 CLI나 STS 플러긴이나 웹앱이겠지.</p>
<p>클파의 기반 전제(Basic Premises)</p>
<ul>
<li>Fail Fast</li>
<li>Self Healing</li>
<li>Horizontally Scalable Components</li>
<li>Distributed State</li>
<li>No Single Point of Failure</li>
<li>Should be as simple as possible</li>
</ul>
<p>한글로 옮기기도 어렵고 이해하기도 어려운  용어들만 써있네. 덴장 ㅋㅋ 무학의 통찰이 필요해.</p>
<p>제대로 동작하지도 않는 상황에서 최적화 로직을 돌릴 필요는 없으니까 Fail Fast를 시키고 그래야 빨리 복구 시킬 수 있다. 실제로 자살하는 앱을 만들어서 배포한담에 얼마나 빨리 복구되는지 실험도 해봤다. 수평확장이 가능하기 떄문에 한 인스턴스로 4천 TPS 정도가 가능하다면 4만 TPS도 문제가 아니다. 분산 시스템이란게 본래가 복잡한데.. 가능한 단순하게 만들려고 노력한다.</p>
<p>기반 패턴</p>
<ul>
<li>이벤트 드리븐</li>
<li>비동기(애싱크로너스)</li>
<li>논 블락킹</li>
<li><strong>Independent(인디페넌), Idempotent(아이뎀포던)</strong></li>
<li>Message Passing</li>
<li>Eventually Consistent</li>
</ul>
<p>클파의 신경 시스템(널브 시스템)에 대해서 이야길 많이 할텐데.. 그게 가능케 하는게 바로 idempotent하기 때문이다. 메시징 시스템은 내가 직접 만들었고.. 나머진 잘.. 몰겠네 블라블라</p>
<p>기반 설계(Basic Design)</p>
<ul>
<li>모든 컴포넌트는 loosely coupled 시킴</li>
<li>메시징 기반</li>
<li>JSON 페이로드</li>
<li>HTTP 또는 File/Blob 데이터 전송</li>
</ul>
<p>커널 특징</p>
<ul>
<li>모두 동적으로 발견한다.</li>
<li>무작위로(? in any order) 실행하고 확장한다.</li>
<li>필요에 따라 빠지거나 추가할 수 있다.</li>
<li>HTTP와 JSON을 사용해서 모니터링</li>
<li>Location independent</li>
</ul>
<p>&#8220;모두 동적으로 발견한다&#8221;는 말은 신경 시스템으로 메시지를 보내서 모든 컴포넌트다 나는 어딨고 나는 무슨 타입이고 실행된지 얼마나 됐고 내 모니터링 풀은 여깄다 등등을 알수있다. 애플리케이션이 돌고 있는 IP와 포트를 알아낼 수 있지만 사실 애플리케이션이 돌고 있는 곳과 아무런 의존성이 없다.</p>
<p>커널 구성요소</p>
<ul>
<li>라우터</li>
<li>클라우드 컨트롤러</li>
<li>DEA</li>
<li>HealthManager</li>
<li>Service Provisioning Agent</li>
<li>Messaging System</li>
</ul>
<p><a href="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-2.13.01.png"><img class="aligncenter size-full wp-image-13567" title="cf kernal" src="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-2.13.01.png" alt="" width="995" height="732" /></a></p>
<p>커널의 구성요소가 어떻게 구성되어 있는지 보여주는 논리적인 뷰인데.. HTTP REST 요청은 모두 라우터를 통해서 들어오기도 하고 일부는 애플리케이션으로 바로 들어오기도 한다. 이것은 즉 애플리케이션에 적용하는 모든 원칙을&#8230; fault tolerance, high availability, scaling을 커널 구성요소에도 그대로 적용한다는 뜻이다. DEA 풀은 매우 클수도 있고 매우 작을 수도 있다. 헬쓰매니저는 이곳에서 유일하게 싱글톤이다.</p>
<p><a href="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-2.22.17.png"><img class="aligncenter size-full wp-image-13568" title="클파 아키텍처" src="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-18-오전-2.22.17.png" alt="" width="1067" height="804" /></a></p>
<p>이건 아키텍처인데 녹색은 HTTP, 파랑은 메시징, 보라는 뭐지..? 왜 말을 안해;;;</p>
<p>오늘은 여기까지. 20분 48초.</p>
<p>&nbsp;</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13565&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13565&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13565&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13565&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13565&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13565</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[클파:인사이드] 클파의 목적은?</title>
		<link>http://whiteship.me/?p=13563</link>
		<comments>http://whiteship.me/?p=13563#comments</comments>
		<pubDate>Mon, 16 Apr 2012 23:16:27 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Cloud Foundry]]></category>
		<category><![CDATA[goal]]></category>
		<category><![CDATA[클파]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13563</guid>
		<description><![CDATA[http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine http://www.slideshare.net/derekcollison/design-of-cloud-foundry Goal! Raise the unit of currency to be the application and its associated services, not the infrastructures. Best of breed delivery platform for all modern applications and frameworks. Favor choice and openness. 여기까지가 6분 13초. 이 뒤부터 본격적인 &#8230; <a href="http://whiteship.me/?p=13563">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine" target="_blank">http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine</a></p>
<p><a href="http://www.slideshare.net/derekcollison/design-of-cloud-foundry" target="_blank">http://www.slideshare.net/derekcollison/design-of-cloud-foundry</a></p>
<p>Goal!</p>
<ul>
<li>Raise the unit of currency to be the application and its associated services, not the infrastructures.</li>
<li>Best of breed delivery platform for all modern applications and frameworks.</li>
<li>Favor choice and openness.</li>
</ul>
<p>여기까지가 6분 13초. 이 뒤부터 본격적인 내용이 시작인데&#8230; 볼 시간이 없구나. 스프링 강의 시작해야겠다;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13563&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13563&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13563&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13563&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13563&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13563</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Cloud Foundry: Inside the machine] What is the Cloud Foundry? [클파:인사이드] 클파는 뭐다?</title>
		<link>http://whiteship.me/?p=13559</link>
		<comments>http://whiteship.me/?p=13559#comments</comments>
		<pubDate>Mon, 16 Apr 2012 23:02:32 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[Cloud Foundry]]></category>
		<category><![CDATA[aPaaS]]></category>
		<category><![CDATA[oPaaS]]></category>
		<category><![CDATA[클파]]></category>
		<category><![CDATA[클파는 뭐다]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13559</guid>
		<description><![CDATA[http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine http://www.slideshare.net/derekcollison/design-of-cloud-foundry 클파 인사이드 동영상 강의 완벽 분석을 위해서 블로깅 시작&#8230; 먼저 클파란 무엇인가? (여기서 클파는 붙여쓰지 않는데 주목.. 가끔 붙여썼는데 앞으론 띄어써야겠다.) 한 마디로 The Open Platform as a Service라고 말할 수 있는데 플랫폼을 어떻게 정의하느냐에 따라 다들 PaaS &#8230; <a href="http://whiteship.me/?p=13559">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine" target="_blank">http://www.infoq.com/presentations/Cloud-Foundry-Inside-the-Machine</a></p>
<p><a href="http://www.slideshare.net/derekcollison/design-of-cloud-foundry" target="_blank">http://www.slideshare.net/derekcollison/design-of-cloud-foundry</a></p>
<p>클파 인사이드 동영상 강의 완벽 분석을 위해서 블로깅 시작&#8230; 먼저 클파란 무엇인가? (여기서 클파는 붙여쓰지 않는데 주목.. 가끔 붙여썼는데 앞으론 띄어써야겠다.)</p>
<p>한 마디로 The Open Platform as a Service라고 말할 수 있는데 플랫폼을 어떻게 정의하느냐에 따라 다들 PaaS 얘기하는게 장황해서.. 좀 더 구체적으로 말하자면 aPaaS라고 말할 수 있다.</p>
<p>aPaaS라고쓰고 앱패스 라고 읽는다.</p>
<p>aPaas란..</p>
<ul>
<li>Application Platform as a Service</li>
<li>Applications and Services</li>
<li>이것에 집중하는것이지&#8230; 다음과 같은건 신경쓰지 않는다.</li>
<ul>
<li>VM, Memory, Storage, Networks, CPUs</li>
</ul>
</ul>
<p>그러니까.. 클파는 뭐다? 앱패스다.</p>
<p>이게 끝일까? 아니다. 클파는 OpenPaaS이기도 하다. 오픈 패~스.</p>
<p>데릭이 말하길&#8230; 그들은 트룰리 이코 시스템 플랫폼을 원한단다&#8230;</p>
<p>OpenPaaS란..</p>
<ul>
<li>다양한 언어</li>
<ul>
<li>루비, 자바, 스칼라, 노드제이에스, 얼랑, 파이썬, PHP</li>
</ul>
<li>다양한 프레임워크</li>
<ul>
<li>레일스, 시나트라, 스프링, 그레일스, 익스프레스, 리프트</li>
</ul>
<li>다양한 서비스</li>
<ul>
<li>마이시퀄, 포스트그레스, 몽고디비, 레디스, 래빗엠큐</li>
</ul>
<li>다양한 Cloud, 다양한 IaaS</li>
<ul>
<li>vSphere, OpenStack, AWS, MicroCloud</li>
</ul>
<li>하이브리드, Public 하게 구성하거나 Private 하게 구성하거나 둘을 혼용하거나..</li>
<li>그리고 이걸 모두 오픈 소스로&#8230; 캬..</li>
</ul>
<p><a href="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-17-오전-10.35.29.png"><img class="aligncenter size-full wp-image-13560" title="oPaaS" src="http://whiteship.me/wp-content/uploads/2012/04/스크린샷-2012-04-17-오전-10.35.29.png" alt="" width="677" height="526" /></a></p>
<p>출처: <a href="http://www.slideshare.net/derekcollison/design-of-cloud-foundry" target="_blank">http://www.slideshare.net/derekcollison/design-of-cloud-foundry</a></p>
<p>그러니까.</p>
<p>클파는 == 앱패스 &amp;&amp; 오픈패스.</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13559&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13559&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13559&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13559&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13559&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13559</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>간만에 일기를 제대로 끄적끄적</title>
		<link>http://whiteship.me/?p=13557</link>
		<comments>http://whiteship.me/?p=13557#comments</comments>
		<pubDate>Mon, 16 Apr 2012 14:04:56 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[일기장]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13557</guid>
		<description><![CDATA[- 총선 망했네.. 대선은 기대도 안 해. 나꼼수 지못미. ㅠ.ㅠ - 회사는 왜이래.. 아 쪽팔리니까 기사좀 그만 내보냈으면 좋겠어. 진짜 제발 진심 쪽팔려 제발 그만해. 쫌. - 클파 완전 재밌어. 하지만 공짜는 없구나. 흑흑&#8230; - 루비 공부해야지. 3장에서 왜 멈췄지..? &#8230; <a href="http://whiteship.me/?p=13557">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>- 총선 망했네.. 대선은 기대도 안 해. 나꼼수 지못미. ㅠ.ㅠ</p>
<p>- 회사는 왜이래.. 아 쪽팔리니까 기사좀 그만 내보냈으면 좋겠어. 진짜 제발 진심 쪽팔려 제발 그만해. 쫌.</p>
<p>- 클파 완전 재밌어. 하지만 공짜는 없구나. 흑흑&#8230;</p>
<p>- 루비 공부해야지. 3장에서 왜 멈췄지..? 어여 합시다. 기선씨. nats랑 vcap 분석 하려면 어여 해야지&#8230;</p>
<p>- 칸타빌레. 비밀이지롱. 캬캬캬.</p>
<p>- 윤군 왜 안보이냐? 어여 나타나. 잼난것 좀 해보자.</p>
<p>- eGov Data라고 들어보셨능가&#8230; 한국형 Spring Data라고 하지뭐.. 캬캬</p>
<p>- 알고리즘 코딩 연습은 꾸준히 해야 돼. 알겠지? 머리가 굳었어도 노력하자꾸나 기선아.</p>
<p>- 용식형은 굿모닝팝스를 매일 빼놓치 않고 듣는데.. 짱이야.. 나도 다시 시작하자. 불량 GMPer. 으흑&#8230;</p>
<p>- IELTS 시험은 1년에 한번씩만 보기로 한거니? 정신차려. 백기선. 총선을 보라고. 더이상 미래는 없는거야.</p>
<div>- 토틀라시안 가고싶은데 자격이 안돼 ㅠ.ㅠ 어흑&#8230; 이건 일단 신경끄고 IETLS 부터 신경쓰자.</div>
<p>- 뭐 빼먹은건 없지? 있나? 몰라 이게 한계야.</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13557&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13557&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13557&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13557&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13557&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13557</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>@Configuration을 사용한 웹 설정 파일 테스트 작성시 난감함&#8230;</title>
		<link>http://whiteship.me/?p=13555</link>
		<comments>http://whiteship.me/?p=13555#comments</comments>
		<pubDate>Mon, 16 Apr 2012 06:42:35 +0000</pubDate>
		<dc:creator>기선</dc:creator>
				<category><![CDATA[3.1]]></category>
		<category><![CDATA[@Configuration]]></category>
		<category><![CDATA[WebMvcConfigurationSupport]]></category>
		<category><![CDATA[스프링 3.1]]></category>

		<guid isPermaLink="false">http://whiteship.me/?p=13555</guid>
		<description><![CDATA[이렇게 코딩을 해두고.. 이 설정 파일에서 빈으로 등록되는 것들이 제대로 등록되나 궁금하니까 테스트를 작성해볼 수 있겠죠. 이런식으로 말이죠. di() 메서드 아무것도 안해도 사실상 제가 원하는 테스트는 저정도면 충분하거든요. 그리고 이정도 테스트는 XML 기반으로 설정할 때도 잘 통과했었는데&#8230;. 흠.. 잘 안됩니다. &#8230; <a href="http://whiteship.me/?p=13555">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="gist-2397205" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kn">package</span> <span class="n">cantabille</span><span class="o">.</span><span class="na">config</span><span class="o">;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="kn">import</span> <span class="nn">cantabille.modules.ModulesPackageMarker</span><span class="o">;</span></div><div class='line' id='LC4'><span class="kn">import</span> <span class="nn">org.springframework.context.annotation.Bean</span><span class="o">;</span></div><div class='line' id='LC5'><span class="kn">import</span> <span class="nn">org.springframework.context.annotation.ComponentScan</span><span class="o">;</span></div><div class='line' id='LC6'><span class="kn">import</span> <span class="nn">org.springframework.context.annotation.Configuration</span><span class="o">;</span></div><div class='line' id='LC7'><span class="kn">import</span> <span class="nn">org.springframework.stereotype.Controller</span><span class="o">;</span></div><div class='line' id='LC8'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.HandlerMapping</span><span class="o">;</span></div><div class='line' id='LC9'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer</span><span class="o">;</span></div><div class='line' id='LC10'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.config.annotation.EnableWebMvc</span><span class="o">;</span></div><div class='line' id='LC11'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry</span><span class="o">;</span></div><div class='line' id='LC12'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport</span><span class="o">;</span></div><div class='line' id='LC13'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.view.InternalResourceViewResolver</span><span class="o">;</span></div><div class='line' id='LC14'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.view.JstlView</span><span class="o">;</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="cm">/**</span></div><div class='line' id='LC17'><span class="cm"> * @author Keesun Baik</span></div><div class='line' id='LC18'><span class="cm"> */</span></div><div class='line' id='LC19'><span class="nd">@Configuration</span></div><div class='line' id='LC20'><span class="nd">@ComponentScan</span><span class="o">(</span></div><div class='line' id='LC21'>		<span class="n">basePackageClasses</span> <span class="o">=</span> <span class="n">ModulesPackageMarker</span><span class="o">.</span><span class="na">class</span><span class="o">,</span></div><div class='line' id='LC22'>		<span class="n">useDefaultFilters</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span></div><div class='line' id='LC23'>		<span class="n">includeFilters</span> <span class="o">=</span> <span class="nd">@ComponentScan.Filter</span><span class="o">(</span><span class="n">Controller</span><span class="o">.</span><span class="na">class</span><span class="o">))</span></div><div class='line' id='LC24'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">WebConfig</span> <span class="kd">extends</span> <span class="n">WebMvcConfigurationSupport</span> <span class="o">{</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'>	<span class="nd">@Override</span></div><div class='line' id='LC27'>	<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">configureDefaultServletHandling</span><span class="o">(</span><span class="n">DefaultServletHandlerConfigurer</span> <span class="n">configurer</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC28'>		<span class="n">configurer</span><span class="o">.</span><span class="na">enable</span><span class="o">();</span></div><div class='line' id='LC29'>	<span class="o">}</span></div><div class='line' id='LC30'><br/></div><div class='line' id='LC31'>	<span class="nd">@Override</span></div><div class='line' id='LC32'>	<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">addResourceHandlers</span><span class="o">(</span><span class="n">ResourceHandlerRegistry</span> <span class="n">registry</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC33'>		<span class="n">registry</span><span class="o">.</span><span class="na">addResourceHandler</span><span class="o">(</span><span class="s">&quot;/resources/**&quot;</span><span class="o">).</span><span class="na">addResourceLocations</span><span class="o">(</span><span class="s">&quot;/static&quot;</span><span class="o">);</span></div><div class='line' id='LC34'>	<span class="o">}</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'>	<span class="nd">@Bean</span></div><div class='line' id='LC37'>	<span class="kd">public</span> <span class="n">InternalResourceViewResolver</span> <span class="nf">viewResolver</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC38'>		<span class="n">InternalResourceViewResolver</span> <span class="n">resolver</span> <span class="o">=</span> <span class="k">new</span> <span class="n">InternalResourceViewResolver</span><span class="o">();</span></div><div class='line' id='LC39'>		<span class="n">resolver</span><span class="o">.</span><span class="na">setViewClass</span><span class="o">(</span><span class="n">JstlView</span><span class="o">.</span><span class="na">class</span><span class="o">);</span></div><div class='line' id='LC40'>		<span class="n">resolver</span><span class="o">.</span><span class="na">setPrefix</span><span class="o">(</span><span class="s">&quot;/WEB-INF/views/&quot;</span><span class="o">);</span></div><div class='line' id='LC41'>		<span class="n">resolver</span><span class="o">.</span><span class="na">setSuffix</span><span class="o">(</span><span class="s">&quot;.jsp&quot;</span><span class="o">);</span></div><div class='line' id='LC42'>		<span class="k">return</span> <span class="n">resolver</span><span class="o">;</span></div><div class='line' id='LC43'>	<span class="o">}</span></div><div class='line' id='LC44'><br/></div><div class='line' id='LC45'><span class="o">}</span></div><div class='line' id='LC46'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2397205/7d0d3410ed57b3c9637b3d01f3a8d37b00cc7d4c/WebConfig.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2397205#file_web_config.java" style="float:right;margin-right:10px;color:#666">WebConfig.java</a>
            <a href="https://gist.github.com/2397205">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>이렇게 코딩을 해두고.. 이 설정 파일에서 빈으로 등록되는 것들이 제대로 등록되나 궁금하니까 테스트를 작성해볼 수 있겠죠.</p>
<div id="gist-2397213" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kn">package</span> <span class="n">cantabille</span><span class="o">.</span><span class="na">config</span><span class="o">;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="kn">import</span> <span class="nn">org.junit.Test</span><span class="o">;</span></div><div class='line' id='LC4'><span class="kn">import</span> <span class="nn">org.junit.runner.RunWith</span><span class="o">;</span></div><div class='line' id='LC5'><span class="kn">import</span> <span class="nn">org.springframework.beans.factory.annotation.Autowired</span><span class="o">;</span></div><div class='line' id='LC6'><span class="kn">import</span> <span class="nn">org.springframework.test.context.ContextConfiguration</span><span class="o">;</span></div><div class='line' id='LC7'><span class="kn">import</span> <span class="nn">org.springframework.test.context.junit4.SpringJUnit4ClassRunner</span><span class="o">;</span></div><div class='line' id='LC8'><span class="kn">import</span> <span class="nn">org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping</span><span class="o">;</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="cm">/**</span></div><div class='line' id='LC11'><span class="cm"> * @author Keesun Baik</span></div><div class='line' id='LC12'><span class="cm"> */</span></div><div class='line' id='LC13'><span class="nd">@RunWith</span><span class="o">(</span><span class="n">SpringJUnit4ClassRunner</span><span class="o">.</span><span class="na">class</span><span class="o">)</span></div><div class='line' id='LC14'><span class="nd">@ContextConfiguration</span><span class="o">(</span><span class="n">classes</span> <span class="o">=</span> <span class="n">WebConfig</span><span class="o">.</span><span class="na">class</span><span class="o">)</span></div><div class='line' id='LC15'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">WebConfigTest</span> <span class="o">{</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>	<span class="nd">@Autowired</span> <span class="n">RequestMappingHandlerMapping</span> <span class="n">rmhm</span><span class="o">;</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>	<span class="nd">@Test</span></div><div class='line' id='LC20'>	<span class="kd">public</span> <span class="kt">void</span> <span class="nf">di</span><span class="o">(){</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'>	<span class="o">}</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'><span class="o">}</span></div><div class='line' id='LC25'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2397213/f92f25bcad195cd5414541e6597857185faaedfd/WebConfigTest.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2397213#file_web_config_test.java" style="float:right;margin-right:10px;color:#666">WebConfigTest.java</a>
            <a href="https://gist.github.com/2397213">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>이런식으로 말이죠. di() 메서드 아무것도 안해도 사실상 제가 원하는 테스트는 저정도면 충분하거든요. 그리고 이정도 테스트는 XML 기반으로 설정할 때도 잘 통과했었는데&#8230;. 흠.. 잘 안됩니다. ApplicationContext를 제대로 만들지 못합니다. 특정 빈을 만들지 못하기 때문이죠. DefaultServlet을 사용하려면 ServletContext가 필요하다는 에러가 나면서 Assert.notNull()에서 걸리고 말죠&#8230; 어찌하면 좋을까나&#8230;</p>
<p>스프링 TestContext를 포기할 수밖에 없는건가&#8230;</p>
<p>그리고 그게 꼭 필요한거면 XML 기반으로 동일한 설정을 할때도 안됐어여 하는거 아닌가..</p>
<p>흠.. 고민이로세.</p>
<p>아.. 그냥 테스트하지 말까.. 너무 당연한거니깐?? ㅋㅋㅋ</p>
<p style="text-align:center;"><a href="http://whiteship.me/?p=13555&amp;emo=0&amp;vote=%EB%B6%88%EC%BE%8C%ED%95%B4" title="불쾌해">불쾌해?</a> <a href="http://whiteship.me/?p=13555&amp;emo=1&amp;vote=%EC%A7%80%EA%B2%A8%EC%9B%8C" title="지겨워">지겨워?</a> <a href="http://whiteship.me/?p=13555&amp;emo=2&amp;vote=%EC%9E%AC%EB%B0%8C%EB%84%A4" title="재밌네">재밌네?</a> <a href="http://whiteship.me/?p=13555&amp;emo=3&amp;vote=%EA%B4%9C%EC%B0%AE%EB%84%A4" title="괜찮네">괜찮네?</a> <a href="http://whiteship.me/?p=13555&amp;emo=4&amp;vote=%EC%A2%8B%EA%B5%AC%EB%82%98" title="좋구나">좋구나?</a> </p>]]></content:encoded>
			<wfw:commentRss>http://whiteship.me/?feed=rss2&#038;p=13555</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Served from: whiteship.me @ 2012-05-18 06:59:19 -->
