<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>vinu</title>
		<link>http://blog.dbza.net/</link>
		<description>1 i f 2  &lt;--- 해석가능하시죠 ?</description>
		<language>ko</language>
		<pubDate>Fri, 11 May 2012 17:52:55 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<managingEditor>vinu</managingEditor>
		<image>
			<title>vinu</title>
			<url>http://cfile28.uf.tistory.com/image/116A1A374C46542C990108</url>
			<link>http://blog.dbza.net</link>
			<description>1 i f 2  &lt;--- 해석가능하시죠 ?</description>
		</image>
		<item>
			<title>HTML5 가속도계 API 이용 ??</title>
			<link>http://blog.dbza.net/192</link>
			<description>&lt;p&gt;&lt;a href=&quot;http://www.albertosarullo.com/blog/javascript-accelerometer-demo-source&quot; target=&quot;_blank&quot; style=&quot;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Dotum, AppleGothic, Helvetica, sans-serif; line-height: 1.25; color: rgb(255, 255, 204); text-decoration: underline; vertical-align: middle; background-color: rgb(47, 99, 156); &quot;&gt;http://www.albertosarullo.com/blog/javascript-accelerometer-demo-source&lt;/a&gt;
&lt;/p&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-192-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-fr/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-fr/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/DerivativeWorks&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이선스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이선스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div class=&quot;another_category another_category_color_violet&quot;&gt;
&lt;h4&gt;'&lt;a href=&quot;/category/dog발;&quot;&gt;dog발;&lt;/a&gt;&amp;nbsp;&gt;&amp;nbsp;&lt;a href=&quot;/category/dog발;/javascript&quot;&gt;javascript&lt;/a&gt;' 카테고리의 다른 글&lt;/h4&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/192&quot; &gt;HTML5 가속도계 API 이용 ??&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
16:28:15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/190&quot; &gt;.attr(&amp;quot;checked&amp;quot;, &amp;quot;&amp;quot;) 버그&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/189&quot; &gt;The Node Beginner Book (Korean version)&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/179&quot; &gt;javascript location.href target&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(3)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/177&quot; &gt;input text용 updown버튼&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(1)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/175&quot; &gt;jQuery 입력폼 글자수 제한&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/10&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;</description>
			<category>javascript</category>
			<author>vinu</author>
			<guid>http://blog.dbza.net/192</guid>
			<comments>http://blog.dbza.net/192#entry192comment</comments>
			<pubDate>Fri, 11 May 2012 16:28:15 +0900</pubDate>
		</item>
		<item>
			<title>Samsung GALAXY NOTE 순정롬 복원법</title>
			<link>http://blog.dbza.net/191</link>
			<description>1. 오딘, 순정롬 준비 (HOME_E160K.FA09.1943_CL867733_REV0000_user_mid_ship.tar.md5)&lt;br /&gt;
2. 전원 끄고 다운로드모드 진입 (볼륨다운버튼 + 홈버튼 + 전원버튼)&lt;br /&gt;
3. 오딘 실행&lt;br /&gt;
4. File[Download] - PDA 클릭 - 순정롬 선택&lt;br /&gt;
5. Start 클릭&lt;br /&gt;
&lt;br /&gt;- 너무 쉬워 그림 따윈 없음.&amp;nbsp;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-191-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-fr/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-fr/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/DerivativeWorks&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이선스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이선스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div class=&quot;another_category another_category_color_violet&quot;&gt;
&lt;h4&gt;'&lt;a href=&quot;/category/Z식;&quot;&gt;Z식;&lt;/a&gt;' 카테고리의 다른 글&lt;/h4&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/191&quot; &gt;Samsung GALAXY NOTE 순정롬 복원법&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/03/09&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;</description>
			<category>Z식;</category>
			<author>vinu</author>
			<guid>http://blog.dbza.net/191</guid>
			<comments>http://blog.dbza.net/191#entry191comment</comments>
			<pubDate>Fri, 09 Mar 2012 15:01:15 +0900</pubDate>
		</item>
		<item>
			<title>.attr(&quot;checked&quot;, &quot;&quot;) 버그</title>
			<link>http://blog.dbza.net/190</link>
			<description>jQuery checkbox&lt;br /&gt;
&lt;br /&gt;.attr(&quot;checked&quot;, &quot;&quot;) 메서드가 안 먹힘.&lt;br /&gt;
&lt;br /&gt;찾아보니... 버그&lt;br /&gt;
&lt;br /&gt;http://bugs.jquery.com/ticket/10248&lt;br /&gt;
&lt;br /&gt;대체방법 :&amp;nbsp;.removeAttr(&quot;checked&quot;);&amp;nbsp;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-190-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-fr/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-fr/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/DerivativeWorks&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이선스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이선스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div class=&quot;another_category another_category_color_violet&quot;&gt;
&lt;h4&gt;'&lt;a href=&quot;/category/dog발;&quot;&gt;dog발;&lt;/a&gt;&amp;nbsp;&gt;&amp;nbsp;&lt;a href=&quot;/category/dog발;/javascript&quot;&gt;javascript&lt;/a&gt;' 카테고리의 다른 글&lt;/h4&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/192&quot; &gt;HTML5 가속도계 API 이용 ??&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
16:28:15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/190&quot; &gt;.attr(&amp;quot;checked&amp;quot;, &amp;quot;&amp;quot;) 버그&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/189&quot; &gt;The Node Beginner Book (Korean version)&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/179&quot; &gt;javascript location.href target&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(3)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/177&quot; &gt;input text용 updown버튼&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(1)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/175&quot; &gt;jQuery 입력폼 글자수 제한&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/10&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;</description>
			<category>javascript</category>
			<author>vinu</author>
			<guid>http://blog.dbza.net/190</guid>
			<comments>http://blog.dbza.net/190#entry190comment</comments>
			<pubDate>Fri, 20 Jan 2012 13:43:18 +0900</pubDate>
		</item>
		<item>
			<title>The Node Beginner Book (Korean version)</title>
			<link>http://blog.dbza.net/189</link>
			<description>&lt;H2&gt;이 문서에 대하여&lt;/H2&gt;
