<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6354485549816224413</id><updated>2026-05-11T05:23:23.582-07:00</updated><category term="팁"/><category term="javascript"/><category term="html"/><category term="Apache Tomcat"/><category term="JSP"/><category term="코드"/><category term="mysql"/><category term="php"/><category term="도구"/><category term="Apache HTTP 서버"/><category term="MyBatis"/><category term="React"/><category term="mac"/><category term="useRef"/><category term="문제 해결"/><category term="서버 구축"/><category term="서버 설정"/><category term="Blogger"/><category term="CORS"/><category term="HTTP 서버"/><category term="IIS 서버"/><category term="JDBC"/><category term="JSP/Servlet"/><category term="Node.js"/><category term="SSL"/><category term="ajax"/><category term="cli"/><category term="closure"/><category term="fetch"/><category term="forwardRef"/><category term="init-author-email"/><category term="init-author-name"/><category term="init.author.email"/><category term="init.author.name"/><category term="servlet 3.0"/><category term="useContext"/><category term="useEffect"/><category term="useImperativeHandle"/><category term="useReducer"/><category term="useState"/><category term="xml parsing"/><category term="서버 설치"/><title type='text'>Web 개발</title><subtitle type='html'>Web 개발 관련 기록</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-5564882200084362285</id><published>2025-02-26T18:43:00.000-08:00</published><updated>2025-02-26T18:43:22.636-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cli"/><category scheme="http://www.blogger.com/atom/ns#" term="init-author-email"/><category scheme="http://www.blogger.com/atom/ns#" term="init-author-name"/><category scheme="http://www.blogger.com/atom/ns#" term="init.author.email"/><category scheme="http://www.blogger.com/atom/ns#" term="init.author.name"/><title type='text'>[npm-cli] npm warn config init.author.name Use `--init-author-name` instead 출력 이유 확인</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;증상:&lt;/h3&gt;&lt;br /&gt;npm 명령 수행 시 아래와 같은 경고 문구 표시&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;npm warn config init.author.name Use `--init-author-name` instead.&lt;br /&gt;npm warn config init.author.email Use `--init-author-email` instead.&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;원인:&lt;/h3&gt;&lt;br /&gt;npm 설정에 init.author.name 값은 init-author-name 로 변경됨&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;관련 github issue &lt;a href=&quot;https://github.com/npm/npm/issues/6642&quot;&gt;#6642&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;해결:&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;값 설정&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;npm config set init-author-name &amp;lt;name&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;npm config set init-author-email &amp;lt;email&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;기존키 삭제&lt;/h4&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;.npmrc 파일에 init.author.name, init.author.email 값 삭제&lt;/div&gt;&lt;div&gt;&lt;br /&gt;.npmrc 파일 위치 (&lt;a href=&quot;https://docs.npmjs.com/cli/v8/configuring-npm/npmrc&quot;&gt;https://docs.npmjs.com/cli/v8/configuring-npm/npmrc&lt;/a&gt;)&lt;/div&gt;&lt;ul class=&quot;components__UnorderedList-sc-13rww2g-10 fqlkab&quot;&gt;
&lt;li&gt;per-project config file (&lt;span style=&quot;font-family: courier;&quot;&gt;/path/to/my/project/.npmrc&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;per-user config file (&lt;span style=&quot;font-family: courier;&quot;&gt;~/.npmrc&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;global config file (&lt;span style=&quot;font-family: courier;&quot;&gt;$PREFIX/etc/npmrc&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;npm builtin config file (&lt;span style=&quot;font-family: courier;&quot;&gt;/path/to/npm/npmrc&lt;/span&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;참고&lt;/h3&gt;&lt;p&gt;init-author-name 과 init-author-email 은 npm init 과정에서 package.json 에 &lt;a href=&quot;https://docs.npmjs.com/cli/v11/configuring-npm/package-json#people-fields-author-contributors&quot;&gt;author 값&lt;/a&gt;을 설정하는데 사용됨&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/5564882200084362285/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2025/02/npm-cli-npm-warn-config-initauthorname.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5564882200084362285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5564882200084362285'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2025/02/npm-cli-npm-warn-config-initauthorname.html' title='[npm-cli] npm warn config init.author.name Use `--init-author-name` instead 출력 이유 확인'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-6812495135884706722</id><published>2023-12-28T23:39:00.000-08:00</published><updated>2024-01-01T21:37:23.275-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fetch"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>fetch + progress</title><content type='html'>&lt;p&gt;fetch + progress&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;요약&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;ArrayBuffer 다운로드 방식을 커스텀&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;예) react + fetch + progress&lt;/p&gt;&lt;iframe src=&quot;https://codesandbox.io/embed/spwldn?view=Editor+%2B+Preview&amp;module=%2Fsandbox.config.json&quot;
     style=&quot;width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;&quot;
     title=&quot;fetch-progress-example&quot;
     allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot;
     sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;
   &gt;&lt;/iframe&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;gzip encoding 시 content length 값 문제&lt;/h3&gt;&lt;div&gt;Transfer-Encoding: gzip&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;증상:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;gzip encoding 시 content-length 는 압축된 데이터 크기이기 때문에 실제 데이터 보다 크기가 작다&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;우회:&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;요청 헤더에 Accept-Encoding 을&amp;nbsp;명시하여 gzip 방지&lt;/li&gt;&lt;ul&gt;&lt;li&gt;주의: 서버 구현에 따름&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;data:image/png;base64,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&quot; /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/6812495135884706722/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2023/12/fetch-progress.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6812495135884706722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6812495135884706722'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2023/12/fetch-progress.html' title='fetch + progress'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-7157781260240683832</id><published>2023-12-28T22:15:00.000-08:00</published><updated>2023-12-29T09:36:11.283-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="React"/><category scheme="http://www.blogger.com/atom/ns#" term="useContext"/><category scheme="http://www.blogger.com/atom/ns#" term="useReducer"/><category scheme="http://www.blogger.com/atom/ns#" term="useRef"/><category scheme="http://www.blogger.com/atom/ns#" term="useState"/><title type='text'>[React] useRef, useState, useReducer, useContext 사용례 비교</title><content type='html'>&lt;h3 style=&quot;text-align: left;&quot;&gt;요약&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;useRef 렌더링 X 변수 설정 필요한 경우 [컴포넌트]&lt;/li&gt;&lt;li&gt;useState 렌더링 O 단순한 데이터 타입 [컴포넌트]&lt;/li&gt;&lt;li&gt;useReducer 렌더링 O 복잡한 데이터 타입 (예: object), 복잡한 operation [컴포넌트]&lt;/li&gt;&lt;li&gt;useContext 여러 컴포넌트에 걸쳐 공유하는 데이터, 함수 [Provider 하위]&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/h3&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;useRef&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;언제?&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;컴포넌트 안에서만 사용되는 한번 초기화되는 변수&lt;/li&gt;&lt;li&gt;렌더링 필요없는 경우&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;사용례&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;비디오 element 조작&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot; src=&quot;https://codesandbox.io/embed/yc5myc?view=Editor+%2B+Preview&amp;amp;module=%2Fsrc%2FApp.tsx&quot; style=&quot;border-radius: 4px; border: 0; height: 500px; overflow: hidden; width: 100%;&quot; title=&quot;video-example&quot;&gt;&lt;/iframe&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/h1&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;useState&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;언제?&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;컴포넌트 안에서만 사용되는 한번 초기화 되는 변수&lt;/li&gt;&lt;li&gt;렌더링 필요한 경우&lt;/li&gt;&lt;li&gt;간단한 데이터 타입 (예: string, number, boolean 등)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;사용례&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;간단한 계산기&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot; src=&quot;https://codesandbox.io/embed/drrzvv?view=Editor+%2B+Preview&amp;amp;module=%2Fsrc%2FApp.tsx&quot; style=&quot;border-radius: 4px; border: 0; height: 500px; overflow: hidden; width: 100%;&quot; title=&quot;calculator&quot;&gt;&lt;/iframe&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/h1&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;useReducer&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;언제?&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;컴포넌트 안에서만 사용되는 한번 초기화 되는 변수&lt;/li&gt;&lt;li&gt;렌더링 필요한 경우&lt;/li&gt;&lt;li&gt;복잡한 데이터 타입 (예: object 등)&lt;/li&gt;&lt;li&gt;데이터를 다루는 다양한 operation 필요한 경우&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;사용례&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;fetch 데이터&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot; src=&quot;https://codesandbox.io/embed/hysrr6?view=Editor+%2B+Preview&amp;amp;module=%2Fsrc%2FApp.tsx&quot; style=&quot;border-radius: 4px; border: 0; height: 500px; overflow: hidden; width: 100%;&quot; title=&quot;fetching-example&quot;&gt;&lt;/iframe&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/h1&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;useContext&lt;/h1&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;언제?&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;여러 컴포넌트에 걸쳐 사용되며 한번 초기화 되는 변수&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;사용례&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;테마 설정&lt;/li&gt;&lt;li&gt;로그인 정보&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot; src=&quot;https://codesandbox.io/embed/8k34wd?view=Editor+%2B+Preview&amp;amp;module=%2Fsrc%2Fapp.tsx&quot; style=&quot;border-radius: 4px; border: 0; height: 500px; overflow: hidden; width: 100%;&quot; title=&quot;theme-example&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/7157781260240683832/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2023/12/react-useref-usestate-usereducer.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7157781260240683832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7157781260240683832'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2023/12/react-useref-usestate-usereducer.html' title='[React] useRef, useState, useReducer, useContext 사용례 비교'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-646449344023754537</id><published>2023-12-20T21:13:00.000-08:00</published><updated>2023-12-20T21:22:23.043-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="forwardRef"/><category scheme="http://www.blogger.com/atom/ns#" term="useImperativeHandle"/><category scheme="http://www.blogger.com/atom/ns#" term="useRef"/><title type='text'>[React] useImperativeHandle 사용 예</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;useImperativeHandle 사용하기&lt;/h2&gt;&lt;p&gt;참고: &lt;a href=&quot;https://react.dev/reference/react/useImperativeHandle&quot;&gt;https://react.dev/reference/react/useImperativeHandle&lt;/a&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;state, callback prop 대신 직접적으로 component 에 명령을 내릴 때 사용&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;data:image/png;base64,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&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;예제) &lt;a href=&quot;https://github.com/bjtj/tjsamples/tree/main/react/useimperativehandle-example&quot;&gt;react + typescript&lt;/a&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import { &lt;b&gt;forwardRef, useRef, useImperativeHandle, useState &lt;/b&gt;} from &#39;react&#39;;&lt;br /&gt;&lt;br /&gt;function App() {&lt;br /&gt;&lt;br /&gt;&amp;nbsp; const mycomponent = useRef&amp;lt;MyComponentElement&amp;gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp; return (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div className=&quot;App&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;MyComponent ref={ref =&amp;gt; mycomponent.current = ref as MyComponentElement} /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div style={{ display: &#39;flex&#39;, gap: 3 }}&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onClick={() =&amp;gt; mycomponent.current?.play()}&amp;gt;Play&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onClick={() =&amp;gt; mycomponent.current?.pause()}&amp;gt;Pause&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onClick={() =&amp;gt; mycomponent.current?.stop()}&amp;gt;Stop&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onClick={() =&amp;gt; alert(mycomponent.current?.getState())}&amp;gt;Get State&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;type MyComponentElement = {&lt;br /&gt;&amp;nbsp; play: () =&amp;gt; void;&lt;br /&gt;&amp;nbsp; pause: () =&amp;gt; void;&lt;br /&gt;&amp;nbsp; stop: () =&amp;gt; void;&lt;br /&gt;&amp;nbsp; getState: () =&amp;gt; string;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;type MyComponentProps = {&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;const MyComponent = &lt;b&gt;forwardRef&lt;/b&gt;&amp;lt;MyComponentElement, MyComponentProps&amp;gt;((props, ref) =&amp;gt; {&lt;br /&gt;&amp;nbsp; const [state, setState] = useState&amp;lt;string&amp;gt;(&#39;idle&#39;);&lt;br /&gt;&lt;span style=&quot;background-color: #cfe2f3;&quot;&gt;&amp;nbsp; &lt;b&gt;useImperativeHandle&lt;/b&gt;(ref, () =&amp;gt; ({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; play: () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setState(&#39;play&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pause: () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setState(&#39;pause&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stop: () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setState(&#39;stop&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; getState: () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return state;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }));&lt;/span&gt;&lt;br /&gt;&amp;nbsp; return (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;p&amp;gt;state: {state}&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp; );&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;export default App;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;설명&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;주로 forwardRef, useRef 와 함께 사용&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/646449344023754537/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2023/12/react-useimperativehandle.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/646449344023754537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/646449344023754537'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2023/12/react-useimperativehandle.html' title='[React] useImperativeHandle 사용 예'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-5095399422049946974</id><published>2023-10-22T08:35:00.000-07:00</published><updated>2023-10-22T08:35:23.457-07:00</updated><title type='text'>[Python] Flask Http Server 예제</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://flask.palletsprojects.com/en/2.0.x/quickstart/&quot;&gt;https://flask.palletsprojects.com/en/2.0.x/quickstart/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;설치&lt;/h4&gt;&lt;p&gt;pip install Flask &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;e.g.) hello.py&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;from flask import Flask&lt;br /&gt;&lt;br /&gt;app = Flask(__name__)&lt;br /&gt;&lt;br /&gt;@app.route(&quot;/&quot;)&lt;br /&gt;def hello_world():&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &quot;&amp;lt;p&amp;gt;Hello, World!&amp;lt;/p&amp;gt;&quot;&lt;/span&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;설명&lt;/h4&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier; font-weight: 400;&quot;&gt;from flask import Flask&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Flask 를 import&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;app = Flask(__name__)&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Flask 인스턴스 생성&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;@app.route(&quot;/&quot;)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;route 설정&lt;/li&gt;&lt;li&gt;&quot;/&quot; 은 root 경로&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;실행&lt;br /&gt;&lt;/h4&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;$ export FLASK_APP=hello&lt;br /&gt;$ flask run&lt;br /&gt;&amp;nbsp;* Running on http://127.0.0.1:5000/&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;data:image/png;base64,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&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/5095399422049946974/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2023/10/python-flask-http-server.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5095399422049946974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5095399422049946974'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2023/10/python-flask-http-server.html' title='[Python] Flask Http Server 예제'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-7903473424816373831</id><published>2023-08-20T00:02:00.002-07:00</published><updated>2023-08-20T00:02:19.376-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="React"/><category scheme="http://www.blogger.com/atom/ns#" term="useEffect"/><title type='text'>[React] useEffect + async 예시</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;useEffect 사용시 async 호출 방식&lt;/h2&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;promise 완료 이벤트 활용&lt;/h3&gt;&lt;p&gt;- 중첩적으로 완료 이벤트 적용 가능한 특성을 이용&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;async function foo() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(&#39;start&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(&#39;done&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;useEffect(() =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let prom = foo();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; prom.&lt;b&gt;then&lt;/b&gt;(() =&amp;gt; console.log(&#39;listener is added&#39;));&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prom.&lt;b&gt;then&lt;/b&gt;((unlisten) =&amp;gt; unlisten());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}, []);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/7903473424816373831/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2023/08/react-useeffect-async.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7903473424816373831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7903473424816373831'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2023/08/react-useeffect-async.html' title='[React] useEffect + async 예시'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-4396982045319942784</id><published>2022-02-04T20:14:00.004-08:00</published><updated>2022-02-04T20:14:46.386-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTTP 서버"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><title type='text'>[Node.js] 간단한 http server 만들기</title><content type='html'>&lt;p&gt;참고: &lt;a href=&quot;https://nodejs.org/en/docs/guides/getting-started-guide/&quot;&gt;https://nodejs.org/en/docs/guides/getting-started-guide/&lt;/a&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;1. 개념&lt;/h3&gt;&lt;p&gt;Node.js (&lt;a href=&quot;https://nodejs.org/en/&quot;&gt;링크&lt;/a&gt;)&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Javascript 기반 프로그램 실행 플랫폼&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;NPM (&lt;a href=&quot;https://www.npmjs.com/&quot;&gt;링크&lt;/a&gt;)&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Node.js 패키지 관리자&lt;/li&gt;&lt;li&gt;손쉬운 설치를 도와주는 도구&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;2. Http Server 실행&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;외부 패키지 없이 구현&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;코드: server.js&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;const http = &lt;b&gt;require&lt;/b&gt;(&#39;http&#39;);&lt;br /&gt;&lt;br /&gt;const hostname = &#39;127.0.0.1&#39;;&lt;br /&gt;const port = 3000;&lt;br /&gt;&lt;br /&gt;const server = &lt;b&gt;http.createServer&lt;/b&gt;((req, res) =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;res.statusCode = 200;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;res.setHeader(&#39;Content-Type&#39;, &#39;text/plain&#39;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;res.end(&#39;Hello World&#39;);&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;b&gt;server.listen&lt;/b&gt;(port, hostname, () =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;console.log(`Server running at http://${hostname}:${port}/`);&lt;br /&gt;});&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;코드 설명&lt;br /&gt;&lt;/h4&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;require()&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;외부 모듈을 import 함&lt;/li&gt;&lt;li&gt;http 모듈은 node.js 를 설치하면 기본으로 내장된 모듈&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/modules.html#requireid&quot;&gt;https://nodejs.org/api/modules.html#requireid&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;http.createServer()&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;http server instance 를 생성함&lt;/li&gt;&lt;li&gt;파마메터로 handler 함수를 넘겨줌&lt;/li&gt;&lt;li&gt;handler 함수는 http request 와 http response 를 입력 받아 처리하는 간단한 함수&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener&quot;&gt;https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;server.listen()&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;서버 가동&lt;/li&gt;&lt;li&gt;파라메터로 넘겨받은 hostname 과 port 번호로 bind 하고 http 요청들을 처리함&lt;/li&gt;&lt;li&gt;세번째 파라메터는 http server 의 가동 준비가 완료되면 호출되는 함수&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/http.html#serverlisten&quot;&gt;https://nodejs.org/api/http.html#serverlisten&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;참고&lt;/h4&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;hostname 을 &#39;0.0.0.0&#39; 으로 주면 같은 네트워크 내에 다른 PC 에서 IP 로 접근 가능&lt;/li&gt;&lt;ul&gt;&lt;li&gt;외부 접근 되지 않으면 방화벽 설정 확인&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;port 을 0 으로 주면 가용한 아무 port (any port) 로 bind 함&lt;/li&gt;&lt;ul&gt;&lt;li&gt;any port 로 bind 한 경우 listen callback 이 불리는 시점에 &lt;span style=&quot;font-family: courier;&quot;&gt;server.address().port&lt;/span&gt; 로 port 번호 확인 가능&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;3. 실행&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;$ &lt;b&gt;node server.js &lt;/b&gt;&lt;br /&gt;Server running at http://127.0.0.1:3000/&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAckAAABxCAYAAAC+0VjdAAAR7klEQVR4Xu2daZAV1RlAP37gjyhgmTJWgMgSGBBNVBYZKiiIAqUsmmiEEVLFIouJohAHogKWSExgLPfEAYSZqoCggURBNIDCoKQAFXAPIHHAhfzQGIbFbaRIfw136Gne0vctPa+nT1uWM69v3/vdc/txuKtNWrdqf0y4IAABCEAAAhA4hUCT87t0Q5K8GBCAAAQgAIEEBJAkrwUEIAABCEAgCQEkyasBAQhAAAIQQJK8AxCAAAQgAAE7AvQk7XiRGgKxJHD06FH5+puv5Gjtd3LM+YcLAnEhgCTj0tLUEwIZElBBHjl8CDlmyI/Hok0ASUa7/YgeAnkncOTLw/JdbW3ey6EACBQiASRZiK1CTBAoIAIHaw7Qiyyg9iCUcAkgyXB5UxoEIkegpuZ/kYuZgCGQKwJIMlckyQcCjZQAkmykDUu1AhFAkoEwkQgC8SWAJOPb9tRcBEnyFkAAAikJIElekDgTQJJxbn3qDoEABDKRZPPmzWX0mFEyxvlXr0WLKuWRhx8NUBpJIFBYBJBkYbVHqNE0a9ZM7p01U/r16yvr11fJPTNnyaFDh0KNgcIKn4CtJK//5XVy26RbpcWZLWTWrNnSvFlzuX3yJKk5UCOPPPKoLF/+t5xUuri4p5SVzZHWP2qdML/lf10h9933ezl48GBOyiOTeBLIuSRPP/178u23tVJbYPuqmjZtKqed1lSOHPmyQVpahTRiRIn0vbyPdO5c5Mawc+duqdqwUZYsWerKST8fP2GcTJlcmvcYNZ4FT5ZLkyYiZXMflNKpU+SYc5DKuJsmIsq8049WAUElOWBgf5kx/W5XjosWVri9RyMo7Vlqr3LM2NHy0Ucfy2xHXlu2bM0KxKubNrp5rFi+4pR8li5b4n723nvvy40lIxFlVqTj/XBOJXmm8+W47LJL5f1/7ZQ9H+wpKLIdOnaQLud1lldeeVUOOH+jDfO65pohckfpZEc+hx0hLpNdO3e5xXfq3MkR53Bp1uwMeeKJBXLzzeOcn5vJRRf2yGt4XkHeNPa4FPWzJxeWI8q8ko9m5kEkWfbAXLn++l9IRUWlPPzQo0mlpL2+226b5KbVnl5p6bSMoVTv3SMlw0cklK3eM1c2onzt9c3y7N+flfvvn5NxnOkeLJ/3Z2nVsqUMGXKtm1RjL71jas563OnK535qAjmTpBHk/v3/kTfe2FaQ3Lt37yYtW/4wVFGqIHVIs6zsIVmy+KmEXKY6vbgbnV6mufIpyUSCNOUiyoJ8bRs8qHSSPP/8LvL86pVJhZWoAjpUqr29Sy/tK598/ElGdQwqSc1ch3hVPLZXnCR58cUXSf8BA+oQLf7LYtm/f3/d7/77c+fMrYdz2PBh0qZNG/ezffv2ydPLnq6739L5S8DIX41Mmrdtu4SZPieSjIIgDdQwRanSeeHF56S8/MmkgjTSMkOwGme+JJlKkIgyzK9dtMoKKkkb4enw61tvb5fBg4a6Q6KZXKkkufqFVdKly3n1sm3XtoN1MY1Jkv4eqx9G//79Zd26de7HRmpGhEaQ5ndN2/7H7WVe+Tw3vQpSLyPGCRMnyIf//tDNz+RlpOvPy7pRQn4ga0lGSZBhi3KiM3w6dOgQufqqoUmbddZ99zhpBtfdP+wMyfbufXnOX4MggkSUOcfeKDJMJ0mtZCphJYJgepKZiMvkF7TMbMqKkyT97TR12lQxYlMJ7t61S3bseLMumfe+/uztWaoIL+nZ05WoClUvI2D9WSX62tat9fIr1C9LVpKMoiDDFOXTzyyRlStXJ+1FhvlSaCydOhWJzkEGGQ7XHrfOUeriouHDRoQZKmUVGIEgklz29BLZsnmrPBxwm8ftt0+S4l49s3q3GkKSd901TcaNH1fXQp999plc0qNXvRZTsZ599tnuZ2vWrJWJE37t/rxq1bNywU8ucH/2PpdoTnLB/AX1yvHPUXrnXDU/733Nb+DA48Om777zrjvX6S3bxDWvfL47vOofNtX7KrmiTp3qeoZeIZrKGnHq70aIXhBGnImEmEicBfba14WTlSS1l6SrRm2u2tpvHXE8b/NI4LSFFs+bb70eWEqBK5lhwhEjb3QWSUwOHI+RZKq51AxD4bGIEQgiSV2408IZQh0/fmKg2s2fXy41ztaMTOYJTQFhS9II0isklY9eZtGNCnL79h11YlRhqST1Wb3MAiBvukSS9ErUX4bW2ytfE5f2ynVBlLaF6aGb8rVsfzn+YU/vvKF/TtHfU9T8VJJf/PcL+fzzz+oJ1bSPEesQxxOrVq6qN7+pkjzr+2fVm7cM9OI0QKKsJNm27bnSrVt3d5J2376PAoWvkszX6lLt2TZtelqgONq0OdedZN627Q3ZuzdY7IEy9iSylaTOS+q2jEt797MtKlB6fzwqQl1U1KpVS/n00/3uPknTyzSSzNf8aKCASVQQBIJIUvdGzphxt1z4066BYn77nR1yh7OQZu2a43NgmVxhS1JltXnz5lNWuprVqEVFHeXan197Ss8yUd1UWHqpQNOtblXxTZ1W6uarQuzVq1edlE3eGtunziKbl9a9VE+S3rLTzUl60xqBmuFWJJnJG3riGSPKfMomi/ASPhpWzLbDrTqHefnlfWXYDfkZ3vRL8oUXV7pSXPnc89K9R1fnizdYBl19jcsMSeb6rYtufkEkqQtxNv1zo3t4gG7tSHWpUGfOnC69f9Ynq/2LYUsy2fykfj53Tplc2f/Kels5/Az8Q55mKNRGkslE55Wud0hYh21N79VGkhq76SnqXCLDrVl+f8OSTpZhuo+HGatKzyuedPGrtFY6wxLlzp7JfFx+SXp/90sRSeajBaKZZxBJas10nlGPohvkrFhNtq1D90mudraLVDgHDQSdv0xGLWxJpupJ6vBmsl6exu8XrFdYNpJM1ZNM1ss1osxGkonmFY04tX66vSPZwh2vbE1bxmbhjvflDVM+mf5RE3aMuqL0RUd8T5QvSLt4R+cMb544Tq5yVsLm62g4JJnpmxPv54JKUinpAp4zzmiW8JQb7W0+tXSxHD58KKsFO6Y1wpZkkDlJ/3yhmRP0HhBg5g0z6Ulq3VPNSSaa+zSHIfgF652T1PnIc875Qd1q03TbNvxziom2gJjVq4nySrTQp1C/ZVnNSforZSS0ZcsWd46rkC6ddysuLs7rHGSi+prDBOY6R7895Rw/l+gyi2p0TvC551blDRuSzBvaRp2xjSRVhHpIwDHnjMNpU39XtwdSDxyYM/ePzjGITdxDB3JxnqrOa675x9q0J9OolIp7FTtz/X2s28nfA/SvbjWi82bsXXnq7cWZFae6KEcX95hTdmx6kt6/IHjL9G6lSba61ghW/6sLf/yrW72HAWga/6pXFePFXS92i62pqanbI+ntHbZo0cL9dYdTP++Wj3QHEVg3TIgP5FSSGrfKSM9u1RehkC5dkq1ntzaEvFWUpaVT3NV87rF0zn4jvTo5S6z1WDpdFVhW9mBeBanlbdq0QV5ev6FudfHChfNE5a3xaCx68s/YsRPc2HTvZo8e3VPu8Syk9iWW/BGwkaRGoaJ8wFlh2bP4EveIuuYtjp/bunXLa+5inVwIUstxDzh3ymndulXKyn/yyafuKtpsz4rNH2FyLmQCOZdkIVe2IWNzDzgfOdxdmKP7FfXatWu3bNhQ5QzFLsvbEKu3zjrPqIcX6NF86S49XnDmjHsD7alMlxf3o03AVpKmtmPGjHb/7x96qSwXLaqINgiijyUBJBnLZqfSEAhOIFNJBi+BlBAoXAJIsnDbhsggUBAEkGRBNANBNBABJNlA4CkWAlEhgCSj0lLEmQ8CSDIfVMkTAo2IAJJsRI1JVawJIElrZDwAgXgROFhzQI45/3BBII4EkGQcW506Q8CCwJEvD8t3tbUWT5AUAo2HAJJsPG1JTSCQFwJHjx6VI84pOfQm84KXTAucAJIs8AYiPAgUAgEV5dfffCVHa79DloXQIMQQGgEkGRpqCoIABCAAgagRQJJRazHihQAEIACB0AggydBQUxAEIAABCESNAJKMWosRLwQgAAEIhEagifP/fmMDVGi4KQgCEIAABKJEoEnrVu2RZJRajFghAAEIQCA0AkgyNNQUBAEIQAACUSOAJKPWYsQLAQhAAAKhEUCSoaGmIAhAAAIQiBoBJBm1FiNeCEAAAhAIjQCSDA01BUEAAhCAQNQIIMmotRjxQgACEIBAaASQZGioKQgCEIAABKJGAElGrcWIFwIQgAAEQiOAJENDTUEQgAAEIBA1Akgyai1GvBCAAAQgEBoBJBkaagqCAAQgAIGoEUCSUWsx4oUABCAAgdAIIMnQUFMQBCAAAQhEjQCSjFqLES8EIAABCIRGAEmGhpqCIAABCEAgagSQZNRajHghAAEIQCA0AvmXZLfpUrVilLRxqrSv4gbpe+/2+pVLdz80FBkWZBV/V5m58RkZLZVyfZ/Zsi3DInkMAhCAAATCIZBGksOlYu9s6evEUnVnBxm9+6Tw3N+XWgRZslCqiv50qiRNFunuWxR1POkJIamdTfxLE31mnXHiBwLH78RQebWsHoUkc0SebCAAAQjkjUD6nqTzh3+FjD0pRKfnVDH4BRnt7xGmCzGdRNLdT5d/ovvay7t1j/Qdtaz+3WSfZ1KGteSRZDaYeRYCEIBAmARyIMmTvU038H1JhhLTSTDF/ZLKPXJ/3xNYkuWfkJoT28YO8rgObTr5V0+sPj7M6RN9qvy73fOyLB/dxh0q/q2UuT87lZSK666QWd7x0qTx1+dTdecNUj2QnmSYLzllQQACEMiUQCBJVv+hT738vXOLJZUvS8fHPMJQGQ1cJ+38vbcMJakCm1Dtmcv0yi5trU/22oqcOAfIXql+bKzMKjrZOw6Uv5l3rJp+ol7DpaRkmSz1DjcnrJ8O75aJTDF8mJNM22QkgAAEIFBABAJJMvlwq68XWVexjXJX27FSb8oyI0k6+VeKjPYJt9s9C2XQ847sAqx8KalcKDJqnQzQHuUUkVucoeLHnR7hLbuvcIaQA+YfZIg5Uf0SPufp3RbQi0AoEIAABCBwKoHsJWmGM9PRbTBJOj3d6r3ST3TRUJE7/Lp2fTvp6EoWSaZrNu5DAAIQiDOBLCUposOVA9YEWOmakSQ1f99wrq5atVgdqr3OW9rJ8WFWp+ep+U1ot1fm9Tne0w2Uf6Y9SXeF7W/kgxNl6YvmznH228AWkDh/66g7BCAQGQKpJanzfyfmI/1bQE7OS9bfVuHWvG5xTYJ7bgIzHJvuvqY9dUjXavuJfw7TrZN4hoNT5Z84vpPlB4jfs4/SrXpVpVS0G8Veych8RQgUAhCIM4H0Pck406HuEIAABCAQawJIMtbNT+UhAAEIQCAVASTJ+wEBCEAAAhBIQgBJ8mpAAAIQgAAEkCTvAAQgAAEIQMCOAD1JO16khgAEIACBGBFAkjFqbKoKAQhAAAJ2BJCkHS9SQwACEIBAjAggyRg1NlWFAAQgAAE7AkjSjhepIQABCEAgRgSQZIwam6pCAAIQgIAdASRpx4vUEIAABCAQIwJIMkaNTVUhAAEIQMCOAJK040VqCEAAAhCIEQEkGaPGpqoQgAAEIGBHAEna8SI1BCAAAQjEiACSjFFjU1UIQAACELAjgCTteJEaAhCAAARiRABJxqixqSoEIAABCNgRQJJ2vEgNAQhAAAIxIoAkY9TYVBUCEIAABOwIIEk7XqSGAAQgAIEYEUCSMWpsqgoBCEAAAnYEkKQdL1JDAAIQgECMCCDJGDU2VYUABCAAATsCSNKOF6khAAEIQCBGBJBkjBqbqkIAAhCAgB0BJGnHi9QQgAAEIBAjAkgyRo1NVSEAAQhAwI4AkrTjRWoIQAACEIgRASQZo8amqhCAAAQgYEcASdrxIjUEIAABCMSIAJKMUWNTVQhAAAIQsCOAJO14kRoCEIAABGJEAEnGqLGpKgQgAAEI2BFAkna8SA0BCEAAAjEigCRj1NhUFQIQgAAE7AggSTtepIYABCAAgRgRQJIxamyqCgEIQAACdgSQpB0vUkMAAhCAQIwIIMkYNTZVhQAEIAABOwJI0o4XqSEAAQhAIEYEkGSMGpuqQgACEICAHQEkaceL1BCAAAQgECMCSDJGjU1VIQABCEDAjsD/AdSzPBUoKSEtAAAAAElFTkSuQmCC&quot; /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/4396982045319942784/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2022/02/nodejs-http-server.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/4396982045319942784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/4396982045319942784'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2022/02/nodejs-http-server.html' title='[Node.js] 간단한 http server 만들기'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-2854203283309006421</id><published>2018-11-12T01:28:00.001-08:00</published><updated>2018-11-12T01:28:02.790-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="closure"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>javascript closure</title><content type='html'>closure 는 함수를 리턴하는 함수로 고립된 scope 영역을 만들어 dynamic scope 로 인한 고민을 덜어 줄 수 있다.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
예)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;function genClosure(i) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; return function () {&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; i++;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return i;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;var closure1 = genClosure(0);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure1()); // 1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure1()); // 2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure1()); // 3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;var closure2 = genClosure(100);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure2()); // 101&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure2()); // 102&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure2()); // 103&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure1()); // 4&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;var i = 10;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;var closure3 = genClosure(i);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;console.log(closure3()); // 11&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;console.log(closure3()); // 12&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;console.log(i); // 10&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/2854203283309006421/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2018/11/javascript-closure.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/2854203283309006421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/2854203283309006421'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2018/11/javascript-closure.html' title='javascript closure'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-5905022716788226616</id><published>2018-03-10T16:48:00.000-08:00</published><updated>2018-03-10T16:48:17.374-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><title type='text'>MySQL 자주 사용하는 명령어</title><content type='html'>&lt;h3&gt;
mysql 설치&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;$ sudo apt install mysql-server&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
mysql 서버 접속&lt;/h3&gt;
사용자 id가 root 이고 password 가 있는 경우&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;$ mysql -u root -p&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;h3&gt;
database 목록 표시&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; show databases;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;h3&gt;
database 생성&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; create database &amp;lt;db name&amp;gt;;&lt;/span&gt;&lt;br /&gt;또는&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; create schema &amp;lt;db name&amp;gt;; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;예)&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; create database test_db;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;
사용할 database 선택&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; use &amp;lt;db name&amp;gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
예)&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; use test_db;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
table 생성&lt;/h3&gt;
&lt;br /&gt;
양식: &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/create-table.html&quot;&gt;http://dev.mysql.com/doc/refman/5.1/en/create-table.html&lt;/a&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; create table table_name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (create_definition, ...)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [table options]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [partition options];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
예)&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; create table users (&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; password varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; email varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primary key (id)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
또는 여러 field 값을 primary key 로 설정&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; create table users (&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; password varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; email varchar(256) not null,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primary key (id&lt;b&gt;, pw&lt;/b&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;
Auto increment&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; create table users (id medium int not null auto_increment, ...)&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;
table 속성 보기&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;msyql&amp;gt; desc &amp;lt;table name&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;예)&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;msyql&amp;gt; desc user;&lt;/span&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
table 제거 &lt;/h3&gt;
&lt;/div&gt;
&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.5/en/drop-table.html&quot;&gt;http://dev.mysql.com/doc/refman/5.5/en/drop-table.html&lt;/a&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; drop table [if exists] table_name [, table_name]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;예)&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; drop table if exists test_tbl;&lt;/span&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
계정 목록&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;mysql&amp;gt; select user from mysql.user;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;h3&gt;
계정 만들기&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; create user &#39;&amp;lt;usename&amp;gt;&#39;@&#39;&amp;lt;host&amp;gt;&#39; identified by &#39;&amp;lt;password&amp;gt;&#39;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; create user &#39;testuser&#39;@&#39;localhost&#39; identified by &#39;testuserpassword&#39;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;h3&gt;
계정 권한 주기&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; grant all privileges on &amp;lt;db name&amp;gt;.* to &amp;lt;user name&amp;gt;@&amp;lt;host&amp;gt; identified by &#39;&amp;lt;password&amp;gt;&#39; with grant option;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
예) &lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;mysql&amp;gt; grant all privileges on test_db.* to &#39;testuser&#39;@&#39;localhost&#39; identified by &#39;testuserpassword&#39; with grant option;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;h3&gt;
DB 백업 (dump)&lt;b&gt; &lt;/b&gt;&lt;/h3&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;$ mysqldump -u [username] -p [db name] &amp;gt; [filename]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;$ mysqldump -u testuser -p testdb &amp;gt; backupdump.sql&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;h3&gt;
DB 백업 복구&lt;/h3&gt;
&lt;br /&gt;
복구하려는 database 는 미리 생성해야 함&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;$ mysql -u [username] -p [db name] &amp;lt; [filename]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
예)&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;$ mysql -u testuser -p testdb &amp;lt; backupdump.sql&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/5905022716788226616/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2018/03/mysql.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5905022716788226616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5905022716788226616'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2018/03/mysql.html' title='MySQL 자주 사용하는 명령어'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-6303611754127791041</id><published>2014-05-13T22:28:00.000-07:00</published><updated>2014-05-13T22:31:06.058-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CORS"/><title type='text'>CORS (Cross-origin resource sharing) 간략한 설명</title><content type='html'>Wiki: &lt;a href=&quot;http://en.wikipedia.org/wiki/Cross-origin_resource_sharing&quot;&gt;http://en.wikipedia.org/wiki/Cross-origin_resource_sharing&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
대략적 내용만 정리합니다.&lt;br /&gt;
&lt;h1&gt;
개요&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;보안상 문제로 어느 시기 부터 웹 브라우저들이 AJAX 로 외부 host 로 접속하는 걸 막기 시작했습니다.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;예를 들어 AJAX 로 http://www.google.com 와 같이 외부 host url 로 접속하는게 불가능 해지고 /relative-path/mypage.html 과 같이 현재 host 의 하부 경로로만 접근 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h1&gt;
CORS 가 필요한 시점&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;그러나 AJAX 로 외부 접근이 필요한 경우에 Response header 에 field 를 추가하여 접근 허용 범위를 정할 수 있습니다&lt;/li&gt;
&lt;li&gt;Header field 에&amp;nbsp; Access-Control-Allow-Origin 를 추가해 줍니다.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Access-Control-Allow-Origin: http://www.example-social-network.com&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;위와 같이 특정 host 로 부터 접근을 허용할 수도 있고 아래와 같이 모든 접근을 허용할 수도 있습니다.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Access-Control-Allow-Origin: *&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;h1&gt;
테스트 방법&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;2대의 PC (IP 주소가 다른 2대의 서버 환경) 에 서버를 구동합니다.&lt;/li&gt;
&lt;li&gt;192.168.0.2 와 192.168.0.3 IP 주소를 사용하는 서버가 있다고 가정합니다.&lt;/li&gt;
&lt;li&gt;192.168.0.2 서버의 웹 페이지에 접속해서 AJAX 로 192.168.0.3 서버의 웹 페이지를 접근 하겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;192.168.0.2 (Apache tomcat)&lt;/b&gt;&lt;/h4&gt;
&lt;i&gt;파일 : cors.jsp&lt;/i&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;%@page contentType=&quot;text/html&quot; pageEncoding=&quot;UTF-8&quot;%&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;CORS test&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;style type=&quot;text/css&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #result {border:solid 1px black;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/style&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script type=&quot;text/javascript&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function $(obj) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (obj instanceof String || typeof obj === &quot;string&quot;) ? document.getElementById(obj) : obj;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function getXMLHttpRequest() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (window.ActiveXObject) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (e1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (window.XMLHttpRequest) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new XMLHttpRequest();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function action(url) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ajax = getXMLHttpRequest();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ajax.onreadystatechange = function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (ajax.readyState) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 1:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 2:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 3:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case 4:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ajax.status === 200) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(&quot;result&quot;).innerHTML = ajax.responseText.replace(/&amp;amp;/g, &quot;&amp;amp;amp;&quot;).replace(/&amp;lt;/g, &quot;&amp;amp;lt;&quot;).replace(/&amp;gt;/g, &quot;&amp;amp;gt;&quot;).replace(/\r/g, &quot;&quot;).replace(/\n/g, &quot;&amp;lt;br /&amp;gt;&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(&quot;result&quot;).innerHTML = &quot;AJAX request failed with status code: &quot; + ajax.status;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ajax.open(&quot;GET&quot;, url, true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ajax.send();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;h1&amp;gt;CORS test&amp;lt;/h1&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onclick=&quot;action(&#39;http://192.168.0.3/apps/hello.html&#39;);return false;&quot;&amp;gt;Action&amp;lt;/button&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div id=&quot;result&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;192.168.0.3 (apache + php)&lt;/b&gt;&lt;/h4&gt;
&lt;i&gt;파일 : apps/hello.html&lt;/i&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;header(&#39;Access-Control-Allow-Origin:*&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;?&amp;gt; &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;Hello&amp;lt;/title&amp;gt;&lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;If you get this message via AJAX request, you are allowed to access me.&amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;테스트 결과&lt;/b&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;http://192.168.0.2:8080/MyApp/cors.jsp 에 접속해서 Action 버튼을 누르면 192.168.0.3 서버의 apps/hello.html 파일에 접근해서 해당 내용을 div 에 표시합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihQogHx4VQ9iY4b8TPlOKI0UhmZXibnVzHSUmOoJ_CE2wTTtU6ShwFFBrGjgbyl1fLrqKyROxQVlnN1rKJVr4RUikgkXK-3Taph03TED_2a2iDHokKasWrOrWtOFHDrvjjd-Tw2rUGdw/s1600/cors-ajax-success.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihQogHx4VQ9iY4b8TPlOKI0UhmZXibnVzHSUmOoJ_CE2wTTtU6ShwFFBrGjgbyl1fLrqKyROxQVlnN1rKJVr4RUikgkXK-3Taph03TED_2a2iDHokKasWrOrWtOFHDrvjjd-Tw2rUGdw/s1600/cors-ajax-success.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;192.168.0.3 서버의 apps/hello.html 의 아래 부분을 주석 처리하면 아래와 같이 실패할 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;//header(&#39;Access-Control-Allow-Origin:*&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;?&amp;gt; &lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamyctAEPV_8tfYiTJc1LXwmjYxNA1cI6cwo0kRnBQcV6vXqJW6A7RCOA5ulePM5V5LdfqclzABgqdOpI8LQrLoBkl7EXXZP2jXPJPJ7HOA5DiZdKr-984hacg6DvsKTAGlkYhKZuEcg/s1600/cors-ajax-fail.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamyctAEPV_8tfYiTJc1LXwmjYxNA1cI6cwo0kRnBQcV6vXqJW6A7RCOA5ulePM5V5LdfqclzABgqdOpI8LQrLoBkl7EXXZP2jXPJPJ7HOA5DiZdKr-984hacg6DvsKTAGlkYhKZuEcg/s1600/cors-ajax-fail.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Firefox 로 테스트 하였습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;팁&lt;/b&gt;&lt;br /&gt;
JSP 페이지에 header 를 추가하려면 다음과 같이 할 수 있습니다.&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;%&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; response.addHeader(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;);&lt;br /&gt;%&amp;gt;&lt;/span&gt; </content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/6303611754127791041/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2014/05/cors-cross-origin-resource-sharing.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6303611754127791041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6303611754127791041'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2014/05/cors-cross-origin-resource-sharing.html' title='CORS (Cross-origin resource sharing) 간략한 설명'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihQogHx4VQ9iY4b8TPlOKI0UhmZXibnVzHSUmOoJ_CE2wTTtU6ShwFFBrGjgbyl1fLrqKyROxQVlnN1rKJVr4RUikgkXK-3Taph03TED_2a2iDHokKasWrOrWtOFHDrvjjd-Tw2rUGdw/s72-c/cors-ajax-success.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-553756218952697745</id><published>2013-04-16T01:10:00.000-07:00</published><updated>2013-04-16T01:10:20.696-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache Tomcat"/><category scheme="http://www.blogger.com/atom/ns#" term="JDBC"/><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><title type='text'>[Tomcat] JDBC pool + MySql</title><content type='html'>참고: &lt;a href=&quot;http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html&quot;&gt;http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MySQL JDBC 드라이버&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;다운로드 - &lt;a href=&quot;http://dev.mysql.com/downloads/connector/j/&quot;&gt;http://dev.mysql.com/downloads/connector/j/&lt;/a&gt;&lt;a href=&quot;http://dev.mysql.com/downloads/connector/j/&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;압축을 풀고 jar 파일을 반드시 Tomcat 설치 폴더의 lib 폴더에 복사 한다.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;주의&lt;/b&gt;: 웹 앱 폴더의 WEB-INF/lib 에 복사하면 context.xml 파일에서 설정할 DataSource 객체의 JNDI 등록이 실패할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;참고&lt;/b&gt;: &lt;a href=&quot;http://stackoverflow.com/questions/13161747/jdbc-apache-tomcat-pooling-jar&quot;&gt;http://stackoverflow.com/questions/13161747/jdbc-apache-tomcat-pooling-jar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;결과물 폴더 구조&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;- 테스트용 프로젝트는 결과적으로 아래와 같은 구조를 갖게 된다. &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBhx_jnWoFO0DxixRgyu8t0jqH6S-LzQlLOvF_MWb81FSuAFqd8nWwvEa2wccBTZ3TsL4BtViTHflQRiyyufUaYofDdF9g5SA-txdiA93z4F_tyYol4C6vRV6x3bW45ZNw4I7Srkob6Q/s1600/jdbc-pool-result.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBhx_jnWoFO0DxixRgyu8t0jqH6S-LzQlLOvF_MWb81FSuAFqd8nWwvEa2wccBTZ3TsL4BtViTHflQRiyyufUaYofDdF9g5SA-txdiA93z4F_tyYol4C6vRV6x3bW45ZNw4I7Srkob6Q/s320/jdbc-pool-result.png&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;테스트를 위한 DB 준비 &lt;/b&gt;&lt;br /&gt;
&amp;nbsp;- 테스트용 DB 계정 생성 및 DB Schema 생성&lt;br /&gt;
&lt;pre&gt;C:\&amp;gt; &lt;b&gt;mysql -u root -p&lt;/b&gt;
Enter password: *******

mysql&amp;gt; &lt;b&gt;grant all privileges on *.* to tester@localhost identified by &#39;changeit&#39; with grant option;&lt;/b&gt;
Query OK, 0 rows affected (0.17 sec)

mysql&amp;gt; &lt;b&gt;create database javatest;&lt;/b&gt;
Query OK, 1 row affected (0.00 sec)

mysql&amp;gt; &lt;b&gt;use javatest;&lt;/b&gt;
Database changed

mysql&amp;gt; &lt;b&gt;create table testdata (id int not null auto_increment primary key, foo varchar(25), bar int);&lt;/b&gt;
Query OK, 0 rows affected (0.24 sec)

mysql&amp;gt; &lt;b&gt;insert into testdata values(null, &#39;hello&#39;, 12345);&lt;/b&gt;
Query OK, 1 row affected (0.02 sec)

mysql&amp;gt; &lt;b&gt;select * from testdata;&lt;/b&gt;
+----+-------+-------+
| id | foo   | bar   |
+----+-------+-------+
|  1 | hello | 12345 |
+----+-------+-------+
1 row in set (0.00 sec)
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;web.xml&lt;/b&gt;&lt;br /&gt;
- 테스트용 서블릿 (com.javatest.MySqlTestServlet) 을 등록했다.&lt;br /&gt;
&lt;pre&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
 xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&quot;
 id=&quot;WebApp_ID&quot; version=&quot;3.0&quot;&amp;gt;
 &amp;lt;display-name&amp;gt;TomcatTest&amp;lt;/display-name&amp;gt;

 &amp;lt;servlet&amp;gt;
  &amp;lt;servlet-name&amp;gt;&lt;b&gt;MySqlTestServlet&lt;/b&gt;&amp;lt;/servlet-name&amp;gt;
  &amp;lt;servlet-class&amp;gt;com.javatest.MySqlTestServlet&amp;lt;/servlet-class&amp;gt;
 &amp;lt;/servlet&amp;gt;

 &amp;lt;servlet-mapping&amp;gt;
  &amp;lt;servlet-name&amp;gt;&lt;b&gt;MySqlTestServlet&lt;/b&gt;&amp;lt;/servlet-name&amp;gt;
  &amp;lt;url-pattern&amp;gt;/MySqlTest&amp;lt;/url-pattern&amp;gt;
 &amp;lt;/servlet-mapping&amp;gt;

 &amp;lt;welcome-file-list&amp;gt;
  &amp;lt;welcome-file&amp;gt;redirect.jsp&amp;lt;/welcome-file&amp;gt;
 &amp;lt;/welcome-file-list&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;redirect.jsp&lt;/b&gt;&lt;br /&gt;
- 테스트용 서블릿 (com.javatest.MySqlTestServlet) 으로 redirect 한다.&lt;br /&gt;
&lt;pre&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;%
response.sendRedirect(&quot;&lt;b&gt;MySqlTest&lt;/b&gt;&quot;);
%&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;context.xml 파일&lt;/b&gt;&lt;br /&gt;
- DataSource 를 생성한다.&lt;br /&gt;
&lt;pre&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt;
&amp;lt;Context docBase=&quot;TomcatTest&quot; path=&quot;/TomcatTest&quot; reloadable=&quot;true&quot;&amp;gt;

&amp;lt;Resource name=&quot;&lt;b&gt;jdbc/mySqlDb&lt;/b&gt;&quot;
auth=&quot;Container&quot;
type=&quot;javax.sql.DataSource&quot;
factory=&quot;org.apache.tomcat.jdbc.pool.DataSourceFactory&quot;
testWhileIdle=&quot;true&quot;
testOnBorrow=&quot;true&quot;
testOnReturn=&quot;false&quot;
validationQuery=&quot;SELECT 1&quot;
validationInterval=&quot;30000&quot;
timeBetweenEvictionRunsMillis=&quot;30000&quot;
maxActive=&quot;100&quot; 
minIdle=&quot;10&quot;
maxWait=&quot;10000&quot;
initialSize=&quot;10&quot; 
removeAbandonedTimeout=&quot;60&quot;
removeAbandoned=&quot;true&quot;
logAbandoned=&quot;true&quot;
minEvictableIdleTimeMillis=&quot;30000&quot; 
jmxEnabled=&quot;true&quot;
jdbcInterceptors=&quot;org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer&quot;
loginTimeout=&quot;10&quot;
username=&quot;&lt;b&gt;tester&lt;/b&gt;&quot;
password=&quot;&lt;b&gt;changeit&lt;/b&gt;&quot;
driverClassName=&quot;com.mysql.jdbc.Driver&quot;
url=&quot;jdbc:mysql://localhost:3306/&lt;b&gt;javatest&lt;/b&gt;?autoReconnect=true&quot;
/&amp;gt;

&amp;lt;/Context&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;MySqlTestServlet.java&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;- 테스트용 서블릿 소스 코드 &lt;br /&gt;
&amp;nbsp;- javax.naming.InitialContext 객체를 생성하고 lookup() 함수로 context.xml 파일에서 설정한 DataSource 객체를 얻는다.&lt;br /&gt;
&amp;nbsp;- 나머지는 일반적인 JDBC 사용법과 같다.&lt;br /&gt;
&amp;nbsp;- JDBC pool 을 사용해도 Connection 객체는 close() 를 해주어야 한다.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;gt; 참고: &lt;a href=&quot;http://stackoverflow.com/questions/4938517/closing-jdbc-connections-in-pool&quot;&gt;http://stackoverflow.com/questions/4938517/closing-jdbc-connections-in-pool&lt;/a&gt;&lt;br /&gt;
&lt;pre&gt;package com.javatest;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class MySqlTestServlet extends HttpServlet {

 protected void doGet(HttpServletRequest request,
   HttpServletResponse response) throws ServletException, IOException {

  response.setContentType(&quot;text/plain&quot;);
  PrintWriter writer = response.getWriter();

  Connection conn = null;

  try {

   Context con = new &lt;b&gt;InitialContext&lt;/b&gt;();
   DataSource ds = (DataSource) con
     .lookup(&quot;java:comp/env/&lt;b&gt;jdbc/mySqlDb&lt;/b&gt;&quot;);
   conn = ds.getConnection();

   Statement st = conn.createStatement();
   ResultSet rs = st.executeQuery(&quot;select * from testdata&quot;);
   ResultSetMetaData rsmd = rs.getMetaData();
   int cnt = rsmd.getColumnCount();
   StringBuffer sb = new StringBuffer();
   for (int i = 0; i &amp;lt; cnt; i++) {
    sb.append(String.format(&quot;[%s]\t&quot;, rsmd.getColumnName(i + 1)));
   }
   writer.println(sb.toString());
   writer.println(&quot;=======================================&quot;);
   while (rs.next()) {
    sb = new StringBuffer();
    for (int i = 0; i &amp;lt; cnt; i++) {
     sb.append(String.format(&quot;[%s]\t&quot;, rs.getString(i + 1)));
    }
    writer.println(sb.toString());
   }

   rs.close();
   st.close();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (conn != null)
    try {
     conn.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
  }
 }

}

&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;실행 결과&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;- http://localhost:8080/TomcatTest/MySqlTest&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Fa32PTVDIOGaBXvc2Jb_9eoPG9cg-ePXM-zufrifjtACZcBrFzc05NLwcbK0ioeMbxsnTnBB-rL_pOlscmFYc6Gxov_QxPyynstCRsQfdb0mMp-sQ_IBe1U2nVP0v3_OanPvvK6Hbg/s1600/jdbc-pool-web-browser.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Fa32PTVDIOGaBXvc2Jb_9eoPG9cg-ePXM-zufrifjtACZcBrFzc05NLwcbK0ioeMbxsnTnBB-rL_pOlscmFYc6Gxov_QxPyynstCRsQfdb0mMp-sQ_IBe1U2nVP0v3_OanPvvK6Hbg/s1600/jdbc-pool-web-browser.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/553756218952697745/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2013/04/tomcat-jdbc-pool-mysql.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/553756218952697745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/553756218952697745'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2013/04/tomcat-jdbc-pool-mysql.html' title='[Tomcat] JDBC pool + MySql'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBhx_jnWoFO0DxixRgyu8t0jqH6S-LzQlLOvF_MWb81FSuAFqd8nWwvEa2wccBTZ3TsL4BtViTHflQRiyyufUaYofDdF9g5SA-txdiA93z4F_tyYol4C6vRV6x3bW45ZNw4I7Srkob6Q/s72-c/jdbc-pool-result.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-8857859314419971598</id><published>2013-04-02T04:01:00.000-07:00</published><updated>2013-04-16T00:02:59.168-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache Tomcat"/><category scheme="http://www.blogger.com/atom/ns#" term="JSP/Servlet"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>Tomcat 서버 + Timer 작업 (스케줄 작업)</title><content type='html'>참고: &lt;a href=&quot;http://stackoverflow.com/questions/791986/background-thread-for-a-tomcat-servlet-app&quot;&gt;http://stackoverflow.com/questions/791986/background-thread-for-a-tomcat-servlet-app&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
ServletContextListener 를 이용하여 앱이 시작할 때와 앱이 종료할 때 이벤트를 처리할 수 있다.&lt;br /&gt;
&lt;br /&gt;
앱이 시작할 때 schedule 작업하는 thread 를 시작하고 앱이 종료할 때 thread 를 종료하는 방식을 응용해 봤다.&lt;br /&gt;
&lt;br /&gt;
web.xml 에 우리의 listener 클래스를 등록한다.&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;listener&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listener-class&amp;gt;com.sample.&lt;b&gt;SampleListener&lt;/b&gt;&amp;lt;/listener-class&amp;gt;
&amp;lt;/listener&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
Listener 클래스는 대략 아래와 같다.&lt;br /&gt;
&lt;pre&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;package com.sample;&lt;/span&gt;

&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;SampleListener&lt;/span&gt;&lt;/b&gt; implements ServletContextListener {

&amp;nbsp;&amp;nbsp;&amp;nbsp; private MyThread myThread = null;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * 앱 시작시 불리는 함수&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void contextInitialized(ServletContextEvent sce) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((myThread == null) || (!myThread.isAlive())) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; myThread = new &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;MyThread&lt;/span&gt;(new MyTask());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; myThread.start();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * 앱 종료시 불리는 함수&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp; public void contextDestroyed(ServletContextEvent sce){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;myThread != null &amp;amp;&amp;amp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;myThread.isAlive()) &lt;/span&gt;&lt;/span&gt;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; myThread.quit();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
실제 작업하는 스레드는 TimerTask 를 등록하고 작업이 진행되는 동안 대기하는 일을 한다.&lt;br /&gt;
예) 매분마다 특정 파일(backup.bat) 을 실행한다.&lt;br /&gt;
&lt;pre&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;/**&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;* 실제 작업하는 클래스&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;*/ &lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;public static class &lt;b&gt;MyTask&lt;/b&gt; extends TimerTask {

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void run() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ProcessBuilder builder = new ProcessBuilder(&quot;c:\\bin\\backup.bat&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Process p = builder.start();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; InputStream in = p.getInputStream();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; while (in.read() != -1) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.sleep(10);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; p.waitFor();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (IOException e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.printStackTrace();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (InterruptedException e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.printStackTrace();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/span&gt;

&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;/**&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;* 앱이 실행되는 동안 작업을 기다리는 스레드&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;*/
public static class &lt;b&gt;MyThread&lt;/b&gt; extends Thread {
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; private boolean done = false;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private Timer timer;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private TimerTask task;
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; public MyThread (TimerTask task) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.task = task;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void quit() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.done = true;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.interrupt();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean finishing() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return (done || Thread.interrupted());
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void run() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; super.run();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; timer = new Timer();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Calendar now = Calendar.getInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; timer.scheduleAtFixedRate(task, now.getTime(), 1000 * 60);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; while (!finishing()) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.sleep(10);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (InterruptedException e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; timer.cancel();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/8857859314419971598/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2013/04/tomcat-timer.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8857859314419971598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8857859314419971598'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2013/04/tomcat-timer.html' title='Tomcat 서버 + Timer 작업 (스케줄 작업)'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-252319687885025449</id><published>2013-01-13T04:36:00.000-08:00</published><updated>2013-01-13T04:36:29.294-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="servlet 3.0"/><category scheme="http://www.blogger.com/atom/ns#" term="문제 해결"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>@WebServlet annotation with Tomcat 7 and 404 error</title><content type='html'>@WebSerlvet annotation 을 사용해서 servlet 을 정의했지만 404 에러가 발생했다.&lt;br /&gt;
문제는 web.xml 파일에 metadata-complete 를 true 로 설정했기 때문이었다.&lt;br /&gt;
&lt;br /&gt;
아래와 같이 metatdata-complete 를 false 로 설정해야 했다.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;div style=&quot;color: #3933ff; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: #009193;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #4e9192;&quot;&gt;web-app&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #932192;&quot;&gt;xmlns:xsi&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;=&lt;/span&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/div&gt;
&lt;div style=&quot;color: #3933ff; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: black;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #932192;&quot;&gt;xmlns&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;=&lt;/span&gt;&quot;http://java.sun.com/xml/ns/javaee&quot;&lt;/div&gt;
&lt;div style=&quot;color: #3933ff; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: black;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #932192;&quot;&gt;xsi:schemaLocation&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;=&lt;/span&gt;&quot;http://java.sun.com/xml/ns/javaee&lt;/div&gt;
&lt;div style=&quot;color: #3933ff; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;      &lt;/span&gt;http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&quot;&lt;/div&gt;
&lt;div style=&quot;color: #932192; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: black;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;metadata-complete&lt;span style=&quot;color: black;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #3933ff;&quot;&gt;&quot;false&quot;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;color: #932192; font-family: Monaco; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: black;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;version&lt;span style=&quot;color: black;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #3933ff;&quot;&gt;&quot;3.0&quot;&lt;/span&gt;&lt;span style=&quot;color: #009193;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
!) eclipse 에서 프로젝트를 clean 하고 다시 build 해야 할 수도 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
참고:&amp;nbsp;&lt;a href=&quot;http://www.coderanch.com/t/548158/Tomcat/WebServlet-annotation-working-Tomcat&quot;&gt;http://www.coderanch.com/t/548158/Tomcat/WebServlet-annotation-working-Tomcat&lt;/a&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/252319687885025449/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2013/01/webservlet-annotation-with-tomcat-7-and.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/252319687885025449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/252319687885025449'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2013/01/webservlet-annotation-with-tomcat-7-and.html' title='@WebServlet annotation with Tomcat 7 and 404 error'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-7930699049132071790</id><published>2012-12-04T20:19:00.000-08:00</published><updated>2012-12-04T20:19:05.284-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="도구"/><title type='text'>Color</title><content type='html'>&lt;script type=&quot;text/javascript&quot;&gt;

var Color = {
r : 0,
g : 0,
b : 0,

$ : function(elt) {return (typeof elt == &#39;string&#39;) ? document.getElementById(elt) : elt;},

onColorChange : function(col, val, updateCb) {
this[col] = val;
updateCb();
},

rgbStyle : function() {
return &quot;rgb(&quot; + this.r + &quot;,&quot; + this.g + &quot;,&quot; + this.b + &quot;)&quot;;
},

toHex : function(num) {
return new Number(num).toString(16).toUpperCase();
},

pad : function(val, pad, len) {
var ret = &quot;&quot;;
if (val.length &lt; len) {
for (var i = 0, li = len - val.length; i &lt; li; i++) {
ret += pad;
}
}
ret += val;
return ret;
}

}

var Post20121215 = {
update : function() {
Color.$(&quot;ret&quot;).style.backgroundColor = Color.rgbStyle();
Color.$(&quot;rgbhex&quot;).innerHTML = &#39;#&#39; + Color.pad(Color.toHex(Color.r), &#39;0&#39;, 2) + 
Color.pad(Color.toHex(Color.g), &#39;0&#39;, 2) + Color.pad(Color.toHex(Color.b), &#39;0&#39;, 2);
Color.$(&quot;rval&quot;).innerHTML = Color.r;
Color.$(&quot;gval&quot;).innerHTML = Color.g;
Color.$(&quot;bval&quot;).innerHTML = Color.b;
}
};

&lt;/script&gt;

&lt;div id=&quot;ret&quot; style=&quot;width:100px;height:100px;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
R &lt;input type=&quot;range&quot; id=&quot;r&quot; max=&quot;255&quot; min=&quot;0&quot; value=&quot;0&quot; onchange=&quot;Color.onColorChange(&#39;r&#39;, this.value, Post20121215.update);&quot; /&gt;&lt;span id=&quot;rval&quot;&gt;&lt;/span&gt;&lt;br /&gt;
G &lt;input type=&quot;range&quot; id=&quot;g&quot; max=&quot;255&quot; min=&quot;0&quot; value=&quot;0&quot; onchange=&quot;Color.onColorChange(&#39;g&#39;, this.value, Post20121215.update);&quot; /&gt;&lt;span id=&quot;gval&quot;&gt;&lt;/span&gt;&lt;br /&gt;
B &lt;input type=&quot;range&quot; id=&quot;b&quot; max=&quot;255&quot; min=&quot;0&quot; value=&quot;0&quot; onchange=&quot;Color.onColorChange(&#39;b&#39;, this.value, Post20121215.update);&quot; /&gt;&lt;span id=&quot;bval&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span id=&quot;rgbhex&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;script type=&quot;text/javascript&quot;&gt;
Post20121215.update();
&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/7930699049132071790/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/12/color.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7930699049132071790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7930699049132071790'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/12/color.html' title='Color'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-8759485452933528315</id><published>2012-11-02T20:51:00.000-07:00</published><updated>2012-11-02T21:16:24.505-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache Tomcat"/><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="문제 해결"/><title type='text'>HttpServletRequest 의 getServletContext() 함수 사용 문제</title><content type='html'>참고:&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions/7860782/request-getservletcontext-not-found-even-with-new-jar&quot;&gt;http://stackoverflow.com/questions/7860782/request-getservletcontext-not-found-even-with-new-jar&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
JSP 페이지에서&amp;nbsp;request.getServletContext() 사용시 아래와 같은 에러가 발생했다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;The method getServletContext() is undefined for the type HttpServletRequest&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Tomcat 7 에서는 문제가 되지 않았지만 tomcat6 에서는 문제가 되었다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;!)&lt;/b&gt; 원인은 HttpServletRequest 의 getServletContext() 함수는 Servlet 3.0 부터 지원되기 때문이었다. Tomcat7 부터 Servlet 3.0 을 지원한다.&lt;br /&gt;
&lt;br /&gt;
그냥 getServletContext() 함수를 부르면 Tomcat 6 와 Tomcat 7 에서도 에러가 발생하지 않았다.&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;lt;%= getServletContext().gerRealPath(&quot;/&quot;) %&amp;gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/8759485452933528315/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/11/httpservletrequest-getservletcontext.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8759485452933528315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8759485452933528315'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/11/httpservletrequest-getservletcontext.html' title='HttpServletRequest 의 getServletContext() 함수 사용 문제'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-2458400434128282897</id><published>2012-10-12T01:22:00.001-07:00</published><updated>2012-10-12T01:22:21.386-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>[JSP] getOutputStream() has already been called for this response 문제</title><content type='html'>&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;참고:&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://kr.forums.oracle.com/forums/thread.jspa?threadID=452123&quot;&gt;https://kr.forums.oracle.com/forums/thread.jspa?threadID=452123&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;jsp 파일에서 response.getOutputStream() 을 부르는 경우 아래와 같은 Exception 이 발생할 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;text-align: -webkit-auto;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;getOutputStream() has already been called for this response&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma; text-align: -webkit-auto;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma; text-align: -webkit-auto;&quot;&gt;이유는 하나의 jsp 파일에서 getWriter() 와 getOutputStream() 를 동시에 부를 수는 없기 때문이다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma; text-align: -webkit-auto;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;getWriter() 함수는 jsp 내부적으로 html 을 렌더링 할 때 호출 된다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;&amp;nbsp;- Tomcat 서버의 경우 만약에 개행 문자없이 오로지 java 코드 파트로만 구성된 jsp 라면 getOutputStream() 함수를 사용할 수 있었다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;&amp;nbsp;- 하지만 서버 마다 다를 수 있으므로 확인해 봐야 할 것이다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Tahoma;&quot;&gt;!) 개행 문자를 아래와 같이 주석을 이용하여 제거하는 방법도 생각해 볼 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;lt;% ... %&amp;gt;&lt;b&gt;&lt;span style=&quot;color: #3d85c6;&quot;&gt;&amp;lt;%--&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #3d85c6;&quot;&gt;--%&amp;gt;&lt;/span&gt;&lt;/b&gt;&amp;lt;%&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/2458400434128282897/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/10/jsp-getoutputstream-has-already-been.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/2458400434128282897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/2458400434128282897'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/10/jsp-getoutputstream-has-already-been.html' title='[JSP] getOutputStream() has already been called for this response 문제'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-7670300726220134522</id><published>2012-10-06T22:16:00.005-07:00</published><updated>2012-10-07T00:28:23.556-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mac"/><category scheme="http://www.blogger.com/atom/ns#" term="서버 구축"/><title type='text'>Mac OS Mountain Lion + apache</title><content type='html'>Mountain Lion 부터는 웹 공유 옵션이 없어졌다.&lt;br /&gt;
참고 :&amp;nbsp;&lt;a href=&quot;http://support.apple.com/kb/HT5230&quot;&gt;http://support.apple.com/kb/HT5230&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
하지만 apache 서버가 이미 OS 에 포함이 되어 있다.&lt;br /&gt;
&lt;br /&gt;
참고:&amp;nbsp;&lt;a href=&quot;http://coolestguyplanettech.com/downtown/install-and-configure-apache-mysql-php-and-phpmyadmin-osx-108-mountain-lion&quot;&gt;http://coolestguyplanettech.com/downtown/install-and-configure-apache-mysql-php-and-phpmyadmin-osx-108-mountain-lion&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
terminal 을 열고 아래 명령을 통해 apache 서버를 실행할 수 있다.&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;$ sudo apachectl start&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
설정 파일은 아래 위치에 있다.&lt;br /&gt;
/etc/apache2&lt;br /&gt;
&lt;br /&gt;
기본 document 경로는 다음과 같다.&lt;br /&gt;
/Library/WebServer/Documents/&lt;br /&gt;
&lt;br /&gt;
기존에 웹 공유를 사용했다면 /Users/사용자아이디/Sites 에 폴더가 지정이 되었을 것이다.&lt;br /&gt;
/etc/apache2/users/ 디렉토리에 사용자아이디.conf 파일을 생성하고 아래와 같이 저장한다.&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;lt;Directory &quot;/Users/사용자아이디/Sites/&quot;&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Options Indexes MultiViews&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;AllowOverride All&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Order allow,deny&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Allow from all&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
그리고 아파치를 재실행한다.&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;$ sudo apachectl restart&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
웹브라우저로 접속해 보자.&lt;br /&gt;
http://localhost:80/~사용자아이디</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/7670300726220134522/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/10/mac-os-mountain-lion-apache.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7670300726220134522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7670300726220134522'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/10/mac-os-mountain-lion-apache.html' title='Mac OS Mountain Lion + apache'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-6663011392088940066</id><published>2012-08-02T05:17:00.001-07:00</published><updated>2012-08-02T05:17:48.294-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>[HTML] input 태그 disabled &amp; readonly 속성</title><content type='html'>input tag 에 disabled 속성을 줄 수 있다.&lt;br /&gt;
disabled=&quot;disabled&quot;&lt;br /&gt;
&lt;br /&gt;
disabled 속성을 주게 되면 form submit 할 때 해당 값은 아예 보내지 않게 된다.&lt;br /&gt;
&lt;br /&gt;
input tag 에 readonly 속성을 아래와 같이 줄 수 있다.&lt;br /&gt;
readonly=&quot;readonly&quot;&lt;br /&gt;
&lt;br /&gt;
form submit 할 때는 값이 포함되고 사용자의 조작을 막을 수 있다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!) 만약 사용자의 조작을 막고 비활성화된 모습을 보여주고 싶다면 readonly 속성을 지정하고 style 을 지정하는 방법을 사용하자.</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/6663011392088940066/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/08/html-input-disabled-readonly.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6663011392088940066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6663011392088940066'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/08/html-input-disabled-readonly.html' title='[HTML] input 태그 disabled &amp; readonly 속성'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-8449270552123024755</id><published>2012-08-02T05:12:00.000-07:00</published><updated>2012-08-02T05:12:28.828-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="MyBatis"/><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><title type='text'>MyBatis + Software caused connection abort: recv failed</title><content type='html'>참고:&amp;nbsp;&lt;a href=&quot;http://linuxism.tistory.com/580&quot;&gt;http://linuxism.tistory.com/580&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
서버를 실행하고 오래 접속을 하지 않으면 아래 와 같은 에러가 발생할 수 있다.&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;Software caused connection abort: recv failed&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
바로 다시 접속하면 연결이 되기는 하지만 신경이 쓰이는 부분이다.&lt;br /&gt;
&lt;br /&gt;
DB 와 연결하고 오래 사용하지 않으면 연결이 끊긴다. 그래서 주기적으로 아주 간단한 query 를 날려 줄 필요가 있다.&lt;br /&gt;
&lt;br /&gt;
아래와 같이 설정 하였다.&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;environments default=&quot;development&quot;&amp;gt;
 &amp;lt;environment id=&quot;development&quot;&amp;gt;
  &amp;lt;transactionManager type=&quot;JDBC&quot;/&amp;gt;
  &amp;lt;dataSource type=&quot;POOLED&quot;&amp;gt;
   &amp;lt;property name=&quot;driver&quot; value=&quot;${jdbc.driver}&quot;/&amp;gt;
   &amp;lt;property name=&quot;url&quot; value=&quot;${jdbc.url}&quot;/&amp;gt;
   &amp;lt;property name=&quot;username&quot; value=&quot;${jdbc.username}&quot;/&amp;gt;
   &amp;lt;property name=&quot;password&quot; value=&quot;${jdbc.password}&quot;/&amp;gt;
   &amp;lt;!-- Pool ping setting : http://linuxism.tistory.com/580 --&amp;gt;
   &amp;lt;property name=&quot;poolMaximumActiveConnections&quot; value=&quot;20&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolMaximumIdleConnections&quot; value=&quot;20&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolMaximumCheckoutTime&quot; value=&quot;20000&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolPingEnabled&quot; value=&quot;true&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolPingQuery&quot; value=&quot;select 1&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolPingConnectionsNotUsedFor&quot; value=&quot;43200&quot;/&amp;gt;
   &amp;lt;property name=&quot;poolTimeToWait&quot; value=&quot;30000&quot;/&amp;gt;
   &amp;lt;property name=&quot;driver.encoding&quot; value=&quot;UTF-8&quot;/&amp;gt;
  &amp;lt;/dataSource&amp;gt;
 &amp;lt;/environment&amp;gt;

...

&lt;/pre&gt;
poolPingEnabled 를 true 로 설정한다.&lt;br /&gt;
poolPingQuery 는 select 1 과 같은 아주 간단한 query 로 설정한다.&lt;br /&gt;
poolPingConnectionsNotUsedFor 에 지정한 시간 만큼 사용하지 않으면 ping query 를 날린다. (millisecond 단위)</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/8449270552123024755/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/08/mybatis-software-caused-connection.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8449270552123024755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8449270552123024755'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/08/mybatis-software-caused-connection.html' title='MyBatis + Software caused connection abort: recv failed'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-7856089101991221093</id><published>2012-07-20T10:07:00.000-07:00</published><updated>2012-07-24T03:25:07.603-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="MyBatis"/><title type='text'>JSP + MyBatis + MySql 샘플</title><content type='html'>참고:&amp;nbsp;&lt;a href=&quot;http://www.mybatis.org/core/ko/index.html&quot;&gt;http://www.mybatis.org/core/ko/index.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
아래 순서로 설명.&lt;br /&gt;
&lt;div style=&quot;border: solid 1px black; padding: 4px;&quot;&gt;
1. MySql DB 구축&lt;br /&gt;
2. 웹앱 생성&lt;br /&gt;
3. MyBatis 설정&lt;br /&gt;
&amp;nbsp; 3.1. 필요한 라이브러리 설치&lt;br /&gt;
&amp;nbsp; 3.2. 환경 설정&lt;br /&gt;
&amp;nbsp; 3.3. 맵퍼 생성&lt;br /&gt;
&amp;nbsp; 3.4. JSP 연동&lt;br /&gt;
4. 웹 페이지 생성&lt;br /&gt;
5. 테스트&lt;/div&gt;
&lt;br /&gt;
최종 폴더 구조:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzcqhmFzUwa3gKv-61yLeYSkPNHfrnxQJPL9pbv3bCwe1EP-jJAEel2KWM7jGic6OZItoNLS1JrJZgpsC4TagXY6To1H-1uyYhmdnUqHJ6enKJ6WZc4FfYOnBafkRnO_c9efgweXx7lQ/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+1.17.33.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzcqhmFzUwa3gKv-61yLeYSkPNHfrnxQJPL9pbv3bCwe1EP-jJAEel2KWM7jGic6OZItoNLS1JrJZgpsC4TagXY6To1H-1uyYhmdnUqHJ6enKJ6WZc4FfYOnBafkRnO_c9efgweXx7lQ/s640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+1.17.33.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;1. MySql DB 구축&lt;/b&gt;&lt;br /&gt;
- 테스트용 계정을 아래와 같이 설정했다.&lt;br /&gt;
User name : &quot;username&quot;&lt;br /&gt;
Password : &quot;password&quot;&lt;br /&gt;
&lt;br /&gt;
1) test 스키마를 생성한다.&lt;br /&gt;
&lt;pre&gt;mysql&amp;gt; create schema test;
&lt;/pre&gt;
&lt;br /&gt;
2) users 테이블을 생성한다.&lt;br /&gt;
&lt;pre&gt;mysql&amp;gt; use test;

mysql&amp;gt;&amp;nbsp;create table users (
`username` varchar(255) not null,
`password` varchar(255) not null,
`email` varchar(255) not null,
primary key (`username`)
) default charset=utf8;
&lt;/pre&gt;
&lt;div class=&quot;p2&quot;&gt;
&lt;br /&gt;
3)&lt;span style=&quot;background-color: white;&quot;&gt;&amp;nbsp;user 를 생성한다.&lt;/span&gt;&lt;/div&gt;
&lt;pre&gt;mysql&amp;gt; create user &#39;username&#39;@&#39;localhost&#39; identified by &#39;password&#39;;
&lt;/pre&gt;
&lt;div class=&quot;p2&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p2&quot;&gt;
4) test 스키마에 대한 권한을 설정한다.&lt;/div&gt;
&lt;pre&gt;mysql&amp;gt; grant all privileges on test.* to &#39;username&#39;@&#39;locahost&#39;;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;2. 웹앱 생성&lt;/b&gt;&lt;br /&gt;
- 폴더 구조&lt;br /&gt;
&lt;pre style=&quot;border: solid 1px black; padding: 4px;&quot;&gt;+ $WEB_APP/
&amp;nbsp; + WEB-INF/
&amp;nbsp; &amp;nbsp; + libs/
&amp;nbsp; &amp;nbsp; - web.xml
&amp;nbsp; + index.jsp
&lt;/pre&gt;
&lt;br /&gt;
web.xml 소스:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
 xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&quot;
 metadata-complete=&quot;true&quot; version=&quot;3.0&quot;&amp;gt;
 
 &amp;lt;welcome-file-list&amp;gt;
 &amp;lt;welcome-file&amp;gt;index.jsp&amp;lt;/welcome-file&amp;gt;
 &amp;lt;/welcome-file-list&amp;gt;
 
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;3. MyBatis 설정&lt;/b&gt;&lt;br /&gt;
3.1. 필요한 라이브러리 설치&lt;br /&gt;
- 다운로드&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;MySql JDBC driver 다운로드 :&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://www.mysql.com/downloads/connector/j/&quot; style=&quot;background-color: white;&quot;&gt;http://www.mysql.com/downloads/connector/j/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;MyBatis 다운로드 :&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://code.google.com/p/mybatis/downloads/list?can=3&amp;amp;q=Product%3DMyBatis&quot; style=&quot;background-color: white;&quot;&gt;http://code.google.com/p/mybatis/downloads/list?can=3&amp;amp;q=Product%3DMyBatis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;commons dbcp 다운로드:&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://commons.apache.org/dbcp/&quot; style=&quot;background-color: white;&quot;&gt;http://commons.apache.org/dbcp/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;commons pool 다운로드:&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://commons.apache.org/pool/&quot; style=&quot;background-color: white;&quot;&gt;http://commons.apache.org/pool/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
- 위 파일들을 다운로드 받아 $WEB_APP/WEB-INF/libs/ 에 복사한다.&lt;br /&gt;
!) MyBatis 폴더에 lib 폴더에 있는 파일들도 복사한다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;asm-3.3.1.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;cglib-2.2.2.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;commons-dbcp-1.4.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;commons-logging-1.1.1.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;commons-pool-1.6.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;log4j-1.2.16.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;mybatis-3.1.1.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;mysql-connector-java-5.1.20-bin.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;slf4j-api-1.6.2.jar&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;slf4j-log4j12-1.6.2.jar&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;3.2. 환경 설정&lt;/span&gt;&lt;br /&gt;
- mybatis 설정 파일인 mybatis-config.xml 파일을 생성한다.(파일 이름은 중요하지 않다)&lt;br /&gt;
!) com.sample.mybatis.config 패키지에 생성하였다.&lt;br /&gt;
!) 파일 내용: JDBC 설정만 들어 있다.&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE configuration
PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;
&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;&amp;gt;

&amp;lt;configuration&amp;gt;
 
 &amp;lt;environments default=&quot;development&quot;&amp;gt;
  &amp;lt;environment id=&quot;development&quot;&amp;gt;
   &amp;lt;transactionManager type=&quot;JDBC&quot;/&amp;gt;
   &amp;lt;dataSource type=&quot;POOLED&quot;&amp;gt;
    &amp;lt;property name=&quot;driver&quot; value=&quot;com.mysql.jdbc.Driver&quot;/&amp;gt;
    &amp;lt;property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost:3306/test&quot;/&amp;gt;
    &amp;lt;property name=&quot;username&quot; value=&quot;username&quot;/&amp;gt;
    &amp;lt;property name=&quot;password&quot; value=&quot;password&quot;/&amp;gt;
   &amp;lt;/dataSource&amp;gt;
  &amp;lt;/environment&amp;gt;
 &amp;lt;/environments&amp;gt;

&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
3.3. 맵퍼 생성&lt;br /&gt;
- 필요한 파일들&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;User.java - 레코드 아이템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;UserMapper.java - SQL 문 수행을 위한 인터페이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;UserMap.xml - SQL 문 맵퍼&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&amp;nbsp;- 소스 코드들&lt;br /&gt;
com.sample.mybatis.dto.User.java:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;package com.sample.mybatis.dto;

public class User {
 private String username;
 private String password;
 private String email;
 
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}
&lt;/pre&gt;
com.sample.mybatis.dao.UserMapper.java:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;package com.sample.mybatis.dao;

import java.util.List;

import com.sample.mybatis.dto.User;

public interface UserMapper {
 public List&amp;lt;User&amp;gt; selectAllUsers();
 public User selectUser(String username);
 public void insertUser(User user);
 public void updateUser(User user);
 public void deleteUser(String username);
}
&lt;/pre&gt;
com.sample.mybatis.sqlmap.UserMap.xml:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE mapper PUBLIC &quot;-//ibatis.apache.org//DTD Mapper 3.0//EN&quot; &quot;http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd&quot;&amp;gt;

&amp;lt;mapper namespace=&quot;com.sample.mybatis.dao.UserMapper&quot;&amp;gt;

&amp;lt;select id=&quot;selectAllUsers&quot; resultType=&quot;User&quot;&amp;gt;
 select username as username,
  password as password,
  email as email
 from users;
&amp;lt;/select&amp;gt;

&amp;lt;select id=&quot;selectUser&quot; parameterType=&quot;string&quot; resultType=&quot;User&quot;&amp;gt;
 select username as username,
  password as password,
  email as email
 from users
 where username=#{username};
&amp;lt;/select&amp;gt;

&amp;lt;insert id=&quot;insertUser&quot; parameterType=&quot;User&quot;&amp;gt;
 insert into users (username, password, email)
  values (#{username}, #{password}, #{email});
&amp;lt;/insert&amp;gt;

&amp;lt;update id=&quot;updateUser&quot; parameterType=&quot;User&quot;&amp;gt;
 update users set
  password=#{password},
  email=#{email}
 where username=#{username}
&amp;lt;/update&amp;gt;

&amp;lt;delete id=&quot;deleteUser&quot; parameterType=&quot;string&quot;&amp;gt;
 delete from users
  where username=#{username}
&amp;lt;/delete&amp;gt;

&amp;lt;/mapper&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
- mybatis-config.xml 에 추가&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE configuration
PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;
&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;&amp;gt;

&amp;lt;configuration&amp;gt;

 &amp;lt;!-- Type alias --&amp;gt;
 &amp;lt;typeAliases&amp;gt;
  &amp;lt;typeAlias alias=&quot;User&quot; type=&quot;com.sample.mybatis.dto.User&quot;/&amp;gt;
 &amp;lt;/typeAliases&amp;gt;
 
 &amp;lt;environments default=&quot;development&quot;&amp;gt;
  &amp;lt;environment id=&quot;development&quot;&amp;gt;
   &amp;lt;transactionManager type=&quot;JDBC&quot;/&amp;gt;
   &amp;lt;dataSource type=&quot;POOLED&quot;&amp;gt;
    &amp;lt;property name=&quot;driver&quot; value=&quot;com.mysql.jdbc.Driver&quot;/&amp;gt;
    &amp;lt;property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost:3306/test&quot;/&amp;gt;
    &amp;lt;property name=&quot;username&quot; value=&quot;username&quot;/&amp;gt;
    &amp;lt;property name=&quot;password&quot; value=&quot;password&quot;/&amp;gt;
   &amp;lt;/dataSource&amp;gt;
  &amp;lt;/environment&amp;gt;
 &amp;lt;/environments&amp;gt;

 &amp;lt;!-- UserMap.xml 등록 --&amp;gt;
 &amp;lt;mappers&amp;gt;
  &amp;lt;mapper resource=&quot;com/sample/mybatis/sqlmap/UserMap.xml&quot; /&amp;gt;
 &amp;lt;/mappers&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
3.4. JSP 연동&lt;br /&gt;
- 서버 시작시에 SqlSessionFactory 를 생성해야 한다.&lt;br /&gt;
- SqlSessionFactory 를 생성하는 서블릿을 생성한다.&lt;br /&gt;
&lt;br /&gt;
com.sample.mybatis.config.MyBatisConfig.java : 서버 시작시 init 함수가 실행된다.&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;package com.sample.mybatis.config;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServlet;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisConfig extends HttpServlet {
 
 private static SqlSessionFactory sqlSessionFactory;
 
 public void init() {
  
  try {
   InputStream inputStream = Resources.getResourceAsStream(&quot;com/sample/mybatis/config/mybatis-config.xml&quot;);
   sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 public static SqlSessionFactory getSqlSessionFactory() {
  return sqlSessionFactory;
 }

 public static void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
  MyBatisConfig.sqlSessionFactory = sqlSessionFactory;
 }
}

&lt;/pre&gt;
&lt;br /&gt;
- web.xml 설정 : load-on-startup 을 설정해 줘야 한다.&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
 xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&quot;
 metadata-complete=&quot;true&quot; version=&quot;3.0&quot;&amp;gt;
 
 &amp;lt;!-- MyBatis initializer 등록 --&amp;gt;
 &amp;lt;servlet&amp;gt;
 &amp;lt;servlet-name&amp;gt;MyBatisInitializer&amp;lt;/servlet-name&amp;gt;
 &amp;lt;servlet-class&amp;gt;com.sample.mybatis.config.MyBatisConfig&amp;lt;/servlet-class&amp;gt;
 
 &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
 &amp;lt;/servlet&amp;gt;
 
 &amp;lt;welcome-file-list&amp;gt;
 &amp;lt;welcome-file&amp;gt;index.jsp&amp;lt;/welcome-file&amp;gt;
 &amp;lt;/welcome-file-list&amp;gt;
 
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;4. 웹 페이지 생성&lt;/b&gt;&lt;br /&gt;
- User 레코드 생성, 수정, 삭제 할 수 있는 페이지 (validation 미포함)&lt;br /&gt;
&lt;br /&gt;
user_control.jsp :
&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;%@ page import=&quot;com.sample.mybatis.config.MyBatisConfig&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;com.sample.mybatis.dao.*&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;com.sample.mybatis.dto.*&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;org.apache.ibatis.session.*&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;java.util.*&quot; %&amp;gt;

&amp;lt;%

// handle operation

if (request.getMethod().equalsIgnoreCase(&quot;POST&quot;)) {
 
 SqlSession sqlSession = MyBatisConfig.getSqlSessionFactory().openSession(true);
 try {
  UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 
  String subtype = request.getParameter(&quot;subtype&quot;);
  if (subtype.equals(&quot;create-user&quot;)) {
   User user = new User();
   user.setUsername(request.getParameter(&quot;username&quot;));
   user.setPassword(request.getParameter(&quot;password&quot;));
   user.setEmail(request.getParameter(&quot;email&quot;));
   userMapper.insertUser(user);
  } else if (subtype.equals(&quot;modify-user&quot;)) {
   User user = new User();
   user.setUsername(request.getParameter(&quot;username&quot;));
   user.setPassword(request.getParameter(&quot;password&quot;));
   user.setEmail(request.getParameter(&quot;email&quot;));
   userMapper.updateUser(user);
  } else if (subtype.equals(&quot;delete-user&quot;)) {
   userMapper.deleteUser(request.getParameter(&quot;username&quot;));
  }
 } finally {
  sqlSession.close();
 }
}

// select users
List&amp;lt;User&amp;gt; users = null;

SqlSession sqlSession = MyBatisConfig.getSqlSessionFactory().openSession(true);
try {
 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 
 users = userMapper.selectAllUsers();
 
} finally {
 sqlSession.close();
}
%&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;User Control&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;h2&amp;gt;Create User&amp;lt;/h2&amp;gt;
&amp;lt;form name=&quot;create-form&quot; method=&quot;post&quot;&amp;gt;
&amp;lt;input type=&quot;hidden&quot; name=&quot;subtype&quot; value=&quot;create-user&quot; /&amp;gt;
Username: &amp;lt;input type=&quot;text&quot; name=&quot;username&quot; value=&quot;&quot; /&amp;gt;&amp;lt;br /&amp;gt;
Password: &amp;lt;input type=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot; /&amp;gt;&amp;lt;br /&amp;gt;
Email: &amp;lt;input type=&quot;email&quot; name=&quot;email&quot; value=&quot;&quot; /&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;input type=&quot;submit&quot; value=&quot;Create&quot; /&amp;gt;
&amp;lt;/form&amp;gt;

&amp;lt;h2&amp;gt;User List&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;%
if (users == null || users.size() == 0) {
 %&amp;gt;&amp;lt;li&amp;gt;no user&amp;lt;/li&amp;gt;&amp;lt;%
} else {
 for (User user : users) {
%&amp;gt;
 &amp;lt;li style=&quot;border:solid 1px black;padding:4px;margin-bottom:5px;&quot;&amp;gt;
 &amp;lt;form name=&quot;modify-form&quot; method=&quot;post&quot;&amp;gt;
 &amp;lt;input type=&quot;hidden&quot; name=&quot;subtype&quot; value=&quot;modify-user&quot; /&amp;gt;
 &amp;lt;input type=&quot;hidden&quot; name=&quot;username&quot; value=&quot;&amp;lt;%= user.getUsername() %&amp;gt;&quot; /&amp;gt;
 Username: &amp;lt;%= user.getUsername() %&amp;gt;&amp;lt;br /&amp;gt;
 Password: &amp;lt;input type=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot; /&amp;gt;&amp;lt;br /&amp;gt;
 Email: &amp;lt;input type=&quot;text&quot; name=&quot;email&quot; value=&quot;&amp;lt;%= user.getEmail() %&amp;gt;&quot; /&amp;gt;&amp;lt;br /&amp;gt;
 &amp;lt;input type=&quot;submit&quot; value=&quot;Modify&quot; /&amp;gt;
 &amp;lt;/form&amp;gt;
 &amp;lt;form name=&quot;delete-form&quot; method=&quot;post&quot;&amp;gt;
 &amp;lt;input type=&quot;hidden&quot; name=&quot;subtype&quot; value=&quot;delete-user&quot; /&amp;gt;
 &amp;lt;input type=&quot;hidden&quot; name=&quot;username&quot; value=&quot;&amp;lt;%= user.getUsername() %&amp;gt;&quot; /&amp;gt;
 &amp;lt;input type=&quot;submit&quot; value=&quot;Delete&quot; /&amp;gt;
 &amp;lt;/form&amp;gt;
 &amp;lt;/li&amp;gt;
&amp;lt;%
 }
}
%&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
!) SqlSessionFactory.openSession() 함수에 true 를 인자로 주면 작업이 끝나면 자동으로 commit 한다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;5. 테스트&lt;/b&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNq6dnGH8XbpzrrE7Y7XL36kYiqyGze4uOCet1dCjXm4dA8bQ8XYAbGbcjgVNSheqm4sw46HRMFflEJL3BOmxGyeFFL_a0M2DhXrtEC2Ae99JZ0uRIr80RecqKveL4zraAa2TqhfCzRQ/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;408&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNq6dnGH8XbpzrrE7Y7XL36kYiqyGze4uOCet1dCjXm4dA8bQ8XYAbGbcjgVNSheqm4sw46HRMFflEJL3BOmxGyeFFL_a0M2DhXrtEC2Ae99JZ0uRIr80RecqKveL4zraAa2TqhfCzRQ/s640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.08.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvpBivse9fYbTNtaJ92eGe4P9hWCQb8Z0Ve0ohDfWQzU1TgPfeGGfHX9VtRyeRPb70Cw7DQRl1vwNW3ttaeq2hhuQNCEB54kDrKJ_wgejcYIUjqDwhcio1ln6ZAbb7k_oo6qyX8u5M7w/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.20.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;408&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvpBivse9fYbTNtaJ92eGe4P9hWCQb8Z0Ve0ohDfWQzU1TgPfeGGfHX9VtRyeRPb70Cw7DQRl1vwNW3ttaeq2hhuQNCEB54kDrKJ_wgejcYIUjqDwhcio1ln6ZAbb7k_oo6qyX8u5M7w/s640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.20.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWzvC2sj_g3rX7Ao8BjqD-hd1YyD2B5xWWu95quAFizqxUrSLzunaKLhzOFHQVn1VD32BlEuN6PrqY3ik77T675VW7-65L7n6WG5opfgHBviITAg1Whh26KIdbrcm_bBbzQtrdnoZAw/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;408&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWzvC2sj_g3rX7Ao8BjqD-hd1YyD2B5xWWu95quAFizqxUrSLzunaKLhzOFHQVn1VD32BlEuN6PrqY3ik77T675VW7-65L7n6WG5opfgHBviITAg1Whh26KIdbrcm_bBbzQtrdnoZAw/s640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+12.48.31.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/7856089101991221093/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/07/jsp-mybatis-mysql.html#comment-form' title='2개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7856089101991221093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/7856089101991221093'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/07/jsp-mybatis-mysql.html' title='JSP + MyBatis + MySql 샘플'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzcqhmFzUwa3gKv-61yLeYSkPNHfrnxQJPL9pbv3bCwe1EP-jJAEel2KWM7jGic6OZItoNLS1JrJZgpsC4TagXY6To1H-1uyYhmdnUqHJ6enKJ6WZc4FfYOnBafkRnO_c9efgweXx7lQ/s72-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-07-21+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+1.17.33.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-8191774961520655684</id><published>2012-06-08T07:52:00.000-07:00</published><updated>2017-03-03T03:19:58.144-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Javascript animation</title><content type='html'>&lt;script type=&quot;text/javascript&quot;&gt;
function myanim(actionFunc, interval) {
this.timer;
this.interval = (interval != null) ? interval : 1000;
this.actionFunc = actionFunc;
}
myanim.prototype.start = function() {
this.stop();
var me = this;
if (this.actionFunc) {
this.loop = function() {me.actionFunc();me.timer=setTimeout(me.loop, me.interval);}
this.loop();
}
}
myanim.prototype.stop = function() {
if (this.timer) clearTimeout(this.timer);
}
&lt;/script&gt;

참고:&amp;nbsp;&lt;a href=&quot;http://www.w3schools.com/js/js_timing.asp&quot;&gt;http://www.w3schools.com/js/js_timing.asp&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Animation 은 일정한 시간 간격으로 객체의 속성 등을 서서히 변화시키는 일이다.&lt;br /&gt;
&lt;br /&gt;
일정한 시간 간격으로 원하는 작업을 하기 위해 setTimeout 함수를 이용한다.&lt;br /&gt;
setTimeout(function, delay);&lt;br /&gt;
&lt;br /&gt;
예) 1초 마다 i 변수에 1을 더하고 표시한다.&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;div id=&quot;value&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
var i = 0;
var func = function() {
 i++;
 document.getElementById(&quot;value&quot;);
 setTimeout(func, 1000);
}
setTimeout(func, 1000);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;div id=&quot;value&quot;&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var i = 0;
var animt;
function tj_js_anim_test() {
if (animt) clearTimeout(animt);
 i = 0;
 var func = function() {
  i++;document.getElementById(&quot;value&quot;).innerHTML = i;
  animt = setTimeout(func, 1000);
 }
 animt = setTimeout(func, 1000);
}
 
&lt;/script&gt;
&lt;input onclick=&quot;tj_js_anim_test();&quot; type=&quot;button&quot; value=&quot;start&quot; /&gt;
&lt;br /&gt;
&lt;b&gt;Animation 객체&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
function myanim(actionFunc, interval) {
 this.timer;
 this.interval = (interval != null) ? interval : 1000;
 this.actionFunc = actionFunc;
}
myanim.prototype.start = function() {
 this.stop();
 var me = this;
 if (this.actionFunc) {
  this.loop = function() {me.actionFunc();setTimeout(me.loop, me.interval);}
  this.loop();
 }
}
myanim.prototype.stop = function() {
 if (this.timer) clearTimeout(this.timer);
}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Animation 객체 사용하기&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;div id=&quot;value2&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
var j = 0;
var anim = new myanim(function(){j++;document.getElementById(&quot;value2&quot;).innerHTML=j;}, 1000);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;div id=&quot;value2&quot;&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var j = 0;
var tj_anim = new myanim(function(){j++;document.getElementById(&quot;value2&quot;).innerHTML=j;}, 1000);
&lt;/script&gt;
&lt;input onclick=&quot;tj_anim.start();&quot; type=&quot;button&quot; value=&quot;start&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Element 이동&lt;/b&gt;&lt;br /&gt;
div 객체의 위치 속성 값을 바꾼다.&lt;br /&gt;
1. div 준비&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&amp;lt;div id=&quot;box1&quot; style=&quot;position:absolute;width:100px;height:100px;border:solid 1px black&quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
2. animation&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
var x = 0;
var anim = new myanim(function(){
 x=(x+1)%100;
 document.getElementById(&quot;box1&quot;).style.left=x + &quot;px&quot;;
}, 50);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;box1-2012-06-08&quot; style=&quot;border: solid 1px black; height: 100px; position: absolute; width: 100px;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;height: 100px; width: 100px;&quot;&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var x = 0;
var tj_box1_anim = new myanim(function(){
 x=(x+1)%100;
 document.getElementById(&quot;box1-2012-06-08&quot;).style.left=x + &quot;px&quot;;
}, 50);
&lt;/script&gt;
&lt;input onclick=&quot;tj_box1_anim.start();&quot; type=&quot;button&quot; value=&quot;start&quot; /&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/8191774961520655684/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/06/javascript-animation.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8191774961520655684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/8191774961520655684'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/06/javascript-animation.html' title='Javascript animation'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-1528751583096711211</id><published>2012-05-31T15:50:00.000-07:00</published><updated>2012-06-11T17:19:37.804-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><title type='text'>Servlet 클래스 등록하기</title><content type='html'>다음과 같은 순서다.&lt;br /&gt;
1. servlet 작성&lt;br /&gt;
2. servlet 컴파일&lt;br /&gt;
3. web.xml 에 등록&lt;br /&gt;
&lt;br /&gt;
myapp 이라는 프로젝트를 만드는 것으로 가정한다.&lt;br /&gt;
대략 아래와 같은 구조이다.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;border: solid 1px black; padding: 5px;&quot;&gt;
&lt;pre&gt;/Users/username/&lt;/pre&gt;
&lt;pre&gt; + project/myapp/src/com/myapp/servlet/&lt;/pre&gt;
&lt;pre&gt;   + &lt;b&gt;HelloServlet.java&lt;/b&gt;&lt;/pre&gt;
&lt;pre&gt; + apache-tomcat/webapps/myapp&lt;/pre&gt;
&lt;pre&gt;   + WEB-INF/&lt;/pre&gt;
&lt;pre&gt;     + classes/com/myapp/servlet/&lt;/pre&gt;
&lt;pre&gt;       + &lt;b&gt;HelloServlet.class&lt;/b&gt;&lt;/pre&gt;
&lt;pre&gt;     + &lt;b&gt;web.xml&lt;/b&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;1. servlet 작성&lt;/b&gt;&lt;br /&gt;
javax.servlet.http.HttpServlet 클래스를 상속받아 doGet 또는 doPost 함수를 작성한다.&lt;br /&gt;
doGet 은 GET 방식으로 접속한 경우 호출 되는 함수이고 doPost 는 POST 방식으로 접속한 경우 호출되는 함수 이다.&lt;br /&gt;
&lt;br /&gt;
예) src 라는 폴더를 만들고 com/myapp/servlet/ 폴더 구조로 HelloServlet.java 를 만듬&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;package com.myspp.servlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class HelloServlet extends HttpServlet {

 @Override
 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  PrintWriter out = response.getWriter();
  out.println(&quot;Hello World&quot;);
 }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;2. servlet 컴파일&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
컴파일 하기 위해선 $TOMCAT_HOME/lib 에 servlet-api.jar 파일이 필요하다.&lt;br /&gt;
-cp 에 servlet-api.jar 를 추가한다.&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;export TOMCAT_HOME=/Users/username/apache-tomcat/&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;export PROEJCT_HOME=/Users/username/project/myapp/&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ javac -cp $TOMCAT_HOME/lib/servlet-api.jar -d $TOMCAT_HOME/webapps/myapp/WEB-INF/classes $(find $PROJECT_HOME/src -name *.java)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
!) 참고&lt;br /&gt;
&amp;nbsp;- Ant 로 컴파일 :&amp;nbsp;&lt;a href=&quot;http://tjjava.blogspot.kr/2012/06/ant.html&quot;&gt;http://tjjava.blogspot.kr/2012/06/ant.html&lt;/a&gt;&lt;br /&gt;
&amp;nbsp;- javac 로 컴파일 :&amp;nbsp;&lt;a href=&quot;http://tjjava.blogspot.kr/search/label/javac&quot;&gt;http://tjjava.blogspot.kr/search/label/javac&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;3. web.xml 에 등록&lt;/b&gt;&lt;br /&gt;
servlet 태그로 servlet class 를 등록하고 servlet-mapping 태그로 url 를 매핑한다.&lt;br /&gt;
&amp;nbsp;!) url pattern 작성시 / 로 시작해야 하는 점에 주의한다.&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&amp;lt;servlet&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;servlet-name&amp;gt;&lt;b&gt;HelloServlet&lt;/b&gt;&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;servlet-class&amp;gt;com.myapp.servlet.HelloServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;
&amp;lt;/servlet&amp;gt;&lt;br /&gt;
&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;servlet-name&amp;gt;&lt;b&gt;HelloServlet&lt;/b&gt;&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;url-pattern&amp;gt;/hello&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;
&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;4. 테스트&lt;/b&gt;&lt;br /&gt;
tomcat 을 재시작한다.&lt;br /&gt;
http://localhost:8080/myapp/hello 로 접속하여 Hello World 를 확인 할 수 있으면 된다.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU7mryB2RNuLhihrzwjwBDGSRypuRMcORVCWVZE_5ni2Q_nPehf_k4pkEqWDX0GacCIYDkzTa3puPtCxQ069BtR8Io2PfqkvyTxIBulaNJwAQWpZqT8EckhSeppsdixOlhxheaW5iZ8g/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-06-01+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+8.03.28.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU7mryB2RNuLhihrzwjwBDGSRypuRMcORVCWVZE_5ni2Q_nPehf_k4pkEqWDX0GacCIYDkzTa3puPtCxQ069BtR8Io2PfqkvyTxIBulaNJwAQWpZqT8EckhSeppsdixOlhxheaW5iZ8g/s1600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-06-01+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+8.03.28.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/1528751583096711211/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/05/servlet.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/1528751583096711211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/1528751583096711211'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/05/servlet.html' title='Servlet 클래스 등록하기'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU7mryB2RNuLhihrzwjwBDGSRypuRMcORVCWVZE_5ni2Q_nPehf_k4pkEqWDX0GacCIYDkzTa3puPtCxQ069BtR8Io2PfqkvyTxIBulaNJwAQWpZqT8EckhSeppsdixOlhxheaW5iZ8g/s72-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA+2012-06-01+%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB+8.03.28.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-5500929339946774674</id><published>2012-05-18T18:46:00.002-07:00</published><updated>2012-05-18T18:48:23.202-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>HTML Doctype</title><content type='html'>HTML 문서의 처음에 doctype 을 지정할 수 있다.&lt;br /&gt;
명시적으로 doctype 을 설정함으로써 다양한 환경에서도 웹페이지가 원하는 모습으로 출력될 수 있도록 한다.&lt;br /&gt;
참고:&amp;nbsp;&lt;a href=&quot;http://hooney.net/2007/08/21/438/&quot;&gt;http://hooney.net/2007/08/21/438/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
예) html 문서의 처음에 아래와 같이 입력한다.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;pre class=&quot;dtd&quot;&gt;&lt;/pre&gt;
&lt;b&gt;HTML4 와 HTML5 Doctype 의 차이점&lt;/b&gt;&lt;br /&gt;
HTML4 는 세가지 Doctype 이 있지만 HTML5 는 Doctype 이 하나이다.&lt;br /&gt;
참고:&amp;nbsp;&lt;a href=&quot;http://www.w3schools.com/html5/tag_doctype.asp&quot;&gt;http://www.w3schools.com/html5/tag_doctype.asp&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
HTML4 보다 고민이 줄었고 외우기 쉬워졌다고 할 수 있겠다.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/5500929339946774674/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/05/html-doctype.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5500929339946774674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/5500929339946774674'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/05/html-doctype.html' title='HTML Doctype'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-1820137694483918058</id><published>2012-05-15T17:11:00.001-07:00</published><updated>2012-05-26T05:27:11.248-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>JSP session 처리</title><content type='html'>&lt;b&gt;[session 활성화]&lt;/b&gt;&lt;br /&gt;
session = request.getSession(true);&lt;br /&gt;
또는&lt;br /&gt;
&amp;lt;%@page session=&quot;true&quot;%&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;- 매개변수를 true 로 주면 기존에 session 이 존재하지 않은 경우 session 을 생성한다.&lt;br /&gt;
참고: &lt;a href=&quot;http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getSession(boolean)&quot;&gt;http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getSession(boolean)&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
!) session 변수는 내부적으로 미리 정의된 변수이기 때문에 새로 선언을 할 수 없다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[session 값 설정]&lt;/b&gt;&lt;br /&gt;
session.setAttribute(&quot;key&quot;, &quot;value&quot;);&lt;br /&gt;
&amp;nbsp;- key 는 string 타입이고 value 는 Object 타입이다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[session 값 얻기]&lt;/b&gt;&lt;br /&gt;
String value = (String)session.getAttribute(&quot;key&quot;);&lt;br /&gt;
&amp;nbsp;- 리턴 타입이 Object 타입이기 때문에 Casting 해줘야 한다.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[session 값 지우기]&lt;/b&gt;&lt;br /&gt;
session.removeAttribute(&quot;key&quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[session timeout 설정]&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
web.xml 파일 설정 (분 단위)&lt;br /&gt;
&amp;lt;session-config&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;session-timeout&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 30&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;lt;/session-timeout&amp;gt;&lt;br /&gt;
&amp;lt;/session-config&amp;gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/1820137694483918058/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/05/jsp-session.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/1820137694483918058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/1820137694483918058'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/05/jsp-session.html' title='JSP session 처리'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6354485549816224413.post-6714458345800511537</id><published>2012-05-14T16:00:00.001-07:00</published><updated>2012-05-15T16:38:41.593-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="팁"/><title type='text'>PHP get / post 처리</title><content type='html'>&lt;b&gt;[Request method 확인]&lt;/b&gt;&lt;br /&gt;
$_SERVER[&#39;REQUEST_METHOD&#39;] 값이 &#39;POST&#39; 또는 &#39;GET&#39; 인지 확인&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[매개 변수 확인]&lt;/b&gt;&lt;br /&gt;
Method type 이 get 인 경우 $_GET[&#39;value&#39;] 에 method type 이 post 이면 $_POST[&#39;value&#39;] 로 확인&lt;br /&gt;
&lt;br /&gt;
예)&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
if ($_SERVER[&#39;REQUEST_METHOD&#39;]==&#39;POST&#39;) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; echo &quot;POST&amp;lt;br /&amp;gt;&quot;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; echo $_POST[&#39;id&#39;];&lt;br /&gt;
} else {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; echo &quot;GET&amp;lt;br /&amp;gt;&quot;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; echo $_GET[&#39;id&#39;];&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;form method=&quot;post&quot;&amp;gt;&lt;br /&gt;
&amp;lt;input type=&quot;text&quot; name=&quot;id&quot; value=&quot;&quot; /&amp;gt;&lt;br /&gt;
&amp;lt;input type=&quot;submit&quot; value=&quot;send&quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/form&amp;gt;</content><link rel='replies' type='application/atom+xml' href='http://webfortj.blogspot.com/feeds/6714458345800511537/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://webfortj.blogspot.com/2012/05/php-get-post.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6714458345800511537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6354485549816224413/posts/default/6714458345800511537'/><link rel='alternate' type='text/html' href='http://webfortj.blogspot.com/2012/05/php-get-post.html' title='PHP get / post 처리'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>