&lt;P&gt;본 문서의 목표는 Node.js용 애플리케이션 개발을 시작을 할 수 있게 만드는 것입니다. 그리고 함께 알아야 하는 “고급” JavaScript에 관한 모든 것을 다룹니다. 본 문서는 전형적인 “Hello World” 튜토리얼 보다는 더 많이 다룹니다. &lt;/P&gt;&lt;A name=status&gt;&lt;/A&gt;
&lt;H3&gt;상태&lt;/H3&gt;
&lt;P&gt;당신은 현재 이 책의 최종버전을 읽고 있습니다. 즉, 새로운 버전의 Node.js에 있는 변경사항들을 반영하거나 오류를 수정할 때만 업데이트 합니다. &lt;/P&gt;
&lt;P&gt;이 책에 있는 코드 예제들은 Node.js 0.4.9에서 동작하는지 테스트 되었습니다. &lt;/P&gt;&lt;A name=intended-audience&gt;&lt;/A&gt;
&lt;H3&gt;대상 독자&lt;/H3&gt;
&lt;P&gt;이 문서는 저와 비슷한 배경을 가진 독자들에게 가장 잘 맞을 겁니다. 적어도 객체지향 언어 –루비, 파이선, PHP, 혹은 자바 같은 언어- 하나 정도에는 경험이 있고, JavaScript에는 약간의 경험만 있으며, Node.js는 이번이 처음인 분들 말입니다. &lt;/P&gt;
&lt;P&gt;이미 다른 언어에 대한 경험을 가진 개발자들을 대상으로 한다는 말은 데이터 타입이나 변수, 제어구조 같은 것들을 이 문서에서 다루지 않다는 뜻입니다. 본 문서를 이해하기 위해서는 그런 기본적인 것들은 미리 알고 있어야 합니다. &lt;/P&gt;
&lt;P&gt;하지만, JavaScript에서의 객체나 함수들은 다른 대부분의 언어들에 대응되는 것과 다르기 때문에, 좀 더 자세히 설명하겠습니다. &lt;/P&gt;&lt;A name=structure&gt;&lt;/A&gt;
&lt;H3&gt;이 문서의 구조&lt;/H3&gt;
&lt;P&gt;이 문서를 마치는 시점에, 유저들에게 웹페이지를 보여주고 파일들을 업로드 할 수 있는 완성된 웹 애플리케이션을 가지게 될 것입니다. &lt;/P&gt;
&lt;P&gt;이 유스케이스를 만족하기 위해 “충분한 정도”까지만 코드를 만드는 것에서 조금 더 나아가서, “세상을 바꾸는 정도”는 아닙니다만, 간결하지만 완결성있는 프레임워크를 만들어서 우리의 애플리케이션의 다른 부분들로부터 깔끔하게 분리할 겁니다. &lt;/P&gt;
&lt;P&gt;우리는 Node.js에서 JavaScript 개발을 하는 것이 브라우저에서 JavaScript를 개발하는 것과 어떻게 다른지를 살펴보는 것으로 시작하려 할겁니다. &lt;/P&gt;
&lt;P&gt;다음으로, “Hello World” 애플리케이션을 작성하는 훌륭한 오랜 전통을 따를 생각입니다. 그리고 그건 “무언가를 하는” 아주 기본이 되는 Node.js 애플리케이션이 될 겁니다. &lt;/P&gt;
&lt;P&gt;그리고 나서는, 우리가 만들기 원하는 “실제” 애플리케이션의 종류가 무엇인지에 대해 논의하고, 이 애플리케이션을 조립하기 위해 구현해야 하는 다른 부분들을 자세히 살펴보고, 하나씩 이 각각의 부분들에 대해 작업을 시작할 생각입니다. &lt;/P&gt;
&lt;P&gt;약속드렸듯이, 우리는 JavaScript의 고급 개념 몇 가지와, 그것을 어떻게 사용하는지, 그리고 우리가 아는 다른 프로그래밍 언어의 개념과 이 개념이 어떻게 다른지 살펴볼 것입니다. &lt;/P&gt;
&lt;P&gt;완성된 애플리케이션의 소스코드는 아래 링크를 통해 다운 받으실 수 있습니다. &lt;A href=&quot;https://github.com/ManuelKiessling/NodeBeginnerBook/tree/master/code/application&quot;&gt;the NodeBeginnerBook Github repository&lt;/A&gt;. &lt;/P&gt;
&lt;DIV id=table-of-contents-headline&gt;차례&lt;/DIV&gt;
&lt;DIV id=table-of-contents&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#about&quot;&gt;이 문서에 대하여&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#status&quot;&gt;상태&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#intended-audience&quot;&gt;대상 독자&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#structure&quot;&gt;이 문서의 구조&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#javascript-and-nodejs&quot;&gt;JavaScript와 Node.js&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#javascript-and-you&quot;&gt;JavaScript와 당신&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#a-word-of-warning&quot;&gt;주의 사항&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#server-side-javascript&quot;&gt;서버사이드 JavaScript&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#hello-world&quot;&gt;&quot;Hello World&quot;&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#a-full-blown-web-application-with-nodejs&quot;&gt;Node.js로 활짝 핀 웹 애플리케이션&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#the-use-cases&quot;&gt;유스케이스&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#the-application-stack&quot;&gt;애플리케이션 스택&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#building-the-application-stack&quot;&gt;애플리케이션 스택 구축하기&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#a-basic-http-server&quot;&gt;기본 HTTP 서버&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#analyzing-our-http-server&quot;&gt;우리의 HTTP 서버를 분석하기&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#passing-functions-around&quot;&gt;함수를 전달하기&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#how-function-passing-makes-our-http-server-work&quot;&gt;어떻게 함수 전달이 HTTP 서버를 동작하게 하는가&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#event-driven-callbacks&quot;&gt;Event-driven callbacks&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#how-our-server-handles-requests&quot;&gt;우리 서버는 요청을 어떻게 처리하는가?&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#finding-a-place-for-our-server-module&quot;&gt;server 모듈의 위치 잡기&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#whats-needed-to-route-requests&quot;&gt;요청을 &quot;route&quot; 하려면?&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#execution-in-the-kongdom-of-verbs&quot;&gt;동사들(verbs)의 나라에서의 실행(execution)&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#routing-to-real-request-handlers&quot;&gt;실제 request handler로 라우팅(routing)하기&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#making-the-request-handlers-respond&quot;&gt;request handler가 응답하게 만들기&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#how-to-not-do-it&quot;&gt;해서는 안되는 것&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#blocking-and-non-blocking&quot;&gt;Blocking 과 non-blocking&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#responding-request-handlers-with-non-blocking-operations&quot;&gt;request handler가 non-blocking 방식으로 동작하면서 응답하기&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#serving-something-useful&quot;&gt;유용한 것을 제공하기&lt;/A&gt; 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#handling-post-requests&quot;&gt;POST 요청 처리하기&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#handling-file-uploads&quot;&gt;파일 업로드 처리하기&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.nodebeginner.org/index-kr.html#conclusion-and-outlook&quot;&gt;결론과 개관&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;&lt;A name=javascript-and-nodejs&gt;&lt;/A&gt;
&lt;H2&gt;JavaScript와 Node.js&lt;/H2&gt;&lt;A name=javascript-and-you&gt;&lt;/A&gt;
&lt;H3&gt;JavaScript와 당신&lt;/H3&gt;
&lt;P&gt;기술적인 부분들에 대해 이야기 하기 앞서, 잠깐 짬을 내서 당신과 JavaScript와의 관계에 대해 이야기 해 봅시다. 이번 챕터를 읽고 나면 이 문서를 계속 읽어야 할지 판단할 수 있을 겁니다. &lt;/P&gt;
&lt;P&gt;만약 당신이 나와 같다면, 당신은 오래 전에 HTML 문서 작성을 계기로 HTML “개발”을 시작했습니다. 당신은 이 재밌는 일을 JavaScript와 함께 했습니다. 하지만 매우 기초적인 방식으로 사용했죠. 웹페이지 이곳 저곳에 상호작용 기능을 추가하는 식으로 말입니다. &lt;/P&gt;
&lt;P&gt;당신이 정말 원했던 것은 “실제의 것”이었습니다. 당신은 어떻게 하면 복잡한 웹 사이트를 만들 수 있는지 알고 싶었습니다. 그래서 PHP나 루비, 자바 같은 프로그래밍 언어를 배웠고, “백엔드”코드를 작성하기 시작했습니다. &lt;/P&gt;
&lt;P&gt;그러면서도, JavaScript에 눈은 계속 두고 있었죠. jQuery나 Prototype같은 것들의 소개를 보면서 말입니다. 그것들은 JavaScript 영토내에서 좀 더 진보해나갔습니다. 그러면서 JavaScript가 실제로는 &lt;EM&gt;window.open()&lt;/EM&gt; 함수 이상이라는 것을 보았습니다. &lt;/P&gt;
&lt;P&gt;하지만, 여전히 이 언어는 프론트앤드에 머물러 있었고, 웹페이지를 꾸미고 싶을 때 마음대로 다룰 수 있는 jQuery가 있다는 것이 좋긴 했지만, 결국 당신은 JavaScript &lt;EM&gt;사용자&lt;/EM&gt;였을 뿐입니다. 결코 JavaScript &lt;EM&gt;개발자&lt;/EM&gt;는 아니었죠. &lt;/P&gt;
&lt;P&gt;그러다 서버 위에서 동작하는 JavaScript, Node.js가 나왔습니다. 너무 멋지지 않습니까? &lt;/P&gt;
&lt;P&gt;이제 비로소 오래되었지만 새로운 JavaScript를 살펴봐야 할 시기라고 마음먹습니다. 하지만 잠시만요. Node.js 애플리케이션을 작성하는 것과 왜 그런 방식으로 작성해야만 하는 것인지, 즉 Javascript를 이해하는 것은 다른 이야기 입니다. &lt;/P&gt;
&lt;P&gt;문제는 이렇습니다. JavaScript는 두 개, 혹은 세 개의 삶(90년대 중반부터 시작된 작고 우스운 DHTML 헬퍼, jQuery나 그 비슷한 종류의 좀 더 진지한 프론트앤드 도구, 그리고 지금은 서버사이드)을 살았기 때문에 JavaScript를 “올바른” 방식으로 배우는 것을 도와줄 정보를 찾는 것이 쉽지는 않습니다.JavaScript를 단순히 사용하는 것이 아니라, 개발하고 있다는 느낄 수 있도록 Node.js 애플리케이션을 작성하기 위해서 말입니다. &lt;/P&gt;
&lt;P&gt;바로 그겁니다. 당신은 이미 경험있는 개발자이고, 여기저기 해킹하듯 새로운 기술을 배우고 나서 엉뚱하게 사용하는 것을 원하지 않습니다. 당신은 올바른 각도로 이것에 접근하고 있다는 것을 확신하고 싶을 겁니다. &lt;/P&gt;
&lt;P&gt;물론, 훌륭한 문서들이 널려 있습니다. 하지만 때로는 문서만으로는 충분하지 않습니다. 필요한 것은 바로 올바른 안내입니다. &lt;/P&gt;
&lt;P&gt;저의 목표가 당신에게 그런 가이드를 제공하는 것입니다. &lt;/P&gt;&lt;A name=a-word-of-warning&gt;&lt;/A&gt;
&lt;H3&gt;주의 사항&lt;/H3&gt;
&lt;P&gt;정말 뛰어난 JavaScript 개발자들이 있습니다. 저는 그런 사람이 아닙니다. &lt;/P&gt;
&lt;P&gt;저는 단지 앞에서 말했던 그런 수준의 사람입니다. 저는 백앤드 웹 애플리케이션 개발에 관해 한 두 개쯤은 알고 있습니다만, 여전히 “진정한” JavaScript에 대해서는 신참이고, Node.js에 대해서는 마찬가지입니다. JavaScript의 좀 더 고급스러운 내용에 대해서는 최근에서야 배웠습니다. 경험 많은 사람이 아니죠. &lt;/P&gt;
&lt;P&gt;그게 바로 이 책에 “초보에서 전문가로”의 책이 아닌 이유입니다. 그 보다는 “아주 초보에서 발전된 초보로”에 더 가까운 책입니다. &lt;/P&gt;
&lt;P&gt;제가 실패하지 않는다면, 이 책은 제가 Node.js를 시작할 때 가지고 있었다면 좋았겠다 싶은 생각이 드는 그런 종류의 문서가 될 것입니다. &lt;/P&gt;&lt;A name=server-side-javascript&gt;&lt;/A&gt;
&lt;H3&gt;서버 사이드 JavaScript&lt;/H3&gt;
&lt;P&gt;첫 번째 JavaScript의 구현체는 브라우저안에 살았습니다. 하지만 단순히 환경에 불과했습니다. JavaScript로 무엇을 할 수 있는지 정의하였습니다만, 해당 언어 자체가 할 수 있는 것이 무엇인지에 대해서는 그다지 많이 알려주지 않았습니다. JavaScript는 “완결성을 가진” 언어입니다. 당신은 이 언어를 수 많은 환경속에서 사용할 수 있고 다른 “완결성을 가진” 언어들과 마찬가지로 무엇이든지 만들어 낼 수 있습니다. &lt;/P&gt;
&lt;P&gt;Node.js는 실제로 단지 다른 환경일 뿐입니다. Node.js는 브라우저 밖, 백앤드에서 JavaScript를 실행할 수 있게 해줍니다. &lt;/P&gt;
&lt;P&gt;백앤드에서 당신이 지정한 JavaScript를 수행하기 위해서는, 잘 해석되고 실행되어야 합니다. Node.js가 하는 것이 바로 그 일입니다. 그리고 그 일은 구글 크롬 브라우저가 사용하는 JavaScript 실행환경과 동일한, 구글의 V8 가상머신을 사용해 이루어집니다. &lt;/P&gt;
&lt;P&gt;거기에 더해서, Node.js는 많은 유용한 모듈을 탑재하고 있습니다. 그렇기 때문에 string을 console로 뿌리는 것 같은 것을 바닥부터 모두 작성할 필요가 없습니다. &lt;/P&gt;
&lt;P&gt;요컨대, Node.js는 서버사이드 JavaScript 실행환경과 라이브러리, 이렇게 두 가지로 이루어져 있습니다. &lt;/P&gt;
&lt;P&gt;이것들을 사용하기 위해서는 Node.js를 설치해야 합니다. &lt;A title=&quot;Building and Installing Node.js&quot; href=&quot;https://github.com/joyent/node/wiki/Installation&quot;&gt;공식 설치 안내 사이트&lt;/A&gt;를 방문해서 설치를 마친 다음에 다시 오시길 정중히 권합니다. &lt;/P&gt;&lt;A name=hello-world&gt;&lt;/A&gt;
&lt;H3&gt;&quot;Hello World&quot;&lt;/H3&gt;
&lt;P&gt;좋습니다. 바로 차가운 물로 뛰어들어보죠. 우리의 첫 번째 Node.js 애플리케이션, “Hello World”를 작성해 봅시다. &lt;/P&gt;
&lt;P&gt;즐겨쓰는 에디터를 실행해서 &lt;EM&gt;helloworld.js&lt;/EM&gt;라는 파일을 만드세요. STDOUT(표준출력)으로 “Hello World” 문자열을 출력할 생각입니다. 그 일을 하는 코드는 다음과 같습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=pln&gt;console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;파일을 저장하고 Node.js를 통해서 실행해 보겠습니다. &lt;/P&gt;&lt;PRE&gt;node helloworld.js&lt;/PRE&gt;
&lt;P&gt;터미널에 &lt;EM&gt;Hello World&lt;/EM&gt;라고 출력될 겁니다. &lt;/P&gt;
&lt;P&gt;좋아요! 조금 심심하죠? 좀 더 리얼한 걸 만들어 봅시다. &lt;/P&gt;&lt;A name=a-full-blown-web-application-with-nodejs&gt;&lt;/A&gt;
&lt;H2&gt;Node.js로 활짝 핀 웹 애플리케이션&lt;/H2&gt;&lt;A name=the-use-cases&gt;&lt;/A&gt;
&lt;H3&gt;유스케이스&lt;/H3&gt;
&lt;P&gt;간단하지만 리얼하게 해 봅시다. &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;사용자는 웹 브라우저로 우리의 웹 애플리케이션을 이용할 수 있다. &lt;/LI&gt;
&lt;LI&gt;사용자가 http://&lt;EM&gt;domain&lt;/EM&gt;/start를 요청하면 파일 업로드 폼이 들어있는 웰컴페이지를 볼 수 있어야 한다. &lt;/LI&gt;
&lt;LI&gt;업로드할 이미지 파일을 선택해서 폼으로 전송하면, 해당 이미지는 http://&lt;EM&gt;domain&lt;/EM&gt;/upload로 업로드 되어야 하며, 업로드가 끝나면 해당 페이지에 표시된다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;이 정도면 충분합니다. 이제, 당신은 구글링을 하고 코드를 좀 만지면 위 요구사항을 달성할 수 있습니다. 하지만 우리가 원하는 건 그게 아닙니다. &lt;/P&gt;
&lt;P&gt;더욱이, 우리가 원하는 것은 목표를 만족하는 가장 기초적인 코드를 작성하는 것이 아니라, 우아하고 적절한 코드를 만드는 것입니다. 우린 의도적으로 좀 더 추상화된 부분을 넣어서 좀 더 복잡한 Node.js 애플리케이션을 만들고 있다는 느낌을 갖게 해볼 예정입니다. &lt;/P&gt;&lt;A name=the-application-stack&gt;&lt;/A&gt;
&lt;H3&gt;애플리케이션 스택&lt;/H3&gt;
&lt;P&gt;우리의 애플리케이션을 면밀하게 살펴봅시다. 유스케이스를 만족시키기 위해서 구현되어야 하는 부분은 어떤 부분인가요? &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;우리는 웹페이지를 제공해야 한다. 따라서 &lt;STRONG&gt;HTTP 서버&lt;/STRONG&gt;가 필요하다. &lt;/LI&gt;
&lt;LI&gt;우리는 서버는 어떤 URL 요청(request)을 받았는지에 따라 다르게 응답해야 한다. 따라서, 요청과 요청을 처리할 핸들러들을 연결짓기 위한 &lt;STRONG&gt;라우터(router)&lt;/STRONG&gt; 같은 것이 필요하다. &lt;/LI&gt;
&lt;LI&gt;서버로 도착한 요청들, 그리고 라우터를 이용해서 라우팅된 요청들을 만족시키기 위해서 실제적인 &lt;STRONG&gt;요청 핸들러(request handlers)&lt;/STRONG&gt;가 필요하다. &lt;/LI&gt;
&lt;LI&gt;라우터는 아마도 들어오는 어떠한 POST 데이터들도 다룰 수 있어야 한다. 그리고 해당 데이터를 다루기 편한 형태로 만들어 request handler 들에게 넘겨야 한다. 따라서 &lt;STRONG&gt;요청 데이터 핸들링(request data handling)&lt;/STRONG&gt;이 필요하다. &lt;/LI&gt;
&lt;LI&gt;URL에 대한 요청을 다루는 것뿐 아니라 URL이 요청되었을 때 내용을 표시할 필요도 있다. 이 말은 즉, request handler 들이 사용자 브라우저로 콘텐트를 보내기 위해 사용할 수 있는 &lt;STRONG&gt;뷰 로직(view logic)&lt;/STRONG&gt;이 필요하다는 이야기다. &lt;/LI&gt;
&lt;LI&gt;마지막이지만 중요한 것으로는, 사용자가 이미지들을 업로드 할 수 있어야 하니까, 세부 사항을 다루는 &lt;STRONG&gt;업로드 핸들링(upload handling)&lt;/STRONG&gt;이 필요할 것이다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;PHP를 이용해서 이런 스택을 구축하는 방법에 대해 잠시 생각해 보는 시간을 가져봅시다. 전형적으로 mod_php5를 가진 아파치 HTTP 서버를 설치하는 것을 생각해 볼 수 있습니다. &lt;br /&gt;
이것은 “웹페이지를 제공하고 HTTP 요청을 받을 수 있어야 한다”는 요구의 전체를 PHP만으로는 이룰 수가 없다는 것을 의미합니다. &lt;/P&gt;
&lt;P&gt;그런데 node의 경우는 조금 다릅니다. Node.js로는 우리는 애플리케이션뿐 아니라, HTTP 서버를 통째로 구현할 것이기 때문입니다. 사실 따지고보면, 우리의 웹 애플리케이션과 웹 서버는 기본적으로 동일합니다. &lt;/P&gt;
&lt;P&gt;해야 할 일이 많은 것처럼 들릴 수 있는데, Node.js를 이용하면 그렇지 않다는 걸 바로 보게 될 것입니다. &lt;/P&gt;
&lt;P&gt;자 우리 애플리케이션 스택의 첫 번째 파트인 HTTP 서버 구현을 시작해 봅시다. &lt;/P&gt;&lt;A name=building-the-application-stack&gt;&lt;/A&gt;
&lt;H2&gt;애플리케이션 스택 구축하기&lt;/H2&gt;&lt;A name=a-basic-http-server&gt;&lt;/A&gt;
&lt;H3&gt;기본 HTTP 서버&lt;/H3&gt;
&lt;P&gt;“리얼한” Node.js 애플리케이션을 만들어야겠다고 생각했을 때, 어떻게 코드를 작성할지 뿐 아니라 어떻게 코드를 구조화 시킬지에 대해 고민을 했습니다. &lt;br /&gt;
한 파일에 다 넣어야 하나? 웹에 있는 대부분의 튜터리얼들은 Node.js에서 하나의 기본 HTTP 서버에서 한 곳에 모든 로직을 갖도록 작성하는 법을 알려주었습니다. 내가 당장 구현하는 것보다 더 많은 것을 해야 할 때에도 내 코드가 가독성이 좋으려면 어떻게 해야 할까요? &lt;/P&gt;
&lt;P&gt;관심사가 다른 코드들을 분리해서 모듈로 넣어 유지하는 것이 상대적으로 쉬운 방법이라는 것을 알게 되었습니다. &lt;/P&gt;
&lt;P&gt;이렇게 하면 Node.js를 가지고 실행할 때 사용하는 main 파일을 깔끔하게 유지할 수 있고, main 파일과 다른 파일에서 서로 가져다 사용하는 모듈들을 깔끔하게 유지할 수 있습니다. &lt;/P&gt;
&lt;P&gt;자 그럼 우리의 애플리케이션을 실행하는 데 쓸 main 파일과 HTTP 서버 코드가 거주하게 될 모듈 파일을 만들어 보겠습니다. &lt;/P&gt;
&lt;P&gt;제가 보기에는 main 파일의 꽤 표준적인 이름은 index.js 입니다. 서버 모듈을 &lt;EM&gt;server.js&lt;/EM&gt;라는 파일로 만드는 것은 괜찮을 것 같습니다. &lt;/P&gt;
&lt;P&gt;자, 서버모듈을 만들어 봅시다. &lt;EM&gt;server.js&lt;/EM&gt; 라는 파일을 프로젝트 루트 디렉토리에 만든 다음 아래 코드를 타이핑해 넣습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이게 끝입니다. 잘 동작하는 HTTP서버를 방금 만들었습니다. 실행해서 확인해 보겠습니다. Node.js로 방금 만든 스크립트를 실행합니다. &lt;/P&gt;&lt;PRE&gt;node server.js&lt;/PRE&gt;
&lt;P&gt;이제 브라우저를 열고 &lt;A href=&quot;http://localhost:8888/&quot; rel=nofollow&gt;http://localhost:8888/&lt;/A&gt; 로 접속합니다. “Hello World”가 찍히는 웹페이지가 보일 겁니다. &lt;/P&gt;
&lt;P&gt;매우 흥미롭습니다. 그렇죠? 지금은 여기서 무슨 일이 일어났는 지를 먼저 살펴봅시다. 프로젝트를 어떻게 구조화 하는 지에 대한 질문은 잠시 미루고, 뒤에서 다시 다루겠습니다. &lt;/P&gt;&lt;A name=analyzing-our-http-server&gt;&lt;/A&gt;
&lt;H3&gt;우리의 HTTP 서버를 분석하기&lt;/H3&gt;
&lt;P&gt;자, 그럼 실제로 뭐가 어떻게 된 건지 살펴봅시다. &lt;/P&gt;
&lt;P&gt;첫 줄은 Node.js에 기본으로 포함된 &lt;EM&gt;http&lt;/EM&gt; 모듈을 읽어 들인 다음, http 라는 이름의 변수를 통해 접근할 수 있게 만들었습니다. &lt;/P&gt;
&lt;P&gt;그 다음 http 모듈에서 제공하는 함수 중 하나인 &lt;EM&gt;createServer&lt;/EM&gt;를 호출합니다. 해당 함수는 객체를 리턴하고, 그 리턴된 객체는 &lt;EM&gt;listen&lt;/EM&gt; 이라는 이름의 함수를 가지고 있습니다. 이 listen 함수는 HTTP서버에서 요청대기할 포트 번호를 나타내는 숫자를 받습니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;http.createServer&lt;/EM&gt;의 괄호 뒤에 나오는 함수 선언에 대해서는 잠시 무시합시다. &lt;/P&gt;
&lt;P&gt;다음과 같은 식으로 8888 port를 listen 하는 서버를 만들 수도 있습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; server &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
server&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;8888포트를 Listen 하는 HTTP 서버를 시작한 다음 아무일도 안 하는 코드입니다. 어떤 요청이 들어오더라도 말입니다. 테스트 해보면 웹 브라우저는 대기상태에 빠집니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;createServer()&lt;/EM&gt; 호출의 첫 번째 파라미터가 있어야 하는 부분에 함수의 정의가 나온 부분이 매우 흥미롭습니다.(당신의 background가 php처럼 더 보수적인 언어라면 이상하게 보일 겁니다). &lt;/P&gt;
&lt;P&gt;이 함수정의는 &lt;EM&gt;createServer()&lt;/EM&gt;에 넘기는 첫 번째 파라미터입니다. JavaScript에서는 함수도 다른 값처럼 파라미터로 넘길 수 있습니다. &lt;/P&gt;&lt;A name=passing-functions-around&gt;&lt;/A&gt;
&lt;H3&gt;함수를 전달하기&lt;/H3&gt;
&lt;P&gt;예를 들면 다음과 같은 것이 가능합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; say&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;word&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;word&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; execute&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;someFunction&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; value&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; someFunction&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;value&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;execute&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;say&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;주의해서 보세요! 우리는 여기서 &lt;EM&gt;say&lt;/EM&gt; 라는 함수를 &lt;EM&gt;execute&lt;/EM&gt; 함수의 첫 번째 파라미터로 넘기고 있습니다. &lt;EM&gt;say&lt;/EM&gt;함수의 return 값을 넘기는 것이 아니라 &lt;EM&gt;say&lt;/EM&gt; 그 자체를 넘기는 겁니다. &lt;/P&gt;
&lt;P&gt;따라서, &lt;EM&gt;say&lt;/EM&gt;는 &lt;EM&gt;execute&lt;/EM&gt; 함수 내에서 &lt;EM&gt;someFunction&lt;/EM&gt; 이라는 변수가 되며 execute는 이 변수에 담긴 함수를 &lt;EM&gt;someFunction()&lt;/EM&gt; 이라고 표시함으로써 호출할 수 있습니다.(변수에 괄호를 치면서) &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;say&lt;/EM&gt;는 한 개의 파라미터를 가지므로 &lt;EM&gt;execute&lt;/EM&gt;는 &lt;EM&gt;someFunction&lt;/EM&gt;을 호출하면서 파라미터를 넘길 수 있습니다. &lt;/P&gt;
&lt;P&gt;방금 한 것처럼 우리는 함수를 그 이름으로 다른 함수의 파라미터로 넘길 수 있습니다. 하지만 이렇게 먼저 정의하고 그것을 넘기는 간접적인 방법을 사용할 필요가 없습니다. 우리는 함수를 정의하면서 동시에 다른 함수의 파라미터로 넘길 수 있습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; execute&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;someFunction&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; value&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; someFunction&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;value&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;execute&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;word&lt;/SPAN&gt;&lt;SPAN class=pun&gt;){&lt;/SPAN&gt;&lt;SPAN class=pln&gt; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;word&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;},&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;우린 &lt;EM&gt;execute&lt;/EM&gt;의 첫 번째 파라미터 위치에 &lt;EM&gt;execute&lt;/EM&gt;에게 넘기려고 하는 함수를 정의했습니다. &lt;/P&gt;
&lt;P&gt;이때 우리는 함수 이름을 줄 필요가 없습니다. 이것이 바로 &lt;EM&gt;anonymous function&lt;/EM&gt; 이라고 불리는 이유입니다. &lt;/P&gt;
&lt;P&gt;이것으로 제가 “advanced” JavaScript 라고 부르고 싶은 것에 대해 처음으로 살짝 맛을 봤습니다. 이제 이것을 기억합시다. JavaScript 에서는 우리는 함수를 다른 함수의 파라미터로 넘길 수 있다. 이것을 함수를 변수에 할당한 후에 넘길 수도 있고, 정의하는 동시에 넘길 수도 있다. &lt;/P&gt;&lt;A name=how-function-passing-makes-our-http-server-work&gt;&lt;/A&gt;
&lt;H3&gt;어떻게 함수 전달이 HTTP 서버를 동작하게 하는가&lt;/H3&gt;
&lt;P&gt;우리의 미니멀리즘적인 HTTP 서버로 되돌아가 봅시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이제 위 코드가 어떤 일을 하는지 명확해집니다. anonymous 함수가 &lt;EM&gt;createServer&lt;/EM&gt; 함수로 전달되었습니다. &lt;/P&gt;
&lt;P&gt;위 코드를 리팩터링 하면 아래와 같이 만들 수 있습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이제 다음과 같은 질문을 할 차례입니다. &lt;/P&gt;&lt;A name=event-driven-callbacks&gt;&lt;/A&gt;
&lt;H3&gt;Event-driven callbacks&lt;/H3&gt;
&lt;P&gt;답은 a) 그리 쉽지 않고(최소한 저에게는), b) Node.js가 동작하는 방식이 어떤가에 있습니다. Node.js가 굉장히 빠른 이유가 바로 이벤트 드리븐 때문입니다. &lt;/P&gt;
&lt;P&gt;배경 설명을 위해 Felix Geisendörfer의 뛰어난 포스트 &lt;A href=&quot;http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb&quot;&gt;Understanding node.js&lt;/A&gt; 를 읽어 보시는 것도 좋을 것 같네요. &lt;/P&gt;
&lt;P&gt;이것은 모두 결국 Node.js가 이벤트 드리븐으로 동작한다는 사실로 귀결됩니다. 오, 저 역시 이것이 정확히 무슨 뜻인지 모릅니다. 하지만 Node.js로 웹 기반 애플리케이션을 만드는 우리들에게 이게 왜 의미가 있는지 한번 살펴봅시다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;http.createServer&lt;/EM&gt; 메소드를 호출할 때, 우리는 서버가 특정 포트를 listen 할 뿐 아니라 HTTP 요청이 올 때 뭔가를 하기를 기대합니다. &lt;/P&gt;
&lt;P&gt;문제는 이것(HTTP 요청)이 비동기적으로 일어난다는 점입니다. HTTP 요청은 언제든지 일어날 수 있지만 우리에게는 하나의 프로세스밖에 없습니다. &lt;/P&gt;
&lt;P&gt;PHP 애플리케이션을 만들때 우린 이런것은 신경 쓰지 않죠. HTTP 요청이 올 때마다 웹서버(보통 Apache)가 이 요청을 위해 새 프로세스를 포크하고 해당하는 PHP 스크립트를 처음부터 끝까지 실행합니다. &lt;/P&gt;
&lt;P&gt;제어흐름의 관점에서 보면, 새로운 요청이 8888 포트로 들어왔을 때 Node.js의 제어 안에 있습니다.(역주: PHP의 경우 새로운 요청이 들어왔을때 제어흐름은 Apache에 있고, Apache가 알아서 처리하죠) 이것을 도대체 어떻게 해결하죠? &lt;/P&gt;
&lt;P&gt;이것이 바로 Node.js/JavaScript의 이벤트 드리븐 디자인이 빛을 발하는 부분입니다. 다만 몇 가지 새로운 개념을 익히긴 해야합니다. 이 개념들을 우리 서버 코드에 어떻게 적용할지 한번 봅시다. &lt;/P&gt;
&lt;P&gt;서버를 생성할 때 서버 생성 메소드의 파라미터로 함수를 넘깁니다. 요청이 올 때마다 파라미터로 넘긴 함수가 호출됩니다. &lt;/P&gt;
&lt;P&gt;요청이 언제 발생할 지는 모르지만 이제 들어오는 요청을 처리할 곳 생겼습니다. 파라미터로 넘긴 함수입니다. 함수를 먼저 정의한 후 넘겼든 anonymous function으로 넘겼든 말이죠. &lt;/P&gt;
&lt;P&gt;이 개념을 &lt;EM&gt;callback&lt;/EM&gt; 이라고 합니다. 우리는 메소드에 함수를 넘기고, 메소드는 관련된 이벤트가 발생하면 이 함수를 &lt;EM&gt;거꾸로 호출(call back)&lt;/EM&gt; 합니다. &lt;/P&gt;
&lt;P&gt;최소한 저에게는 이것을 이해하는 데 좀 시간이 걸렸습니다. 확실히 이해가 되지 않으면 Felix의 블로그 포스트를 다시 읽어보세요. &lt;/P&gt;
&lt;P&gt;이 새로운 개념을 가지고 동작을 시켜 볼까요? 서버를 생성한 후 아무런 HTTP 요청이 발생하지 않아서 우리가 넘긴 callback 함수도 호출되지 않고 있다면, 우리 코드가 동작한다는 것을 어떻게 알 수 있을까요? 아래와 같이 해 봅시다: &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;EM&gt;onRequest&lt;/EM&gt; 함수 (callback)가 호출될 때 텍스트를 찍기 위해서 &lt;EM&gt;console.log&lt;/EM&gt;를 사용했습니다. 또 HTTP 서버를 &lt;EM&gt;시작하자마자&lt;/EM&gt; 다른 텍스트를 하나 찍었습니다. &lt;/P&gt;
&lt;P&gt;이것을 실행하면(&lt;EM&gt;node server.js&lt;/EM&gt;), “Server has started”라고 커맨드라인에 찍힙니다. 서버에 요청을 할 때마다(브라우저로 &lt;A href=&quot;http://localhost:8888/&quot; rel=nofollow&gt;http://localhost:8888/&lt;/A&gt; 을 열어서) “Request received.” 라고 커맨드 라인에 찍힙니다. &lt;/P&gt;
&lt;P&gt;callback을 가진 이벤트 드리븐 비동기 서버사이드 JavaScript가 동작하다! :-) &lt;/P&gt;
&lt;P&gt;(한번의 브라우저 요청에 “Request received.” 메시지가 두번 STDOUT으로 찍히는 것은 대부분의 브라우저가 http://localhost:8888/을 요청할 때 http://localhost:8888/favicon.ico를 로드하려고 하기 때문이에요). &lt;/P&gt;&lt;A name=how-our-server-handles-requests&gt;&lt;/A&gt;
&lt;H3&gt;우리 서버는 요청을 어떻게 처리하는가?&lt;/H3&gt;
&lt;P&gt;네. 이제 나머지 코드를 얼른 분석해 봅시다. 바로 callback 함수인 &lt;EM&gt;onRequest()&lt;/EM&gt; 입니다. &lt;/P&gt;
&lt;P&gt;callback으로 &lt;EM&gt;onRequest()&lt;/EM&gt; 함수가 호출될때 두 개의 파라미터가 넘어옵니다. &lt;EM&gt;reqeust&lt;/EM&gt;와 &lt;EM&gt;response&lt;/EM&gt; 죠. &lt;/P&gt;
&lt;P&gt;이것들은 객체인데요, HTTP 요청을 자세히 핸들링하거나 응답을 보내는데에 이 객체들의 메소드를 사용할 수 있습니다. &lt;/P&gt;
&lt;P&gt;우리 코드는 요청이 올 때마다 &lt;EM&gt;response.writeHead()&lt;/EM&gt; 함수를 사용해서 HTTP status 200 과 content-type을 응답 헤더로 보내고, &lt;EM&gt;response.write()&lt;/EM&gt; 함수로 “Hello World” 텍스트를 HTTP 응답 바디로 보냅니다. &lt;/P&gt;
&lt;P&gt;마지막으로 &lt;EM&gt;response.end()&lt;/EM&gt;로 응답을 마무리하죠. &lt;/P&gt;
&lt;P&gt;여기서는 요청의 자세한 내용에 대해서 신경 쓰지 않았습니다. 그래서 &lt;EM&gt;request&lt;/EM&gt; 객체는 사용하지 않았죠. &lt;/P&gt;&lt;A name=finding-a-place-for-our-server-module&gt;&lt;/A&gt;
&lt;H3&gt;server 모듈의 위치 잡기&lt;/H3&gt;
&lt;P&gt;네. 제가 나중에 애플리케이션을 구조화 하겠다고 약속했었죠? 지금 우리는 기본적인 HTTP 서버 코드가 있는 &lt;EM&gt;server.js&lt;/EM&gt; 파일과 모듈들을 적재하고 애플리케이션을 시작시키는 main file인 &lt;EM&gt;index.js&lt;/EM&gt; 파일을 가지고 있습니다. &lt;/P&gt;
&lt;P&gt;server.js를 Node.js 모듈로 만들어서 아직 작성하지 않은 &lt;EM&gt;index.js&lt;/EM&gt; main 파일에서 사용하도록 해 봅시다. &lt;/P&gt;
&lt;P&gt;아시는 것처럼, 아래와 같이 우리 코드에서 이미 모듈을 사용하고 있지요. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;...&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(...);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Node.js의 내부 어딘가에 “http” 라는 모듈이 있으며, 이를 require 하고 지역 변수에 할당해서 사용할 수 있습니다. &lt;/P&gt;
&lt;P&gt;이렇게 하면 지역변수가 &lt;EM&gt;http&lt;/EM&gt; 모듈이 제공하는 모든 public 메소드를 사용할 수 있는 객체가 됩니다. &lt;/P&gt;
&lt;P&gt;모듈의 이름으로 지역변수의 이름을 선택하는 것이 일반적이지만, 우리가 원하는 이름으로 지역변수 이름을 선택할 수도 있습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; foo &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;...&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;foo&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(...);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;좋습니다. Node.js의 내부모듈을 사용하는 것은 확실히 알겠군요. 그럼 모듈을 어떻게 직접 만들고 사용할 수 있을까요? &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;server.js&lt;/EM&gt; 스크립트를 모듈로 만들면서 알아봅시다. &lt;/P&gt;
&lt;P&gt;사실 별로 수정할 것도 없습니다. 코드를 모듈로 만든다는 것은 모듈을 필요로 하는 스크립트에 제공할 기능의 일부를 &lt;EM&gt;export&lt;/EM&gt; 하는 것입니다. &lt;/P&gt;
&lt;P&gt;export 할 필요가 있는 우리 HTTP 서버의 기능은 단순합니다. 우리 서버모듈을 require 하는 스크립트는 단순히 서버를 시작하는 것이 필요한 거죠. &lt;/P&gt;
&lt;P&gt;이렇게 하기 위해, 서버 코드를 &lt;EM&gt;start&lt;/EM&gt; 라는 함수 안에 넣고 이 함수를 export 하겠습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이런 방식으로 main 파일인 &lt;EM&gt;index.js&lt;/EM&gt;를 만들고, HTTP 서버를 시작시킬 수 있습니다. server에 대한 코드는 &lt;EM&gt;server.js&lt;/EM&gt; 파일에 있지만요. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;index.js&lt;/EM&gt; 파일을 만들고 내용을 아래와 같이 만듭시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; server &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./server&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;server&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;보시다시피, 우리 서버 모듈을 다른 내장 모듈과 똑같이 사용할 수 있습니다: 파일을 require 하고, 지역변수에 할당하면 export 된 함수를 쓸 수 있게 되지요. &lt;/P&gt;
&lt;P&gt;됐습니다. 이제 main 스크립트를 통해 애플리케이션을 구동해서 기존과 완전히 동일하게 동작하는지 봅시다. &lt;/P&gt;&lt;PRE&gt;node index.js&lt;/PRE&gt;
&lt;P&gt;대단하죠. 이제 애플리케이션의 다른 부분을 다른 파일에 넣고 그것들을 모듈로 만들어서 서로 엮을 수 있게 되었습니다. &lt;/P&gt;
&lt;P&gt;아직 우리는 애플리케이션의 아주 초기 부분만을 만들었습니다. 단지 HTTP 요청을 받는거죠. 이제 요청을 가지고 뭔가를 할 필요가 있죠. 브라우저가 요청한 URL에 따라 반응을 다르게 하는 겁니다. &lt;/P&gt;
&lt;P&gt;아주 단순한 애플리케이션이라면 이 작업을 &lt;EM&gt;onRequest()&lt;/EM&gt; callback 함수에 구현할 수 있죠. 하지만 우리 애플리케이션이 좀 더 재밌기 위해서 좀 더 추상화를 해보자구요. &lt;/P&gt;
&lt;P&gt;다른 HTTP 요청이 코드의 다른 부분을 가리키도록 하는 것을 “라우팅(routing)” 이라고 합니다. 자 그럼 &lt;EM&gt;router&lt;/EM&gt;를 만들어 봅시다. &lt;/P&gt;&lt;A name=whats-needed-to-route-requests&gt;&lt;/A&gt;
&lt;H3&gt;요청을 &quot;route&quot; 하려면?&lt;/H3&gt;
&lt;P&gt;요청 URL과 GET/POST 파라미터를 router로 전달하면 router는 어떤 코드를 실행할지 결정할 수 있어야 합니다. (이 실행할 코드는 우리 애플리케이션의 세 번째 부분이에요: 요청을 받았을 때 실제 일을 하는 request handler 들의 집합입니다.) &lt;/P&gt;
&lt;P&gt;따라서, HTTP 요청에서 URL과 GET/POST 파라미터를 뽑아내야 합니다. 이것을 router 부분에서 구현해야 하는지 server 부분(혹은 server 모듈) 부분에서 구현해야 하는지는 논란의 여지가 있습니다. 일단 지금은 HTTP server의 일부로 만들어 봅시다. &lt;/P&gt;
&lt;P&gt;우리에게 필요한 모든 정보는 &lt;EM&gt;request&lt;/EM&gt; 객체를 - callback 함수인 &lt;EM&gt;onRequest()&lt;/EM&gt; 함수의 첫 번째 파라미터로 전달받은 - 통해 접근할 수 있습니다. 하지만 이 정보를 얻어내기 위해 &lt;EM&gt;url&lt;/EM&gt; 과 &lt;EM&gt;querystring&lt;/EM&gt; 이라는 모듈이 추가로 필요합니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;url&lt;/EM&gt; 모듈은 URL의 각각의 부분 (예를들면 URL path와 query string) 을 뽑아낼 수 있는 메소드를 제공합니다. &lt;EM&gt;querystring&lt;/EM&gt;은 query string을 request 파라미터로 파싱 하는데 사용합니다. &lt;/P&gt;&lt;PRE&gt;                               url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&amp;amp;hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)[&quot;foo&quot;]    |
                                            |
                         querystring(string)[&quot;hello&quot;]
&lt;/PRE&gt;
&lt;P&gt;나중에 보겠지만 &lt;EM&gt;querystring&lt;/EM&gt; 모듈을 POST 요청의 body를 파싱하는데에도 사용할 수 있습니다. &lt;/P&gt;
&lt;P&gt;브라우저가 요청한 URL path가 무엇인지 알 수 있도록 하는 로직을 &lt;EM&gt;onRequest()&lt;/EM&gt; 함수에 추가해 봅시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;좋아요. 이제 URL path를 기준으로 요청을 구분할 수 있게 되었습니다. 이걸 이용하면 URL path를 기반으로 요청을 request handler로 매핑하는 router(아직 안 만들었죠)를 만들 수 있겠네요. &lt;/P&gt;
&lt;P&gt;우리 애플리케이션 관점에서 보면, &lt;EM&gt;/start&lt;/EM&gt; 요청과 &lt;EM&gt;/upload&lt;/EM&gt; 요청을 각각 다른 코드에서 처리하도록 할 수 있다는 것입니다. 곧 모든 것이 어떻게 맞아떨어지는지 보게 될겁니다. &lt;/P&gt;
&lt;P&gt;좋아요. 이제 진짜로 router를 만듭시다. &lt;EM&gt;router.js&lt;/EM&gt; 라는 새 파일을 만들고 내용을 아래와 같이 입력합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;네. 이 코드는 기본적으로 아무것도 안 하죠. 하지만 지금은 이걸로 좋습니다. router에 좀 더 로직을 추가하기 전에 일단 이 router를 server와 어떻게 엮을지 봅시다. &lt;/P&gt;
&lt;P&gt;HTTP server가 router를 사용한다는 것을 알게 해야 합니다. 이 의존성을 강하게 만들 수도 있지만 다른 프로그래밍 언어를 통해 배운 대로 dependency injection을 통해 server와 router를 느슨하게 결합할 겁니다.(배경지식을 위해 Martin Fowler 의 &lt;A href=&quot;http://martinfowler.com/articles/injection.html&quot;&gt;Dependency Injection에 대한 좋은 포스트&lt;/A&gt;를 읽어보는걸 추천합니다.) &lt;/P&gt;
&lt;P&gt;먼저 router 함수를 파라미터로 넘길 수 있도록 server의 &lt;EM&gt;start()&lt;/EM&gt; 함수를 확장합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;그리고 &lt;EM&gt;index.js&lt;/EM&gt;를 확장합니다. 여기서 router 함수를 server로 주사(inject) 합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; server &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./server&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; router &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./router&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;server&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;router&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;여기서도 다시 함수를 넘기고 있지요. 이런 것은 이제 우리에게 새로울 것도 없습니다. &lt;/P&gt;
&lt;P&gt;이제 애플리케이션을 시작하고(&lt;EM&gt;node index.js&lt;/EM&gt;), URL을 요청하면, 애플리케이션의 출력으로 HTTP server가 router를 사용하고 pathname을 넘기는 것을 볼 수 있습니다. &lt;/P&gt;&lt;PRE&gt;bash$ node index.js
Request for /foo received.
About to route a request for /foo&lt;/PRE&gt;
&lt;P&gt;(다소 짜증나는 /favicon.ico 요청 관련 출력은 생략했어요). &lt;/P&gt;&lt;A name=execution-in-the-kongdom-of-verbs&gt;&lt;/A&gt;
&lt;H3&gt;동사들(verbs)의 나라에서의 실행(execution)&lt;/H3&gt;
&lt;P&gt;잠깐 functional programming 에 대해 이야기를 해볼게요. &lt;/P&gt;
&lt;P&gt;함수를 전달하는 것은 단지 기술적인 고려사항이 아니에요. 소프트웨어 디자인의 관점에서 보면 이것은 거의 철학적인 이야기입니다. 잠깐 생각해 봅시다. index 파일에서 &lt;EM&gt;router&lt;/EM&gt; 객체를 server로 전달할 수도 있고, server 는 이 객체의 &lt;EM&gt;route&lt;/EM&gt; 함수를 호출할 수도 있습니다. &lt;/P&gt;
&lt;P&gt;이 방식으로 우리는 물건(thing)을 전달하고 server는 무슨 일인가를 하는데에 이 물건(thing)을 사용합니다. 헤이 router야~~, 이것 좀 보내(route) 줄래? &lt;/P&gt;
&lt;P&gt;하지만 server는 그런 것(thing)이 필요 없죠. 다만 뭔가를 &lt;EM&gt;할&lt;/EM&gt; 필요가 있는 것 뿐 입니다. 그리고 뭔가를 하려면 물건(things)이 필요한 게 아니라 &lt;EM&gt;행동(actions)&lt;/EM&gt;이 필요하죠. &lt;EM&gt;명사(nouns)&lt;/EM&gt;는 필요 없고 &lt;EM&gt;동사(verbs)&lt;/EM&gt;가 필요합니다. &lt;/P&gt;
&lt;P&gt;이 아이디어의 핵심에 있는 근본적인 정신변화를 이해하니 functional programming을 진정으로 이해할 수 있었습니다. &lt;/P&gt;
&lt;P&gt;Steve Yegge의 걸작 &lt;A href=&quot;http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html&quot;&gt;Execution in the Kingdom of Nouns&lt;/A&gt; 을 읽었을 때 이것을 이해했습니다. 지금 읽어보세요. 이것은 제가 본 소프트웨어와 관련된 최고의 저술 중에 하나입니다. &lt;/P&gt;&lt;A name=routing-to-real-request-handlers&gt;&lt;/A&gt;
&lt;H3&gt;실제 request handler로 라우팅(routing) 하기&lt;/H3&gt;
&lt;P&gt;비즈니스로 돌아옵시다. 이제 우리가 의도한 대로 HTTP server와 router는 친구가 되어서 서로 이야기를 나눕니다. &lt;/P&gt;
&lt;P&gt;당연히, 이걸로는 부족합니다. “Routing” 은 다른 URL을 다르게 처리하고 싶다는 말이죠. &lt;EM&gt;/start&lt;/EM&gt; 요청에 대한 “비즈니스 로직”은 &lt;EM&gt;/upload&lt;/EM&gt; 요청과는 다른 함수에서 처리하고 싶습니다. &lt;/P&gt;
&lt;P&gt;router는 요청에 대해 실제로 뭔가를 할 만한 곳이 아닙니다. 애플리케이션이 더 복잡해지면 router를 확장하기가 쉽지가 않아집니다. &lt;/P&gt;
&lt;P&gt;요청이 route 될 함수를 request handler 라고 부르기로 하고 곧바로 뛰어들어가 봅시다. &lt;/P&gt;
&lt;P&gt;새로운 애플리케이션 부분이니까 새 모듈로 만들어야겠습니다. requestHandlers 라는 모듈을 만들고, 각각의 request handler를 위한 껍데기(placeholder) 함수들을 추가한 후 이 모듈의 메소드로 export 합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이제 router와 request handler를 엮었으므로 우리 router가 어딘가로 route 할 수 있게 되었습니다. &lt;/P&gt;
&lt;P&gt;이 시점에 결정이 필요합니다: requestHandler 모듈을 router에 하드코딩 된 방식으로 묶을 것이냐, 아니면 의존관계 주입(dependency injection)으로 좀 더 처리할 것이냐? 모든 패턴과 마찬가지로 의존 관계 주입은 그 자체를 위해 사용하는 것이 아닙니다. 여기에서는 router와 request handler를 느슨하게 묶어서 router의 재사용을 크게 높입니다. &lt;/P&gt;
&lt;P&gt;이렇게 하려면 request handler를 server에서 router로 전달해야 하는데, 이건 더 잘못된 느낌을 줍니다. 왜냐하면 main 파일에서 server로 보내고 server에서 router로 보내야 하기 때문이죠. &lt;/P&gt;
&lt;P&gt;그럼 어떻게 전달하는 게 좋을까요? 지금은 두 개의 handler가 있지만 실제 애플리케이션에서는 handler의 수가 늘어나고 다양해 질 겁니다. 그리고 새 URL request handler가 추가될 때마다 router에서 request와 handler를 매핑하는 일을 하고 싶진 않습니다. 게다가 &lt;EM&gt;if request == x then call handler y&lt;/EM&gt;와 같은 코드는 추악함 이상이 될겁니다. &lt;/P&gt;
&lt;P&gt;다양한 항목이 있고, 각각은 (요청된 URL)문자열에 매핑된다? 오, 연관배열이 딱 맞아떨어질것 같긴 합니다만.. &lt;/P&gt;
&lt;P&gt;음. 조금 실망스럽게도 JavaScript는 연관배열을 지원하지 않는답니다. 그런데, 알고보니 연관배열이 필요한 경우에는 객체를 사용하면 된다는군요. &lt;/P&gt;
&lt;P&gt;여기 좋은 소개가 있습니다. &lt;A href=&quot;http://msdn.microsoft.com/en-us/magazine/cc163419.aspx&quot;&gt;http://msdn.microsoft.com/en-us/magazine/cc163419.aspx&lt;/A&gt;, 관련된 부분을 인용해 보면: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;C++과 C#에서, 객체는 class나 struct의 인스턴스를 지칭합니다. 객체는 그것이 어떤 템플릿(이를테면, class)으로 인스턴스화 되었느냐에 따라 다른 프로퍼티와 메소드를 가집니다. (하지만) JavaScript 객체는 다릅니다. JavaScript에서 객체는 단지 이름/값 쌍의 컬렉션에 불과합니다. - JavaScript 객체는 키 값이 문자열인 사전(dictionary)이라고 생각하세요. &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;만약 JavaScript 객체가 단순히 이름/값 쌍의 컬렉션이라면 어떻게 메소드를 가질 수 있죠? 네, 값은 문자열 일수도 숫자일수도 함수!일 수도 있습니다. &lt;/P&gt;
&lt;P&gt;오케이, 다시 코드로 돌아와서 requestHandlers의 리스트를 객체로 넘기고, 느슨한 연결을 위해 이 객체를 &lt;EM&gt;route()&lt;/EM&gt;로 주사(inject) 하려고 합니다. &lt;/P&gt;
&lt;P&gt;이 객체를 main 파일인 &lt;EM&gt;index.js&lt;/EM&gt;에 넣어 봅시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; server &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./server&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; router &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./router&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./requestHandlers&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/start&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;server&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;router&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;EM&gt;handle&lt;/EM&gt;은 &quot;사물(thing)&quot; (여기에선 request handler들의 컬렉션)에 가깝지만 동사처럼 이름을 지었습니다. 곧 보게 되겠지만 결과적으로 router의 멋진 표현(방식)이 될 겁니다. &lt;/P&gt;
&lt;P&gt;보시는 바와 같이, 다른 URL을 동일한 request handler에 매핑하는 것은 매우 쉽습니다. 키/값 쌍에 &lt;EM&gt;&quot;/&quot;&lt;/EM&gt;와 &lt;EM&gt;requestHandlers.start&lt;/EM&gt; 를 추가하면 &lt;EM&gt;/start&lt;/EM&gt; 요청뿐 아니라 &lt;EM&gt;/&lt;/EM&gt; 요청도 &lt;EM&gt;start&lt;/EM&gt; handler로 연결됩니다. &lt;/P&gt;
&lt;P&gt;객체를 정의한 후에 server에게 별도의 파라미터로 전달합니다. &lt;EM&gt;server.js&lt;/EM&gt;를 다음과 같이 바꿉시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello World&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;EM&gt;start()&lt;/EM&gt; 함수에 &lt;EM&gt;handle&lt;/EM&gt; 파라미터를 추가했고 handle 객체를 &lt;EM&gt;route()&lt;/EM&gt; callback 에 첫 번째 파라미터로 넘겼습니다. &lt;/P&gt;
&lt;P&gt;이제 &lt;EM&gt;route()&lt;/EM&gt; 함수를 수정해야죠. &lt;EM&gt;router.js&lt;/EM&gt; 파일입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;typeof&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;===&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'function'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;No request handler found for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;여기에 우리가 해야 할 일은, 주어진 pathname에 해당하는 request handler가 있는지 체크하고, 존재하면 그 함수를 호출하는 겁니다. 연관배열에서 요소에 접근하는 것처럼 객체에서 request handler 함수에 접근할 수 있으므로, “&lt;EM&gt;pathname&lt;/EM&gt;을 &lt;EM&gt;handle&lt;/EM&gt; 해줘~”로 읽히는 멋진 &lt;EM&gt;handle[pathname]();&lt;/EM&gt; 함수를 갖게 되었습니다. &lt;/P&gt;
&lt;P&gt;좋군요. 이것이 server와 router 그리고 request handler를 함께 묶기 위해 필요한 전부입니다. 애플리케이션을 실행하고 브라우저로 &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt; 를 요청하면 정확한 request handler가 호출된 것을 확인할 수 있습니다. &lt;/P&gt;&lt;PRE&gt;Server has started.
Request for /start received.
About to route a request for /start
Request handler 'start' was called.&lt;/PRE&gt;
&lt;P&gt;브라우저로 &lt;A href=&quot;http://localhost:8888/&quot; rel=nofollow&gt;http://localhost:8888/&lt;/A&gt; 을 열면 역시 &lt;EM&gt;start&lt;/EM&gt; request handler가 동작합니다. &lt;/P&gt;&lt;PRE&gt;Request for / received.
About to route a request for /
Request handler 'start' was called.&lt;/PRE&gt;&lt;A name=making-the-request-handlers-respond&gt;&lt;/A&gt;
&lt;H3&gt;request handler가 응답하게 만들기&lt;/H3&gt;
&lt;P&gt;아름답지요? 이제 오직 request handler만이 브라우저에게 뭔가를 보낼 수 있게 된다면 한결 좋아지겠죠. 그렇죠? &lt;/P&gt;
&lt;P&gt;기억해 봅시다. 브라우저에 찍히는 “Hello World” 는 여전히 &lt;EM&gt;server.js&lt;/EM&gt; 파일의 &lt;EM&gt;onRequest&lt;/EM&gt; 함수에서 오는거죠. &lt;/P&gt;
&lt;P&gt;결국 “request 처리”란 “request에 응답하는 것”입니다. 이제 &lt;EM&gt;onRequest&lt;/EM&gt;가 하는 것처럼 request handler가 브라우저에 이야기할 수 있게 해줘야 합니다. &lt;/P&gt;&lt;A name=how-to-not-do-it&gt;&lt;/A&gt;
&lt;H4&gt;해서는 안되는 것&lt;/H4&gt;
&lt;P&gt;PHP나 Ruby 배경을 가진 개발자처럼 직관적인 접근 방식을 따르고 싶을 수 있는데, 매력적이고 상당히 그럴듯해 보이지만, 예상치 못한 때에 갑자기 망쳐버릴 수 있습니다. &lt;/P&gt;
&lt;P&gt;“직관적인 접근 방식”이란 이런 겁니다. requesthandler는 사용자에게 보여주려는 내용을 &lt;EM&gt;return()&lt;/EM&gt;하고, 그러면 &lt;EM&gt;onRequest&lt;/EM&gt; 함수는 이 응답 데이터를 user에게 보내는 방식입니다. &lt;/P&gt;
&lt;P&gt;이렇게 한번 해보고, 이게 왜 그리 좋지 않은 아이디어인지 봅시다. &lt;/P&gt;
&lt;P&gt;우리는 request handler로부터 시작해서, 브라우저에 표시하고자 하는 내용을 request handler가 return하도록 만듭니다. &lt;EM&gt;requestHandlers.js&lt;/EM&gt;를 다음과 같이 고칠 필요가 있습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Start&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;좋군요. 마찬가지로 router는 request handler가 return 한 것을 server에게 return 해야 합니다. 따라서, &lt;EM&gt;router.js&lt;/EM&gt;를 다음과 같이 고칩니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;typeof&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;===&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'function'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;No request handler found for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;404 Not found&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;보시다시피, route 못하는 요청이 있으면 약간의 텍스트를 return 하게 했습니다. &lt;/P&gt;
&lt;P&gt;마지막으로, &lt;EM&gt;server.js&lt;/EM&gt;를 아래와 같이 바꿔서 request handler가 router를 통해 return 한 내용을 브라우저에 응답하도록 수정합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; content &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;content&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;수정한 애플리케이션을 다시 구동하면 모든 것이 매력적으로 동작합니다. &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt;를 요청하면 “Hello Start”가 출력되고, &lt;A href=&quot;http://localhost:8888/upload&quot; rel=nofollow&gt;http://localhost:8888/upload&lt;/A&gt;는 “Hello Upload”가, &lt;A href=&quot;http://localhost:8888/foo&quot; rel=nofollow&gt;http://localhost:8888/foo&lt;/A&gt;는 “404 Not found”가 나옵니다. &lt;/P&gt;
&lt;P&gt;좋아요. 그런데 이게 왜 문제라는 거죠? 짧게 대답하자면 이렇습니다. 나중에 request handler 중 하나가 non-blocking 동작을 해야할 때 문제에 생기기 때문입니다. &lt;/P&gt;
&lt;P&gt;좀 더 긴 대답을 들어 봅시다. &lt;/P&gt;&lt;A name=blocking-and-non-blocking&gt;&lt;/A&gt;
&lt;H4&gt;Blocking 과 non-blocking&lt;/H4&gt;
&lt;P&gt;이야기 했듯이, 문제는 request handler에 non-blocking 동작을 포함시킬 때 발생합니다. 먼저 blocking 동작에 대해 이야기를 하고, 그 후에 non-blocking 동작에 대해 이야기 할게요. &lt;/P&gt;
&lt;P&gt;그리고 “blocking” 과 “non-blocking”의 뜻을 설명하는 대신에 request handler에 blocking 동작을 추가할 때 무슨 일이 생기는지 직접 보여 드리겠습니다. &lt;/P&gt;
&lt;P&gt;이를 위해, &lt;EM&gt;start&lt;/EM&gt; request handler에서 “Hello Start” 문자열을 return 하기 전에 10초 동안 기다리도록 수정할 겁니다. JavaScript에 &lt;EM&gt;sleep()&lt;/EM&gt; 같은 건 없기 때문에 다른 짓을 해야 합니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;requestHandlers.js&lt;/EM&gt;를 아래와 같이 고칩시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; sleep&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;milliSeconds&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; startTime &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;new&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=typ&gt;Date&lt;/SPAN&gt;&lt;SPAN class=pun&gt;().&lt;/SPAN&gt;&lt;SPAN class=pln&gt;getTime&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;while&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;new&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=typ&gt;Date&lt;/SPAN&gt;&lt;SPAN class=pun&gt;().&lt;/SPAN&gt;&lt;SPAN class=pln&gt;getTime&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; startTime &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; milliSeconds&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; sleep&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;10000&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Start&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이게 무엇을 하는 것인지 살펴보면: &lt;EM&gt;start()&lt;/EM&gt; 함수가 호출되면 Node.js는 10초를 기다리고 “Hello Start”를 return 합니다. &lt;EM&gt;upload()&lt;/EM&gt;를 호출하면 기존처럼 곧바로 return 합니다. &lt;/P&gt;
&lt;P&gt;(10초를 sleep 하는 것 말고 다른 것을 상상할 수도 있겠죠. 오랜 시간이 걸리는 계산과 같은 blocking operation 이 start() 안에 존재할 수 있습니다.) &lt;/P&gt;
&lt;P&gt;이 변화가 무엇을 의미하는지 봅시다. &lt;/P&gt;
&lt;P&gt;애플리케이션을 재시작 한 후에 무슨 일이 일어나는지 보기 위해 조금 복잡한 절차를 따라주세요. 첫째, 브라우저 두 개나 탭 두 개를 열어주세요. 첫 번째 브라우저의 주소창에 &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt;를 입력만 하고 아직은 이 URL로 이동하진 마세요. &lt;/P&gt;
&lt;P&gt;두 번째 브라우저의 주소창에 &lt;A href=&quot;http://localhost:8888/upload&quot; rel=nofollow&gt;http://localhost:8888/upload&lt;/A&gt;를 입력하고 역시 엔터를 치지는 말아주세요. &lt;/P&gt;
&lt;P&gt;이제 다음과 같이 합니다.: 첫 번째 윈도우(“/start”)에 엔터를 치고 재빨리 두 번째 윈도우(“/upload”)로 가서 엔터를 칩니다. &lt;/P&gt;
&lt;P&gt;우리가 예상한 대로 /start URL은 로드하는데 10초가 걸립니다. 하지만 /upload 의 request handler에는 &lt;EM&gt;sleep()&lt;/EM&gt;이 없음에도 불구하고 /upload URL &lt;EM&gt;또한&lt;/EM&gt; 로드하는 데 10초가 걸립니다. &lt;/P&gt;
&lt;P&gt;왜요? &lt;EM&gt;start()&lt;/EM&gt;가 blocking 동작을 포함하기 때문이죠. 마치 “다른 모든 것을 일하지 못하게 막는 것”과 같죠. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;“node에서는 모든 게 병렬로 수행된다. 당신 code만 빼고.”&lt;/EM&gt;라는 말처럼 이건 문제입니다. &lt;/P&gt;
&lt;P&gt;Node.js는 다수의 동시작업을 처리할 수 있지만 thread를 나누는 방식으로 하지 않습니다. 사실 Node.js는 단일 thread입니다. 대신, Node.js는 동시작업을 event loop을 실행해서 처리하며 개발자들은 이것을 사용할 수 있습니다. 우리는 blocking 동작을 피하고 non-blocking 동작을 사용해야만 합니다. &lt;/P&gt;
&lt;P&gt;그러기 위해서는 callback으로 함수를 다른 함수에게 넘겨야 합니다. 언젠가 어떤 이벤트가 발생하면 (예를들면 10초 sleep을 한다거나, database에 질의를 하거나, 값비싼 계산을 하거나) 이 함수를 호출하게 되겠지요. &lt;/P&gt;
&lt;P&gt;이런식으로 이야기 하는거죠. &lt;EM&gt;“헤이, probablyExpensiveFunction(), 니 일을 해줘. 하지만 나 Single Node.js 쓰레드는 네가 끝낼 때까지 여기서 기다리지 않을거야. 네 아래에 있는 코드 라인을 계속 실행할거야. 그러니 여기 이 callbackFunction()을 가져가서 네가 너의 비싼 일을 모두 끝냈을 때 호출해 주겠니? 고마워!”&lt;/EM&gt; &lt;/P&gt;
&lt;P&gt;(이것에 대해 더 자세히 읽고 싶다면 Mixu의 &lt;A href=&quot;http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/&quot;&gt;Understanding the node.js event loop&lt;/A&gt;. 라는 포스트를 살펴보세요) &lt;/P&gt;
&lt;P&gt;이제 우리가 만들었던 “request handler가 response를 handling” 하는 식의 방법이 왜 non-blocking 동작을 제대로 하지 못하도록 하는지 살펴봅시다. &lt;/P&gt;
&lt;P&gt;다시 한번, 먼저 애플리케이션을 수정해서 문제가 발생하는 것을 경험해 봅시다. &lt;/P&gt;
&lt;P&gt;이번에도 &lt;EM&gt;start&lt;/EM&gt; request handler를 사용합니다. 아래와 같이 수정해 주세요(&lt;EM&gt;requestHandlers.js&lt;/EM&gt; 파일이에요). &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; exec &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;child_process&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; content &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;empty&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;ls -lah&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stderr&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; content &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; content&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;보시는 것처럼, 우리는 새로운 Node.js 모듈인 &lt;EM&gt;child_process&lt;/EM&gt;를 사용했습니다. 매우 단순하지만 쓸모가 많은 non-blocking 동작인 &lt;EM&gt;exec()&lt;/EM&gt;을 사용하기 위해서 입니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;exec()&lt;/EM&gt;은 shell 커맨드를 Node.js 안에서 실행시킵니다. 이 예에서는 현재 디렉토리에 있는 모든 파일 리스트를 가져오는데 사용해서 브라우저가 &lt;EM&gt;/start&lt;/EM&gt; URL을 요청할 때 이 리스트를 출력할 수 있습니다. &lt;/P&gt;
&lt;P&gt;코드가 매우 직관적이죠. &lt;EM&gt;content&lt;/EM&gt; 라는 새 변수를 생성하고(초기값은 “empty”로), “ls -alh”를 실행하고, 이 결과로 변수를 채우고 변수를 return 합니다. &lt;/P&gt;
&lt;P&gt;언제나처럼 애플리케이션을 구동시키고 &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt;를 방문합니다. &lt;/P&gt;
&lt;P&gt;멋진 웹페이지가 로드되고 “empty” 문자열이 출력됩니다. 뭐가 잘못된 거죠? &lt;/P&gt;
&lt;P&gt;짐작하셨겠지만, &lt;EM&gt;exec()&lt;/EM&gt;이 non-blocking 방식으로 마법을 부렸습니다. blocking &lt;EM&gt;sleep&lt;/EM&gt; operation 처럼 애플리케이션을 정지시키지 않고 상당히 비싼 shell operation (매우 큰 파일을 복사한다거나 하는)을 실행할 수 있게 해주기 때문에 exec()은 매우 좋은 겁니다. &lt;/P&gt;
&lt;P&gt;(이것을 증명하고 싶다면 “ls -lah”를 “find /” 처럼 더 비싼 operation 으로 바꿔 보세요) &lt;/P&gt;
&lt;P&gt;하지만 브라우저에 그 결과를 출력하지 못하기 때문에 이 우아한 non-blocking operation을 좋아할 수만은 없습니다. 그렇죠? &lt;/P&gt;
&lt;P&gt;그러면, 고쳐 봅시다. 그러면서 왜 지금의 아키텍쳐는 제대로 동작하지 않는지 이해해 보자구요. &lt;/P&gt;
&lt;P&gt;문제는 &lt;EM&gt;exec()&lt;/EM&gt;이 non-blocking 으로 동작하기 위해서 callback 함수를 사용해야 한다는 것입니다. &lt;/P&gt;
&lt;P&gt;우리 예에서는 &lt;EM&gt;exec()&lt;/EM&gt; 함수의 두 번째 파라미터로 전달한 anonymous 함수입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stderr&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; content &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;그리고 여기에 문제의 뿌리가 놓여있습니다: 우리의 코드는 동기적으로 동작합니다. 즉 &lt;EM&gt;exec()&lt;/EM&gt;을 호출하자 마자 Node.js는 이어서 &lt;EM&gt;return content;&lt;/EM&gt;를 실행합니다. 바로 이 시점에 &lt;EM&gt;content&lt;/EM&gt;는 여전히 “empty” 입니다. 왜냐하면 &lt;EM&gt;exec()&lt;/EM&gt;은 비동기적으로 동작하기 때문에 &lt;EM&gt;exec()&lt;/EM&gt;에 전달된 callback 함수는 아직 호출되지 않았던 것이죠. &lt;/P&gt;
&lt;P&gt;“ls -lah” 는 매우 싸고 빠른 operation 입니다. (디렉토리에 수백만 개의 파일이 존재하지 않는다면) 따라서 callback이 상대적으로 빠르게 호출됩니다. 그럼에도 불구하고 이 일은 비동기적으로 일어납니다. &lt;/P&gt;
&lt;P&gt;이것을 더욱 확실하게 보여주는 더 비싼 커맨드를 생각해 봅시다: “find /” 는 제 장비에서 대략 1분이 걸리지만 request handler에서 “ls -lah”를 “find /”로 바꾸어도 /start URL을 요청할 때 여전히 즉시 HTTP 응답을 받게 됩니다. 이제 Node.js가 애플리케이션을 계속 실행하는 중에 &lt;EM&gt;exec()&lt;/EM&gt;은 백그라운드에서 수행한다는 것이 확실합니다. 그리고 &lt;EM&gt;exec()&lt;/EM&gt;에 넘긴 callback 함수는 “find /” 커맨드의 동작이 끝났을 때 호출될 것입니다. &lt;/P&gt;
&lt;P&gt;그럼 우리는 어떻게 현재 디렉토리의 파일 리스트를 사용자에게 보여주려는 우리 목표를 이룰 수 있을까요? &lt;/P&gt;
&lt;P&gt;어떻게 하면 &lt;EM&gt;안&lt;/EM&gt; 되는지를 배웠으니까, 이제 request handler가 브라우저에게 올바른 방식으로 응답하는 방법을 논의해 봅시다. &lt;/P&gt;&lt;A name=responding-request-handlers-with-non-blocking-operations&gt;&lt;/A&gt;
&lt;H4&gt;request handler가 non-blocking 방식으로 동작하면서 응답하기&lt;/H4&gt;
&lt;P&gt;제가 방금 “올바른 방식” 이라는 표현을 사용했는데. 위험한 말입니다. 대부분은 “올바른 방식”이 하나만 존재하는 것이 아닙니다. &lt;/P&gt;
&lt;P&gt;이번 경우에는 함수를 전달하는 것이 한 방법입니다. 한번 살펴봅시다. &lt;/P&gt;
&lt;P&gt;현재 우리 애플리케이션은 사용자에게 보여주고 싶은 content를 request handler에서 HTTP server로 전달할 수 있습니다. 다음과 같은 여러 애플리케이션 레이어들을 거쳐 넘기는 식으로 식으로 말입니다. (request handler -&amp;gt; router -&amp;gt; server). &lt;/P&gt;
&lt;P&gt;새로운 접근 방법은 다음과 같습니다: content를 server로 보내는 대신 server를 content로 보낼겁니다. 좀 더 자세히 이야기 하면, &lt;EM&gt;response&lt;/EM&gt; 객체 (server의 callback 함수인 &lt;EM&gt;onRequest()&lt;/EM&gt; 에서 얻은)를 router를 통해 request handler에게 주사(inject) 합니다. 이제 handler는 이 객체가 가진 함수들을 이용해서 스스로 요청에 응답할 수 있게 되었습니다. &lt;/P&gt;
&lt;P&gt;설명은 충분합니다. 이제 하나씩 애플리케이션을 고쳐 봅시다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;server.js&lt;/EM&gt;부터 시작합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;EM&gt;route()&lt;/EM&gt; 함수가 값을 return 하길 기다리는 대신 세 번째 파라미터로 &lt;EM&gt;response&lt;/EM&gt; 객체를 전달했습니다. 또 &lt;EM&gt;onRequest()&lt;/EM&gt;에서는 &lt;EM&gt;response&lt;/EM&gt;의 메소드 호출을 모두 제거했습니다. 이제 &lt;EM&gt;route&lt;/EM&gt;가 처리해야 하니까요. &lt;/P&gt;
&lt;P&gt;다음은 router.js 입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;typeof&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;===&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'function'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;](&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;No request handler found for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;404&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;404 Not found&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;비슷한 패턴입니다: request handler가 return 하도록 하는 대신 &lt;EM&gt;response&lt;/EM&gt; 객체를 전달했습니다. &lt;/P&gt;
&lt;P&gt;마땅한 request handler를 찾지 못하는 경우 직접 “404” header와 body를 응답하도록 처리해야 합니다. &lt;/P&gt;
&lt;P&gt;이제 마지막으로 &lt;EM&gt;requestHandlers.js&lt;/EM&gt; 입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; exec &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;child_process&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;ls -lah&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stderr&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;handler 함수가 response를 파라미터로 받았고 request에 응답하기 위해 이 객체를 직접 사용하고 있습니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;start&lt;/EM&gt; handler는 &lt;EM&gt;exec()&lt;/EM&gt; 함수의 anonymous callback 에서 응답합니다. 그리고 &lt;EM&gt;upload&lt;/EM&gt; handler는 여전히 단순하게 “Hello Upload”를 응답하지만 이번에는 직접 &lt;EM&gt;response&lt;/EM&gt; 객체를 사용하지요. &lt;/P&gt;
&lt;P&gt;이제 애플리케이션을 다시 시작하면(&lt;EM&gt;node index.js&lt;/EM&gt;) 제대로 동작할 겁니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;/start&lt;/EM&gt; 요청에 있는 비싼 동작에도 불구하고 &lt;EM&gt;/upload&lt;/EM&gt; 요청이 곧바로 응답되는 것을 (block 되지 않고) 확인하고 싶다면, 아래와 같이 &lt;EM&gt;requestHandlers.js&lt;/EM&gt;를 고쳐보세요. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; exec &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;child_process&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; exec&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;find /&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt; timeout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=lit&gt;10000&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; maxBuffer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=lit&gt;20000&lt;/SPAN&gt;&lt;SPAN class=pun&gt;*&lt;/SPAN&gt;&lt;SPAN class=lit&gt;1024&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;},&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; stderr&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;stdout&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이렇게 하면 &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt; 에 대한 요청이 최소한 10초가 걸리게 되지만 /start가 여전히 동작 중일 때에도 &lt;A href=&quot;http://localhost:8888/upload&quot; rel=nofollow&gt;http://localhost:8888/upload&lt;/A&gt; 요청은 곧바로 응답합니다. &lt;/P&gt;&lt;A name=serving-something-useful&gt;&lt;/A&gt;
&lt;H3&gt;유용한 것을 제공하기&lt;/H3&gt;
&lt;P&gt;지금까지 우리가 한 일은 멋지긴 했습니다만, 우리의 멋진 사이트로 고객에게 가치를 제공하지는 못했습니다. &lt;/P&gt;
&lt;P&gt;server, router, request handlers가 있으니 이제 사이트에 컨텐트를 추가해서 사용자가 파일을 선택하고, 이 파일을 업로드하고, 업로드한 파일을 보는 유스케이스를 제공할 수 있습니다. 단순하게 하기 위해 이미지 파일만 업로드 하고 볼 수 있다고 가정하겠습니다. &lt;/P&gt;
&lt;P&gt;네. 이제 하나씩 해 봅시다. 대부분 지금까지 다룬 JavaScript 테크닉과 이론을 가지고 할 겁니다. 그리고 조금 새로운 것도 나올 겁니다. &lt;/P&gt;
&lt;P&gt;하나씩이라고 했는데 두 단계입니다: 첫 번째로 POST 요청(파일 업로드는 아니지만)을 처리하는 방법을 살펴볼 겁니다. 두 번째는 파일 업로드를 처리하기 위해 Node.js의 외부 모듈을 사용할 겁니다. 제가 이런 방식을 선택한 이유는 두 가지가 입니다. &lt;/P&gt;
&lt;P&gt;첫째, Node.js로 기본적인 POST 요청을 처리하는 것은 상대적으로 쉽습니다만 연습해 볼 가치는 충분합니다. &lt;br /&gt;
둘째, Node.js로 파일 업로드( 즉 multipart POST 요청)를 처리하는 것은 &lt;EM&gt;간단하지 않아서&lt;/EM&gt; 이 튜토리얼의 범위를 넘어갑니다. 하지만 외부 모듈을 사용하는 것은 그 자체로 의미가 있어서 beginner 튜토리얼에 포함할만 합니다. &lt;/P&gt;&lt;A name=handling-post-requests&gt;&lt;/A&gt;
&lt;H4&gt;POST 요청 처리하기&lt;/H4&gt;
&lt;P&gt;뻔하고 단순한 것으로 합시다: textarea를 하나 제공해서 사용자가 내용을 채우고 submit 해서 POST 요청을 서버로 보냅니다. 이 요청을 받아서 textarea 내부의 내용을 출력하겠습니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;/start&lt;/EM&gt; 요청에서 textarea를 위한 HTML을 뿌려줘야 하니까 &lt;EM&gt;requestHandler.js&lt;/EM&gt;에 추가해 봅시다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;textarea name=&quot;text&quot; rows=&quot;20&quot; cols=&quot;60&quot;&amp;gt;&amp;lt;/textarea&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Submit text&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Hello Upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이제 이 사이트가 Webby Awards(국제 우수 웹사이트 상)을 받지 않는다면 누가 받을까 모르겠네요. 브라우저로 &lt;A href=&quot;http://localhost:8888/start&quot; rel=nofollow&gt;http://localhost:8888/start&lt;/A&gt; 를 요청하면 이 단순한 form을 볼 수 있습니다. 만약 안된다면 애플리케이션을 재시작 안 했을 겁니다. &lt;/P&gt;
&lt;P&gt;view 컨텐트를 request handler 안에 가지고 있는 게 추악하다구요? 하지만 저는 이 튜토리얼에 더 이상의 추상화 (즉, view와 controller 로직을 분리하는 것)를 하지 않기로 했습니다. 그렇게 하는 것이 JavaScript나 Node.js를 설명하는 관점에서는 의미 있는 것이 아니라고 생각하기 때문입니다. &lt;/P&gt;
&lt;P&gt;그보다 좀 재미있는 문제를 봅시다. 사용자가 이 form을 submit 할 때 POST 요청은 &lt;EM&gt;/upload&lt;/EM&gt; request handler로 갑니다. &lt;/P&gt;
&lt;P&gt;이제 우린 전문가 같은 초보가 되고 있으니까, POST 데이터가 비동기 callback을 사용해서 non-blocking 방식으로 처리된다는 것이 놀랍지 않습니다. &lt;/P&gt;
&lt;P&gt;POST 요청은 상당히 클겁니다. 누구도 사용자가 몇 메가바이트의 텍스트를 입력하는 것을 막을 수 없겠죠. 전체 데이터 블록을 하나로 처리하는 것은 blocking operation 방법이 될 것입니다. &lt;/P&gt;
&lt;P&gt;전체 프로세스를 non-blocking 으로 만들려면, POST 데이터를 작은 청크로 나누고 특정 이벤트 때마다 callback을 호출하는 방식으로 만들어야 합니다. 이 이벤트가 &lt;EM&gt;data&lt;/EM&gt; (POST 데이터의 새 청크가 도착했다)와 &lt;EM&gt;end&lt;/EM&gt; (모든 청크를 다 받았다) 입니다. &lt;/P&gt;
&lt;P&gt;이 이벤트가 발생했을때 어떤 callback이 호출되어야 할지 Node.js 에게 알려줘야 하는데, HTTP 요청이 올 때 &lt;EM&gt;onRequest&lt;/EM&gt; callback 함수가 넘겨받은 &lt;EM&gt;request&lt;/EM&gt; 객체에 &lt;EM&gt;listener&lt;/EM&gt; 함수들을 추가하는 방식으로 할 수 있습니다. &lt;/P&gt;
&lt;P&gt;기본적으로 이렇게 보일 겁니다: &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;addListener&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;data&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;chunk&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=com&gt;// called when a new chunk of data was received&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;addListener&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;end&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=com&gt;// called when all chunks of data have been received&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이 로직을 어디에 구현해야 할까요? 지금은 server 에서만 request 객체에 접근 가능합니다. router와 request handler 에는 &lt;EM&gt;request&lt;/EM&gt; 객체를 전달하지 않았거든요. &lt;EM&gt;response&lt;/EM&gt; 객체만 전달했었죠. &lt;/P&gt;
&lt;P&gt;제 생각에, request 로부터 오는 모든 data를 애플리케이션에게 전달하는 것은 HTTP server의 역할입니다. 그래서 POST data를 server에서 받고 최종 data를 router와 request handler로 보내는 게 좋겠습니다. 그러면 그것으로 무엇을 할지 결정할 수 있겠죠. &lt;/P&gt;
&lt;P&gt;그러니까 &lt;EM&gt;data&lt;/EM&gt;와 &lt;EM&gt;end&lt;/EM&gt; 이벤트 callback을 server에 두고 &lt;EM&gt;data&lt;/EM&gt; callback에서 모든 POST 데이터 청크를 모은 다음에, &lt;EM&gt;end&lt;/EM&gt; callback에서 router를 호출하면서 모든 데이터 청크를 전달합니다. 그러면 결국 request handler 까지 갈 겁니다. &lt;/P&gt;
&lt;P&gt;자 이제 &lt;EM&gt;server.js&lt;/EM&gt; 부터 시작합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;setEncoding&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;utf8&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;addListener&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;data&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;postDataChunk&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; postData &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postDataChunk&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Received POST data chunk '&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; postDataChunk &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;'.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;addListener&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;end&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;기본적으로 세 가지 일을 했습니다: 첫째, 받을 데이터의 인코딩을 UTF-8로 세팅했고, 새로운 POST 데이터 청크가 올 때마다 &lt;EM&gt;postData&lt;/EM&gt; 변수에 차곡차곡 쌓는 역할을 하는 “data” 이벤트 listener를 추가했습니다. 그리고 모든 POST 데이터가 모였을 때 호출되는 &lt;EM&gt;end&lt;/EM&gt; 이벤트 callback에서 postData 변수를 router로 전달했습니다. POST 데이터도 router 전달했는데요, request handler에서 필요하게 됩니다. &lt;/P&gt;
&lt;P&gt;제품 코드(production code)라면 청크가 올 때마다 콘솔 로그를 찍도록 하는 것은 안좋은 생각입니다만 (POST 데이터가 수 메가 바이트가 될 수 있죠?), 무슨 일이 벌어지는지 보는 것은 괜찮겠죠. &lt;/P&gt;
&lt;P&gt;이 부분에서 좀 살펴보는 것도 좋습니다. textarea에 적은량의 텍스트를 넣다가 그 크기를 늘려가게 되면 &lt;EM&gt;data&lt;/EM&gt; callback이 실제로 여러 번 호출됩니다. &lt;/P&gt;
&lt;P&gt;더 기막힌 걸 애플리케이션에 추가해 봅시다. /upload 페이지에 받은 내용을 표시할 겁니다. 이렇게 하기 위해서는 &lt;EM&gt;postData&lt;/EM&gt;를 request handler로 전달해야 합니다. &lt;EM&gt;router.js&lt;/EM&gt;를 아래와 같이 수정합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;typeof&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;===&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'function'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;](&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;No request handler found for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;404&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;404 Not found&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;그리고 &lt;EM&gt;requestHandlers.js&lt;/EM&gt;의 &lt;EM&gt;upload&lt;/EM&gt; request handler에서 응답에 이 데이터를 추가합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;textarea name=&quot;text&quot; rows=&quot;20&quot; cols=&quot;60&quot;&amp;gt;&amp;lt;/textarea&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Submit text&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;You've sent: &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;됐습니다. 이제 POST 데이터를 받아서 request handler에서 사용할 수 있습니다. &lt;/P&gt;
&lt;P&gt;이 토픽의 마지막 할 일은 이렇습니다. 지금은 POST 요청의 전체 body를 router와 request handler로 넘기고 있는데, 향후에 POST 데이터를 구성하는 개별 필드를 사용하고 싶을 수 있습니다. 이 경우에는 &lt;EM&gt;text&lt;/EM&gt; 필드의 값이죠. &lt;/P&gt;
&lt;P&gt;우린 이미 &lt;EM&gt;querystring&lt;/EM&gt; 모듈에 대해 알고 있죠. 이런식으로 사용하겠습니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; querystring &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;querystring&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;textarea name=&quot;text&quot; rows=&quot;20&quot; cols=&quot;60&quot;&amp;gt;&amp;lt;/textarea&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Submit text&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;You've sent the text: &quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; querystring&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;text&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;네. 초보자 튜토리얼에서 POST 데이터 처리에 대해 다룰 내용은 모두 다뤘습니다. &lt;/P&gt;&lt;A name=handling-file-uploads&gt;&lt;/A&gt;
&lt;H4&gt;파일 업로드 처리하기&lt;/H4&gt;
&lt;P&gt;이제 마지막 유스케이스로 갑니다. 우리 계획은 사용자가 이미지 파일을 업로드 하면 업로드된 이미지를 브라우저에 출력하는 것이었습니다. &lt;/P&gt;
&lt;P&gt;90년대로 돌아간다면, 이 기능이 기업공개를 할만한 비즈니스 모델을 가능하게 해줄것 같습니다만, 오늘날에는 우리에게 두 가지를 가르쳐 줍니다. Node.js 외부 library를 설치하는 방법과 이것을 코드에서 사용하는 방법이죠. &lt;/P&gt;
&lt;P&gt;우리가 사용할 외부 모듈은 Felix Geisendörfer가 만든 &lt;EM&gt;node-formidable&lt;/EM&gt; 입니다. 이 모듈은 들어오는 파일 데이터를 파싱해서 처리하는 모든 자잘한 것들을 잘 추상화 해 놨습니다. 결국 파일 데이터를 받아서 처리하는 것은 단지 POST 데이터를 처리하는 것입니다. 하지만 그 자세한 처리가 어렵고 복잡하기 때문에, 여기서는 미리 만들어진 솔루션을 쓰는 것이 좋겠습니다. &lt;/P&gt;
&lt;P&gt;Felix의 코드(모듈)을 사용하기 위해 적절한 모듈이 필요합니다. Node.js는 &lt;EM&gt;NPM&lt;/EM&gt;이라는 자체의 패키지 관리자를 가지고 있습니다. NPM은 Node.js 외부 모듈을 매우 쉽게 설치할 수 있게 해줍니다. Node.js가 잘 동작하는 시스템이라면 단지 커맨드 라인에 아래와 같이 타이핑 하면 됩니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-bash&quot;&gt;&lt;SPAN class=pln&gt;npm install formidable&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;만약 아래와 같이 출력된다면 &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-bash&quot;&gt;&lt;SPAN class=pln&gt;npm info build &lt;/SPAN&gt;&lt;SPAN class=typ&gt;Success&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; formidable@1&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=lit&gt;0.2&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
npm ok&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;잘 된 겁니다. &lt;/P&gt;
&lt;P&gt;이제 &lt;EM&gt;formidable&lt;/EM&gt; 모듈을 코드에서 사용할 수 있습니다. 내부 모듈을 사용할 때 했던 것처럼 require만 해주면 됩니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; formidable &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;formidable&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;formidable이 사용하는 은유는 HTTP POST로 submit 된 “form”을 Node.js에서 파싱할 수 있게 (“parseable”) 한다는 겁니다. 다음과 같이 사용하면 됩니다. 새 &lt;EM&gt;IncomingForm&lt;/EM&gt;을 생성합니다. 이것은 submit된 form의 추상화 객체인데 이것으로 &lt;EM&gt;request&lt;/EM&gt; 객체를 파싱하여 submit된 파일과 필드들을 얻을 수 있습니다. &lt;/P&gt;
&lt;P&gt;node-formidable 프로젝트 페이지에서 가져온 이 예제는 서로 다른 부분이 어떻게 함께 동작하는지 잘 보여줍니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; formidable &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;'formidable'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;'http'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; sys &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;'sys'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;req&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;req&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;==&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'/upload'&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;&amp;amp;&amp;amp;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; req&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;method&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;toLowerCase&lt;/SPAN&gt;&lt;SPAN class=pun&gt;()&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;==&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'post'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=com&gt;// parse a file upload&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; form &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;new&lt;/SPAN&gt;&lt;SPAN class=pln&gt; formidable&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=typ&gt;IncomingForm&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; form&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;req&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;err&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; fields&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; files&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;'content-type'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'text/plain'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;'received upload:\n\n'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;sys&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;inspect&lt;/SPAN&gt;&lt;SPAN class=pun&gt;({&lt;/SPAN&gt;&lt;SPAN class=pln&gt;fields&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; fields&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; files&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; files&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}));&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;return&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=com&gt;// show a file upload form&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;'content-type'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'text/html'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; res&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; enctype=&quot;multipart/form-data&quot; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;text&quot; name=&quot;title&quot;&amp;gt;&amp;lt;br&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;file&quot; name=&quot;upload&quot; multiple=&quot;multiple&quot;&amp;gt;&amp;lt;br&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Upload&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이 코드를 파일에 추가하고 &lt;EM&gt;node&lt;/EM&gt;를 통해 실행하면, 파일 업로드를 포함하는 단순한 form을 submit 할 수 있고, &lt;EM&gt;form.parse&lt;/EM&gt; 함수의 callback 에 파라미터로 넘어가는 &lt;EM&gt;files&lt;/EM&gt; 객체가 어떻게 생겼는지 살펴볼 수 있습니다. &lt;/P&gt;&lt;PRE class=lang-js&gt;received upload:

{ fields: { title: 'Hello World' },
  files:
   { upload:
      { size: 1558,
        path: '/tmp/1c747974a27a6292743669e91f29350b',
        name: 'us-flag.png',
        type: 'image/png',
        lastModifiedDate: Tue, 21 Jun 2011 07:02:41 GMT,
        _writeStream: [Object],
        length: [Getter],
        filename: [Getter],
        mime: [Getter] } } }&lt;/PRE&gt;
&lt;P&gt;우리 유스케이스대로 동작하게 하기 위해서 이 form 파싱 로직을 우리 코드에 넣어야 하고, 업로드된 파일 (&lt;EM&gt;/tmp&lt;/EM&gt; 폴더에 저장될 겁니다)의 내용을 어떻게 브라우저에 보여줄지 방법을 찾아야 합니다. &lt;/P&gt;
&lt;P&gt;뒤에 것을 먼저 봅시다. 로컬 하드 드라이브에 이미지 파일이 있을 때 브라우저 요청에 어떻게 응답할 수 있을까요? &lt;/P&gt;
&lt;P&gt;당연히 이 파일의 내용을 Node.js server에서 읽어야 하는데요, 역시, 이런일을 하는 모듈이 있습니다. &lt;EM&gt;fs&lt;/EM&gt; 라는 모듈입니다. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;/show&lt;/EM&gt; 라는 URL을 위한 또 하나의 request handler를 추가합시다. 이것은 &lt;EM&gt;/tmp/test.png&lt;/EM&gt; 라는 파일의 내용을 뿌려줄 겁니다. 당연히 먼저 실제 png 이미지 파일을 이 위치에 저장해야겠죠. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;requestHandlers.js&lt;/EM&gt;를 다음과 같이 수정합니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; querystring &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;querystring&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; fs &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;fs&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'content=&quot;text/html; charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;textarea name=&quot;text&quot; rows=&quot;20&quot; cols=&quot;60&quot;&amp;gt;&amp;lt;/textarea&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Submit text&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;You've sent the text: &quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; querystring&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;text&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'show' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; fs&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;readFile&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/tmp/test.png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;500&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;\n&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;image/png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;show &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이 request handler를 &lt;EM&gt;/show&lt;/EM&gt; 라는 URL 과 매핑해야겠죠. &lt;EM&gt;index.js&lt;/EM&gt;에서요. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; server &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./server&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; router &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./router&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;./requestHandlers&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/start&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/upload&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/show&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; requestHandlers&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;server&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;router&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;서버를 재시작하고 브라우저로 &lt;A href=&quot;http://localhost:8888/show&quot; rel=nofollow&gt;http://localhost:8888/show&lt;/A&gt; 를 열면 &lt;EM&gt;/tmp/test.png&lt;/EM&gt; 파일이 보여야 합니다. &lt;/P&gt;
&lt;P&gt;좋습니다. 이제 우리가 해야할 것은 &lt;/P&gt;
&lt;P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;EM&gt;/start&lt;/EM&gt;의 form 에 파일 업로드 element를 추가하고, &lt;/LI&gt;
&lt;LI&gt;업로드된 파일을 &lt;EM&gt;/tmp/test.png&lt;/EM&gt;에 저장하기 위해서 node-formidable을 &lt;EM&gt;upload&lt;/EM&gt; request handler 에 추가하고, &lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;/upload&lt;/EM&gt; URL의 출력 HTML 에 업로드된 이미지를 추가합니다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;스텝 1은 단순하죠. HTML form의 encoding type 에 &lt;EM&gt;multipart/form-data&lt;/EM&gt;를 추가하고, textarea는 삭제합니다. 파일 업로드 input 필드를 추가하고 submit 버튼의 텍스트를 “Upload file”이라고 바꿉니다. 이렇게 해 봅시다. &lt;EM&gt;requestHandlers.js&lt;/EM&gt; 파일입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; querystring &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;querystring&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; fs &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;fs&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'content=&quot;text/html; charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; enctype=&quot;multipart/form-data&quot; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;file&quot; name=&quot;upload&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Upload file&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;You've sent the text: &quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; querystring&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;text&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; postData&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'show' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; fs&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;readFile&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/tmp/test.png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;500&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;\n&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;image/png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;show &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;멋집니다. 다음 스텝은 조금 복잡합니다. 첫 번째 문제는, 파일 업로드를 &lt;EM&gt;upload&lt;/EM&gt; request handler에서 처리하고 싶은데 이렇게 하려면 &lt;EM&gt;request&lt;/EM&gt; 객체를 &lt;EM&gt;form.parse&lt;/EM&gt; 함수에 넘겨줘야 합니다. &lt;/P&gt;
&lt;P&gt;하지만 우리에겐 &lt;EM&gt;response&lt;/EM&gt; 객체와 &lt;EM&gt;postData&lt;/EM&gt; 배열밖에 없죠. 슬프게도 &lt;EM&gt;request&lt;/EM&gt; 객체를 server에서 router 로, 또 request handler로 전달하고 다녀야 할 것 같습니다. 더 고상한 해결책이 있을 수도 있겠지만, 지금은 이렇게 해야겠네요. &lt;/P&gt;
&lt;P&gt;하는 김에, &lt;EM&gt;postData&lt;/EM&gt; 관련 코드를 server와 request handler 에서 날려버립시다. 파일 업로드에 이런 코드가 필요하지 않을 뿐더러 다른 문제를 일으킬 수도 있어요. 이미 server에서 &lt;EM&gt;request&lt;/EM&gt; 객체의 &lt;EM&gt;data&lt;/EM&gt; 이벤트를 “소모했기” 때문에 &lt;EM&gt;form.parse&lt;/EM&gt;에서도 이 이벤트를 받아야 하는데 더 이상 이 이벤트를 받을 수 없게 됩니다. (왜냐하면 Node.js는 어떤 data도 버퍼링 하지 않기 때문이죠) &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;server.js&lt;/EM&gt; 부터 시작해 봅시다. postData 처리와 &lt;EM&gt;request.setEncoding&lt;/EM&gt; 부분을 삭제합니다. 그리고 대신 &lt;EM&gt;request&lt;/EM&gt;를 router로 넘깁니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; http &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;http&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;url&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;url&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot; received.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; http&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;createServer&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;onRequest&lt;/SPAN&gt;&lt;SPAN class=pun&gt;).&lt;/SPAN&gt;&lt;SPAN class=pln&gt;listen&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;8888&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Server has started.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;다음으로 &lt;EM&gt;router.js&lt;/EM&gt; 입니다. postData를 넘기는 것은 더 이상 필요 없습니다. 대신 &lt;EM&gt;request&lt;/EM&gt;를 넘기면 되죠. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;About to route a request for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;typeof&lt;/SPAN&gt;&lt;SPAN class=pln&gt; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;]&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;===&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'function'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; handle&lt;/SPAN&gt;&lt;SPAN class=pun&gt;[&lt;/SPAN&gt;&lt;SPAN class=pln&gt;pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;](&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;No request handler found for &quot;&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; pathname&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;404&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;404 Not found&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;route &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; route&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;이제 &lt;EM&gt;request&lt;/EM&gt; 객체를 &lt;EM&gt;upload&lt;/EM&gt; request handler 함수에서 사용할 수 있게 되었습니다. node-formidable 이 업로드되는 파일을 &lt;EM&gt;/tmp&lt;/EM&gt;에 로컬파일로 잘 저장할 겁니다. 하지만 파일이 &lt;EM&gt;/tmp/test.png&lt;/EM&gt;에 남아있는지는 우리 스스로 확인을 해 봅시다. 단순하게 유지하기 위해서 오직 PNG 이미지만 업로드 하는 것으로 가정합니다. &lt;/P&gt;
&lt;P&gt;이제 &lt;EM&gt;fs.renameSync(path1, path2)&lt;/EM&gt;가 동작할 건데요, 이름이 암시하듯이 이것은 동기적으로 동작합니다. 따라서 만약 rename 동작이 비싸고 시간이 오래 걸린다면 blocking을 초래하겠죠. 우리는 모두 성인이고 우리가 뭘 하는지 알고 있다고 동의합시다. &lt;/P&gt;
&lt;P&gt;업로드된 파일을 관리하는 코드 몇줄과 rename 코드를 넣읍시다. &lt;EM&gt;requestHandler.js&lt;/EM&gt; 파일입니다. &lt;/P&gt;&lt;PRE class=&quot;prettyprint lang-js&quot;&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; querystring &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;querystring&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; fs &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;fs&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;),&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; formidable &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; require&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;formidable&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'start' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; body &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'charset=UTF-8&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/head&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;form action=&quot;/upload&quot; enctype=&quot;multipart/form-data&quot; '&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'method=&quot;post&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;file&quot; name=&quot;upload&quot; multiple=&quot;multiple&quot;&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;input type=&quot;submit&quot; value=&quot;Upload file&quot; /&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/form&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/body&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=str&gt;'&amp;lt;/html&amp;gt;'&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;body&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'upload' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;var&lt;/SPAN&gt;&lt;SPAN class=pln&gt; form &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;new&lt;/SPAN&gt;&lt;SPAN class=pln&gt; formidable&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=typ&gt;IncomingForm&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;about to parse&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; form&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;parse&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;request&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; fields&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; files&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;parsing done&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; fs&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;renameSync&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;files&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;path&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/tmp/test.png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/html&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;received image:&amp;lt;br/&amp;gt;&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;&amp;lt;img src='/show' /&amp;gt;&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; console&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;log&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Request handler 'show' was called.&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; fs&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;readFile&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;/tmp/test.png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;function&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;if&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error&lt;/SPAN&gt;&lt;SPAN class=pun&gt;)&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;500&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;text/plain&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;error &lt;/SPAN&gt;&lt;SPAN class=pun&gt;+&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;\n&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=kwd&gt;else&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;writeHead&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=lit&gt;200&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;{&lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;Content-Type&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;:&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;image/png&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;write&lt;/SPAN&gt;&lt;SPAN class=pun&gt;(&lt;/SPAN&gt;&lt;SPAN class=pln&gt;file&lt;/SPAN&gt;&lt;SPAN class=pun&gt;,&lt;/SPAN&gt;&lt;SPAN class=pln&gt; &lt;/SPAN&gt;&lt;SPAN class=str&gt;&quot;binary&quot;&lt;/SPAN&gt;&lt;SPAN class=pun&gt;);&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; response&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;end&lt;/SPAN&gt;&lt;SPAN class=pun&gt;();&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN class=pun&gt;});&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;/SPAN&gt;&lt;SPAN class=pun&gt;}&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
&lt;br /&gt;exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;start &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; start&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;upload &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; upload&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;SPAN class=pln&gt;&lt;br /&gt;
exports&lt;/SPAN&gt;&lt;SPAN class=pun&gt;.&lt;/SPAN&gt;&lt;SPAN class=pln&gt;show &lt;/SPAN&gt;&lt;SPAN class=pun&gt;=&lt;/SPAN&gt;&lt;SPAN class=pln&gt; show&lt;/SPAN&gt;&lt;SPAN class=pun&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;자 다 됐습니다. 서버를 재시작 하고 유스케이스가 완전히 잘 동작합니다. 로컬 하드 드라이브에 있는 PNG 이미지를 선택하고, 서버에 업로드하고, 웹페이지에 출력됩니다. &lt;/P&gt;&lt;A name=conclusion-and-outlook&gt;&lt;/A&gt;
&lt;H2&gt;결론과 개관&lt;/H2&gt;
&lt;P&gt;축하합니다. 우리의 미션을 달성했습니다. 우리는 단순하지만 제대로 된 Node.js 웹 애플리케이션을 작성했습니다. 우리는 서버 사이드 JavaScript, 함수형 프로그래밍, blocking 과 non-blocking 동작, callback, 이벤트, custom, 내부, 외부 모듈 그 외에 여러 가지에 대해 이야기 했습니다. &lt;/P&gt;
&lt;P&gt;물론 우리가 다루지 않은 많은 내용들이 있습니다. 데이터베이스와 어떻게 통신하는지, 유닛 테스트를 어떻게 작성하는지, NPM을 통해 설치할 수 있는 외부 모듈을 어떻게 만드는지, GET 요청을 어떻게 다루는지와 같은 단순한 것들도 있지요. &lt;/P&gt;
&lt;P&gt;하지만 그것은 초보자를 대상으로한 모든 책들의 운명입니다. 모든 내용을 자세히 다룰 수는 없죠. &lt;/P&gt;
&lt;P&gt;좋은 소식은 Node.js 커뮤니티가 매우 활발하다는 (카페인을 먹은 ADHD-과잉운동성장애 아이를 긍정적으로 상상해보세요) 것입니다. 이것은 자료와, 당신이 질문할 곳이 많다는 의미입니다. 더 많은 정보를 위해서는 아마 &lt;A href=&quot;https://github.com/joyent/node/wiki&quot;&gt;Node.js community wiki&lt;/A&gt;와 &lt;A href=&quot;http://www.nodecloud.org/&quot;&gt;the NodeCloud directory&lt;/A&gt; 가 가장 좋은 시작 지점이 될 겁니다. &lt;/P&gt;&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-189-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-fr/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-fr/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/DerivativeWorks&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이선스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이선스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div class=&quot;another_category another_category_color_violet&quot;&gt;
&lt;h4&gt;'&lt;a href=&quot;/category/dog발;&quot;&gt;dog발;&lt;/a&gt;&amp;nbsp;&gt;&amp;nbsp;&lt;a href=&quot;/category/dog발;/javascript&quot;&gt;javascript&lt;/a&gt;' 카테고리의 다른 글&lt;/h4&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/192&quot; &gt;HTML5 가속도계 API 이용 ??&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
16:28:15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/190&quot; &gt;.attr(&amp;quot;checked&amp;quot;, &amp;quot;&amp;quot;) 버그&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/189&quot; &gt;The Node Beginner Book (Korean version)&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2012/01/13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/179&quot; &gt;javascript location.href target&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(3)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/177&quot; &gt;input text용 updown버튼&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(1)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/175&quot; &gt;jQuery 입력폼 글자수 제한&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/02/10&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;</description>
			<category>javascript</category>
			<author>vinu</author>
			<guid>http://blog.dbza.net/189</guid>
			<comments>http://blog.dbza.net/189#entry189comment</comments>
			<pubDate>Fri, 13 Jan 2012 12:28:14 +0900</pubDate>
		</item>
		<item>
			<title>iPhone4s</title>
			<link>http://blog.dbza.net/188</link>
			<description>&lt;DIV style=&quot;TEXT-ALIGN: center&quot;&gt;&lt;STRONG&gt;나와 함께 하는 iPhone 친구들&lt;br /&gt;
&lt;/STRONG&gt;&lt;br /&gt;
&lt;/DIV&gt;
&lt;P style=&quot;TEXT-ALIGN: center; MARGIN: 0px&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://cfile7.uf.tistory.com/image/181CC84A4EC0AD77155EC2&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;4-8CDA85D1-742584-800.jpg&quot; height=&quot;707&quot; width=&quot;360&quot;/&gt;&lt;/div&gt;&lt;/P&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-188-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-fr/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-fr/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/DerivativeWorks&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이선스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=&quot;_blank&quot;&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이선스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div class=&quot;another_category another_category_color_violet&quot;&gt;
&lt;h4&gt;'&lt;a href=&quot;/category/1if2;&quot;&gt;1if2;&lt;/a&gt;&amp;nbsp;&gt;&amp;nbsp;&lt;a href=&quot;/category/1if2;/1상;&quot;&gt;1상;&lt;/a&gt;' 카테고리의 다른 글&lt;/h4&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/188&quot; &gt;iPhone4s&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/11/14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/187&quot; &gt;Steve Jobs 1955-2011&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/10/06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/186&quot; &gt;iOS개발자등록... 그리고 iPhone, iPad2&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/07/12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/185&quot; &gt;WWDC 2011&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/06/07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/184&quot; &gt;iPad2 주문완료&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/04/29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;a href=&quot;/183&quot; &gt;그림의 떡 iPad2&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;span&gt;(0)&lt;/span&gt;
&lt;/th&gt;
&lt;td&gt;
2011/04/06&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;</description>
			<category>1상;</category>
			<category>1if2;</category>
			<category>Apple</category>
			<category>blog.dbza.net</category>
			<category>iPhone 4s</category>
			<author>vinu</author>
			<guid>http://blog.dbza.net/188</guid>
			<comments>http://blog.dbza.net/188#entry188comment</comments>
			<pubDate>Mon, 14 Nov 2011 14:56:57 +0900</pubDate>
		</item>
	</channel>
</rss>
