<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>관심쟁이 영호</title>
    <link>https://bestkingit.tistory.com/</link>
    <description>관심쟁이영호의 블로그
jkijki1249@gmail.com</description>
    <language>ko</language>
    <pubDate>Tue, 30 Jun 2026 17:57:10 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>관심쟁이 영호</managingEditor>
    <image>
      <title>관심쟁이 영호</title>
      <url>https://tistory1.daumcdn.net/tistory/3118262/attach/d03d3966929d4099b5005b6efe77c9c3</url>
      <link>https://bestkingit.tistory.com</link>
    </image>
    <item>
      <title>velog로 이사합니다!</title>
      <link>https://bestkingit.tistory.com/180</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 새롭게 이사하게 되었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@jkijki12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@jkijki12&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1632129598180&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;jkijki12 (YoungHo-Cha) - velog&quot; data-og-description=&quot;Database 이름 짓기 어려우세요? DB를 사용하면서 누구나 Naming에 대해서 고민한 적이 있을 것이다.나 또한 &amp;quot;이게 맞나?&amp;quot;라고 생각하며, 이름을 결정한 적이 많았다.Database Naming RuleSchemaTableColumnPrimary &quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@jkijki12&quot; data-og-url=&quot;https://velog.io/@jkijki12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4no6i/hyLFIZhy4o/hb0Em90cElh8B7v6kbSHPk/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500&quot;&gt;&lt;a href=&quot;https://velog.io/@jkijki12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@jkijki12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4no6i/hyLFIZhy4o/hb0Em90cElh8B7v6kbSHPk/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;jkijki12 (YoungHo-Cha) - velog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Database 이름 짓기 어려우세요? DB를 사용하면서 누구나 Naming에 대해서 고민한 적이 있을 것이다.나 또한 &quot;이게 맞나?&quot;라고 생각하며, 이름을 결정한 적이 많았다.Database Naming RuleSchemaTableColumnPrimary&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;놀러오세용!&lt;/p&gt;</description>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/180</guid>
      <comments>https://bestkingit.tistory.com/180#entry180comment</comments>
      <pubDate>Mon, 20 Sep 2021 18:20:11 +0900</pubDate>
    </item>
    <item>
      <title>[#5 이미지 검색 프로젝트] python http 서버 만들기</title>
      <link>https://bestkingit.tistory.com/177</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 포스팅에서는 데이터를 DB에 INSERT 하는 것 까지 완성했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1632052057314&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#4 이미지 검색 및 최저가 검색] Python - MySQL 연동하기!&quot; data-og-description=&quot;오늘은 앞서 스크래핑한 내용을 MySQL에 저장하는 작업을 할 것이다. [#2 Search Shop &amp;amp; Price] 크롤링 2탄 ㅣ Json 형태 크롤링하기 ㅣ Ajax 동적으로 크롤링하기 이전에 포스팅한 [#1 SSP] 크롤링을 해보자! &quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/175&quot; data-og-url=&quot;https://bestkingit.tistory.com/175&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dUei8T/hyLD2LsCCA/DABuyn8KbKoVbyjbmFg2h0/img.png?width=711&amp;amp;height=328&amp;amp;face=0_0_711_328,https://scrap.kakaocdn.net/dn/bceZTm/hyLD70kFlM/sMCmqZYiXbzHjoBDfr9Tmk/img.png?width=711&amp;amp;height=328&amp;amp;face=0_0_711_328,https://scrap.kakaocdn.net/dn/nztPN/hyLFsPh2Fg/hdpc2e4pXHg7cxMaqmp6Nk/img.png?width=1366&amp;amp;height=407&amp;amp;face=0_0_1366_407&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/175&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/175&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dUei8T/hyLD2LsCCA/DABuyn8KbKoVbyjbmFg2h0/img.png?width=711&amp;amp;height=328&amp;amp;face=0_0_711_328,https://scrap.kakaocdn.net/dn/bceZTm/hyLD70kFlM/sMCmqZYiXbzHjoBDfr9Tmk/img.png?width=711&amp;amp;height=328&amp;amp;face=0_0_711_328,https://scrap.kakaocdn.net/dn/nztPN/hyLFsPh2Fg/hdpc2e4pXHg7cxMaqmp6Nk/img.png?width=1366&amp;amp;height=407&amp;amp;face=0_0_1366_407');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#4 이미지 검색 및 최저가 검색] Python - MySQL 연동하기!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 앞서 스크래핑한 내용을 MySQL에 저장하는 작업을 할 것이다. [#2 Search Shop &amp;amp; Price] 크롤링 2탄 ㅣ Json 형태 크롤링하기 ㅣ Ajax 동적으로 크롤링하기 이전에 포스팅한 [#1 SSP] 크롤링을 해보자!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리의 목표를 다시 생각해보면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;스프링 Server (http/Get) 크롤링 요청 -&amp;gt; 파이썬 Server 크롤링 후 DB 저장 -&amp;gt; True 리턴&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 오늘은 파이썬을 통하여 http 통신이 가능한 서버를 만들어 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모듈 다운로드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 적용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모듈 다운로드&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;필요한 모듈은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632052113859&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from flask import Flask, jsonify, request
import naverCrawl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;naverCrawl&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 http로 get요청을 받을 경우에 크롤링을 해야 하기 때문에, &quot;naverCrawl&quot;을 import 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;flask&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬에서 서버를 생성하도록 돕는 모듈이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;jsonify&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문자열을 json 형식으로 변경해주는 모듈이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;설치를 해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632052752382&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install flask&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 적용&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632052199771&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from flask import Flask, jsonify, request
import naverCrawl

app = Flask(__name__)

@app.route('/get_data')
def doCrawl():
    
    query = request.args[&quot;query&quot;]

    
    check = naverCrawl.doCrawling(query)
    
    return jsonify(check = check)

if __name__ == '__main__':
    app.run(host=&quot;localhost&quot;, port=&quot;9000&quot;, debug=True)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나는 host : localhost / port : 9000으로 실행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;debug 속성은 True를 했을 경우, 디버그 모드가 on 되어 코드를 수정하면 항상 서버에 반영되도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 요청을 해보자!&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;127&quot; data-filename=&quot;xxdd.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cR3WIq/btrfpCkCXp2/RKYKRn8WfVZ3p49d1EesmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cR3WIq/btrfpCkCXp2/RKYKRn8WfVZ3p49d1EesmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cR3WIq/btrfpCkCXp2/RKYKRn8WfVZ3p49d1EesmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcR3WIq%2FbtrfpCkCXp2%2FRKYKRn8WfVZ3p49d1EesmK%2Fimg.png&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;127&quot; data-filename=&quot;xxdd.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;올바르게 Response가 온 것을 볼 수 있다!!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;확장 프로그램을 통해서 요청을 해보자.&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 사용할 확장 프로그램은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1632054972575&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Talend API Tester - Free Edition&quot; data-og-description=&quot;Visually interact with REST, SOAP and HTTP APIs.&quot; data-og-host=&quot;chrome.google.com&quot; data-og-source-url=&quot;https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm/related&quot; data-og-url=&quot;https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/69Moh/hyLFBeqfXR/jXaib2m8jb9LYnalq8ODF0/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128&quot;&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm/related&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm/related&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/69Moh/hyLFBeqfXR/jXaib2m8jb9LYnalq8ODF0/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Talend API Tester - Free Edition&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Visually interact with REST, SOAP and HTTP APIs.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chrome.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;596&quot; data-filename=&quot;vvcczxccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDTftd/btrfoRJmjkX/tXO6xH0AVkRQwMZ5RAzJu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDTftd/btrfoRJmjkX/tXO6xH0AVkRQwMZ5RAzJu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDTftd/btrfoRJmjkX/tXO6xH0AVkRQwMZ5RAzJu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDTftd%2FbtrfoRJmjkX%2FtXO6xH0AVkRQwMZ5RAzJu1%2Fimg.png&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;596&quot; data-filename=&quot;vvcczxccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;짜란! 잘 도착했다 ㅎㅎㅎㅎㅎ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;굳!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬 서버는 완료했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 스프링으로 넘어가자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project/SSP - 이미지 검색 및 최저가 검색</category>
      <category>flask</category>
      <category>json</category>
      <category>Response</category>
      <category>server</category>
      <category>서버</category>
      <category>스크래핑</category>
      <category>크롤링</category>
      <category>파이썬</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/177</guid>
      <comments>https://bestkingit.tistory.com/177#entry177comment</comments>
      <pubDate>Sun, 19 Sep 2021 21:39:31 +0900</pubDate>
    </item>
    <item>
      <title>[#3 이미지 검색 프로젝트] API 응답 객체화(클래스화?) 하기!</title>
      <link>https://bestkingit.tistory.com/176</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링한 내용을 list를 통해서 전달하지 않고 객체를 생성하여 getter, setter로 편하게 이용하고 싶어서 작업을 조금 더 하려고 한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클래스 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 클래스에 적용하기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;클래스 생성&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;model.py&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632049946630&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class model():
  title = ''
  price = ''
  type =''
  fileName =''
  link =''
  filePath = ''

  def __init__(self):
        self.name = '정보 없음'
        self.type = '정보 없음'
        self.address = '정보 없음'
        self.price ='정보 없음'
        self.filePath = '정보 없음'
        self.link = '정보 없음'
        

  def setTitle(self, title):
        self.title = title
  
  def getTitle(self):
      
    return self.title
  
  def setPrice(self, price):
        self.price = price
  
  def getPrice(self):
    
    return self.price
  
  def setType(self, type):
        self.type = type
  
  def getType(self):
    
    return self.type

  def setFileName(self, fileName):
        self.fileName = fileName
  
  def getFileName(self):
    
    return self.fileName
  def setLink(self, link):
        self.link = link
  
  def getLink(self):
    
    return self.link
  def setFilePath(self, filePath):
        self.filePath = filePath
  
  def getFilePath(self):
      
    return self.filePath&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이썬에서 고유하게 지원하는 get / set 모듈이 있을 것이다. 하지만 모듈에는 별도의 추가 내용이 있을 것이므로, 가볍게 사용하기 위해서 내가 원하는 함수만 선언하여 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;내가 수집할 내용은&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;title : 상품 이름&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;link : 상품 링크&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;price : 상품 가격&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;fileName : 저장된 사진 이름&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;filePath : 저장된 사진의 경로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;type : 상품 타입 (검색 단어로 지정했다. 나중에 where 절을 이용하기 위해서 적어두었다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;크롤링 클래스에 적용하기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해야하는 적용은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 내용을 model 클래스로 적절하게 파싱 하고, DB 저장 클래스로 보낸다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;1. 방금 생성한 model 클래스 정보를 가져온다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632050322181&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import model&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;2. 모델을 생성하고 초기화해준다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632050402605&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;      getModel = model.model()
      getModel.setTitle(title)
      getModel.setPrice(price)
      getModel.setLink(link)
      getModel.setType(searchModel)
      getModel.setFileName(fileName)
      getModel.setFilePath(filePath)
      DAO.insertData(getModel)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DAO는 insert를 할 클래스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>get</category>
      <category>PYTHON</category>
      <category>set</category>
      <category>객체</category>
      <category>크롤링</category>
      <category>클래스</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/176</guid>
      <comments>https://bestkingit.tistory.com/176#entry176comment</comments>
      <pubDate>Sun, 19 Sep 2021 20:21:48 +0900</pubDate>
    </item>
    <item>
      <title>[#4 이미지 검색 프로젝트] Python - MySQL 연동하기!</title>
      <link>https://bestkingit.tistory.com/175</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 앞서 스크래핑한 내용을 MySQL에 저장하는 작업을 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631813802462&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#2 Search Shop &amp;amp; Price] 크롤링 2탄 ㅣ Json 형태 크롤링하기  ㅣ Ajax 동적으로 크롤링하기&quot; data-og-description=&quot;이전에 포스팅한 [#1 SSP] 크롤링을 해보자! SSP에서 가장 핵심적인 크롤링을 해보자. 목차 툴 라이브러리 설치 User-Agent 쿠팡에서 정보 긁어오기 네이버에서 정보 긁어오기 번개장터에서 정보 긁어&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/173&quot; data-og-url=&quot;https://bestkingit.tistory.com/173&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/x1hE9/hyLCJK89B9/TwIf4v0a5iKahz6CVJdy01/img.png?width=800&amp;amp;height=308&amp;amp;face=0_0_800_308,https://scrap.kakaocdn.net/dn/cBfGeK/hyLCDc443S/5HLDSaSamdQvzL2xw8LAJ1/img.png?width=800&amp;amp;height=308&amp;amp;face=0_0_800_308,https://scrap.kakaocdn.net/dn/cDOLcK/hyLCKwwZXp/OKf1ZEKfqcfqjIwr3ljNpK/img.png?width=1010&amp;amp;height=390&amp;amp;face=0_0_1010_390&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/173&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/173&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/x1hE9/hyLCJK89B9/TwIf4v0a5iKahz6CVJdy01/img.png?width=800&amp;amp;height=308&amp;amp;face=0_0_800_308,https://scrap.kakaocdn.net/dn/cBfGeK/hyLCDc443S/5HLDSaSamdQvzL2xw8LAJ1/img.png?width=800&amp;amp;height=308&amp;amp;face=0_0_800_308,https://scrap.kakaocdn.net/dn/cDOLcK/hyLCKwwZXp/OKf1ZEKfqcfqjIwr3ljNpK/img.png?width=1010&amp;amp;height=390&amp;amp;face=0_0_1010_390');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#2 Search Shop &amp;amp; Price] 크롤링 2탄 ㅣ Json 형태 크롤링하기 ㅣ Ajax 동적으로 크롤링하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전에 포스팅한 [#1 SSP] 크롤링을 해보자! SSP에서 가장 핵심적인 크롤링을 해보자. 목차 툴 라이브러리 설치 User-Agent 쿠팡에서 정보 긁어오기 네이버에서 정보 긁어오기 번개장터에서 정보 긁어&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;MySQL DB 준비하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Python - MySQL 연동하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;테스트&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;MySQL DB 준비하기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;MySQL을 설치한다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 생략 -&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;MySQL DB를 생성한다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1632045976654&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DATABASE crawl CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

show databases;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;CREATE DATABASE &quot;생성할 DB 이름&quot; CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 지정해준 DB이름으로 DB를 생성한다. 문자 세팅은 utf8로 한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;SHOW DATABASES;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 생성된 DATABASE를 모두 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래와 같이 생성된 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;328&quot; data-filename=&quot;xxz.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNRiy8/btrfo5mOzQs/rGgTdBuYDDVIEYmuQ5Pyc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNRiy8/btrfo5mOzQs/rGgTdBuYDDVIEYmuQ5Pyc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNRiy8/btrfo5mOzQs/rGgTdBuYDDVIEYmuQ5Pyc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNRiy8%2Fbtrfo5mOzQs%2FrGgTdBuYDDVIEYmuQ5Pyc0%2Fimg.png&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;328&quot; data-filename=&quot;xxz.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;TABLE을 생성하자.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1632046137001&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE model (

    title TEXT NOT NULL, 
    price TEXT, 
    link TEXT, 
    imagePath TEXT, 
    fileName TEXT
    
    );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;타입(길이)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;NULL&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DEFAULT&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;title&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TEXT&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;price&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TEXT&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;imagePath&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TEXT&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;fileName&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TEXT&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;link&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TEXT&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 과정에 title, price, imagePath, fileName, link를 받아온다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내용 중에, 암호화가 되어 있는 부분이 있어서 길이를 예상할 수가 없었다. 그래서 TEXT로 타입을 지정해주었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Python - MySQL 연동하기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;1. pymysql을 설치한다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632046622655&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install pymysql&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;2. Python과 연결할 계정을 설정해준다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632046683962&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conn = pymysql.connect(host= &quot;localhost&quot;, user=&quot;root&quot;, password=&quot;1234&quot;, db=&quot;crawl&quot;, charset=&quot;utf8&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;host&quot; 부분을 특정 ip로 할 경우, MySQL DB 서버에 접근할 수 있다. (대형 서비스를 운영하는 실무에서는 이렇게 하겠지!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;3. cursor를 설정한다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632046778075&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curs = conn.cursor()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;커서란?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&quot;데이터베이스 커서&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(Cursor)는 일련의 데이터에 순차적으로 액세스할 때 검색 및 &quot;현재 위치&quot;를 포함하는 데이터 요소이다.&quot; - 위키백과&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;다시 말하자면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;db를 운용할 때, 많은 양의 데이터를 쓰고나 뽑거나 수정하거나 해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;해당 조작을 하기위해서는 현재 위치에 대한 정보가 필요하다. 현재 위치에 대한 정보를 cursor가 가지게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;4. sql을 작성한다.&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632047042204&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sql = &quot;insert into model (title, price, link, data_type, fileName, imagePath) VALUES (&quot;+ '\''+str(getModel.getTitle()) + '\''', '+ '\''+ str(getModel.getPrice())+'\'' + ', '+ '\''+str(getModel.getLink()) + '\''+', ' + '\''+ str(getModel.getType()) + '\''+', '+ '\''+str(getModel.getFileName())+'\''+', '+ '\''+str(getModel.filePath)+'\'' + ')'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하드코딩 처럼 작성하는 것을 싫어한다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;관련 모듈이 있는지 다음에 찾아보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;5. sql을 보내자&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632047088106&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curs.execute(sql)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;sql이 연결된 db에서 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;execute를 하게 되면, MySQL에서 트랜잭션이 실행된다. 그리고 보낸 sql이 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면 완료되는 것이 아니다. 트랜잭션을 종료해야 데이터 변경에 대한 일이 완료가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;6. commit 하자&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632047112070&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conn.commit()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;commit을 하게 되면 insert를 해주었던 내용이 MySQL에 최종 저장이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;7. conn을 종료해주자.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1632047275016&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def close_conn(self):
        conn.close()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;최종 코드&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1632047377170&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pymysql
import model
from typing import Type


def get_db():

    return pymysql.connect(host= &quot;localhost&quot;, user=&quot;root&quot;, password=&quot;1234&quot;, db=&quot;crawl&quot;, charset=&quot;utf8&quot;)

def insertData(getModel: Type[model.model]) :

    
    conn = get_db()
    curs = conn.cursor()
    sql = &quot;insert into model (title, price, link, data_type, fileName, imagePath) VALUES (&quot;+ '\''+str(getModel.getTitle()) + '\''', '+ '\''+ str(getModel.getPrice())+'\'' + ', '+ '\''+str(getModel.getLink()) + '\''+', ' + '\''+ str(getModel.getType()) + '\''+', '+ '\''+str(getModel.getFileName())+'\''+', '+ '\''+str(getModel.filePath)+'\'' + ')'
    curs.execute(sql)

    
    conn.commit()
    
    

def close_conn() :
    conn.close()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&quot;close_conn&quot;을 하나의 함수에서 빼놓은 이유는 반복해서 insert를 할 것이기 때문이다. 매번 close를 하게 되면 그 또한 낭비라고 생각이 된다.&lt;/li&gt;
&lt;li&gt;get_db라고 함수를 새롭게 정의한 이유는 서버로 요청이 올 때 마다 connection을 새롭게 지정해주어야 하기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;테스트&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 클래스에서 DB INSERT 클래스 실행을 해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;407&quot; data-filename=&quot;zxcv112.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpqKTm/btrfzjKj6HJ/kldXoO8mnKCB2WZEpRkhh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpqKTm/btrfzjKj6HJ/kldXoO8mnKCB2WZEpRkhh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpqKTm/btrfzjKj6HJ/kldXoO8mnKCB2WZEpRkhh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpqKTm%2FbtrfzjKj6HJ%2FkldXoO8mnKCB2WZEpRkhh0%2Fimg.png&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;407&quot; data-filename=&quot;zxcv112.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;올바르게 적용된 것을 알 수 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project/SSP - 이미지 검색 및 최저가 검색</category>
      <category>connection</category>
      <category>cursor</category>
      <category>insert</category>
      <category>mysql</category>
      <category>pymysql</category>
      <category>PYTHON</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/175</guid>
      <comments>https://bestkingit.tistory.com/175#entry175comment</comments>
      <pubDate>Sun, 19 Sep 2021 20:03:39 +0900</pubDate>
    </item>
    <item>
      <title>[#8 Spring Boot 정주행] 유연한 컨트롤러 만들기 ㅣ Handler, Adapter, 다형성</title>
      <link>https://bestkingit.tistory.com/174</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금까지 여러 종류의 모양을 반환하는 컨트롤러를 만들어보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;path부터 modelAndView 까지.. 계속해서 발전해왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631616655605&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#6-1 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자&quot; data-og-description=&quot;이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다! 하지만 문제가 있었다. 이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서 MVC 프레임워크를 만&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/166?category=472106&quot; data-og-url=&quot;https://bestkingit.tistory.com/166&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bgcCWa/hyLBCd6Q9H/4RwPIkgJuKslvBHlWIlPz1/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/bbrh5Y/hyLBt2xamW/MgKw4ESANe8giKhtRSjNR0/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/AxNcQ/hyLByQja50/oOcJr92gt2BaUr6WovwgV1/img.png?width=979&amp;amp;height=589&amp;amp;face=0_0_979_589&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/166?category=472106&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/166?category=472106&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bgcCWa/hyLBCd6Q9H/4RwPIkgJuKslvBHlWIlPz1/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/bbrh5Y/hyLBt2xamW/MgKw4ESANe8giKhtRSjNR0/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/AxNcQ/hyLByQja50/oOcJr92gt2BaUr6WovwgV1/img.png?width=979&amp;amp;height=589&amp;amp;face=0_0_979_589');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#6-1 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다! 하지만 문제가 있었다. 이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서 MVC 프레임워크를 만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631616670804&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기&quot; data-og-description=&quot;이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View &amp;amp; 또 다른 Servlet으로 넘겨주는 함수가 모든 컨트롤러에 적용된다는 것&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/167?category=472106&quot; data-og-url=&quot;https://bestkingit.tistory.com/167&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oAvfS/hyLBrXWefO/7MohGhagIAZPGH1INE1MI0/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/bF8T4k/hyLBAUS6ky/3fIqifBBGdqUhN1w7ucI81/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/jBu94/hyLBzhnZQm/7a2ymHEp7IX70R9JonQGq0/img.png?width=1225&amp;amp;height=769&amp;amp;face=0_0_1225_769&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/167?category=472106&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/167?category=472106&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oAvfS/hyLBrXWefO/7MohGhagIAZPGH1INE1MI0/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/bF8T4k/hyLBAUS6ky/3fIqifBBGdqUhN1w7ucI81/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/jBu94/hyLBzhnZQm/7a2ymHEp7IX70R9JonQGq0/img.png?width=1225&amp;amp;height=769&amp;amp;face=0_0_1225_769');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View &amp;amp; 또 다른 Servlet으로 넘겨주는 함수가 모든 컨트롤러에 적용된다는 것&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631616680002&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#7 SpringBoot 정주행] ViewResolver를 만들어보자!&quot; data-og-description=&quot;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기 이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View..&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/168?category=472106&quot; data-og-url=&quot;https://bestkingit.tistory.com/168&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gHunY/hyLBE31T0C/lDlYSrkEPu8mFufE4TWlRK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bIOwGQ/hyLBHsW108/ieKApLkyF0N6bHLMmgbsT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/69UbX/hyLBHmaROQ/CMiW7D1EkTLzyz9kRPc7f1/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/168?category=472106&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/168?category=472106&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gHunY/hyLBE31T0C/lDlYSrkEPu8mFufE4TWlRK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bIOwGQ/hyLBHsW108/ieKApLkyF0N6bHLMmgbsT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/69UbX/hyLBHmaROQ/CMiW7D1EkTLzyz9kRPc7f1/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#7 SpringBoot 정주행] ViewResolver를 만들어보자!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기 이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데.. 개발자의 입장에서 modelAndView 1개만 반환해야 한다면 답답할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;model과 view가 필요가 없는데, modelAndView를 반환해야하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발자가 무엇을 반환하든 상관없는 모양으로 만들어보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 뒷내용을 이해하려면 객체의 &quot;다형성&quot;에 관해서 잘 알아야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;혹시나 모른다면! 다음 글을 보도록 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631616744152&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JAVA]추상클래스와 추상메서드에 대해서! ㅣ Abstract&quot; data-og-description=&quot;오늘은 추상클래스와 추상메서드에 대해서 공부를 해볼 계획이다. 추상클래스? 추상클래스는 완성하지않은 메서드를 가지고 있는 클래스를 말한다! 한마디로, 몸통부분인 &amp;quot;{}&amp;quot;가 없는 것을 말한&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/134?category=332453&quot; data-og-url=&quot;https://bestkingit.tistory.com/134&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/edEqc5/hyLBtaoitv/K92Gxpcf0bqxf2vsvWQvUk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/PUPFp/hyLBsCxJYJ/z4PeuEJsznsSDaPkk2wSzk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jhhOg/hyLBFhz8Tc/73vzKIFksZibltHeudpIhk/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/134?category=332453&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/134?category=332453&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/edEqc5/hyLBtaoitv/K92Gxpcf0bqxf2vsvWQvUk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/PUPFp/hyLBsCxJYJ/z4PeuEJsznsSDaPkk2wSzk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jhhOg/hyLBFhz8Tc/73vzKIFksZibltHeudpIhk/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JAVA]추상클래스와 추상메서드에 대해서! ㅣ Abstract&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 추상클래스와 추상메서드에 대해서 공부를 해볼 계획이다. 추상클래스? 추상클래스는 완성하지않은 메서드를 가지고 있는 클래스를 말한다! 한마디로, 몸통부분인 &quot;{}&quot;가 없는 것을 말한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631616766109&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JAVA] 인터페이스 ㅣ Interface&quot; data-og-description=&quot;오늘은 인터페이스에 관해서 공부를 할 예정이다. (출간된 &amp;quot;자바의 정석&amp;quot; 책을 참고했습니다.) 인터페이스란? - 추상 메서드의 집합이다. (추상 메서드 : 구현을 하지않은 메서드) - 모든 멤버가 pu&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/135?category=332453&quot; data-og-url=&quot;https://bestkingit.tistory.com/135&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VOMos/hyLBF9J6dd/ErpbCFgH3LjSRIF0s1B0mK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/UF6TK/hyLBrXWlIm/JKJtJXip0QYIBjmoJyaMZK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bmT11K/hyLBH0MdDy/YXLrnjDcD6Zie2k1I9Sdf0/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/135?category=332453&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/135?category=332453&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VOMos/hyLBF9J6dd/ErpbCFgH3LjSRIF0s1B0mK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/UF6TK/hyLBrXWlIm/JKJtJXip0QYIBjmoJyaMZK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bmT11K/hyLBH0MdDy/YXLrnjDcD6Zie2k1I9Sdf0/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JAVA] 인터페이스 ㅣ Interface&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 인터페이스에 관해서 공부를 할 예정이다. (출간된 &quot;자바의 정석&quot; 책을 참고했습니다.) 인터페이스란? - 추상 메서드의 집합이다. (추상 메서드 : 구현을 하지않은 메서드) - 모든 멤버가 pu&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어댑터와 핸들러&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어댑터 만들기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;핸들러 만들기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;마치며&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어댑터와 핸들러&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어댑터와 핸들러를 이해하기 전에, 위에서 이야기했던 내용을 계속해서 해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발자들은 반환 값을 상관하지 않고 여러 가지 방식 중에서 자기가 원하는 것을 반환하고 싶다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(model, view, path, string 기타 등등..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그러기 위해서는 어떻게 해야 할까?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 그림을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1577&quot; data-origin-height=&quot;509&quot; data-filename=&quot;xcxcxcxc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dquxAl/btrfcXvDWs4/5KvEr8ZyFKGtB2kjbxdEgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dquxAl/btrfcXvDWs4/5KvEr8ZyFKGtB2kjbxdEgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dquxAl/btrfcXvDWs4/5KvEr8ZyFKGtB2kjbxdEgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdquxAl%2FbtrfcXvDWs4%2F5KvEr8ZyFKGtB2kjbxdEgk%2Fimg.png&quot; data-origin-width=&quot;1577&quot; data-origin-height=&quot;509&quot; data-filename=&quot;xcxcxcxc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이해하기 힘들 수 있다. 천천히 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;핸들러란?&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전에 사용했던 Controller랑 똑같은 개념이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;핸들러 어댑터란?&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;핸들러가 어떠한 값을 보내든 ModelAndView로 바꾸어주는 어댑터라고 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어댑터는 &quot;Stirng -&amp;gt; ModelAndView&quot;, &quot;Model -&amp;gt; ModelAndView&quot;, &quot;void -&amp;gt; ModelAndView&quot; 등등 가능한 모든 반환 값을 ModelAndView로 바꾸어주는 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;왜 필요한가?&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 제대로 이해해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발자가 어떤 값을 컨트롤러로 반환할지 모른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 개발자가 어떠한 값을 리턴하더라도 상관없이 그 값을 ModelAndView로 바꾸어주기로 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇게 되는 경우 리턴 값을 딱히 신경 쓰지 않아도 될 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해야 할 작업&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 먼저, 반환할 값에 타입에 따라 어댑터를 생성해준다. 그리고 Front Controller에 어댑터를 추가해준다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController.java 추가&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631780476521&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//...//

private void initHandlerAdapters() {
 handlerAdapters.add(new ControllerV3HandlerAdapter());
 handlerAdapters.add(new ControllerV4HandlerAdapter()); //V4 추가
}

//...//&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #ee2323;&quot;&gt;2. handlerAdapter 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631780623362&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface MyHandlerAdapter {

    boolean support(Object handler);

    Model handle(HttpServletRequest request, HttpServletResponse response,
                 Object handler) throws ServletException, IOException;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;handle : 어댑터는 각 반환 값을 ModelAndView로 바꾸어주는 로직을 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;support&amp;nbsp;: Front Controller가 해당 어댑터가 사용자가 요청한 내용을 처리할 수 있는지 확인하기 위한 support 메소드를 추가해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 특정한 반환 값을 대처하는 Adapter를 만들자.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631780690652&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ControllerV3HandlerAdapter implements MyHandlerAdapter {
	 @Override
	 public boolean supports(Object handler) {
	 return (handler instanceof ControllerV3);
	 }
	 @Override
	 public ModelView handle(HttpServletRequest request, HttpServletResponseresponse, Object handler) {
 	ControllerV3 controller = (ControllerV3) handler;
 	Map&amp;lt;String, String&amp;gt; paramMap = createParamMap(request);
	 ModelView mv = controller.process(paramMap);
	 return mv;
 }
 
 //...//&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ControllerV3는 ModelView의 타입을 반환하는 컨트롤러이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최종적으로 ModelView로 FrontController에 반환해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 다른 타입을 반환하는 내용을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631780832710&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Override
 public ModelView handle(HttpServletRequest request, HttpServletResponseresponse, Object handler) {
 	
    ControllerV4 controller = (ControllerV4) handler;
 	Map&amp;lt;String, String&amp;gt; paramMap = createParamMap(request);
	 Map&amp;lt;String, Object&amp;gt; model = new HashMap&amp;lt;&amp;gt;();
	 String viewName = controller.process(paramMap, model);

 	ModelView mv = new ModelView(viewName);
 	mv.setModel(model);

 	return mv;
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ControllerV4는 viewName인 String을 반환하는 Controller이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;viewName을 ModelView로 바꾸어 리턴하는 모습이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 컨트롤러(핸들러) 반환 값에 따른 어댑터를 전부 생성해주면 어떤 반환 값이던 ModelAndView(ModelView)로 Front Controller가 받을 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4. FrontController는 어댑터 check와 어댑터 실행을 전담한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 코드를 보며 이해해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631781052062&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 	Object handler = getHandler(request);
 	if (handler == null) {
 		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
 		return;
 	}
    
	 MyHandlerAdapter adapter = getHandlerAdapter(handler);
 	ModelView mv = adapter.handle(request, response, handler);
 	MyView view = viewResolver(mv.getViewName());
 	view.render(mv.getModel(), request, response);
 	}
    
    //요청에서 uri를 뽑는 메소드
 	private Object getHandler(HttpServletRequest request) {
 	String requestURI = request.getRequestURI();
 	return handlerMappingMap.get(requestURI);
 	}
    
    // 해당 요청을 다룰 수 있는 adapter 찾기
 	private MyHandlerAdapter getHandlerAdapter(Object handler) {
 	for (MyHandlerAdapter adapter : handlerAdapters) {
 		if (adapter.supports(handler)) {
 			return adapter;
 	}
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드를 보면 handler를 얻고, 해당 핸들러가 지원하는지, support로 체크를 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;support 체크를 통과하여 어댑터를 찾으면 해당 어댑터의 handle을 호출한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 어댑터는 핸들러(컨트롤러)를 실행하게 된다. 그리고 컨트롤러의 반환 값을 ModelAndView로 변환하여 리턴한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ModelAndView를 받은 Front Controller는 ModelAndView를 ViewResolver를 거쳐 올바른 path로 바꾸어주고 view에 Model을 넘겨준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금까지 했던 과정의 끝에 도달했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내용을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;717&quot; data-filename=&quot;11222.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lWB49/btrfiatyL7F/qorU9IiURbOae7mVjdRa8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lWB49/btrfiatyL7F/qorU9IiURbOae7mVjdRa8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lWB49/btrfiatyL7F/qorU9IiURbOae7mVjdRa8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlWB49%2FbtrfiatyL7F%2FqorU9IiURbOae7mVjdRa8k%2Fimg.png&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;717&quot; data-filename=&quot;11222.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;굳!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 구조를 이해했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아주 놀랍게도....&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 구조가 스프링이랑 똑같다!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(스프링은 더 많다 참고로)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링에서는 거의 모든 타입의 어댑터, 뷰 리졸버가 구현되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;끝!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 시간부터는 스프링에 대해서 공부해보자!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;해당 포스팅은 &quot;인프런 - 김영한 개발자님의 스프링 MVC 1편&quot;을 참고하여 작성되었습니다.&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>MVC</category>
      <category>뷰리졸버</category>
      <category>스프링</category>
      <category>프론트 컨트롤러</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/174</guid>
      <comments>https://bestkingit.tistory.com/174#entry174comment</comments>
      <pubDate>Thu, 16 Sep 2021 17:43:32 +0900</pubDate>
    </item>
    <item>
      <title>[#2 이미지 검색 프로젝트] 크롤링 2탄 ㅣ Json 형태로 Request하기  ㅣ Ajax 동적으로 API 요청하기</title>
      <link>https://bestkingit.tistory.com/173</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전에 포스팅한&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1631638342213&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#1 SSP] 크롤링을 해보자!&quot; data-og-description=&quot;SSP에서 가장 핵심적인 크롤링을 해보자. 목차 툴 라이브러리 설치 User-Agent 쿠팡에서 정보 긁어오기 네이버에서 정보 긁어오기 번개장터에서 정보 긁어오기 툴 language : python 3.9.7 ide &amp;nbsp;: Visual Studio&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/172?category=507777&quot; data-og-url=&quot;https://bestkingit.tistory.com/172&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jws9r/hyLBuOeZZJ/dWLqsLg1Q07rp5ImrfSvv1/img.png?width=800&amp;amp;height=146&amp;amp;face=0_0_800_146,https://scrap.kakaocdn.net/dn/csxvFV/hyLBFvr6od/2RPx8sFm9PFAyu8hxsKcD0/img.png?width=800&amp;amp;height=146&amp;amp;face=0_0_800_146,https://scrap.kakaocdn.net/dn/bwd7FA/hyLBwrMGUD/kDfJrYTdII7s4IBkFrjIXK/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/172?category=507777&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/172?category=507777&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jws9r/hyLBuOeZZJ/dWLqsLg1Q07rp5ImrfSvv1/img.png?width=800&amp;amp;height=146&amp;amp;face=0_0_800_146,https://scrap.kakaocdn.net/dn/csxvFV/hyLBFvr6od/2RPx8sFm9PFAyu8hxsKcD0/img.png?width=800&amp;amp;height=146&amp;amp;face=0_0_800_146,https://scrap.kakaocdn.net/dn/bwd7FA/hyLBwrMGUD/kDfJrYTdII7s4IBkFrjIXK/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#1 SSP] 크롤링을 해보자!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SSP에서 가장 핵심적인 크롤링을 해보자. 목차 툴 라이브러리 설치 User-Agent 쿠팡에서 정보 긁어오기 네이버에서 정보 긁어오기 번개장터에서 정보 긁어오기 툴 language : python 3.9.7 ide &amp;nbsp;: Visual Studio&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;포스팅을 계속해서 코딩하다 보니까 치명적인 오류를 발견하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해결방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Ajax 요청 보내기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또 다른 문제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;문제 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;리팩토링&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제와 해결&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네이버 홈페이지를 들어가 보았다. 처음에 페이지가 로드되었을 때는 5개 정도의 상품이 로드되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 스크롤이 어느 정도 내려가야 Ajax-Json 통신으로 데이터를 새롭게 받는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 코드로 작성된 크롤링을 실행하면, 올바르게 작성되었지만 상품이 5개까지 밖에 없다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 수정하기로 했다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-Json 통신을 수행하는 URL을 찾아라!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;검색&quot; 버튼을 클릭했을 때, 날아가는 URL을 찾아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제 사이트에서 network탭에서 찾아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1010&quot; data-origin-height=&quot;390&quot; data-filename=&quot;cvbcvbcvbcb.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cq2Oia/btre5u0qvvP/PmFA32okGkxFEOvnJhME1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cq2Oia/btre5u0qvvP/PmFA32okGkxFEOvnJhME1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cq2Oia/btre5u0qvvP/PmFA32okGkxFEOvnJhME1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcq2Oia%2Fbtre5u0qvvP%2FPmFA32okGkxFEOvnJhME1k%2Fimg.png&quot; data-origin-width=&quot;1010&quot; data-origin-height=&quot;390&quot; data-filename=&quot;cvbcvbcvbcb.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;저기서 어떤 것인지 감이 안 온다.. 처음엔 막막했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하나씩 눌러가며 뒤져보아도, 데이터가 넘어오는 것을 알아볼 수가 없었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 header에 Request URL을 전부 복붙 하여 URL GET 요청을 하나하나 해보기 시작했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;199&quot; data-filename=&quot;ZZXX.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O2ui9/btre34VKlWj/KkNVSh8XWkuzDpu2HGXGM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O2ui9/btre34VKlWj/KkNVSh8XWkuzDpu2HGXGM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O2ui9/btre34VKlWj/KkNVSh8XWkuzDpu2HGXGM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO2ui9%2Fbtre34VKlWj%2FKkNVSh8XWkuzDpu2HGXGM0%2Fimg.png&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;199&quot; data-filename=&quot;ZZXX.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어랍쇼? 이게 되네? 이걸 나진이(-틀-)?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1271&quot; data-origin-height=&quot;916&quot; data-filename=&quot;ZXCCC.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bta32l/btreY3pNYDr/wD0XLeWDErvIZZOMBrlNAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bta32l/btreY3pNYDr/wD0XLeWDErvIZZOMBrlNAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bta32l/btreY3pNYDr/wD0XLeWDErvIZZOMBrlNAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbta32l%2FbtreY3pNYDr%2FwD0XLeWDErvIZZOMBrlNAk%2Fimg.png&quot; data-origin-width=&quot;1271&quot; data-origin-height=&quot;916&quot; data-filename=&quot;ZXCCC.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오오오오오옹오오오오오오 JSON 넘어온다!!!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 글을 보는 누군가도 &quot;네이버 쇼핑&quot;에서 답답한 심정을 느꼈을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;십 년 묵은 체증이 내려가길 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그러면 이거 바로 받아야지?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데 그전에... 나는 스크롤을 통해서 요청을 했지만 크롤링 프로그램에선 어떻게 요청을 보내야 하나?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;페이지 URL을 보내면 또 5개가 나올 텐데?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 찾아본 곳이 다음 블로그 글이다! 도움이 많이 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631641982083&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;selenium사용하지 않고 네이버쇼핑 검색결과 크롤링하기&quot; data-og-description=&quot;네이버 쇼핑의 검색 결과가 필요해졌습니다. 검색 페이지 크롤링하면 되니까 어렵지 않게 할 수 있을 거라고 생각했었는데 그게 아니었습니다. 대신 검색정보를 담고 있는 JSON파일을 찾을 수 있&quot; data-og-host=&quot;kwonkyo.tistory.com&quot; data-og-source-url=&quot;https://kwonkyo.tistory.com/529&quot; data-og-url=&quot;https://kwonkyo.tistory.com/529&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/esXgVr/hyLBA12BOX/5MUDL7tBDAJKkwuEyMOES1/img.png?width=800&amp;amp;height=578&amp;amp;face=0_0_800_578,https://scrap.kakaocdn.net/dn/bhNvub/hyLBCeuuV8/G4m1du9NhtEGnf6SQ8MBuK/img.png?width=800&amp;amp;height=578&amp;amp;face=0_0_800_578,https://scrap.kakaocdn.net/dn/8XuV0/hyLByXrPFE/K974Q8klhA66QgkkFuAWZ1/img.png?width=1335&amp;amp;height=920&amp;amp;face=0_0_1335_920&quot;&gt;&lt;a href=&quot;https://kwonkyo.tistory.com/529&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kwonkyo.tistory.com/529&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/esXgVr/hyLBA12BOX/5MUDL7tBDAJKkwuEyMOES1/img.png?width=800&amp;amp;height=578&amp;amp;face=0_0_800_578,https://scrap.kakaocdn.net/dn/bhNvub/hyLBCeuuV8/G4m1du9NhtEGnf6SQ8MBuK/img.png?width=800&amp;amp;height=578&amp;amp;face=0_0_800_578,https://scrap.kakaocdn.net/dn/8XuV0/hyLByXrPFE/K974Q8klhA66QgkkFuAWZ1/img.png?width=1335&amp;amp;height=920&amp;amp;face=0_0_1335_920');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;selenium사용하지 않고 네이버쇼핑 검색결과 크롤링하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;네이버 쇼핑의 검색 결과가 필요해졌습니다. 검색 페이지 크롤링하면 되니까 어렵지 않게 할 수 있을 거라고 생각했었는데 그게 아니었습니다. 대신 검색정보를 담고 있는 JSON파일을 찾을 수 있&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kwonkyo.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Ajax 요청 보내기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Ajax를 Get Method로 보냈을 건데.. 내가 어떻게 만드냐..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네이버 회사에서 나온 것일 텐데&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 좋은 방법을 알았지~~&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;cURL (bash)로 복사해주자!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;675&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQBwaQ/btre5bz5iPl/HSxNLajiOvS7pYgz2KfSz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQBwaQ/btre5bz5iPl/HSxNLajiOvS7pYgz2KfSz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQBwaQ/btre5bz5iPl/HSxNLajiOvS7pYgz2KfSz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQBwaQ%2Fbtre5bz5iPl%2FHSxNLajiOvS7pYgz2KfSz1%2Fimg.png&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;675&quot; data-filename=&quot;blob&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;※ cURL 이란? : cURL은 다양한 프로토콜 요청을 지원해주는 것이라고 생각하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;저기에서 내가 복사한 것은, 내가 보낸 요청을 cURL (bash)로 다운로드가 되는&amp;nbsp;것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;저러한 cURL을 파이썬 코드로 변환해주는 사이트로 가자!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1631642520663&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Convert curl command syntax to Python requests, Ansible URI, browser fetch, MATLAB, Node.js, R, PHP, Strest, Go, Dart, Java, JSO&quot; data-og-description=&quot;Language Ansible Browser (fetch) Dart Elixir Go Java JSON Node.js (fetch) Node.js (request) MATLAB PHP Python R Rust Strest&quot; data-og-host=&quot;curl.trillworks.com&quot; data-og-source-url=&quot;https://curl.trillworks.com/&quot; data-og-url=&quot;https://curl.trillworks.com/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://curl.trillworks.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://curl.trillworks.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Convert curl command syntax to Python requests, Ansible URI, browser fetch, MATLAB, Node.js, R, PHP, Strest, Go, Dart, Java, JSO&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Language Ansible Browser (fetch) Dart Elixir Go Java JSON Node.js (fetch) Node.js (request) MATLAB PHP Python R Rust Strest&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;curl.trillworks.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 Python 코드로 변환하여 복붙 하면 Json 호출 끝&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;호출받은 것에서 내가 필요한 데이터를 추출하여 뽑아보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631642567993&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
import json

# http header 설정
headers = {
    'authority': 'search.shopping.naver.com',
    'sec-ch-ua': '&quot;Google Chrome&quot;;v=&quot;93&quot;, &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Chromium&quot;;v=&quot;93&quot;',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
    'sec-ch-ua-platform': '&quot;Windows&quot;',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://search.shopping.naver.com/search/all?query=%EB%AA%A8%EC%9E%90&amp;amp;frm=NVSHATC&amp;amp;prevQuery=%EB%83%89%EC%9E%A5%EA%B3%A0',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    'cookie': 'NNB=NOLCMFH6MS3WA; NDARK=Y; _ga=GA1.2.36707839.1627031989; _ga_7VKFYR6RV1=GS1.1.1627031988.1.1.1627032122.60; nx_ssl=2; AD_SHP_BID=23; spage_uid=; sus_val=VXtY32Une32saj6a3yBFPHvC',
}

# parameter 설정
params = (
    ('query', '\uBAA8\uC790'),
    ('catId', '50000181'),
)


# 받은 Json 저장
response = requests.get('https://search.shopping.naver.com/api/search/aside', headers=headers, params=params)

# json을 리스트로 받기
itemlist = json.loads(response.text)


# 추출하려는 값의 key를 입력
for i in itemlist['luckyToday']['items']:
    title = i['productName']
    price = i['price'] 
    print('productName=',title,'price=',price)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;굳!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;229&quot; data-filename=&quot;zxzx.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4EEdm/btre4OZsRd8/vVGgeTz5XsvGc4z4csyTiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4EEdm/btre4OZsRd8/vVGgeTz5XsvGc4z4csyTiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4EEdm/btre4OZsRd8/vVGgeTz5XsvGc4z4csyTiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4EEdm%2Fbtre4OZsRd8%2FvVGgeTz5XsvGc4z4csyTiK%2Fimg.png&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;229&quot; data-filename=&quot;zxzx.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또 다른 문제&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;받아오는 데이터의 크기를 보니까 13개의 상품을 받아온다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼... 2페이지는..? 3페이지는? 노답이다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 request 요청에 대해서 조금 만져보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 사진을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;568&quot; data-filename=&quot;zxxzzcvcvcvcvcvcvcvcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8QZqS/btre4Od4vyB/wFVWv89f3tXyzcjXh3xnK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8QZqS/btre4Od4vyB/wFVWv89f3tXyzcjXh3xnK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8QZqS/btre4Od4vyB/wFVWv89f3tXyzcjXh3xnK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8QZqS%2Fbtre4Od4vyB%2FwFVWv89f3tXyzcjXh3xnK1%2Fimg.png&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;568&quot; data-filename=&quot;zxxzzcvcvcvcvcvcvcvcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;잘 보일지는 모르겠다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;params 설정 부분에 &quot;pagingIndex&quot;의 value를 바꾸어주었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;계속해서 데이터가 바뀌는 것을 볼 수 있었다. (페이지 개념이겠지!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1000, 800 등과 같은 아주 큰 수로 설정했을 때, 1000과 800에서의 데이터는 똑같다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;너무나 큰 수를 입력하게 되면, 가장 마지막의 데이터를 Response 한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전략&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링할 때, &quot;pagingIndex&quot;의 value를 기준으로 여러 번 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;previous data를 가지고 새롭게 받은 데이터가 previous data와 같다면 크롤링을 종료한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(더 이상 반환받을 데이터가 없기 때문에!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;previous data를 가져야 하는 이유&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떤 데이터를 입력받아 크롤링을 실행할지, 모른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자가 말도 안 되는 검색어를 입력한다면? 결과 페이지가 2개로 작을 수도 있다. 없을 수도 있다. 그래서 요청을 하고 이전에 응답을 받은 값을 저장해두었다가 다음 요청에 대한 응답이랑 비교를 해준다. 같은 값이 나오면 while문을 종료한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;너무나 많은 메모리를 소모하지 않을까?&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;previous 변수에 계속해서 새로운 값을 할당해서 변수로 인한 고정적인 메모리 사용은 계속해서 유지가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(그리고 크롤링 서버는 크롤링과 DB Write만 하기 때문에 비교적 메모리 여유가 있을 것이다!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;but, 많은 요청이 들어온다면 (고정적 메모리 사용) x 데이터가 없는 요청 수.. 거의 무한으로 증가할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금은 많은 고민을 하지 않고, 개발을 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추 후에, 홀수의 응답 값 내용만 비교 또는 마지막 5개의 응답 값 내용만 비교 등등으로 고치면 된다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제 해결하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 1~9의 pagingIndex를 요청하도록 코드를 작성하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631714784838&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
import json

#헤더는 고정이다.
headers = {
    'authority': 'search.shopping.naver.com',
    'sec-ch-ua': '&quot;Google Chrome&quot;;v=&quot;93&quot;, &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Chromium&quot;;v=&quot;93&quot;',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'logic': 'PART',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
    'sec-ch-ua-platform': '&quot;Windows&quot;',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://search.shopping.naver.com/search/all?query=%EB%AA%A8%EC%9E%90&amp;amp;frm=NVSHATC&amp;amp;prevQuery=%EB%AA%A8%EC%9E%90',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    'cookie': 'NNB=NOLCMFH6MS3WA; NDARK=Y; _ga=GA1.2.36707839.1627031989; _ga_7VKFYR6RV1=GS1.1.1627031988.1.1.1627032122.60; nx_ssl=2; AD_SHP_BID=23; spage_uid=; BMR=s=1631641124319&amp;amp;r=https%3A%2F%2Fm.blog.naver.com%2FPostView.naver%3FisHttpsRedirect%3Dtrue%26blogId%3Dteenager4282%26logNo%3D220962394004&amp;amp;r2=https%3A%2F%2Fwww.google.com%2F; sus_val=G6C9UIqZv3AcfjeJP38FmfXG',
}


responseList = [] # previous랑 비교하기 위한 로직이다.
number = 1
while number &amp;lt; 10 :
  print('number = ',number)
  pageingIndex = number
  params = (
    ('sort', 'rel'),
    ('pagingIndex', 9),
    ('pagingSize', '20'),
    ('viewType', 'list'),
    ('productSet', 'total'),
    ('deliveryFee', ''),
    ('deliveryTypeValue', ''),
    ('frm', 'NVSHATC'),
    ('query', '\uBAA8\uC790'),
    ('origQuery', '\uBAA8\uC790'),
    ('iq', ''),
    ('eq', ''),
    ('xq', ''),
  )
  response = requests.get('https://search.shopping.naver.com/api/search/all', headers=headers, params=params)
  # json을 리스트로 받기
  itemlist = json.loads(response.text)
  # 추출하려는 값의 key를 입력
  for i in itemlist['shoppingResult']['products']:
      title = i['productName']
      price = i['price'] 

      print('productName=',title,'price=',price)

  number = number + 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;python이 익숙하지 않다 보니.. 코드가 개판 같기도 하고..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;콘솔을 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;905&quot; data-filename=&quot;zxcvvvvvvv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHHZF9/btrfc8bzuuK/AQHQeGCNgmc94UGArKSGh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHHZF9/btrfc8bzuuK/AQHQeGCNgmc94UGArKSGh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHHZF9/btrfc8bzuuK/AQHQeGCNgmc94UGArKSGh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHHZF9%2Fbtrfc8bzuuK%2FAQHQeGCNgmc94UGArKSGh1%2Fimg.png&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;905&quot; data-filename=&quot;zxcvvvvvvv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2, 3, 4 마다 달라지는 모습을 볼 수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ㅇㅋ 일단 number 값에 따라 다른 request 완료.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 이제 받은 response를 이전에 받은 response와 같은지 비교해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;단, 첫 번째 비교에는 list가 null 값이니 number가 1일 때는 로직이 수행되지 않도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631722246017&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
import json

headers = {
    'authority': 'search.shopping.naver.com',
    'sec-ch-ua': '&quot;Google Chrome&quot;;v=&quot;93&quot;, &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Chromium&quot;;v=&quot;93&quot;',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'logic': 'PART',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
    'sec-ch-ua-platform': '&quot;Windows&quot;',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://search.shopping.naver.com/search/all?query=%EB%AA%A8%EC%9E%90&amp;amp;frm=NVSHATC&amp;amp;prevQuery=%EB%AA%A8%EC%9E%90',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    'cookie': 'NNB=NOLCMFH6MS3WA; NDARK=Y; _ga=GA1.2.36707839.1627031989; _ga_7VKFYR6RV1=GS1.1.1627031988.1.1.1627032122.60; nx_ssl=2; AD_SHP_BID=23; spage_uid=; BMR=s=1631641124319&amp;amp;r=https%3A%2F%2Fm.blog.naver.com%2FPostView.naver%3FisHttpsRedirect%3Dtrue%26blogId%3Dteenager4282%26logNo%3D220962394004&amp;amp;r2=https%3A%2F%2Fwww.google.com%2F; sus_val=G6C9UIqZv3AcfjeJP38FmfXG',
}

previousItemList = []
preResponse = ''
number = 1
while number &amp;lt; 100 :
  print('number = ',number)
  pageingIndex = number
  params = (
    ('sort', 'rel'),
    ('pagingIndex', pageingIndex),
    ('pagingSize', '20'),
    ('viewType', 'list'),
    ('productSet', 'total'),
    ('deliveryFee', ''),
    ('deliveryTypeValue', ''),
    ('frm', 'NVSHATC'),
    ('query', '\uBAA8\uC790'),
    ('origQuery', '\uBAA8\uC790'),
    ('iq', ''),
    ('eq', ''),
    ('xq', ''),
  )
  response = requests.get('https://search.shopping.naver.com/api/search/all', headers=headers, params=params)
  # json을 리스트로 받기
  itemlist = json.loads(response.text)
  
  # 첫번째 호출에는 list가 비교가 안되니 continue를 한다.
  if number == 1 :
      number = number + 1
      previousItemList = itemlist
      continue
    #아래 if문 비교를 수정해야할 듯 하다..
  if previousItemList['shoppingResult']['products'][0]['productName'] == itemlist['shoppingResult']['products'][0]['productName']:
    print('같아서 끝-----')
    break
  
  previousItemList = itemlist
  
  
  # 추출하려는 값의 key를 입력
  for i in itemlist['shoppingResult']['products']:
      title = i['productName']
      price = i['price'] 

      print('productName=',title,'price=',price)
    


  number = number + 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;로직은 완성되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;똑같은 응답이 왔을 때(더 이상 받을 값이 없을 때), 반복문을 종료하도록 만들자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예시로 number를 10000부터 받도록 해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 코드에서 number = 1을 10000으로 바꾸자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 continue가 포함되어있는 if 체크를 10000으로 바꾸어주자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631722377301&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;number = 10000&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1631722421021&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 10번만 돌리자!
while number &amp;lt; 10011 :&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1631722389958&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  if number == 10000 :
      number = number + 1
      previousItemList = itemlist
      continue&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결과는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;63&quot; data-filename=&quot;zxczxccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bApA5o/btrfbmIGeeq/gTIIkyHeI2qWa43wCy6sC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bApA5o/btrfbmIGeeq/gTIIkyHeI2qWa43wCy6sC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bApA5o/btrfbmIGeeq/gTIIkyHeI2qWa43wCy6sC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbApA5o%2FbtrfbmIGeeq%2FgTIIkyHeI2qWa43wCy6sC0%2Fimg.png&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;63&quot; data-filename=&quot;zxczxccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫 번째 호출 때는 같은 응답을 받았는지 체크를 할 필요가 없어서 넘어갔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;두 번째 호출 때는 10000의 호출과 똑같은 값이어서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;while문을 종료한 모습이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드가 너무 어지럽다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 리펙토링을 해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리팩토링&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1631723465796&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
import json

# Request에서 사용될 header 생성
headers = {
    'authority': 'search.shopping.naver.com',
    'sec-ch-ua': '&quot;Google Chrome&quot;;v=&quot;93&quot;, &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Chromium&quot;;v=&quot;93&quot;',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'logic': 'PART',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
    'sec-ch-ua-platform': '&quot;Windows&quot;',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://search.shopping.naver.com/search/all?query=%EB%AA%A8%EC%9E%90&amp;amp;frm=NVSHATC&amp;amp;prevQuery=%EB%AA%A8%EC%9E%90',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    'cookie': 'NNB=NOLCMFH6MS3WA; NDARK=Y; _ga=GA1.2.36707839.1627031989; _ga_7VKFYR6RV1=GS1.1.1627031988.1.1.1627032122.60; nx_ssl=2; AD_SHP_BID=23; spage_uid=; BMR=s=1631641124319&amp;amp;r=https%3A%2F%2Fm.blog.naver.com%2FPostView.naver%3FisHttpsRedirect%3Dtrue%26blogId%3Dteenager4282%26logNo%3D220962394004&amp;amp;r2=https%3A%2F%2Fwww.google.com%2F; sus_val=G6C9UIqZv3AcfjeJP38FmfXG',
}

## 함수 부분 ##
#####################################################################################################################

def isRepeat(previousItemList, itemList) :
    
    #같은 값을 응답받으면 True 리턴
    if previousItemList['shoppingResult']['products'][0]['productName'] == itemList['shoppingResult']['products'][0]['productName']:
        print('같아서 끝-----')
        return True
    #아니면 False 리턴
    return False

def printData(itemList) :
    # 추출하려는 값의 key를 입력
    for i in itemList['shoppingResult']['products']:
      title = i['productName']
      price = i['price'] 
      print('productName=',title,'price=',price)

def makeRequestAndGetResponse(number) :
    pageingIndex = number

    params = (
      ('sort', 'rel'),
      ('pagingIndex', pageingIndex),
      ('pagingSize', '20'),
       ('viewType', 'list'),
       ('productSet', 'total'),
       ('deliveryFee', ''),
      ('deliveryTypeValue', ''),
        ('frm', 'NVSHATC'),
       ('query', '\uBAA8\uC790'),
       ('origQuery', '\uBAA8\uC790'),
      ('iq', ''),
      ('eq', ''),
      ('xq', ''),
     )

    
    response = requests.get('https://search.shopping.naver.com/api/search/all', headers=headers, params=params)
    return response

## 로직부분 ##
#####################################################################################################################

# 중복 체크를 위한 변수
previousItemList = []

number = 1
while number &amp;lt; 100 :
  print('number = ',number)
  
  # 네이버를 향한 Request 생성 and 네이버로부터 response 받기
  response = makeRequestAndGetResponse(number)

  # json을 리스트로 받기
  itemList = json.loads(response.text)
  
  # 첫번째 호출에는 list가 비교가 안되니 continue를 한다.
  if number == 1 :
      number = number + 1
      previousItemList = itemList
      printData(itemList)
      continue
  
  # 반복 응답 Check Method
  # 응답이 같은 값으로 반복되었는지 확인하는 메서드를 실행한다. True일 경우 중복이라서 break
  if isRepeat(previousItemList, itemList) :
      break
  
  previousItemList = itemList
  
  printData(itemList)
  number = number + 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;훨씬 깔끔하쥬?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음에는 mySQL에 저장하는 작업을 해보자.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Project/SSP - 이미지 검색 및 최저가 검색</category>
      <category>json</category>
      <category>PYTHON</category>
      <category>네이버쇼핑</category>
      <category>스크래핑</category>
      <category>크롤링</category>
      <category>파이썬</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/173</guid>
      <comments>https://bestkingit.tistory.com/173#entry173comment</comments>
      <pubDate>Thu, 16 Sep 2021 01:39:19 +0900</pubDate>
    </item>
    <item>
      <title>[#1 이미지 검색 프로젝트] 크롤링을 해보자!</title>
      <link>https://bestkingit.tistory.com/172</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;SSP에서 가장 핵심적인 크롤링을 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;툴&lt;/li&gt;
&lt;li&gt;라이브러리 설치&lt;/li&gt;
&lt;li&gt;User-Agent&lt;/li&gt;
&lt;li&gt;쿠팡에서 정보 긁어오기&lt;/li&gt;
&lt;li&gt;네이버에서 정보 긁어오기&lt;/li&gt;
&lt;li&gt;번개장터에서 정보 긁어오기&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;툴&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;language : python 3.9.7&lt;/li&gt;
&lt;li&gt;ide&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;: Visual Studio Code&lt;/li&gt;
&lt;li&gt;Browser&amp;nbsp; &amp;nbsp;: Google Chrome&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;라이브러리 설치&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;VS Code에서 개발할 폴더를 생성한다.&lt;/li&gt;
&lt;li&gt;터미널을 켠다.&lt;/li&gt;
&lt;li&gt;개발 폴더로 디렉터리가 설정되어 있지 않아 있다면, cd 명령어를 통해서 현재 프로젝트 폴더로 이동해주자.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;Requests 라이브러리 설치&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 명령어를 입력하자.&lt;/p&gt;
&lt;pre id=&quot;code_1631603413687&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install requests&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Requests 라이브러리는 html을 받아오는데 도움을 주는 라이브러리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;beautifulsoup4 라이브러리 설치&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 명령어를 입력하자.&lt;/p&gt;
&lt;pre id=&quot;code_1631603578748&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install beautifulsoup4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;beautifulsoup4 라이브러리를 통해서 Requests 라이브러리가 받아온 html의 내용을 추출할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;lxml 라이브러리 설치&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631604771458&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install lxml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xml 코드 사용을 도와주는 라이브러리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(html이 대표적인 xml코드)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;User-Agent&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User-Agent는 어떠한 정보를 서버에 요청했을 때, 어느 경로를 통해서 해당 요청을 했는지 알려주는 식별자라고 생각하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 입장에서는 요청한 주체가 휴대폰 or 웹 브라우저 or 기타 중에서 무엇인지 모른다. 그래서 User-Agent를 통해서 식별하도록 약속하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에 사용하고 있는 Chrome, Explorer, iphone, galaxy에서 자동으로 해당 User-Agent를 삽입해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 모른다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User-Agent가 필요한 이유는 휴대폰에 보여주는 화면과 컴퓨터로 보여주는 화면이 다르기 때문이다. 또한 Chrome과 Explorer가 또 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 필요하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631604020030&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시를 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 브라우저 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 기기 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 기기 cpu 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 기기 os 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;등등 많은 정보를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User-Agent를 확인해보자. 다음 링크를 들어가 보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631604122949&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;Website&quot; data-og-title=&quot;What is my user agent?&quot; data-og-description=&quot;Every request your web browser makes includes your User Agent; find out what your browser is sending and what this identifies your system as.&quot; data-og-host=&quot;www.whatismybrowser.com&quot; data-og-source-url=&quot;https://www.whatismybrowser.com/detect/what-is-my-user-agent&quot; data-og-url=&quot;https://www.whatismybrowser.com/detect/what-is-my-user-agent&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/SoO7r/hyLByP39lh/jS7nCdxkdBkYOfEC7CdZXK/img.png?width=670&amp;amp;height=670&amp;amp;face=0_0_670_670&quot;&gt;&lt;a href=&quot;https://www.whatismybrowser.com/detect/what-is-my-user-agent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.whatismybrowser.com/detect/what-is-my-user-agent&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/SoO7r/hyLByP39lh/jS7nCdxkdBkYOfEC7CdZXK/img.png?width=670&amp;amp;height=670&amp;amp;face=0_0_670_670');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;What is my user agent?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Every request your web browser makes includes your User Agent; find out what your browser is sending and what this identifies your system as.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.whatismybrowser.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크에 들어가면 다음 사진과 같은 글이 보일 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;149&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGwnWI/btreXqyD85S/BXb2fsln6gzylxjjMlnIk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGwnWI/btreXqyD85S/BXb2fsln6gzylxjjMlnIk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGwnWI/btreXqyD85S/BXb2fsln6gzylxjjMlnIk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGwnWI%2FbtreXqyD85S%2FBXb2fsln6gzylxjjMlnIk0%2Fimg.png&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;149&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 window, chrome을 이용하여 접속했다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;쿠팡에서 정보 긁어오기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에 대해서 설명 없이 바로 시작하는 감이 있지만, 코드를 보면 바로 이해가 갈 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저, 쿠팡 사이트 URL이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠팡을 접속하여 링크를 가지고 오자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;1. 쿠팡에 접속한다.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;2. 검색창에 아무거나 검색해본다.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;163&quot; data-filename=&quot;ZCC.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djuRtp/btre0bNSahg/nfFUrFuBplo9K7GoQoVa40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djuRtp/btre0bNSahg/nfFUrFuBplo9K7GoQoVa40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djuRtp/btre0bNSahg/nfFUrFuBplo9K7GoQoVa40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjuRtp%2Fbtre0bNSahg%2FnfFUrFuBplo9K7GoQoVa40%2Fimg.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;163&quot; data-filename=&quot;ZCC.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;3. URL을 확인한다.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;44&quot; data-filename=&quot;XZCVV.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WUiNC/btreZ1EEmos/GCEpIWKx51Tx0QrpHGE4K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WUiNC/btreZ1EEmos/GCEpIWKx51Tx0QrpHGE4K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WUiNC/btreZ1EEmos/GCEpIWKx51Tx0QrpHGE4K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWUiNC%2FbtreZ1EEmos%2FGCEpIWKx51Tx0QrpHGE4K0%2Fimg.png&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;44&quot; data-filename=&quot;XZCVV.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;4. 다른 것을 검색해보자.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 &quot;니트&quot;를 검색했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;5. URL을 확인해보자.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;43&quot; data-filename=&quot;XCVCVVVVVVV.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/slPMA/btreZ0eGylx/vsKzZFeR61H9AZbyJubei0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/slPMA/btreZ0eGylx/vsKzZFeR61H9AZbyJubei0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/slPMA/btreZ0eGylx/vsKzZFeR61H9AZbyJubei0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FslPMA%2FbtreZ0eGylx%2FvsKzZFeR61H9AZbyJubei0%2Fimg.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;43&quot; data-filename=&quot;XCVCVVVVVVV.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;6. 어떤 점이 달라지는지 확인해보자.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL을 통해서 GET 방식으로 요청하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파라미터는 component, q, channel이 있다. component와 channel은 모르겠고, q에 검색하려는 내용을 넣을 수 있다는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;7. 찾으려는 내용이 어떻게 구성되어있는지 살펴보자.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 찾으려는 내용은 다음 사진에 나와있는 가격과 제목이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;603&quot; data-filename=&quot;cvcvcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be0Lkb/btreYbOP9Ub/FbOPBB7E4vIErboL6d6szK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be0Lkb/btreYbOP9Ub/FbOPBB7E4vIErboL6d6szK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be0Lkb/btreYbOP9Ub/FbOPBB7E4vIErboL6d6szK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe0Lkb%2FbtreYbOP9Ub%2FFbOPBB7E4vIErboL6d6szK%2Fimg.png&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;603&quot; data-filename=&quot;cvcvcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 도구를 실행하여 해당 태그에 대한 정보를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제목은&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;29&quot; data-filename=&quot;z11.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xvEJP/btreT5akPmV/rKr0DhQGqlsIIjuZGiLtg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xvEJP/btreT5akPmV/rKr0DhQGqlsIIjuZGiLtg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xvEJP/btreT5akPmV/rKr0DhQGqlsIIjuZGiLtg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxvEJP%2FbtreT5akPmV%2FrKr0DhQGqlsIIjuZGiLtg0%2Fimg.png&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;29&quot; data-filename=&quot;z11.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;div 태그&quot;와 &quot;class = name&quot; 이라는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가격은&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;28&quot; data-filename=&quot;z22.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbIn7/btreY2joInv/SCUZkbHIZpHqcPBK3K2pA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbIn7/btreY2joInv/SCUZkbHIZpHqcPBK3K2pA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbIn7/btreY2joInv/SCUZkbHIZpHqcPBK3K2pA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbIn7%2FbtreY2joInv%2FSCUZkbHIZpHqcPBK3K2pA1%2Fimg.png&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;28&quot; data-filename=&quot;z22.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;strong 태그&quot; 와 &quot;class = price-value&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그럼 코딩을 해보자!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631604862249&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
from bs4 import BeautifulSoup # BeautifulSoup 라이브러리 import

# User-Agent 지정
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'}

# 긁어오려는 사이트 URL
url = &quot;https://www.coupang.com/np/search?component=&amp;amp;q=가디건&amp;amp;channel=user&quot;

# res에는 해당 url의 html이 들어있다.
res = requests.get(url, headers= headers)

# 받아온 html을 soup에 입력
soup = BeautifulSoup(res.text, &quot;lxml&quot;)

# 추출한 후 print
print(soup.find(&quot;div&quot;, attrs ={&quot;class&quot;:&quot;name&quot;}).get_text())
print(soup.find(&quot;strong&quot;, attrs ={&quot;class&quot;:&quot;price-value&quot;}).get_text())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL : 내용을 보면 &quot;가디건&quot;을 통해서 입력했다는 것을 알 수 있다. 사용자가 입력한 값에 따라 해당 &quot;가디건&quot; 부분을 수정해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;soup.find : 태그를 찾는 메서드이다. 속성을 추가로 기입하여 더 상세히 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 화면은..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;45&quot; data-filename=&quot;xcvv3.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2As0v/btreYlwIvof/hKyMJilHVpaUHweWJkkBXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2As0v/btreYlwIvof/hKyMJilHVpaUHweWJkkBXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2As0v/btreYlwIvof/hKyMJilHVpaUHweWJkkBXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2As0v%2FbtreYlwIvof%2FhKyMJilHVpaUHweWJkkBXk%2Fimg.png&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;45&quot; data-filename=&quot;xcvv3.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 출력된 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 해당 값이 나왔다고 해당 게시물이 최상단에 있는 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 html 구조를 css를 통해서 조작했을 가능성이 높기 때문이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이러한 내용을 긁어왔을 때, 이미지 객체 추출 작업, DB insert 작업을 해주면 그만이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;네이버에서 정보 긁어오기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 쿠팡과 같은 방법으로 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수행한 사이트는 &quot;네이버 쇼핑&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631607637364&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests #requests 라이브러리 import
from bs4 import BeautifulSoup # BeautifulSoup 라이브러리 import

# User-Agent 지정
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'}

# 긁어오려는 사이트 URL
url = &quot;https://search.shopping.naver.com/search/all?query=신발&amp;amp;cat_id=&amp;amp;frm=NVSHATC&quot;

# res에는 해당 url의 html이 들어있다.
res = requests.get(url, headers= headers)

# 받아온 html을 soup에 입력
soup = BeautifulSoup(res.text, &quot;lxml&quot;)

# 추출한 후 print
print(soup.find(&quot;a&quot;, attrs ={&quot;class&quot;:&quot;basicList_link__1MaTN&quot;}).get_text())
print(soup.find(&quot;span&quot;, attrs = {&quot;class&quot;:&quot;price_num__2WUXn&quot;}).get_text())&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롤링해서 정상적으로 받아와 지는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 받아온 데이터를 입맛에 맞게 변형해주고 해당 데이터들을 mySQL에 저장해보자.&lt;/p&gt;</description>
      <category>Project/SSP - 이미지 검색 및 최저가 검색</category>
      <category>PYTHON</category>
      <category>검색</category>
      <category>쇼핑</category>
      <category>스크래핑</category>
      <category>최저가</category>
      <category>크롤링</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/172</guid>
      <comments>https://bestkingit.tistory.com/172#entry172comment</comments>
      <pubDate>Tue, 14 Sep 2021 17:42:25 +0900</pubDate>
    </item>
    <item>
      <title>[#0 이미지 검색 프로젝트] 프로젝트 계획</title>
      <link>https://bestkingit.tistory.com/171</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에 새롭게 구상한 프로젝트를 실시할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트에 대한 전반적인 계획을 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;SSP - Search Shop &amp;amp; Price&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 프로젝트는 이미지 검색, 최저가 검색을 구현하는 서비스이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목적&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 서비스를 개발하게 된 이유는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631600515121&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;친구가 특이한 스타일의 옷을 찾고있었다. 
친구가 검색한 검색어는 &quot;등에 지퍼가 있는 후드티&quot;였다. 
나올리가 있나... 
많이 답답해보였다. 생각해보니까 나 또한 같은 문제로 검색에 어려움을 느낀적이 있다. 

개발해보자!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전체적으로 어려울 것이라 생각되어 덜컥 겁이 났다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데 &quot;세상 살다 보면 이것보다 어려운 문제들이 많은데 이것도 성공하지 못하면 다른 문제는 어쩔래? 라는 생각이 들어, 바로 개발해야겠다는 생각이 들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;본론으로 돌아가 목적을 다시 이야기하자면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이미지 검색 서비스를 개발하여 많은 사람들에게 좀 더 나은 세상을 살아갈 수 있게 도와주기 위함이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;데이터 입출력 및 기술스택&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #0593d3; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;데이터는 어디서 구하나?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터는 Python의 BeautifulSoup을 이용하여, 크롤링을 할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 사이트는 네이버, 쿠팡이다. (더 추가할 수도, 줄일 수도 있다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #0593d3; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;데이터 입출력&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;입력&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Python이 동작하는 서버는 DB Insert만 수행한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;출력&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바/스프링 서버에서 DB를 읽어와서, 사용자에게 http - json 형태로 Response 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;DB 기술 스택&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;mySQL을 이용할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;DB 분산화&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB Replication을 이용하여 master - slave1, slave2까지 구현할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아직 정확히는 정하지 않았지만 MMM or MHA 방식을 구현할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(DB 분산화에 대한 공부가 부족하여 계획에서 문제가 있을 수도..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;※ 이미지 검색에 필요한 이미지 인식 컴포넌트? 들에 대한 데이터도 추가할 예정이다. 공부해야 확실히 말할 수 있을 것 같아서 일단 생략해둔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;데이터 구성&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터 내용은 다음과 같이 구성할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;NAME : 실제 웹사이트에 등록된 상품 이름&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URL : 해당 상품의 href&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;PRICE : 해당 상품의 가격&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이미지 인식에 필요한 기타 데이터들..&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;서버&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버는 총 2~3개가 될 듯하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;프론트 서버&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹에서 동작하는 프론트 서버가 될 듯하다. (프론트 실력이 없어서 아주 저급할 수도..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JS를 이용하여 사용자가 Canvas에 그림을 그려 검색을 하면, 그림을 분석하여 자바/스프링 서버에 넘긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;백엔드 서버&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바/스프링으로 구성된 서버다. 프론트와 http - json 통신을 한다. DB에서 출력을 주로 한다. 가능하면 수정도 적용할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 백엔드 서버 분산화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;임시 서버를 2~3개 더 생성할 예정이다. (해당 내용은 공부가 부족하다.. 공부하고 수정하자!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버 2개는 AWS를 사용할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;b&gt;DB 서버&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;앞서 이야기했던, python으로 구성할 예정이다. 해당 서버는 백엔드와 소통하지 않는다. 단순 입력만 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;일정&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;구체적인 일정은 아직 생각 중이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개략적으로 보면 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style14&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;9월 3주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;9월 4주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;10월 1주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;10월 2주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;10월 3주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;10월 4주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;11월 1주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;11월 2주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;11월 3주&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롤링 구현&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB 설계&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;백엔드 구현&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프론트엔드 구현&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이미지 인식 구현&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB 서버 분산화&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;백엔드 서버 분산화&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;배포&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.558%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기타 및 유지보수&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25582%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.13956%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.06982%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.76744%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.6512%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.65104%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.53492%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18609%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 9.18605%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;버전 관리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;툴 : git / github&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;브랜치 전략 : main / develop / release&amp;nbsp; / hotfix / feature&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;백엔드 api 설계&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 추후에 포스팅할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;걱정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;학교 공부, ADYB 프로젝트, CS 공부, 자바 공부, 코드 공부... 많다!!!!!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래도 해야지 ㅋㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파이팅이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;미래의 영호야&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project/SSP - 이미지 검색 및 최저가 검색</category>
      <category>backend</category>
      <category>db</category>
      <category>FRONT</category>
      <category>PYTHON</category>
      <category>server</category>
      <category>spring</category>
      <category>계획</category>
      <category>크롤링</category>
      <category>프로젝트</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/171</guid>
      <comments>https://bestkingit.tistory.com/171#entry171comment</comments>
      <pubDate>Tue, 14 Sep 2021 16:04:59 +0900</pubDate>
    </item>
    <item>
      <title>[#1 코드로 이해하는 객체지향 설계]  객체, 설계</title>
      <link>https://bestkingit.tistory.com/170</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대망의 첫 장이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아 시작하기 전에, 저자님이 핵심적으로 전해주는 말이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 책은 프로그래밍 패러다임의 &quot;객체지향 패러다임&quot;에 대해서 설명하는 책이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;객체지향 패러다임은 계속해서 발전하고 변화하고 있다. 우리가 공부하는 &quot;객체지향 패러다임&quot;은 버스 노선 중 1개다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 현재의 정류소에서 &quot;객체지향 패러다임&quot; 버스를 탑승할 뿐이다. 탑승하여(책을 이해하여) 패러다임의 종점까지 함께 달려보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1장 객체, 설계&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1장에서 저자님은 추상적인 이론에 대한 설명보단, 코드를 통해서 몸소 느껴봄을 강조한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드를 통해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;객&lt;/b&gt;&lt;b&gt;체지향 프로그램을 설계하고 유지 보수하는 데 필요한 원칙과 기법&lt;/b&gt;&lt;/span&gt;을 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;알아보고 핵심적인 내용을 정리해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #0593d3;&quot;&gt;1장에서의 저자님이 말하고자하는 의견은,&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631528556913&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;좋은 설계를 하여야 한다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇다면 좋은설계는 무엇일까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631528589822&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;오늘 요구하는 기능을 온전히 수행하면서 내일의 변경을 매끄럽게 수용할 수 있는 설계&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #0593d3;&quot;&gt;위에서 말하는 좋은설계는 어떻게 하는 걸까?&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631528701677&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;객체지향 설계를 하도록 노력해야한다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;객체지향 설계&quot;는 어떻게 해야 하는 걸까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;책에서는 절차 지향의 예시 코드를 통해서 비유를 해주었다. 1장에서 나오는 &quot;객체지향으로의 첫걸음&quot;은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631529424942&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;캡슐화&quot;를 이용하여 의존성을 제거하자.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;의존성이란 무엇일까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;말 그대로 하나의 객체가 다른 객체에 의존하고 있다는 것을 말한다. 의존성이 많이 존재하게 된다면 아주 작은 요구사항이 변경되었을 때, 체인 효과가 일어나 아주 거대한 유지보수가 필요할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;의존성을 최대한 제거하여 각 객체마다 독자적인 &quot;책임&quot;을 가지도록 하여야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;책임이란?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631532032397&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;책임을 각 객체에게 나누어주는 것이 &quot;객체지향 설계&quot;의 핵심이다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;책임을 각 개체에게 나누어주면, 요구사항이 변경되어 유지보수가 필요할 때 해당 객체만 바꾸어주면 되는 효과가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2장 객체지향 프로그래밍&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #0593d3;&quot;&gt;2장에서의 저자님이 말하는 핵심은 다음과 같다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631534201732&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;코드를 유연하게 하라.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드를 유연하게 한다는 것이 무슨 말일까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;유연&quot;을 책에서는 예시를 통해서 설명해주니, 보고 이해한 내 생각을 써본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631534569510&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;하나의 코드를 고정시키고 성격이 비슷한 객체들을 해당 코드 1개로만 운영하는 것&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;쓰고 보니 좀 이상하다.. 다시 이야기하자면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;자판기를 떠올려라. 자판기의 음료수 캔들은 같은 틀을 가지고 있지만 전부 다른 음료수이다. 자판기는 어떤 음료수가 올지 모르는 상태에서 틀만 정해두었을 뿐이다.&quot;라고 생각하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드를 유연하게 하는 것 또한 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드를 어떻게 유연하게 할까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;저자가 추천하는 핵심적인 방법은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631534767194&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;상속과 인터페이스를 이용하라&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상속과 인터페이스의 다형성을 이용하는 방법이 대표적이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;※ 아주아주 비슷한 게 &quot;오버 로딩&quot;이 있다. &quot;오버 로딩&quot;은 파라미터에 따라 다른 코드를 동작시킬 수 있다. 하나 다형성을 이용한 코드는 일괄처리되는 것이 특징(파라미터를 넘긴 다음 동작이 달라짐!!)이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다형성이란 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631534959959&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;동일한 파라미터를 전송하지만 실제로 어떤 메서드가 실행될 것인지는
메세지를 수신하는 객체의 클래스가 무엇이냐에 따라 달라진다&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1~2장에서는 객체지향 프로그래밍을 구성하는 다양한 요소와 구현 기법을 살펴봤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클래스, 추상 클래스, 인터페이스를 조합해서 객체지향 프로그램을 구조화하는 기본적인 방법과 상속을 이용해 다형성을 구현하는 기법을 소개했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 시간에는 &quot;역할, 책임, 협력&quot;을 좀 더 상세히 알아보도록 하자!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>학교공부/자바의 왕!</category>
      <category>object</category>
      <category>객체</category>
      <category>객체지향</category>
      <category>다형성</category>
      <category>상속</category>
      <category>인터페이스</category>
      <category>자바</category>
      <category>추상화</category>
      <category>캡슐화</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/170</guid>
      <comments>https://bestkingit.tistory.com/170#entry170comment</comments>
      <pubDate>Mon, 13 Sep 2021 21:15:20 +0900</pubDate>
    </item>
    <item>
      <title>[#0 오브젝트 - 코드로 이해하는 객체지향 설계] 정주행 시작!</title>
      <link>https://bestkingit.tistory.com/169</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문득 답답한 마음에 가까운 서점을 가서 IT 서적을 둘러보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수많은 서적중에서 유난히 나의 눈길을 끌었던 책이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 책의 이름은&lt;b&gt; &quot;오브젝트 / 코드로 이해하는 객체지향 설계&quot; - 조영호 지음&quot;&lt;/b&gt; 이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 펴보지도 않았다. 그냥 너무 읽고싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무작정 구매를 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구매를 하고 목차를 살펴보니, 내가 매일매일 고민했던 객체에 관해서 수많은 예시와 다양한 시각으로 풀어서 꼭꼭 눌러담은 느낌이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정성들여 책을 정독할 것이지만, 객체에 대한 나의 호기심을 100% 채워줄 수는 없을 것이다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(객체는 너무 방대하니까!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 단 1%라도 채울 수 있다면 나는 만족이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 매일매일 이 책을 읽으며 내가 다시 읽을 수 있도록 요약 정리를 해볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 TOPDOWN 방식으로 &amp;nbsp;웹 API 디자인 &amp;gt;&amp;nbsp; Clean Code &amp;amp; Effective Java를 읽어볼 예정이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순탄하게 완료하기를..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>학교공부/자바의 왕!</category>
      <category>객체</category>
      <category>오브젝트</category>
      <category>정독</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/169</guid>
      <comments>https://bestkingit.tistory.com/169#entry169comment</comments>
      <pubDate>Mon, 13 Sep 2021 18:03:01 +0900</pubDate>
    </item>
    <item>
      <title>[#7 SpringBoot 정주행] ViewResolver를 만들어보자!</title>
      <link>https://bestkingit.tistory.com/168</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631507996263&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기&quot; data-og-description=&quot;이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View &amp;amp; 또 다른 Servlet으로 넘겨주는 함수가 모든 컨트롤러에 적용된다는 것&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/167&quot; data-og-url=&quot;https://bestkingit.tistory.com/167&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4Gfut/hyLzWxty8b/s6dEbUQjXhm1W9cd5OkTbK/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/tmA7O/hyLz5BcgdF/QoL0ObghWKvIslo1hA6k4k/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/bmK2Yk/hyLzUfmqvC/q8ndvD5Yk12lKmIckfVns1/img.png?width=1225&amp;amp;height=769&amp;amp;face=0_0_1225_769&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/167&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/167&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4Gfut/hyLzWxty8b/s6dEbUQjXhm1W9cd5OkTbK/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/tmA7O/hyLz5BcgdF/QoL0ObghWKvIslo1hA6k4k/img.png?width=800&amp;amp;height=502&amp;amp;face=0_0_800_502,https://scrap.kakaocdn.net/dn/bmK2Yk/hyLzUfmqvC/q8ndvD5Yk12lKmIckfVns1/img.png?width=1225&amp;amp;height=769&amp;amp;face=0_0_1225_769');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다. 하지만 View의 Path를 설정하는 부분과, Servlet에서 View &amp;amp; 또 다른 Servlet으로 넘겨주는 함수가 모든 컨트롤러에 적용된다는 것&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 포스팅에 문제점이 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- path에 &quot;/WEB-INF/views/&quot;와 &quot;. jsp&quot;의 중복&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- &lt;b&gt;HttpServletRequest, HttpServletResponse의 불필요한 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅에서 viewResolver를 통해서 위의 문제를 해결해볼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller 수정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController 수정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model 추가&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금까지는 서블릿에 종속적인 HttpServletRequest를 사용해왔다! 또한 Model도 request에 저장했다. 이제 서블릿에 종속적인 성격을 없애고, view path까지 전달하는 Model을 생성해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model 코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model.java&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631509937743&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Model {
    private String viewTitle;
    private Map&amp;lt;String, Object&amp;gt; model = new HashMap&amp;lt;&amp;gt;();
    public Model(String viewTitle) {
        this.viewTitle = viewTitle;
    }
    public String getViewName() {
        return viewTitle;
    }
    public void setViewName(String viewName) {
        this.viewTitle = viewName;
    }
    public Map&amp;lt;String, Object&amp;gt; getModel() {
        return model;
    }
    public void setModel(Map&amp;lt;String, Object&amp;gt; model) {
        this.model = model;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;viewTitle : Controller가 반환하는 view의 이름이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;model&amp;nbsp; &amp;nbsp; : Controller가 View에 전달하려는 데이터이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller 수정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음으로는 Controller가 Model객체를 이용하도록 바꾸어주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserRegisterController.java 수정&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631510665142&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserRegisterController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();

    @Override
    public Model logic(Map&amp;lt;String, String&amp;gt; requestResponseMap) throws ServletException, IOException {
		
        /*
        * 서블릿으로 넘어온 내용 파싱
        */
        String username = (String) requestResponseMap.get(&quot;username&quot;); 
        int age = Integer.parseInt((String) requestResponseMap.get(&quot;age&quot;));
 
 
 		//이 부분에서 validation 처리 해야 함! (인터셉터나 필터링으로 낚아채서 해도되고..)
		
        /*
        * Repository에 User 정보 저장
        */
        User user = new User(Long.parseLong(username), age);
        userRepository.save(user);
		
        /*
        * 사용자에게 반환할 View의 정보를 담고있는 Model 생성 후 반환
        */
        Model model = new Model(&quot;userList&quot;);
        model.getModel().put(&quot;user&quot;, user);

        return model;

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserListController.java 수정&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631510587463&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserListController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();
    @Override
    public Model logic(Map&amp;lt;String, String&amp;gt; requestResponseMap) throws ServletException, IOException {
        List&amp;lt;User&amp;gt; users = userRepository.findAll();

        Model model = new Model(&quot;users&quot;);
        model.getModel().put(&quot;users&quot;, users);

        return model;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;BoardListController.java 수정&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631510713345&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class BoardListController implements TestController{

    //board Repository 필요

    @Override
    public Model logic(Map requestResponseMap) throws ServletException, IOException {

        String path = &quot;boardlist&quot;;
        
        //board Repository에서 board정보를 찾고 Model의 Map에 해당 Object를 저장해야함
        return new Model(path);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 전에는 View를 직접 만들어 넘겨주었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 이제는 Model이라는 객체를 따로 만들어서 반환을 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController 수정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller가 반환하는 타입이 바뀌었으니, FrontController에도 적용해주어야 한다. 그리고 pathTitle로 반환이 되므로, FrontController에서 suffix, prefix를 더해주는 작업을 해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 코드는 해당 기능들을 적용한 코드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController.java&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631511274084&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//servlet/test로 시작하는 모든 URI요청은 여기로 받는다.
@WebServlet(name = &quot;frontController&quot;, urlPatterns = &quot;servlet/test/*&quot;)
public class FrontController extends HttpServlet {

    private Map&amp;lt;String, TestController&amp;gt; controllerList = new HashMap&amp;lt;&amp;gt;();

// Controller는 총 3개이다.
    public FrontController(){
        controllerList.put(&quot;servlet/test/boardList&quot;, new
                BoardListController());
        controllerList.put(&quot;servlet/test/register&quot;, new
                UserRegisterController());
        controllerList.put(&quot;servlet/test/Users&quot;, new
                UserListController());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse
            resp)
            throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        TestController controller = controllerList.get(requestURI);
        if (controller == null) {
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

		// 서블릿에서 넘어온 request와 response를 Map에 담아준다.
        Map&amp;lt;String, String&amp;gt; requestResponseMap = createParamMap(req);
        
        // Contrller에서 반환하는 Model을 받는다.
        Model afterControllerModel= controller.logic(requestResponseMap);
		
        // Model에 있는 viewTitle을 받는다.
        // getter에 오타가 있다.. (예제 코드를 보며 쓰다보니..)
        String viewName = afterControllerModel.getViewName();
		
        // viewTitle에 suffix와 prefix를 붙이는 viewResolver를 동작시킨다.
        View view = viewResolver(viewName);
        
        // view로 넘겨준다.
        view.render(afterControllerModel.getModel(), req, resp);


    }
    
    // 서블릿으로부터 넘어오는 req, resp를 Map에 파싱해주는 메소드
    private Map&amp;lt;String, String&amp;gt; createParamMap(HttpServletRequest request) {
        Map&amp;lt;String, String&amp;gt; requestResponseMap = new HashMap&amp;lt;&amp;gt;();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -&amp;gt; requestResponseMap.put(paramName,
                        request.getParameter(paramName)));
        return requestResponseMap;
    }
    
    // viewTitle에 suffix와 prefix를 붙여주는 메소드
    private View viewResolver(String viewName) {
        return new View(&quot;/WEB-INF/views/&quot; + viewName + &quot;.jsp&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주석을 하나씩 달아두었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전체적인 흐름을 순서대로 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자의 요청이 온다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController로 가장 먼 저 도착한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FC는 요청 정보를 보고 해당하는 Controller의 logic 함수를 실행한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller는 로직을 수행하고 Model 객체(이제.. view 데이터, view title을 곁들인)를 반환한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FC는 Model을 받고 model의 view title을 view Resolver를 통해 suffix, prefix를 붙여준다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;view를 실행한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;글을 마치며..&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿 종속성을 제거했다!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;view 코드 중복 문제를 해결했다!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또또또또또또 문제가 있다..ㅋㅋㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;문제는&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;개발자가 귀찮다. Model - View구조를 생각하며 하기엔 너무 힘겹다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;매번 객체를 만들어주고 객체를 반환해주고..&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;그래서 다음 포스팅에서는 개발자가 편하게 개발할 수 있는 방향으로 코드를 수정해보자!&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>map</category>
      <category>model</category>
      <category>spring</category>
      <category>springboot</category>
      <category>view</category>
      <category>viewpath</category>
      <category>ViewResolver</category>
      <category>백엔드</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/168</guid>
      <comments>https://bestkingit.tistory.com/168#entry168comment</comments>
      <pubDate>Mon, 13 Sep 2021 14:42:59 +0900</pubDate>
    </item>
    <item>
      <title>[#6-2 Spring Boot 정주행] View Path를 없애보자! ㅣ MVC 프레임워크 만들기</title>
      <link>https://bestkingit.tistory.com/167</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 포스팅에서 FrontController를 통해서 공통 처리를 가능하게 하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 View의 Path를 설정하는 부분과, Servlet에서 View &amp;amp; 또 다른 Servlet으로 넘겨주는 함수가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 컨트롤러에 적용된다는 것을 알 수가 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅은 View Path 중복 코드 문제를 해결한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 이전 포스팅의 코드를 계속해서 사용할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631431484514&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#6 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자&quot; data-og-description=&quot;이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다! 하지만 문제가 있었다. 이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서 MVC 프레임워크를 만&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/166&quot; data-og-url=&quot;https://bestkingit.tistory.com/166&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/A5DUj/hyLzTzPJbv/uVHXu1uVv0eRIufQqNqML0/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/sJxyK/hyLyX4SxZt/6Xk7tcSEpJI55WWNN8AjQK/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/ctT3RA/hyLyOmAzRa/hBsLFlSRHzgxgWK3Vn8Qr1/img.png?width=979&amp;amp;height=589&amp;amp;face=0_0_979_589&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/166&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/166&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/A5DUj/hyLzTzPJbv/uVHXu1uVv0eRIufQqNqML0/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/sJxyK/hyLyX4SxZt/6Xk7tcSEpJI55WWNN8AjQK/img.png?width=800&amp;amp;height=462&amp;amp;face=0_0_800_462,https://scrap.kakaocdn.net/dn/ctT3RA/hyLyOmAzRa/hBsLFlSRHzgxgWK3Vn8Qr1/img.png?width=979&amp;amp;height=589&amp;amp;face=0_0_979_589');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#6 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다! 하지만 문제가 있었다. 이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서 MVC 프레임워크를 만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전략&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;FrontController 수정&lt;/li&gt;
&lt;li&gt;문제점&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전략&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;생각해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;view의 Path 설정 코드가 중복되는 것을 막기위해서는 어떻게 해야 할까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내 생각에는 다음 방법을 사용하면 좋을 듯하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631431642907&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. View 라는 새로운 객체를 만든다.
2. 컨트롤러에서 View 객체에 Path를 지정한다.
3. 컨트롤러는 FrontController에 View를 리턴한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;말로 해서 잘 이해가 안 될 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 코드로 직접 보도록 하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 적용&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 먼저 View를 생성해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;View.java 생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631431927626&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class View {

    private String path;

    public View(String path){

        this.path = path;

    }

    public void render(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;render를 보면 이전에 중복 문제가 있던 코드가 있는 것을 볼 수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도메인도 하나 추가해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User.java 생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631432493345&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class User {

    Long name;
    int age;

    public User(){
        ;
    }
    public User(Long userName, int userAge){
        this.name = userName;
        this.age = userAge;
    }
    public Long getName() {
        return name;
    }

    public void setName(Long name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 User를 저장할 Repository도 만들어보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserRepository.java 생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631432617389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserRepository {

    private static Map&amp;lt;Long, User&amp;gt; store = new HashMap&amp;lt;&amp;gt;();
    private static long sequence = 0L;
    private static final UserRepository instance = new UserRepository();
    public static UserRepository getInstance() {
        return instance;
    }
    private UserRepository() {
    }
    public User save(User user) {
        user.setName(++sequence);
        store.put(user.getName(), user);
        return user;
    }
    public User findById(Long id) {
        return store.get(id);
    }
    public List&amp;lt;User&amp;gt; findAll() {
        return new ArrayList&amp;lt;&amp;gt;(store.values());
    }
    public void clearStore() {
        store.clear();
    }


};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring의 IOC, DI를 이용하면 Static 없이 편하게 사용할 수 있겠지만, 현재는 스프링을 사용하지 않으니까 Static으로 임시적으로 싱글톤 Repository를 사용하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 Controller를 더 만들어보자. (각자 다른 Path와 logic 메서드를 가지기 위해서)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserRegister.java 추가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631433492284&quot; class=&quot;java&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserRegisterController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();

    @Override
    public View logic(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String username = req.getParameter(&quot;username&quot;);
        int age = Integer.parseInt(req.getParameter(&quot;age&quot;));
        User user = new User(Long.parseLong(username), age);
        userRepository.save(user);
        req.setAttribute(&quot;user&quot;, user);
        return new View(&quot;/WEB-INF/views/userList.jsp&quot;);

    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserListController.java 추가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631433383472&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserListController implements TestController{

    private UserRepository userRepository = UserRepository.getInstance();
    @Override
    public View logic(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        List&amp;lt;User&amp;gt; users = userRepository.findAll();
        request.setAttribute(&quot;users&quot;, users);
        return new View(&quot;/WEB-INF/views/members.jsp&quot;);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;BoardListController.java 추가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631433226568&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class BoardListController implements TestController{

    //board Repository 필요

    @Override
    public View logic(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String path = &quot;/WEB-INF/views/boardlist.jsp&quot;;

        //board List를 request에 포함 시켜 return 해야 함.

        return new View(path);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController.java 수정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController에도 수정해야 할 부분이 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;View가 추가되었으니, Controller가 뱉은 View의 render를 실행해주는 메서드를 추가해야 한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631433950314&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;frontController&quot;, urlPatterns = &quot;servlet/test/*&quot;)
public class FrontController extends HttpServlet {

    private Map&amp;lt;String, TestController&amp;gt; controllerList = new HashMap&amp;lt;&amp;gt;();

    public FrontController(){
        controllerList.put(&quot;servlet/test/boardList&quot;, new
                BoardListController());
        controllerList.put(&quot;servlet/test/register&quot;, new
                UserRegisterController());
        controllerList.put(&quot;servlet/test/Users&quot;, new
                UserListController());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse
            resp)
            throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        TestController controller = controllerList.get(requestURI);
        if (controller == null) {
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        View view= controller.logic(req, resp);

        view.render(req, resp);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 완벽히 수행하는 것을 볼 수 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최종적으로 완성한 내용을 그림으로 도식화해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1225&quot; data-origin-height=&quot;769&quot; data-filename=&quot;view도입.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFYMKU/btreTHykLti/yjnM2O7Kt4wLAYPW7zcof1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFYMKU/btreTHykLti/yjnM2O7Kt4wLAYPW7zcof1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFYMKU/btreTHykLti/yjnM2O7Kt4wLAYPW7zcof1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFYMKU%2FbtreTHykLti%2FyjnM2O7Kt4wLAYPW7zcof1%2Fimg.png&quot; data-origin-width=&quot;1225&quot; data-origin-height=&quot;769&quot; data-filename=&quot;view도입.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또또... 문제가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;path에 &quot;/WEB-INF/views/&quot;와 &quot;. jsp&quot;가 중복된다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #f3c000;&quot;&gt;HttpServletRequest, HttpServletResponse가 꼭 필요하진 않다!&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 다음 포스팅에는 해당 문제점을 해결하는 방향대로 가보자!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 포스팅 글은 : 인프런의 &quot;김영한 개발자님의 강의 - Spring MVC 1편&quot;을 참고하여 작성했습니다.&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>Controller</category>
      <category>frontcontroller</category>
      <category>MVC</category>
      <category>path</category>
      <category>servlet</category>
      <category>spring</category>
      <category>view</category>
      <category>web</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/167</guid>
      <comments>https://bestkingit.tistory.com/167#entry167comment</comments>
      <pubDate>Sun, 12 Sep 2021 17:18:37 +0900</pubDate>
    </item>
    <item>
      <title>[#6-1 Spring Boot 정주행] MVC 프레임워크를 직접 만들어보자</title>
      <link>https://bestkingit.tistory.com/166</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전에 포스팅한 글에서 서블릿 dispatcher를 통해서 JSP를 반환하는 것까지 성공했다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 문제가 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅에서는 해당 문제들을 짚어보고 하나씩 해결해보면서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;MVC 프레임워크를 만들어보는 과정을 가질 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(참고로 Spring 또한 해당 역사를 밟아오면서 발달한 것이다!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631427146252&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#5 Spring Boot 정주행] HTTP로 HTML을 응답해보자!&quot; data-og-description=&quot;이번 시간에는 서버를 만들어서 html을 리턴해보자! 먼저 서버를 만들자. 다음에 나오는 코드는 이전 시간에 했던 프로젝트에서 계속 유지한다. [#3 Spring Boot 정주행] HttpServletRequest, HttpServletResponse&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/165&quot; data-og-url=&quot;https://bestkingit.tistory.com/165&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fTXju/hyLyOUpClI/IMETFUa3k3BpPlFncGI871/img.png?width=800&amp;amp;height=300&amp;amp;face=0_0_800_300,https://scrap.kakaocdn.net/dn/kzAZG/hyLyPMxSFB/fPkox90h5yu3VttXrk069k/img.png?width=800&amp;amp;height=300&amp;amp;face=0_0_800_300,https://scrap.kakaocdn.net/dn/B0FTU/hyLyQknL6A/AkSqKKJQqx5krCZv3OxNNK/img.png?width=1114&amp;amp;height=419&amp;amp;face=0_0_1114_419&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/165&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/165&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fTXju/hyLyOUpClI/IMETFUa3k3BpPlFncGI871/img.png?width=800&amp;amp;height=300&amp;amp;face=0_0_800_300,https://scrap.kakaocdn.net/dn/kzAZG/hyLyPMxSFB/fPkox90h5yu3VttXrk069k/img.png?width=800&amp;amp;height=300&amp;amp;face=0_0_800_300,https://scrap.kakaocdn.net/dn/B0FTU/hyLyQknL6A/AkSqKKJQqx5krCZv3OxNNK/img.png?width=1114&amp;amp;height=419&amp;amp;face=0_0_1114_419');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#5 Spring Boot 정주행] HTTP로 HTML을 응답해보자!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 시간에는 서버를 만들어서 html을 리턴해보자! 먼저 서버를 만들자. 다음에 나오는 코드는 이전 시간에 했던 프로젝트에서 계속 유지한다. [#3 Spring Boot 정주행] HttpServletRequest, HttpServletResponse&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;FrontController&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;FrontController 만들기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;문제점 2&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 포스팅의 글에서는 여러 가지의 문제점이 있었다. 문제점은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp; 1. 포워드의 중복이 생겼다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자가 여러가지의 요청을 하는데, 해당 요청을 할 때마다 다음과 같은 코드가 삽입된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631427310992&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// view가 저장되어있는 path 
String Path = &quot;&quot;/WEB-INF/views/test.jsp&quot;;

RequestDispatcher dispatcher = req.getRequestDispatcher(Path);
dispatcher.forward(req, resp);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp; 2. 사용되지 않을 때가 있는 코드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;HttpServletRequest req / HttpServletResponse resp&quot; 둘 중 1개가 쓰이지 않을 경우도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇게 된다면 쓸 때 없는 메모리 낭비가 생기게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp; 3. 공통처리가 힘들다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기능이 점차적으로 증가할 것인데, dispatcher를 하나하나&amp;nbsp;지정 해주고 기능 따라 메서드까지 호출해야 함에 문제가 생길 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프론트 컨트롤러가 무엇일까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 그림을 통해서 비교해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;537&quot; data-filename=&quot;프론트 전.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vsCoC/btreLhnA7rQ/vKKkK0APPK2TGZtnJt1LKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vsCoC/btreLhnA7rQ/vKKkK0APPK2TGZtnJt1LKk/img.png&quot; data-alt=&quot;프론트 컨트롤러 도입 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vsCoC/btreLhnA7rQ/vKKkK0APPK2TGZtnJt1LKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvsCoC%2FbtreLhnA7rQ%2FvKKkK0APPK2TGZtnJt1LKk%2Fimg.png&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;537&quot; data-filename=&quot;프론트 전.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프론트 컨트롤러 도입 전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;589&quot; data-filename=&quot;프론트 후.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cD1dHR/btreONeG2EP/pvws8O3zXXnWpXtKozC2f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cD1dHR/btreONeG2EP/pvws8O3zXXnWpXtKozC2f1/img.png&quot; data-alt=&quot;프론트 컨트롤러 도입 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cD1dHR/btreONeG2EP/pvws8O3zXXnWpXtKozC2f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcD1dHR%2FbtreONeG2EP%2Fpvws8O3zXXnWpXtKozC2f1%2Fimg.png&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;589&quot; data-filename=&quot;프론트 후.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프론트 컨트롤러 도입 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그림으로 보면 바로 알 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프런트 컨트롤러는 사용자의 요청을 가장 먼저 받게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 요청에 따라 다른 Controller를 호출해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 나눈 이유가 무엇일까??&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이쪽에서 언급한 문제점들을 개선하기 위함이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; background-color: #dddddd;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController에서 사용자의 요청에 대한 &quot;공통 처리&quot;를 할 수 있기 때문이다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController를 도입 하기 전에는 모든 Controller 앞에 &quot;공통적인 로직&quot;이 존재하는 것을 알 수 있다. 공통적인 로직의 코드가 어렵고 길다면 매우 힘들 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 FrontController에 해당 공통 로직을 한 번만 입력된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;좀 더 간편해졌다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 프론트 컨트롤러를 직접 만들어보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController 만들기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;생성 순서를 생각해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;특정 요청을 FrontController로 받기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;요청을 받고, 공통 로직을 수행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;요청에 해당하는 Controller를 호출한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자에게 html, json 등을 리턴해준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;특정 요청을 FrontController로 받기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController.java 생성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631430427800&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//servlet/test로 시작하는 모든 URI요청은 여기로 받는다.
@WebServlet(name = &quot;frontController&quot;, urlPatterns = &quot;servlet/test/*&quot;)
public class FrontController extends HttpServlet {

    private Map&amp;lt;String, TestController&amp;gt; controllerList = new HashMap&amp;lt;&amp;gt;();

    public FrontController(){
        controllerList.put(&quot;servlet/test/&quot;, new
                UserController());
        controllerList.put(&quot;servlet/test/register&quot;, new
                UserController());
        controllerList.put(&quot;servlet/test/users&quot;, new
                UserController());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse
            response)
            throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        TestController controller = controllerList.get(requestURI);
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        controller.logic(request, response);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;FrontController이다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자의 요청에 따라 다른 컨트롤러를 호출해줄 HashMap을 가진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 url에 따라 다른 Controller를 호출한다. (현재는 1개의 컨트롤러가 끝이다.)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;service&quot; 메서드에서 들어온 uri에 따라 매핑된 controller를 찾고 해당 controller의 logic 메서드를 호출한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TestController.java 생성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631430440927&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface TestController {

    void logic(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;


};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바 인터페이스 다형성을 통해서 서로 다른 객체를 하나의 HashMap에 저장하고, 호출하기 위해서 필요한 Interface를 선언해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 interface를 구현하는 Controller는 logic이라는 메서드를 통해 컨트롤러 기능을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UserController.java 생성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631430404326&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserController implements TestController{

    @Override
    public void logic(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        String viewPath = &quot;/WEB-INF/views/test.jsp&quot;;
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;TestController를 구현하는 것이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller만의 고유한 기능을 logic에서 수행하여야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 해설&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자가 URI를 통해서 요청한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 먼저 FrontController에 요청이 도착한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;FrontController의 service 메서드에서 요청 URI에 맞는 Controller를 찾아서 호출한다. 없으면 상태 코드를 SC_NOT_FOUND로 설정한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller의 login 함수가 실행되고, 해당하는 view를 사용자에게 리턴해준다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 공통적인 로직을 FrontController에서 수행할 수 있게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;service 함수에서 URI 매핑을 성공하면, 해당하는 매핑에 따라 다른 로직을 적용하거나&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여러 개의 Controller에 공통적인 처리를 할 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제점 2&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아직 문제가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨트롤러에 다음과 같은 코드가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631430948631&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String viewPath = &quot;/WEB-INF/views/test.jsp&quot;;

RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);

dispatcher.forward(request, response);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 코드를 계속해서 적용하는 방식으로 정하게 된다면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 컨트롤러에 해당 코드가 포함되어 있게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #1b711d; background-color: #f3c000;&quot;&gt;그래서 다음 포스팅에서는 viewPath와 서블릿을 넘기는 forward 메서드를 별도로 빼줄 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>backend</category>
      <category>Dispatcher</category>
      <category>frontcontroller</category>
      <category>java</category>
      <category>JSP</category>
      <category>servlet</category>
      <category>spring</category>
      <category>spring boot</category>
      <category>web</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/166</guid>
      <comments>https://bestkingit.tistory.com/166#entry166comment</comments>
      <pubDate>Sun, 12 Sep 2021 16:21:38 +0900</pubDate>
    </item>
    <item>
      <title>[#5 Spring Boot 정주행] HTTP로 HTML을 응답해보자!</title>
      <link>https://bestkingit.tistory.com/165</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 시간에는 서버를 만들어서 html을 리턴해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 서버를 만들자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음에 나오는 코드는 이전 시간에 했던 프로젝트에서 계속 유지한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1631256692009&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#3 Spring Boot 정주행] HttpServletRequest, HttpServletResponse 이용해보자! ㅣ 서블릿 체험&quot; data-og-description=&quot;오늘은 이전 포스팅에서 다루었던 서블릿을 코드로 직접 확인하자! 목차 프로젝트 생성 HttpServletRequest 확인 HttpServletResponse 확인 프로젝트 생성 스프링으로 시작할 것이다. 1. 스프링 부트 프로젝&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/163&quot; data-og-url=&quot;https://bestkingit.tistory.com/163&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cUpkzj/hyLxwlXxdR/BJ2QixpKFUfThsx6dEsuy0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bxdHNJ/hyLxziImFz/et69WjSSxGY30tXZbgPWtK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dBOLws/hyLyWpOJsf/aXvFs4Wa5Q3BUIZb2ija21/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/163&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/163&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cUpkzj/hyLxwlXxdR/BJ2QixpKFUfThsx6dEsuy0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bxdHNJ/hyLxziImFz/et69WjSSxGY30tXZbgPWtK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dBOLws/hyLyWpOJsf/aXvFs4Wa5Q3BUIZb2ija21/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#3 Spring Boot 정주행] HttpServletRequest, HttpServletResponse 이용해보자! ㅣ 서블릿 체험&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 이전 포스팅에서 다루었던 서블릿을 코드로 직접 확인하자! 목차 프로젝트 생성 HttpServletRequest 확인 HttpServletResponse 확인 프로젝트 생성 스프링으로 시작할 것이다. 1. 스프링 부트 프로젝&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1631256996675&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;ServletTest&quot;, urlPatterns = &quot;/servlet&quot;)
public class HttpServletTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType(&quot;text/html&quot;);
        resp.setCharacterEncoding(&quot;utf-8&quot;);

        PrintWriter httpBodyWriter = resp.getWriter(); //HttpServletResponse 객체에 존재하는 HTTP Body writer

        httpBodyWriter.write(&quot;&amp;lt;!DOCTYPE html&amp;gt;\n&quot; +
                &quot;&amp;lt;html&amp;gt;\n&quot; +
                 &quot;&amp;lt;head&amp;gt;\n&quot; +
                 &quot; &amp;lt;meta charset=\&quot;UTF-8\&quot;&amp;gt;\n&quot; +
                 &quot; &amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;\n&quot; +
                 &quot;&amp;lt;/head&amp;gt;\n&quot; +
                 &quot;&amp;lt;body&amp;gt;\n&quot; +
                  &quot;&amp;lt;form action=\&quot;/servlet/users/save\&quot; method=\&quot;post\&quot;&amp;gt;\n&quot; +
                  &quot; id: &amp;lt;input type=\&quot;text\&quot; name=\&quot;id\&quot; /&amp;gt;\n&quot; +
                  &quot; password: &amp;lt;input type=\&quot;text\&quot; name=\&quot;password\&quot; /&amp;gt;\n&quot; +
                  &quot; &amp;lt;button type=\&quot;submit\&quot;&amp;gt;등록&amp;lt;/button&amp;gt;\n&quot; +
                  &quot;&amp;lt;/form&amp;gt;\n&quot; +
                 &quot;&amp;lt;/body&amp;gt;\n&quot; +
                &quot;&amp;lt;/html&amp;gt;\n&quot;);


    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 크롬을 켜서 localhost:8080/servlet로 URI를 보내보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;419&quot; data-filename=&quot;zxcvzxcvzxcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf2KIA/btreJxJQ2yR/lQpHtZUKRU5fHSGLAh0571/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf2KIA/btreJxJQ2yR/lQpHtZUKRU5fHSGLAh0571/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf2KIA/btreJxJQ2yR/lQpHtZUKRU5fHSGLAh0571/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf2KIA%2FbtreJxJQ2yR%2FlQpHtZUKRU5fHSGLAh0571%2Fimg.png&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;419&quot; data-filename=&quot;zxcvzxcvzxcv.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롬 브라우저를 통해 spring에서 등록한 &quot;/sevlet&quot;을 요청했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 서버에서 html을 생성하여 다시 응답해준 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 위 사진과 같이 입력 폼이 2개가 나왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;마찬가지로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리가 &quot;www.naver.com&quot; 을 입력하면 네이버 홈이 나오는 것도 같은 원리이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위 코드에서 정의된 &quot;writer&quot;을 통해서 html을 써넣으려니(자바 코드에 html 코드를 써넣으려니..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;보기에 너무 불편하고 java, html 코드가 같이 있어서 매우 힘들다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 html을 만들어놓고 지정한 부분만 동적으로 html 코드가 생성되도록 해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음은 JSP를 이용하여 HTML코드에 JAVA코드를 심어 놓은 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631258485025&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page import=&quot;hello.servlet.domain.member.MemberRepository&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;hello.servlet.domain.member.Member&quot; %&amp;gt;
&amp;lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&amp;gt;
&amp;lt;%
// request, response 사용 가능
 	MemberRepository memberRepository = MemberRepository.getInstance();
 	System.out.println(&quot;save.jsp&quot;);
 	String username = request.getParameter(&quot;username&quot;);
 	int age = Integer.parseInt(request.getParameter(&quot;age&quot;));
 	Member member = new Member(username, age);
 	System.out.println(&quot;member = &quot; + member);
 	memberRepository.save(member);
%&amp;gt;
	&amp;lt;html&amp;gt;
		&amp;lt;head&amp;gt;
 		&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
		&amp;lt;/head&amp;gt;
		&amp;lt;body&amp;gt;
			성공
			&amp;lt;ul&amp;gt;
 				&amp;lt;li&amp;gt;id=&amp;lt;%=member.getId()%&amp;gt;&amp;lt;/li&amp;gt;
 				&amp;lt;li&amp;gt;username=&amp;lt;%=member.getUsername()%&amp;gt;&amp;lt;/li&amp;gt;
 				&amp;lt;li&amp;gt;age=&amp;lt;%=member.getAge()%&amp;gt;&amp;lt;/li&amp;gt;
			&amp;lt;/ul&amp;gt;
			&amp;lt;a href=&quot;/index.html&quot;&amp;gt;메인&amp;lt;/a&amp;gt;
		&amp;lt;/body&amp;gt;
	&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;출처 : 인프런 - Spring MVC 1편 (김영한 개발자님) 강의의 예제 코드&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;html 코드에 자바코드를 심었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 서블릿에서 html 코드를 하나하나 보내지않아도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JSP는 html 코드 안에 있는 자바코드이며&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전역객체, 자바 함수, 변수 등등을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 한다면 서블릿에서 해당 html 파일을 호출하는 코드를 추가해야할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨트롤러를 다음 코드처럼 바꾸어 주자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631363217007&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;ServletTest&quot;, urlPatterns = &quot;/servlet&quot;)
public class HttpServletTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // view가 저장되어있는 path
        String Path = &quot;&quot;/WEB-INF/views/test.jsp&quot;;

        // dispatcher에 path 등록
        RequestDispatcher dispatcher = req.getRequestDispatcher(Path);

        // dispatcher를 통해서 view를 리턴
        dispatcher.forward(req, resp);


    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;dispatcher.forward : 다른 jsp나 서블릿으로 이동시켜주는 dispatcher의 메서드이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;참고로 jsp를 사용하려며 관련 라이브러리를 다운로드받아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더더욱 알아보기가 편해졌고 코드 오류도 덜 나게 되었다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;또 문제가 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 JSP 코드를 보면 JSP 1개에 너무나 많은 기능이 있는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;수백, 수천 줄이 포함되어야 할&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실무 코드에서 HTML에 대한 코드 뿐만 아니라, 비즈니스 로직까지 포함되게 되면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;너무나 많은 코드와 너무나 많은 기능을 가지고 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더군다나, JSP내용이 그대로 HTML 코드에 나와 위험하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이또한 코드로 분리를 해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 MVC 패턴이 나오게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;그럼 MVC가 무엇인지 알아보자!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;M : Model&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;V : View&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;C : Controller&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Model : 뷰에 그려 넣을 내용을 담아두는 객체이다. 사용자에 따라, 행동에 따라 다른 내용을 가지고 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;View : 뷰에서는 Model에 들어있는 내용에 따라 동적으로 화면을 그린다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Controller : HTTP 요청을 받고 필요한 작업(유효성 검사, http 검사 등등)들을 수행한 다음, 비즈니스 로직을 실행한다. 그리고 뷰에 넘어갈 모델에 필요한 내용을 담아준다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그림을 통해서 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;486&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cv6GfK/btreIVYU8rQ/LTawrufmE5r5fDQ5jl4eTk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cv6GfK/btreIVYU8rQ/LTawrufmE5r5fDQ5jl4eTk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cv6GfK/btreIVYU8rQ/LTawrufmE5r5fDQ5jl4eTk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cv6GfK/btreIVYU8rQ/LTawrufmE5r5fDQ5jl4eTk/img.gif&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;486&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 그림에서 보면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;View에서 사용자 요청&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller가 모델을 조작 및 응답할 View 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;선택된 View는 컨트롤러로부터 받은 Model을 보며 View 생성&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model, Controller, View가 서로 상호작용하며 움직이는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;글을 마치며&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;html 코드에 자바코드를 심어놓는 작업을 마쳤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여러가지의 문제가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 글에서 해당 문제와 해결하는 과정을 밟아보자!&lt;/span&gt;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>Controller</category>
      <category>HTML</category>
      <category>JSP</category>
      <category>model</category>
      <category>MVC</category>
      <category>MVC패턴</category>
      <category>spring</category>
      <category>view</category>
      <category>서블릿</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/165</guid>
      <comments>https://bestkingit.tistory.com/165#entry165comment</comments>
      <pubDate>Fri, 10 Sep 2021 16:36:42 +0900</pubDate>
    </item>
    <item>
      <title>[#4 Spring Boot 정주행] Http에 대해서 알아보자!</title>
      <link>https://bestkingit.tistory.com/164</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;살아오면서 한 번쯤은 HTTP라는 단어를 들어본 적이 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 그렇게 들어보았던 HTTP에 대해서 공부를 해볼 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URI? URL?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP 시작 라인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP Method?&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP Status?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP Header?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URI? URL? URN?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URI, URL, URN과 같은 단어도 분명 한번은 들어보았을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 위키백과에서 나온 설명을 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URL&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URL&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;은 네트워크 상에서 자원이 어디 있는지를 알려주기 위한 규약이다. 즉,&amp;nbsp;&lt;/span&gt;컴퓨터 네트워크&lt;span style=&quot;color: #202122;&quot;&gt;와 검색&amp;nbsp;&lt;/span&gt;메커니즘&lt;span style=&quot;color: #202122;&quot;&gt;에서의 위치를 지정하는,&amp;nbsp;&lt;/span&gt;웹 리소스&lt;span style=&quot;color: #202122;&quot;&gt;에 대한 참조이다. 쉽게 말해서, 웹 페이지를 찾기위한 주소를 말한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URN&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URN&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;은&amp;nbsp;&lt;/span&gt;urn:scheme&lt;span style=&quot;color: #202122;&quot;&gt;&amp;nbsp;을 사용하는&amp;nbsp;&lt;/span&gt;URI&lt;span style=&quot;color: #202122;&quot;&gt;를 위한 역사적인 이름이다. URN은 영속적이고, 위치에 독립적인 자원을 위한 지시자로 사용하기 위해 1997년도&amp;nbsp;&lt;/span&gt;RFC 2141&lt;span style=&quot;color: #202122;&quot;&gt;&amp;nbsp;문서에서 정의되었다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;URI&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;통합 자원 식별자&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;Uniform Resource Identifier&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;b&gt;URI&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;)는 인터넷에 있는 자원을 나타내는 유일한 주소이다. URI의 존재는 인터넷에서 요구되는 기본 조건으로서 인터넷 프로토콜에 항상 붙어 다닌다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;흠.. 뭔가 어렵다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;쉽게 풀어서 이야기하자면,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;URI는 URL과 URN을 포함하고 있는 넓은 개념이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URL은 &lt;a href=&quot;http://www.naver.com/news와&quot;&gt;www.naver.com/news와&lt;/a&gt; 같이 naver에 있는 news라는 리소스를 지칭하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;인터넷 환경에서 효율적인 주소가 될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP는 무엇일까?? 먼저 서버와 클라이언트간의 통신에 대해서 생각해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 사용자가 ID와 PASSWORD값을 입력하고 &quot;로그인&quot;버튼을 누른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 서버로 로그인을 한다는 &quot;요청&quot;이 인터넷망을 통해서 넘어간다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 말하는 &quot;요청&quot;은 어떤 식으로 날아가게 되는걸까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;방법은 수십 가지가 될 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631248251671&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LOGIN
ID: COCA
PASSWORD: 123&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 날아갈 수도 있고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631248276341&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;COCA&amp;amp;PASSWORD&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게도 가능하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;방법은 수백만 가지가 될 수 있다! 해당 서버의 개발자 마음대로 짤 수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데 여기서 개발자마다 자기의 방식대로 하게 된다면..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;난장판이 된다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서! 개발자들 간에 규약을 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기본적인 HTTP 구조를 먼저 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP 요청 메시지의 예이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631248938090&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /apple?id=coca&amp;amp;password=123 HTTP/1.1
Host: www.naver.com

기타 내용(없어도 댐)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP 응답 메세지의 예이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631248979205&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type:text/plain;charset=UTF-8
Content-Length: 500

hi!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리가 실생활에서 작성하는 보고서의 양식처럼&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;요청과 응답에 양식을 넣어&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;거기에 맞추어서 요청과 응답을 하도록 Protocol이라는 규약을 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그중에서 가장 많이 쓰이고 효율적이라고 평가되는 것이 HTTP 프로토콜이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;좀 더 쉽게 이야기를 다시 하면!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;편지를 쓸 때,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;To. &amp;amp; From. 을 넣는 형식이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;이것 또한 프로토콜인 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP Header&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위에서 보았던 예시로 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631252890425&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /apple?id=coca&amp;amp;password=123 HTTP/1.1
Host: www.naver.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;GET : HTTP 메서드를 표현한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;/apple : 해당 사이트에 요청하는 리소스&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;? : 리소스를 요청하며 함께 보내는 데이터의 시작&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;id=coca&amp;amp;password=123 : id와 password를 보냄&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP/1.1 : HTTP 버전&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와 같이 HTTP 메시지에는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로토콜에 따라서 의미가 부여되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;헤더에는 HTTP 전송에 필요한 부가정보가 포함되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;바디 데이터에 대한 정보나, 바디 크기, 애플리케이션 정보, 캐시 정보 등등이 엄청나게 많다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP Method?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URI를 통해서 &quot;www.naver.com/user&quot; 라고 하면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버에서는 어떤 행동을 해야 할지 모른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user를 보여달라는 것인가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user를 수정하라는 뜻인가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 행위를 표현하는 메서드를 같이 포함한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP 메서드는 GET, POST, PUT, DELETE, PATCH, CONNECT&amp;nbsp; 등등 많은 종류가 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대표적으로 사용되는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;GET, POST, DELETE를 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;GET : 단순 조회를 요청하는 메서드이다. 시작 라인에 명시되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;POST : 수정을 요청하는 메서드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;DELETE : 삭제를 요청하는 메서드다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;명시적으로 나타내는 것이므로, GET을 통해 수정 요청도 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 최근에 HTTP 메서드를 기반으로 서버를 만드는 RestFulAPI가 유행하는 추세이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 각각의 의미에 맞는 메서드를 사용하는 습관을 들이자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP Status&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP 상태 코드란?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클라이언트가 요청을 보내었을 때, 서버 측에서 HTTP 응답이 온다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 성공, 실패, 처리 중, 클라이언트 에러, 서버 에러 등등 갖가지의 경우가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그것을 상태 코드로 명시를 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태 코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;100~199 : 요청 수신 성공 및 처리 중&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;200~299 : 성공&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 200 : 요청 성공 및 정상적 응답&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 201 : 요청 성공 및 새로운 리소스 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 202 : 요청 접수 및 처리 완료 x&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 204 : 요청 성공 및 응답 데이터 없음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;300~399 : Redirection&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 300 : Multiple Choices&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP Header&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 헤더를 상세히 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631255559533&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /apple?id=coca&amp;amp;password=123 HTTP/1.1
Content-Type: application/json
Content-Length:18
Content-Language: ko

{&quot;name&quot;:&quot;youngho&quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Content-Type : 보내는 데이터의 미디어 타입과 문자 인코딩에 대한 정보이다.&lt;/span&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;text/html; charset-utf-8 : html 형식이라는 타입을 데이터로 이룰 때, 지정해주는 타입이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;application/json : json 형태의 타입을 데이터로 이룰 때, 지정해주는 타입이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;image/png : image 파일의 타입을 데이터로 이룰 때, 지정해주는 타입이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Content-Encoding : 데이터를 압축하기 위해서 사용한다.&lt;/span&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;gzip&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;deflate&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;identity&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Content-Language : 데이터의 언어를 표현한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Content-Length : 바이트 단위로 데이터의 길이를 표현한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;From: 이메일 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Referer: 이전의 웹 페이지 주소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User-Agent : 요청 유저의 애플리케이션 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Server : 요청을 처리하는 서버의 소프트웨어 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Date : 메시지 생성 날짜&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Host : 요청한 호스트의 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Location : 페이지 리다이렉션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Authorization : 클라이언트의 인증 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Cookie : 클라이언트가 서버에서 받은 쿠키를 저장하고, 다시 요청 시 전달&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Set-Cookie : 서버에서 클라이언트로 쿠키를 전달하고, 웹 브라우저가 해당 쿠키를 저장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>http</category>
      <category>http body</category>
      <category>HTTP Header</category>
      <category>Method</category>
      <category>uri</category>
      <category>url</category>
      <category>URN</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/164</guid>
      <comments>https://bestkingit.tistory.com/164#entry164comment</comments>
      <pubDate>Fri, 10 Sep 2021 15:38:04 +0900</pubDate>
    </item>
    <item>
      <title>[#3 Spring Boot 정주행] HttpServletRequest, HttpServletResponse 이용해보자! ㅣ 서블릿 체험</title>
      <link>https://bestkingit.tistory.com/163</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 이전 포스팅에서 다루었던 서블릿을 코드로 직접 확인하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 생성&lt;/li&gt;
&lt;li&gt;HttpServletRequest 확인&lt;/li&gt;
&lt;li&gt;HttpServletResponse 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트 생성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링으로 시작할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 스프링 부트 프로젝트 생성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://start.spring.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://start.spring.io/&lt;/a&gt; 에서 프로젝트를 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Project : Gradle&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Language : Java&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Packaging : war&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Dependencies : spring web, lombok&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나머지는 있는 그대로 만들자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ide 툴로 해당 폴더의 build.gradle을 open 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;생성된 gradle 코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631174996613&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins {
	id 'org.springframework.boot' version '2.5.4'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
	id 'war'
}

group = 'start'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. @ServeletComponent 등록&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ServletApplication.java (start.io 에서 입력한 name에 따라 이름이 다르다!)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631175202457&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@SpringBootApplication
@ServletComponentScan
public class ServletApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServletApplication.class, args);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. HttpServlet 생성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿이 오면 전담할 클래스가 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631175381964&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;ServletTest&quot;, urlPatterns = &quot;/servlet&quot;)
public class HttpServletTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.service(req, resp);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- urlPatterns에 맞추어 http 요청이 들어오면 서블릿 컨테이너는 해당 클래스의 service 메서드를 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 이때, http의 내용을 파싱 하여 HttpServletRequest, HttpServletResponse 객체로 넘겨준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 해당 Request와 Response를 확인해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HttpServletRequest 확인하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Request는 사용자의 요청을 말한다. 여기에서는 Http 내용을 말한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드는 다음과 같이 구성했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HttpServletTest.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631176010847&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;ServletTest&quot;, urlPatterns = &quot;/servlet&quot;)
public class HttpServletTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(&quot;request : &quot; + req);
        System.out.println(&quot;parameter : &quot; + req.getParameter(&quot;id&quot;));
        System.out.println(&quot;ContextPath : &quot; + req.getContextPath());
        System.out.println(&quot;Cookies : &quot; + req.getCookies());
        System.out.println(&quot;Method : &quot; + req.getMethod());
        System.out.println(&quot;RequestURI : &quot; + req.getRequestURI());
        System.out.println(&quot;ContentLength : &quot; + req.getContentLength());

    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 크롬을 켜서 다음 uri로 요청을 보내보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631176035164&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:8080/servlet?id=abc123&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 콘솔창을 확인해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631176062876&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;request : org.apache.catalina.connector.RequestFacade@1787a475
parameter : abc123
ContextPath : 
Cookies : null
Method : GET
RequestURI : /servlet
ContentLength : -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와 같이 콘솔창에 출력되는 것을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇다. 서블릿 컨테이너가 http 요청을 알아서 올바르게 잘라준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 get@()만 호출하면 원하는 데이터를 얻을 수 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;너무 편하다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HttpServletResponse&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 반대로 우리가 Http 형식으로 String을 만들어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 또한 만만치 않은 작업이다. 띄어쓰기, 알파벳, 대소문자 중에 1개라도 틀리면 올바른 요청이 아니기 때문이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이번에도 서블릿 컨테이너를 통해 Http Response를 생성해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HttpServletTest.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631176388972&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@WebServlet(name = &quot;ServletTest&quot;, urlPatterns = &quot;/servlet&quot;)
public class HttpServletTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(&quot;response : &quot; + resp);
        resp.setContentType(&quot;text/plain&quot;);
        System.out.println(&quot;set content-type : &quot; + resp.getContentType());

    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 다음 내용으로 요청하고 콘솔창을 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631176480808&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:8080/servlet&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롬 브라우저를 통해서 http response를 살펴보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음과 같은 내용이 왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1631176524719&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Request URL: http://localhost:8080/servlet
Request Method: GET
Status Code: 200 
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
Connection: keep-alive
Content-Length: 0
Content-Type: text/plain
Date: Thu, 09 Sep 2021 08:33:42 GMT
Keep-Alive: timeout=60
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:8080
sec-ch-ua: &quot;Google Chrome&quot;;v=&quot;93&quot;, &quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Chromium&quot;;v=&quot;93&quot;
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: &quot;Windows&quot;
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정말 길다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿 컨테이너가 저 많은 내용을 알아서 붙여서 보내주었다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정말 편리하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위에서 확인했듯이, 서블릿 컨테이너를 이용함으로 인해서 http 요청 및 http 응답을 아주 편하게 이용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/163</guid>
      <comments>https://bestkingit.tistory.com/163#entry163comment</comments>
      <pubDate>Thu, 9 Sep 2021 17:39:17 +0900</pubDate>
    </item>
    <item>
      <title>[#2  Spring Boot 정주행] 웹 기본 구조, 서블릿, HTTP</title>
      <link>https://bestkingit.tistory.com/162</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 웹에서 이루어지는 상호 작용을 전반적으로 살펴보고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;몇 가지의 기술 들을 살펴볼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 기본 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;웹 기본 구조&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자와 서버로 나누어 생각해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리가 네이버에서 &quot;뉴스&quot; 버튼을 클릭하면 뉴스 화면으로 이동한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 내부에서는 어떻게 이루어질까??&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음을 보면서 이해해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자가 &quot;뉴스&quot; 버튼을 클릭한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자의 웹 브라우저가 요청 메시지를 보낸다. (ex. naver.com/news)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;naver.com가 DNS를 거쳐 naver의 ip주소로 변경되어 보내진다. (ex. 192.123.123/news)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;192.123.123/news 정보가 웹 애플리케이션 서버를 거쳐 http 메시지로 변경된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;naver의 서블릿 컨테이너로 해당 http 메세지가 도착한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;naver의 서블릿 컨테이너는 http 메세지를 읽고 그에 해당하는 내용을 사용자의 웹브라우저에게 돌려준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자의 웹브라우저는 해당 내용을 읽고 사용자가 이용할 수 있게 변환해서 보여준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;HTTP&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP는 Protocol이다. 다음 포스팅에 더 상세히 살펴볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 가볍게만 다루자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컴퓨터와 컴퓨터간에 정보를 주고받는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 예시에서 사용자가 뉴스가 보고 싶어서 뉴스 버튼을 클릭했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그때 생성되는 http를 보면&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631173236768&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&amp;amp;age=20&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와 같이 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더 많은 정보를 담을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각각의 내용은 정보를 주고받으면서 서로 필요한 내용을 가지고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;서블릿&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿은 위키백과에서 다음과 같이 설명한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&quot;자바 서블릿&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(Java Servlet)은&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_(%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%EC%96%B8%EC%96%B4)&quot;&gt;자바&lt;/a&gt;&lt;span style=&quot;color: #202122;&quot;&gt;를 사용하여 웹페이지를 동적으로 생성하는 서버 측 프로그램 혹은 그 사양을 말하며, 흔히 &quot;서블릿&quot;이라 불린다.&quot;라고&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt; 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;위의 예시에서 보면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 애플리케이션이 생성한 http 메시지를 읽고 그에 해당하는 동작을 수행하는 naver 측의 java 프로그램이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서블릿에는 여러 가지의 기능이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HTTP를 자동으로 파싱 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;java로 코드를 짠다고 생각하자. 위와 같은 http가 도착하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;POST인지 GET인지 for문을 돌려서 contains 함수를 통해 확인해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Content-Type은 무엇인지 확인해야 한다. 귀찮다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바 서블릿에서는 HTTP 메시지가 도착하면 알아서 파싱을 해준다. 그래서 우리는 getContentType()과 같이 메서드 호출만 하여 해당 요청 내용을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또한 응답 메시지도 HTTP 형식으로 자동으로 만들어준다!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 글은 서블릿을 직접 사용해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>http</category>
      <category>servlet</category>
      <category>spring</category>
      <category>springboot</category>
      <category>web</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/162</guid>
      <comments>https://bestkingit.tistory.com/162#entry162comment</comments>
      <pubDate>Thu, 9 Sep 2021 17:03:29 +0900</pubDate>
    </item>
    <item>
      <title>[#1 Spring Boot 정주행]  Spring &amp;amp; Spring Boot가 무엇인가?</title>
      <link>https://bestkingit.tistory.com/161</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아는 동생이 개발자를 준비해보겠다고 전화가 왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;백엔드를 지망하고 있어서 대표적인 Spring 공부를 추천했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그런데 동생이&amp;nbsp; &quot;그래서 Spring이 무엇인가요?&quot;라고 물었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;명쾌하게 대답하지 못하는 내 자신을 보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;Spring은 웹 개발을 하기 위해서 각종 도구와 기술이 집약되어있는 프레임워크야&quot;라고 이야기했지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;솔직히 나도 완벽히 이해하지 못하고 있는 느낌이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이번 기회에 Spring MVC 구조를 살펴보며 차근차근 다루어볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅 글의 목적은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring &amp;amp; Spring Boot란 무엇인가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Web Application&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;귀차니즘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Framework&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring Boot&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 먼저 JAVA가 무엇인지 알아야 될 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대부분의 사람들이 알 거라고 생각한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA란 &quot;&lt;b&gt;자바&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(Java)는&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_(%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%EC%96%B8%EC%96%B4)&quot;&gt;자바&lt;/a&gt;&lt;span style=&quot;color: #202122;&quot;&gt;로 기술된 프로그램 개발 및 실행을 할 수 있는 소프트웨어 모임의 총칭이다.&quot; - 위키백과&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;라고 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;비유를 하여 내 생각대로 정리를 하자면,&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;JAVA는 마치 모래성의 모래와 같다고 생각한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모래의 기본적인 점성, 강도 등등을 이용하여 모래성을 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 애플리케이션 또한,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA의 특성을 이용하여 짓는 모래성과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA의 메모리 조작, 연산, 객체지향 개념 등등을 이용하여 웹 애플리케이션을 만드는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 가장 먼저 배우는 것이 C, JAVA, Python 등과 같은 프로그래밍 언어를 배우는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(걸을 줄 알아야 뛸 것이고, 점프를 할 것이고..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Web Application&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 애플리케이션은 무엇일까? 이것을 이해하기 위해서는 가장 먼저 애플리케이션에 대해서 알아두어야 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;애플리케이션이란 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;특정한 일을 하도록 설계된 프로그램&quot;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JAVA를 처음 배우며, &quot;Hello World&quot;를 출력해본 적이 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 또한 &quot;Hello World를 출력하는 Application&quot;이라고 부를 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 웹 애플리케이션은 무엇인가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;요약해서 말하자면, &quot;웹 애플리케이션이란 웹 상에서 동작하는 애플리케이션이다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;말 그대로 이야기하는 것과 같아서 나도 당황스럽다..ㅋㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;554&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TrgGK/btrevHUZ0Y0/eKeQrDcrKa7p7Wc8hIQPxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TrgGK/btrevHUZ0Y0/eKeQrDcrKa7p7Wc8hIQPxk/img.png&quot; data-alt=&quot;출처 :&amp;amp;amp;nbsp;https://velog.io/@aerirang647/2020-02-06-1502-%EC%9E%91%EC%84%B1%EB%90%A8-91k6acegdu&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TrgGK/btrevHUZ0Y0/eKeQrDcrKa7p7Wc8hIQPxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTrgGK%2FbtrevHUZ0Y0%2FeKeQrDcrKa7p7Wc8hIQPxk%2Fimg.png&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;554&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;nbsp;https://velog.io/@aerirang647/2020-02-06-1502-%EC%9E%91%EC%84%B1%EB%90%A8-91k6acegdu&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 그림에서 &quot;WAS&quot;가 웹 애플리케이션이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;웹을 통해 어떠한 요청을 하면 요청에 따라 동적인 동작을 하도록 설계된 프로그램이다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더 쉽게 이야기하자면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네이버에서 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;뉴스&quot; 버튼을 클릭 시, 뉴스 화면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;웹툰&quot; 버튼을 클릭 시, 웹툰 화면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;메일&quot; 버튼을 클릭 시, 메일 화면이 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네이버 회사 컴퓨터에 해당 버튼이 클릭되면, 해당하는 화면이 나오도록 JAVA로 코딩되어 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그게 웹 애플리케이션이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;귀차니즘&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금까지 살아오면서 로그인을 해본 적 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;로그인은 모든 페이지가 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ID와 PASSWORD를 입력하고 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맞으면 로그인 성공 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맞지 않으면 로그인 실패&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 페이지가 2가지의 값을 입력받고 해당하는 입력이 올바른 입력인지 웹 애플리케이션이 체크를 하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 그에 해당하는 코드를 웹 애플리케이션에 써넣었을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;매번 같은 코드를 입력해야 하는데 귀찮다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이러한 코드를 하나의 뭉탱이로 묶어서 사용하고 싶은 곳에 코드를 다운로드만 하게 함으로써 코드를 치지 않게 하면 어떨까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 그렇게 사용하게 되었다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 뭉탱이를 &quot;라이브러리&quot;라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 라이브러리를 다운로드하고 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대표적으로 &quot;JAVA의 String&quot;도 JAVA의 라이브러리인 &lt;span style=&quot;color: #4d5156;&quot;&gt;&amp;nbsp;java.lang.String에 들어있는 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ㅇㅋ 귀차니즘 해결&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Framework&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또 다른 문제가 생겼다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각종 코드를 다운로드하여 편하게 사용하는 것은 완료하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 코드의 양이 방대해지면서, 개발자마다 코드의 구조가 너무나 다른 것이다.. 협업하기 너무 힘든 것이다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 효율적인 코드 구조를 인도하는 Frame을 만들어 제공을 했다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 하나의 Frame안에서 work를 한다 해서 Framework라 일컫는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링은 JAVA 진영의 대표적인 Framework이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위키백과에서는 다음과 같이 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&quot;스프링 프레임워크&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%98%81%EC%96%B4&quot;&gt;영어&lt;/a&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;Spring Framework&lt;/span&gt;&lt;span style=&quot;color: #202122;&quot;&gt;)는&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4_%ED%94%8C%EB%9E%AB%ED%8F%BC)&quot;&gt;자바 플랫폼&lt;/a&gt;&lt;span style=&quot;color: #202122;&quot;&gt;을 위한&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%98%A4%ED%94%88_%EC%86%8C%EC%8A%A4&quot;&gt;오픈 소스&lt;/a&gt;&lt;span style=&quot;color: #202122;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98_%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC&quot;&gt;애플리케이션 프레임워크&lt;/a&gt;&lt;span style=&quot;color: #202122;&quot;&gt;로서 간단히&amp;nbsp;&lt;/span&gt;&lt;b&gt;스프링&lt;/b&gt;&lt;span style=&quot;color: #202122;&quot;&gt;(Spring)이라고도 한다. 동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공하고 있다.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #202122;&quot;&gt;웹 앱을 개발하면서 필요한 요소와 서비스를 제공해주는 것이다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring Boot&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #202122; font-family: 'Noto Serif KR';&quot;&gt;Spring과 Spring Boot에 대한 정확한 차이를 모르는 사람도 많을 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring을 사용하면서 사람들이 또 귀차니즘을 느낀다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring에 apache 서버를 장착, bean 등록 등과 같이 불편한 점을 느끼기 시작했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이러한 불편한 일을 자동적으로 지원해주는 Spring Boot가 생겨난 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추가 내용&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring에서 제공하는 서비스를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;엄청나게 많아서 하나하나 볼 수 없지만 대표적인 몇 가지를 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #006dd7;&quot;&gt;Spring Container&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #006dd7;&quot;&gt;Dependency Injection(DI)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #006dd7;&quot;&gt;ORM (Object Relational Mapping) 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #006dd7;&quot;&gt;AOP (Aspect Oriented Programming) 지원&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;등등 수십 가지가 더 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추후에 해당 기술들에 대한 공부를 하며 글을 올려보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>framework</category>
      <category>java</category>
      <category>Programming</category>
      <category>spring</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/161</guid>
      <comments>https://bestkingit.tistory.com/161#entry161comment</comments>
      <pubDate>Thu, 9 Sep 2021 16:12:44 +0900</pubDate>
    </item>
    <item>
      <title>Oauth에 대해서 알아보자!</title>
      <link>https://bestkingit.tistory.com/160</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWhImH/btreiPDTuBF/1XBZ1oIk68HlkFpUwBPiBK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWhImH/btreiPDTuBF/1XBZ1oIk68HlkFpUwBPiBK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWhImH/btreiPDTuBF/1XBZ1oIk68HlkFpUwBPiBK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWhImH%2FbtreiPDTuBF%2F1XBZ1oIk68HlkFpUwBPiBK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/He6JY/btreg2KJ6nS/YbPaun2Zb5B00Z4h0TO8Vk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/He6JY/btreg2KJ6nS/YbPaun2Zb5B00Z4h0TO8Vk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/He6JY/btreg2KJ6nS/YbPaun2Zb5B00Z4h0TO8Vk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHe6JY%2Fbtreg2KJ6nS%2FYbPaun2Zb5B00Z4h0TO8Vk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEMvI4/btrea16W7KH/PSJTA3tgu6Lksh7RWdLdJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEMvI4/btrea16W7KH/PSJTA3tgu6Lksh7RWdLdJ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEMvI4/btrea16W7KH/PSJTA3tgu6Lksh7RWdLdJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEMvI4%2Fbtrea16W7KH%2FPSJTA3tgu6Lksh7RWdLdJ1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OIJdO/btreiPw9kdO/m2UYHBBeCuU91ey1zASbNK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OIJdO/btreiPw9kdO/m2UYHBBeCuU91ey1zASbNK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OIJdO/btreiPw9kdO/m2UYHBBeCuU91ey1zASbNK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOIJdO%2FbtreiPw9kdO%2Fm2UYHBBeCuU91ey1zASbNK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9I0Mm/btreib78wwi/vpWJKzKPYAYiNIi5zEVx0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9I0Mm/btreib78wwi/vpWJKzKPYAYiNIi5zEVx0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9I0Mm/btreib78wwi/vpWJKzKPYAYiNIi5zEVx0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9I0Mm%2Fbtreib78wwi%2FvpWJKzKPYAYiNIi5zEVx0k%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;7.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceDcpD/btrec4PRAiK/nP2bOIsHg2L1MKe7Yp0af1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceDcpD/btrec4PRAiK/nP2bOIsHg2L1MKe7Yp0af1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceDcpD/btrec4PRAiK/nP2bOIsHg2L1MKe7Yp0af1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceDcpD%2Fbtrec4PRAiK%2FnP2bOIsHg2L1MKe7Yp0af1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;7.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;8.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMeWn/btreg2KJ6sH/1K9B9TkQuYaJj9xI4KVrJK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMeWn/btreg2KJ6sH/1K9B9TkQuYaJj9xI4KVrJK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMeWn/btreg2KJ6sH/1K9B9TkQuYaJj9xI4KVrJK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMeWn%2Fbtreg2KJ6sH%2F1K9B9TkQuYaJj9xI4KVrJK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;8.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;9.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciNWyV/btree5gCL0H/jXglThSdssTQO99bmpI5SK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciNWyV/btree5gCL0H/jXglThSdssTQO99bmpI5SK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciNWyV/btree5gCL0H/jXglThSdssTQO99bmpI5SK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciNWyV%2Fbtree5gCL0H%2FjXglThSdssTQO99bmpI5SK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;9.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;10.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/COTUK/btreiRBHV6w/KVAxpVDkr1KBCR80TgInL0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/COTUK/btreiRBHV6w/KVAxpVDkr1KBCR80TgInL0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/COTUK/btreiRBHV6w/KVAxpVDkr1KBCR80TgInL0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCOTUK%2FbtreiRBHV6w%2FKVAxpVDkr1KBCR80TgInL0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;10.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;11.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zUYmZ/btreg4hvPPJ/GolyFFOrw1LCc6NghpVrIk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zUYmZ/btreg4hvPPJ/GolyFFOrw1LCc6NghpVrIk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zUYmZ/btreg4hvPPJ/GolyFFOrw1LCc6NghpVrIk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzUYmZ%2Fbtreg4hvPPJ%2FGolyFFOrw1LCc6NghpVrIk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;11.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT/IT이모저모</category>
      <category>authorization</category>
      <category>google</category>
      <category>jwt</category>
      <category>oauth</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/160</guid>
      <comments>https://bestkingit.tistory.com/160#entry160comment</comments>
      <pubDate>Mon, 6 Sep 2021 18:47:09 +0900</pubDate>
    </item>
    <item>
      <title>Git과 gitHub에 대해서 알아보자!</title>
      <link>https://bestkingit.tistory.com/159</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0U29m/btree34cumG/knCbjk6eQvkCHILyA7okOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0U29m/btree34cumG/knCbjk6eQvkCHILyA7okOk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0U29m/btree34cumG/knCbjk6eQvkCHILyA7okOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0U29m%2Fbtree34cumG%2FknCbjk6eQvkCHILyA7okOk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bO8usU/btrec5gUxE7/UlwLmfUfXCkxp52TkLAtkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bO8usU/btrec5gUxE7/UlwLmfUfXCkxp52TkLAtkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bO8usU/btrec5gUxE7/UlwLmfUfXCkxp52TkLAtkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbO8usU%2Fbtrec5gUxE7%2FUlwLmfUfXCkxp52TkLAtkk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd67mX/btrd9lxQsm4/uzbKuIdsLM8i3qayAZDfO1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd67mX/btrd9lxQsm4/uzbKuIdsLM8i3qayAZDfO1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd67mX/btrd9lxQsm4/uzbKuIdsLM8i3qayAZDfO1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd67mX%2Fbtrd9lxQsm4%2FuzbKuIdsLM8i3qayAZDfO1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2Pj0c/btreiPKFLpW/hZ7rGTcaPh4CPKvwIdCvKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2Pj0c/btreiPKFLpW/hZ7rGTcaPh4CPKvwIdCvKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2Pj0c/btreiPKFLpW/hZ7rGTcaPh4CPKvwIdCvKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2Pj0c%2FbtreiPKFLpW%2FhZ7rGTcaPh4CPKvwIdCvKk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpgYQT/btrehBe4fOO/mhO0Kj4xAupkw8yWWa8A51/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpgYQT/btrehBe4fOO/mhO0Kj4xAupkw8yWWa8A51/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpgYQT/btrehBe4fOO/mhO0Kj4xAupkw8yWWa8A51/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpgYQT%2FbtrehBe4fOO%2FmhO0Kj4xAupkw8yWWa8A51%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gm7NM/btreiRoaIWv/uz1wWtBKLgnQZcSpm3fLS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gm7NM/btreiRoaIWv/uz1wWtBKLgnQZcSpm3fLS1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gm7NM/btreiRoaIWv/uz1wWtBKLgnQZcSpm3fLS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGm7NM%2FbtreiRoaIWv%2Fuz1wWtBKLgnQZcSpm3fLS1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT/IT이모저모</category>
      <category>Git</category>
      <category>github</category>
      <category>Programming</category>
      <category>개발자</category>
      <category>버전관리</category>
      <category>협업</category>
      <category>형상관리</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/159</guid>
      <comments>https://bestkingit.tistory.com/159#entry159comment</comments>
      <pubDate>Mon, 6 Sep 2021 18:45:54 +0900</pubDate>
    </item>
    <item>
      <title>Socket에 대해서 알아보자! with Spring</title>
      <link>https://bestkingit.tistory.com/158</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/20yq5/btrehkqZk6h/KVIHYXSiNya1eMQQtFV9C0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/20yq5/btrehkqZk6h/KVIHYXSiNya1eMQQtFV9C0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/20yq5/btrehkqZk6h/KVIHYXSiNya1eMQQtFV9C0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F20yq5%2FbtrehkqZk6h%2FKVIHYXSiNya1eMQQtFV9C0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9LqOi/btrehG1DiAk/TkBc7gDWqg68zB7fHNChT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9LqOi/btrehG1DiAk/TkBc7gDWqg68zB7fHNChT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9LqOi/btrehG1DiAk/TkBc7gDWqg68zB7fHNChT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9LqOi%2FbtrehG1DiAk%2FTkBc7gDWqg68zB7fHNChT1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pAK2c/btrd65aUewE/9qstyWCs3uSdsedKPXhog0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pAK2c/btrd65aUewE/9qstyWCs3uSdsedKPXhog0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pAK2c/btrd65aUewE/9qstyWCs3uSdsedKPXhog0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpAK2c%2Fbtrd65aUewE%2F9qstyWCs3uSdsedKPXhog0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tmHAo/btrd2lyfdnw/RIx5Ji81gaYnC4zG3pKG00/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tmHAo/btrd2lyfdnw/RIx5Ji81gaYnC4zG3pKG00/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tmHAo/btrd2lyfdnw/RIx5Ji81gaYnC4zG3pKG00/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtmHAo%2Fbtrd2lyfdnw%2FRIx5Ji81gaYnC4zG3pKG00%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wuegO/btrd64QCdYf/PsgSbxWkSkT7TXWG8GKF70/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wuegO/btrd64QCdYf/PsgSbxWkSkT7TXWG8GKF70/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wuegO/btrd64QCdYf/PsgSbxWkSkT7TXWG8GKF70/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwuegO%2Fbtrd64QCdYf%2FPsgSbxWkSkT7TXWG8GKF70%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drtdv6/btrehHlVlpj/TJONBA2CWEwU9nJ9mY9Fr0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drtdv6/btrehHlVlpj/TJONBA2CWEwU9nJ9mY9Fr0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drtdv6/btrehHlVlpj/TJONBA2CWEwU9nJ9mY9Fr0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdrtdv6%2FbtrehHlVlpj%2FTJONBA2CWEwU9nJ9mY9Fr0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;7.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEka26/btrea1Tq6lG/KnCu0MKHR5vfklbXG5YFX0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEka26/btrea1Tq6lG/KnCu0MKHR5vfklbXG5YFX0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEka26/btrea1Tq6lG/KnCu0MKHR5vfklbXG5YFX0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEka26%2Fbtrea1Tq6lG%2FKnCu0MKHR5vfklbXG5YFX0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;7.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;8.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ep5yyh/btred0zAzLq/hIClOIwJhOEEOfTdbLjOek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ep5yyh/btred0zAzLq/hIClOIwJhOEEOfTdbLjOek/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ep5yyh/btred0zAzLq/hIClOIwJhOEEOfTdbLjOek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fep5yyh%2Fbtred0zAzLq%2FhIClOIwJhOEEOfTdbLjOek%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;8.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;9.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbFFMn/btreiQJyY4g/lkkXsr6eAzMeaV96M8MFPK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbFFMn/btreiQJyY4g/lkkXsr6eAzMeaV96M8MFPK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbFFMn/btreiQJyY4g/lkkXsr6eAzMeaV96M8MFPK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbFFMn%2FbtreiQJyY4g%2FlkkXsr6eAzMeaV96M8MFPK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;9.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;10.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/48aIs/btrd7SPA3h0/BzokSdeKcgOv7bkcwk4ndK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/48aIs/btrd7SPA3h0/BzokSdeKcgOv7bkcwk4ndK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/48aIs/btrd7SPA3h0/BzokSdeKcgOv7bkcwk4ndK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F48aIs%2Fbtrd7SPA3h0%2FBzokSdeKcgOv7bkcwk4ndK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;10.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;11.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWk4uR/btrehBsAKid/Fr3iSFkpkYvzFzKrJAO4s1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWk4uR/btrehBsAKid/Fr3iSFkpkYvzFzKrJAO4s1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWk4uR/btrehBsAKid/Fr3iSFkpkYvzFzKrJAO4s1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWk4uR%2FbtrehBsAKid%2FFr3iSFkpkYvzFzKrJAO4s1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;11.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;12.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RdmNX/btreaQjFXp1/H5k6Ky1nxu88zh8ldeCHf0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RdmNX/btreaQjFXp1/H5k6Ky1nxu88zh8ldeCHf0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RdmNX/btreaQjFXp1/H5k6Ky1nxu88zh8ldeCHf0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRdmNX%2FbtreaQjFXp1%2FH5k6Ky1nxu88zh8ldeCHf0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;12.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;13.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blbEVs/btrehBzlCKL/7MMxN3bBLkfmM2HdCTLiDk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blbEVs/btrehBzlCKL/7MMxN3bBLkfmM2HdCTLiDk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blbEVs/btrehBzlCKL/7MMxN3bBLkfmM2HdCTLiDk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblbEVs%2FbtrehBzlCKL%2F7MMxN3bBLkfmM2HdCTLiDk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;13.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;14.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIM6ma/btreib1mvWQ/NqK2DKb8HUoM8SyOKa5lQk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIM6ma/btreib1mvWQ/NqK2DKb8HUoM8SyOKa5lQk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIM6ma/btreib1mvWQ/NqK2DKb8HUoM8SyOKa5lQk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIM6ma%2Fbtreib1mvWQ%2FNqK2DKb8HUoM8SyOKa5lQk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;14.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;15.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TVMkQ/btrea1Tq6tm/MMYGcJXZ8oT26sYrr6BTI1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TVMkQ/btrea1Tq6tm/MMYGcJXZ8oT26sYrr6BTI1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TVMkQ/btrea1Tq6tm/MMYGcJXZ8oT26sYrr6BTI1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTVMkQ%2Fbtrea1Tq6tm%2FMMYGcJXZ8oT26sYrr6BTI1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;15.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;16.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c71C5Z/btrd64pzySF/BtWwLHPVO7ZeZjdRZhK3v0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c71C5Z/btrd64pzySF/BtWwLHPVO7ZeZjdRZhK3v0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c71C5Z/btrd64pzySF/BtWwLHPVO7ZeZjdRZhK3v0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc71C5Z%2Fbtrd64pzySF%2FBtWwLHPVO7ZeZjdRZhK3v0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;16.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;17.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bexLaa/btreiRoaED6/kivK46JCKzPLPrCcjmDTC1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bexLaa/btreiRoaED6/kivK46JCKzPLPrCcjmDTC1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bexLaa/btreiRoaED6/kivK46JCKzPLPrCcjmDTC1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbexLaa%2FbtreiRoaED6%2FkivK46JCKzPLPrCcjmDTC1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;17.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;18.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X4dZM/btree4vjdOO/rneW77kCVdB5y9UGw1jJHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X4dZM/btree4vjdOO/rneW77kCVdB5y9UGw1jJHk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X4dZM/btree4vjdOO/rneW77kCVdB5y9UGw1jJHk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX4dZM%2Fbtree4vjdOO%2FrneW77kCVdB5y9UGw1jJHk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;18.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;19.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvDArG/btrehli5EuS/WbUiOfW7nfcjGalE46JhAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvDArG/btrehli5EuS/WbUiOfW7nfcjGalE46JhAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvDArG/btrehli5EuS/WbUiOfW7nfcjGalE46JhAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvDArG%2Fbtrehli5EuS%2FWbUiOfW7nfcjGalE46JhAk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;19.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;20.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LqOdS/btrehkEtW2P/wQcdZ4gjXK6fohpZ2MnjUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LqOdS/btrehkEtW2P/wQcdZ4gjXK6fohpZ2MnjUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LqOdS/btrehkEtW2P/wQcdZ4gjXK6fohpZ2MnjUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLqOdS%2FbtrehkEtW2P%2FwQcdZ4gjXK6fohpZ2MnjUk%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;20.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;21.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VOAU0/btrd2k69JOR/EO2Uxh1DUoAmjTkU7Rgm30/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VOAU0/btrd2k69JOR/EO2Uxh1DUoAmjTkU7Rgm30/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VOAU0/btrd2k69JOR/EO2Uxh1DUoAmjTkU7Rgm30/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVOAU0%2Fbtrd2k69JOR%2FEO2Uxh1DUoAmjTkU7Rgm30%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;21.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;22.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lAwcg/btreiaOWk8Y/vdi77kOu1as03RDcNDo7a1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lAwcg/btreiaOWk8Y/vdi77kOu1as03RDcNDo7a1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lAwcg/btreiaOWk8Y/vdi77kOu1as03RDcNDo7a1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlAwcg%2FbtreiaOWk8Y%2Fvdi77kOu1as03RDcNDo7a1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;22.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;23.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tYuaj/btreh2Dt45h/QRkyCN9OtYxgaKcLFdHgA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tYuaj/btreh2Dt45h/QRkyCN9OtYxgaKcLFdHgA0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tYuaj/btreh2Dt45h/QRkyCN9OtYxgaKcLFdHgA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtYuaj%2Fbtreh2Dt45h%2FQRkyCN9OtYxgaKcLFdHgA0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;23.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;24.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OpVyb/btrehlcnZwB/DbgOqpuAjt0SazIJSbfk3K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OpVyb/btrehlcnZwB/DbgOqpuAjt0SazIJSbfk3K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OpVyb/btrehlcnZwB/DbgOqpuAjt0SazIJSbfk3K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOpVyb%2FbtrehlcnZwB%2FDbgOqpuAjt0SazIJSbfk3K%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;24.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;25.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clDeq8/btrehDcSalc/VF9OiA2glbf0qJHrWwzs3K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clDeq8/btrehDcSalc/VF9OiA2glbf0qJHrWwzs3K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clDeq8/btrehDcSalc/VF9OiA2glbf0qJHrWwzs3K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclDeq8%2FbtrehDcSalc%2FVF9OiA2glbf0qJHrWwzs3K%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;25.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT/IT이모저모</category>
      <category>broker</category>
      <category>SOCKET</category>
      <category>sockjs</category>
      <category>spring</category>
      <category>stomp</category>
      <category>topic</category>
      <category>구독</category>
      <category>실시간</category>
      <category>알림</category>
      <category>채팅</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/158</guid>
      <comments>https://bestkingit.tistory.com/158#entry158comment</comments>
      <pubDate>Mon, 6 Sep 2021 18:44:47 +0900</pubDate>
    </item>
    <item>
      <title>Mail Protocol과 Mail 동작 구성 보기! with Spring</title>
      <link>https://bestkingit.tistory.com/157</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rG6dd/btrd64JXLAr/1mCkAnjy9cu4VBNN4uQko0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rG6dd/btrd64JXLAr/1mCkAnjy9cu4VBNN4uQko0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rG6dd/btrd64JXLAr/1mCkAnjy9cu4VBNN4uQko0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrG6dd%2Fbtrd64JXLAr%2F1mCkAnjy9cu4VBNN4uQko0%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;1.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYwdvr/btrea2Y5e1F/NX8qfJGz7JBwbkpiIIVDak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYwdvr/btrea2Y5e1F/NX8qfJGz7JBwbkpiIIVDak/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYwdvr/btrea2Y5e1F/NX8qfJGz7JBwbkpiIIVDak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYwdvr%2Fbtrea2Y5e1F%2FNX8qfJGz7JBwbkpiIIVDak%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;2.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oZ74d/btrehCrv7qD/qWAOiKSKVAkAnkVjDbgnd1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oZ74d/btrehCrv7qD/qWAOiKSKVAkAnkVjDbgnd1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oZ74d/btrehCrv7qD/qWAOiKSKVAkAnkVjDbgnd1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoZ74d%2FbtrehCrv7qD%2FqWAOiKSKVAkAnkVjDbgnd1%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;3.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/42vKq/btreg3bSl4g/PKtbKux2vkAlGkH8I1eI8k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/42vKq/btreg3bSl4g/PKtbKux2vkAlGkH8I1eI8k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/42vKq/btreg3bSl4g/PKtbKux2vkAlGkH8I1eI8k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F42vKq%2Fbtreg3bSl4g%2FPKtbKux2vkAlGkH8I1eI8k%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;4.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BuBNN/btrea2xZ3GH/uBk3OqKEsrUqOPGMFYUp4K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BuBNN/btrea2xZ3GH/uBk3OqKEsrUqOPGMFYUp4K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BuBNN/btrea2xZ3GH/uBk3OqKEsrUqOPGMFYUp4K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBuBNN%2Fbtrea2xZ3GH%2FuBk3OqKEsrUqOPGMFYUp4K%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;5.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4aCo7/btreh1YTVFX/UK2fXxKmhY0ja6PkQJBMnK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4aCo7/btreh1YTVFX/UK2fXxKmhY0ja6PkQJBMnK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4aCo7/btreh1YTVFX/UK2fXxKmhY0ja6PkQJBMnK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4aCo7%2Fbtreh1YTVFX%2FUK2fXxKmhY0ja6PkQJBMnK%2Fimg.jpg&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;6.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT/IT이모저모</category>
      <category>IMAP</category>
      <category>Mail</category>
      <category>POP3</category>
      <category>SMTP</category>
      <category>spring</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/157</guid>
      <comments>https://bestkingit.tistory.com/157#entry157comment</comments>
      <pubDate>Mon, 6 Sep 2021 18:43:41 +0900</pubDate>
    </item>
    <item>
      <title>[ADYB] 게시판 댓글기능 구현</title>
      <link>https://bestkingit.tistory.com/156</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 게시판에 댓글기능을 구현할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도메인 설계 and 연관관계 매핑&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Controller 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Repository 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;뷰 구현&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도메인&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도메인 내용은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Reply&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 160px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;기타&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Long sequenceId&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시퀀스 전략, Primary Key&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User user&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ManyToOne 관계(user가 1)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;댓글 작성자&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Board board&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ManyToOne 관계(board가 1)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;댓글이 포함되는 게시글&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Timestamp createDate&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Timestamp&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;작성일&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;String Content&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;댓글 내용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1628151264408&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
@Entity(name = &quot;reply&quot;)
public class Reply {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int replyId;

    @NotNull
    @NotBlank
    @Size(min = 1, max = 255)
    @Column(nullable = false, length = 120)
    String content;

    @ManyToOne
    @JoinColumn(name=&quot;boardId&quot;)
    private Board board;

    @ManyToOne
    @JoinColumn(name=&quot;userId&quot;)
    private User user;

    @CreationTimestamp
    private Timestamp createDate;



};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Board&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Board에 Reply 추가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1628151420662&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@OneToMany(mappedBy = &quot;board&quot;)
private List&amp;lt;Reply&amp;gt; reply;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User에 Reply 추가&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1628151434082&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@OneToMany(mappedBy = &quot;user&quot;)
private List&amp;lt;Reply&amp;gt; replyList;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨트롤러 구현&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우선 전략은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;board view에 댓글을 form으로 생성한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;controller와 post매핑하여 조작되도록 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드로 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1628151665714&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
public class ReplyController {

    @Autowired
    private final ReplyService replyService;

    @PostMapping(&quot;/reply_write&quot;)
    public String replyWrite(@ModelAttribute Reply reply, Long boardId, @SessionAttribute(name = SessionConst.LOGIN_USER, required = false)
            User user){

        return replyService.replyWrite(reply, user, boardId);

    }

    @PostMapping(&quot;/reply_delete&quot;)
    public String replyDelete(@ModelAttribute Reply reply, @SessionAttribute(name = SessionConst.LOGIN_USER, required = false)
            User user){


        return replyService.replyDelete(reply);
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;위 코드를 보면, 작성 및 삭제를 post로 나누어 놓았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 Repository를 만들고 컨트롤러에 적용해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Repository 생성&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Repository는 Spring JPA data를 이용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ReplyRepository&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1628151787475&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface ReplyRepository extends JpaRepository&amp;lt;Reply, Long&amp;gt; {
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Service 생성&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ReplyService&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1628153229851&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class ReplyService {

    @Autowired
    private final ReplyRepository replyRepository;

    @Autowired
    private final BoardRepository boardRepository;

    @Autowired
    private final UserRepository userRepository;

    public String replyWrite(Reply reply, User user, Long boardId){

        User findUser = userRepository.findByUserId(user.getUserId());
        Optional&amp;lt;Board&amp;gt; findBoard = boardRepository.findById(boardId);

        reply.setBoard(findBoard.get());
        reply.setUser(findUser);
        replyRepository.save(reply);

        return &quot;home&quot;;
    }

    public String replyDelete(Reply reply){

        replyRepository.delete(reply);

        return &quot;home&quot;;
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Write 부분에서는 board, user을 설정해주고 저장했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Delete 부분에서는 해당 reply만 삭제해주었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(User, board는 어차피 mappedBy 처리라서 따로 처리해주지 않아도 된다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;뷰 구현&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존에 있던 페이지에서 추가해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존페이지는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(Thymeleaf를 사용했다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1628153390730&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html th:replace=&quot;~{layouts/base :: layout(~{::title},~{::section})}&quot;
      xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;게시판 조회&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;section class=&quot;masthead text-center&quot;&amp;gt;

    &amp;lt;div class=&quot;jumbotron&quot;  th:object=&quot;${board}&quot;&amp;gt;
        &amp;lt;h1 class=&quot;display-4&quot; th:text=&quot;${board.title}&quot;&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
        &amp;lt;br&amp;gt;
        &amp;lt;hr&amp;gt;
        &amp;lt;br&amp;gt;
        &amp;lt;div th:each=&quot;path : ${board.userFileList}&quot;&amp;gt;
            &amp;lt;br&amp;gt;
            &amp;lt;img th:src=&quot;${path.filePath}&quot; class=&quot;card-img-top&quot; alt=&quot;...&quot; style=&quot;width: 200px; height 300px;&quot;&amp;gt;
            &amp;lt;br&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;br&amp;gt;&amp;lt;hr&amp;gt;&amp;lt;br&amp;gt;
        &amp;lt;p class=&quot;lead&quot; th:text=&quot;${board.content}&quot;&amp;gt;This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.&amp;lt;/p&amp;gt;
        &amp;lt;hr&amp;gt;&amp;lt;br&amp;gt;
        &amp;lt;p th:text=&quot;${board.user.userId}&quot;&amp;gt;It uses utility classes for typography and spacing to space content out within the larger container.&amp;lt;/p&amp;gt;

        &amp;lt;br&amp;gt;&amp;lt;hr&amp;gt;&amp;lt;br&amp;gt;

        &amp;lt;!-- Reply Section --&amp;gt;

        &amp;lt;div class=&quot;input-group mb-3&quot;&amp;gt;

            &amp;lt;form id=&quot;reply&quot; action=&quot;/reply_write&quot; method=&quot;post&quot;&amp;gt;
                &amp;lt;input type=&quot;text&quot; id=&quot;content&quot; name=&quot;content&quot; class=&quot;form-control&quot; placeholder=&quot;댓글을 입력해주세요..&quot; aria-label=&quot;댓글을 입력해주세요..&quot; aria-describedby=&quot;basic-addon2&quot;&amp;gt;
                &amp;lt;input type=&quot;hidden&quot; id=&quot;boardId&quot; name=&quot;boardId&quot; th:value=&quot;${board.boardId}&quot;&amp;gt;
                &amp;lt;div class=&quot;input-group-append&quot;&amp;gt;
                    &amp;lt;button class=&quot;btn btn-outline-secondary&quot; type=&quot;submit&quot;&amp;gt;등록&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;



        &amp;lt;!-- Reply Section End --&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;
            &amp;lt;a class=&quot;btn btn-primary btn-lg&quot; href=&quot;/board&quot; role=&quot;button&quot;&amp;gt;목록으로&amp;lt;/a&amp;gt;
        &amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;

&amp;lt;/section&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Reply 기능은 form으로 이루어져 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Reply 기능의 내용은 content이고, hidden으로 정의되어있는 것은 해당 board의 id를 넘기는 것이다. (매핑에 필요하기 때문에)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기타 입터셉터 처리까지 해주었다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;끝!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project/ADYB - 쇼핑몰</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/156</guid>
      <comments>https://bestkingit.tistory.com/156#entry156comment</comments>
      <pubDate>Thu, 5 Aug 2021 19:50:10 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] Model 과 ModelAndView 차이.</title>
      <link>https://bestkingit.tistory.com/155</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;946&quot; data-filename=&quot;KakaoTalk_20210804_201314931.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MD02f/btrbbSdTjGN/VbKTXC6U5azXqj0HQQhvI0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MD02f/btrbbSdTjGN/VbKTXC6U5azXqj0HQQhvI0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MD02f/btrbbSdTjGN/VbKTXC6U5azXqj0HQQhvI0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMD02f%2FbtrbbSdTjGN%2FVbKTXC6U5azXqj0HQQhvI0%2Fimg.jpg&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;946&quot; data-filename=&quot;KakaoTalk_20210804_201314931.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터셉터에서 세션 처리를 하는 도중에 문제가 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Controller에서 Model을 이용하여 view에 넣어주었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HandlerInterceptor의 postHandle에는 ModelAndView를 이용하는 것이다..(확장하면 되지만 있는 그대로를 이용하자!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같겠지 생각하며 addAttribute를 찾아보았지만 없다....(세션에 있는 User 정보를 넣고 싶다고!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 ModelAndView로 Model에 데이터를 넣는 방법을 찾아보면서 Model과 ModelAndView를 확실히 다루어 볼 예정이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 알아둬야 할 것이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model, ModelAndView에서&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model이란 무엇인가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 그림을 보자! (발로 그린 그림이다..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림을 보면&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Controller에서의 데이터를 Model에 담는다.&lt;/li&gt;
&lt;li&gt;View는 Model에 담겨있는 데이터만 쏙쏙 골라서 화면에 바인딩해준다!&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 저렇게 나누어서 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 간단하다. 수많은 개발자들이 서로 일을 편하게 하기 위해서 저렇게 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 다루어야 할 점이 있지만, 여기까지만 알아두고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 차이점에 대해서 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실제 Model 사용 예시&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄 요약 : ModelAndView는 Model에서 기능을 추가한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model (Controller -&amp;gt; Model)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드를 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1628075831986&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/apple&quot;)
public String test(@ModelAttribute Member member,HttpServletRequest request, Model model){
        
    model.addAttribute(&quot;Member&quot;, member);
        
    return &quot;home&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;코드 설명:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@ModelAttribute를 통해서 사용자가 입력한 내용을 Member객체에 파싱 하여 member를 받는다.&lt;/li&gt;
&lt;li&gt;&quot;home&quot;에서 &quot;member&quot;가 가지고 있는 요소를 이용하기 위해, member를 model에 담아준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 사실 @ModelAttribute를 이용하면 자동으로 해당 member를 model에 담아준다.. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 View -&amp;gt; Model&lt;/p&gt;
&lt;pre id=&quot;code_1628075994143&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html th:replace=&quot;~{layouts/base :: layout(~{::title},~{::section})}&quot;
      xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;홈 입니다.&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;section th:object=&quot;${member}&quot;&amp;gt;

    &amp;lt;button type=&quot;button&quot; onclick=&quot;location.href='/modify'&quot; th:if=&quot;${member.memberId != null}&quot;&amp;gt;회원수정&amp;lt;/button&amp;gt;

    &amp;lt;/section&amp;gt;
&amp;lt;/section&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Thymeleaf 템플릿 엔진을 통해서 member를 조회하는 모습이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 ${member}가 가능한 이유는 해당 html을 호출한 Controller에서 model에 &quot;member&quot;를 담아주었기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Model vs ModelAndView&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model 객체는 별로 기능이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style7&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Method&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;addAttribute&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model에 속성추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getAttribute&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model에 있는 속성을 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;addAttributes&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model에 속성을 여러개 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getAttributes&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model에 속성을 여러개 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;containsAttributes&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model에 특정한 속성이 있는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;mergeAttributes&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Model 두개를 합침&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도 기능이 끝..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ModelAndView&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model에 비해서 더욱 확장성 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(내부적으로 확인해보니까 ModelMap이 들어있다. ModelMap은 Model보다 크고 ModelAndView보다 작다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style7&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;setViewName&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;view 이름을 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getViewName&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;view 이름을 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;setView&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;view 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getView&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;view 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;hasView&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;설정되어있는 view가 있는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getModelMap&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;내부의 모델 Map 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getModel&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;내부 모델 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;getStatus&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;상태 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것 이외에도 더 많다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model은 속성을 추가 삭제만 할 수 있는 기능이지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ModelAndView는 view설정, model설정, 상태 설정, 기타 기능까지 많다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡할수록 ModelAndView를 사용하겠지!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>backend</category>
      <category>Controller</category>
      <category>model</category>
      <category>ModelAndView</category>
      <category>MVC</category>
      <category>springboot</category>
      <category>view</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/155</guid>
      <comments>https://bestkingit.tistory.com/155#entry155comment</comments>
      <pubDate>Wed, 4 Aug 2021 20:31:59 +0900</pubDate>
    </item>
    <item>
      <title>[ADYB] 게시판 글쓰기 구현 ㅣ JPA + Spring Boot + Thymeleaf</title>
      <link>https://bestkingit.tistory.com/154</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오늘은 게시판 글쓰기를 구현할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Board 도메인 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;뷰 구현하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Board Repository 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;컨트롤러 구현하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;서비스 구현하기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Board 도메인 생성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1627973394889&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
@Entity(name = &quot;board&quot;)
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int boardId;

    @Column(nullable = false, length = 100)
    private String title;

    @Lob
    private String content;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name=&quot;userId&quot;)
    private User user;

    @OneToMany(mappedBy = &quot;board&quot;)
    private List&amp;lt;Reply&amp;gt; reply;

    @ColumnDefault(&quot;0&quot;)
    private int count;

    @CreationTimestamp
    private Timestamp createDate;

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;user는 다대일 매핑으로 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;LAZY로 지연 로딩을 실시한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;뷰 구현하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;뷰는 다음과 같이 간단히 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627973394890&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html th:replace=&quot;~{layouts/base :: layout(~{::title},~{::section})}&quot;
      xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
    &amp;lt;title&amp;gt;게시판 쓰기&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;section class=&quot;masthead text-center&quot;&amp;gt;
&amp;lt;div&amp;gt;
게시판 쓰기 입니다.

&amp;lt;/div&amp;gt;
    id=&quot;signUpForm&quot; action=&quot;/signup&quot; method=&quot;post&quot; th:object=&quot;${user}&quot;
    &amp;lt;form id=&quot;board&quot; action=&quot;/board_write&quot; method=&quot;post&quot; th:object=&quot;${board}&quot;&amp;gt;

        제목 : &amp;lt;input name=&quot;title&quot; id=&quot;title&quot; type=&quot;text&quot;&amp;gt;
        내용 : &amp;lt;input name=&quot;content&quot; id=&quot;content&quot; type=&quot;text&quot;&amp;gt;


        &amp;lt;button type=&quot;submit&quot;&amp;gt;제출&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;

&amp;lt;/section&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Board Repository 생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973394891&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface BoardRepository extends JpaRepository&amp;lt;Board, String&amp;gt; {

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;간단히 CRUD만 구현!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1627973394891&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
@Slf4j
public class BoardWriterController {

    private final BoardWriteService boardWriteService;
    @GetMapping(&quot;/board_write&quot;)
    public String BoardWriter(
            @SessionAttribute(name = SessionConst.LOGIN_USER, required = false)
                    User user, Model model
    ){

        addUser(user, model);
        return &quot;board_write&quot;;
    }

    @PostMapping(&quot;/board_write&quot;)
    public String BoardWriter(@ModelAttribute Board board, @SessionAttribute(name = SessionConst.LOGIN_USER, required = false)
            User user){

        boardWriteService.write(board, user);
        return &quot;redirect:/&quot;;

    }


    public void addUser(User user, Model model){
        if(user == null) {
            model.addAttribute(&quot;user&quot;, new User());
            return;
        }
        model.addAttribute(&quot;user&quot;, user);
        return;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;GET, POST 매핑 두 가지가 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;GET은 뷰를 리턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;POST는 게시글 쓰기 폼 데이터를 받는 매핑이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;서비스 구현하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1627973394892&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@Slf4j
@RequiredArgsConstructor
public class BoardWriteService {
    private final BoardRepository boardRepository;
    private final UserRepository userRepository;
    public void write(Board board, User user){

        User findUser = userRepository.findByUserId(user.getUserId());
        board.setUser(findUser);
        boardRepository.save(board);

    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;컨트롤러에서 넘겨준 user를 이용하여 userRepository에서 user 객체를 받아온다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;board에 user를 set 해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;boardRepository.save를 이용하여 board 객체를 저장한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;※ 여기서 userRepository를 이용하여 user 객체를 받아오지 않고, 컨트롤러에서 &quot;@ModelAttribute&quot;를 통해서 받아온 user를 바로 board.setUser(user)를 해주면 에러가 뜬다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;이유는 : &quot;@ModelAttribute&quot;에서 받아온 user는 그냥 바인딩된 객체일 뿐, DB에 등록된 객체가 아니기 때문이다. FK를 이어주어야 하는데, JPA는 해당 user가 기존에 로그인한 user인지 모른다. 그래서 userRepository의 findByUserId를 통해서 user를 가지고 와서 save를 해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 게시판 조회를 구현할 예정이다.&lt;/p&gt;</description>
      <category>Project/ADYB - 쇼핑몰</category>
      <category>ADYB</category>
      <category>board</category>
      <category>server</category>
      <category>게시판</category>
      <category>백엔드</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/154</guid>
      <comments>https://bestkingit.tistory.com/154#entry154comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:50:14 +0900</pubDate>
    </item>
    <item>
      <title>[ADYB] Spring Boot ㅣ 로그아웃 구현하기 ㅣ 세션 만료시키기</title>
      <link>https://bestkingit.tistory.com/153</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 로그아웃을 구현할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용이 작기때문에 목차따윈 없다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;세션 만료시키기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션을 만료하는 방법은 많다. 나느 그 중에서 HttpSession 클래스에 구현되어있는 invalidate 메소드를 이용할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황 : &quot;로그아웃&quot; 버튼을 클릭할 시, 즉시 세션을 파괴하고 홈으로 리다이렉트한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러부터 생성해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;LogOutController.java&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973353456&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
public class LogOutController {

    @GetMapping(&quot;/logout&quot;)
    public String logout(HttpServletRequest request){

        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }
        return &quot;redirect:/&quot;;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 구성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자의 request로 부터 Session을 얻는다.&lt;/li&gt;
&lt;li&gt;Session을 null check 해준다.&lt;/li&gt;
&lt;li&gt;Session이 null이 아닐 경우 (세션이 있다.) 세션을 만료시킨다. null일 경우 아무 작업을 하지 않는다.&lt;/li&gt;
&lt;li&gt;홈으로 리다이렉트 해준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 세션이 없어진 것을 볼 수 있다.&lt;/p&gt;</description>
      <category>Project/ADYB - 쇼핑몰</category>
      <category>session</category>
      <category>만료</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/153</guid>
      <comments>https://bestkingit.tistory.com/153#entry153comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:49:26 +0900</pubDate>
    </item>
    <item>
      <title>[ADYB] Session이 없으면 특정페이지 접근못하게 하기</title>
      <link>https://bestkingit.tistory.com/152</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오늘은 Session이 없으면 특정 페이지에 접근을 하지 못하게 하는 작업을 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전략&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;인터셉터 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;WebConfig 등록&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;전략&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;특정 페이지 URL 요청 시, Interceptor를 통해서 세션을 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;세션이 존재하지 않을 경우 &quot;home&quot;으로 redirect해준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;세션 체크를 할 특정 페이지는 회원 수정, 게시판 글 작성이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;인터셉터 생성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 먼저 인터셉터를 생성하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;SessionCheckInterceptor.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973302546&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
public class SessionCheckInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler) throws Exception {
		
        //Session Check - Session X
        if(request.getSession().getAttribute(SessionConst.LOGIN_USER) == null){
        	
            // 세션이 없을 시, login으로 Redirect
            response.sendRedirect(&quot;/login&quot;);
            return false;
        }
		
        // Session O
        return true;

    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;코드 설명:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span&gt;request.getSession().getAttribute(SessionConst.LOGIN_USER) == null)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;로그인 세션이 있는지 확인한다. 세션이 null일 경우(세션이 존재하지 않는 경우) if문에 진입한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span&gt;response.sendRedirect(&quot;/login&quot;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;세션이 없는 경우에 &quot;/login&quot; 으로 보낸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;WebConfig 등록&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1627973302547&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class WebConfig implements WebMvcConfigurer {
        registry.addInterceptor(new SessionCheckInterceptor())
                .order(2)
                .addPathPatterns(&quot;/modify&quot;, &quot;/board_write&quot;)
                .excludePathPatterns(&quot;/css/**&quot;, &quot;/*.ico&quot;, &quot;/error&quot;,&quot;/login&quot;);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;코드 설명:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span&gt;&quot;registry.addInterceptor(new SessionCheckInterceptor()) : 인터셉터를 등록한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&quot;.order(2)&quot; : 2번째 인터셉터이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&quot;addPathPatterns(&quot;/modify&quot;, &quot;/board_write&quot;) : &quot;/modify&quot;, &quot;/board_write&quot; 에만 인터셉터를 실행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;.excludePathPatterns : 지정한 것은 해당 인터셉터를 실행하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Project/ADYB - 쇼핑몰</category>
      <category>cookie</category>
      <category>interceptor</category>
      <category>session</category>
      <category>validation</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/152</guid>
      <comments>https://bestkingit.tistory.com/152#entry152comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:48:49 +0900</pubDate>
    </item>
    <item>
      <title>[#6] JPA를 이용한 로그인</title>
      <link>https://bestkingit.tistory.com/151</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;JPA를 이용한 로그인&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 포스팅은 로그인 기능을 구현 내용과 구현 중 맞닿은 에러에 대해서 다룰 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 내용은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Login 프론트 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Login 컨트롤러 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;UserRepository 기능 확장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Login 서비스 구현&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Login 프론트 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;먼저 코드를 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973263085&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;

    &amp;lt;title&amp;gt;로그인&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
로그인입니다.

&amp;lt;form method=&quot;post&quot; action=&quot;/login&quot;&amp;gt;
    ID :&amp;lt;input type=&quot;text&quot; name=&quot;id&quot;&amp;gt;&amp;lt;br&amp;gt;
    PASSWORD :&amp;lt;input type=&quot;text&quot; name=&quot;password&quot;&amp;gt;&amp;lt;br&amp;gt;
    &amp;lt;button type=&quot;submit&quot;&amp;gt;제출&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;form 태그를 통해서 post 요청을 수행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;상대경로를 통해 &quot;/login&quot;으로 요청을 수행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;id와 password를 입력할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Login 컨트롤러 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드로 바로 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627973263087&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
@Slf4j
public class LoginController {
    @Autowired
    private final UserRepository userRepository;
    @Autowired
    private final LoginService loginService;

    @GetMapping(&quot;/login&quot;)
    public String login() {
        return &quot;login&quot;;
    }

    @PostMapping(&quot;/login&quot;)
    public String loginId(@ModelAttribute User user) {
    
        loginService.login(user);

        return &quot;redirect:/&quot;;

    }
    
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;GetMapping : &quot;/login&quot;으로 매핑된다. 뷰 리졸버를 통해서 &quot;login.html&quot;을 호출한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;PostMapping: &quot;/login&quot;으로 매핑된다. LoginService의 login 메소드를 실행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;홈을 리다이렉트한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;UserRepository 기능 확장&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 부분을 보면서 살짝 고생했다.. ㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;먼저, 코드를 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627973263088&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {
    @Query(&quot;select m from user m where m.id = ?1&quot;)
    List&amp;lt;User&amp;gt; finduser(String id, String password);
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;UserRepository를 수정하였다. query문에 password도 찾아야하는데 일단은 조금만 뒤에 완성하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그냥 내생각 : JpaRepository를 이용하여 &quot;findOne&quot;이나 &quot;findById&quot;를 이용하려했는데, 설정된 파라미터 정보를 보니까 Option&amp;lt;&amp;gt;, Long Id인 것이다. 근데 회원은 String 타입의 id와 String 타입의 password를 입력하는데, Long으로 보낼 수도 없다. 그래서 GeneratedValue로 sequenceid를 넣어야하는가 싶은데 상식적으로 누가 sequenceid로 검색을 하나.. 그래서 새롭게 만들었다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;먼저, 생성할 쿼리를 지정해주어야한다. 방법은 &quot;@Query&quot; 어노테이션을 사용한다. 괄호안에 쿼리를 써주자.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;두번째로, 리턴타입을 User라고 할 수 없다고 판단된다. 컨트롤러처럼 ModelAttribute가 적용이 안된다. 그래서 List로 받았다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;세번째로, 테이블에 이름을 지정해주어야한다. 쿼리문을 살펴보면 user 테이블을 조회하였다. 그래서 명시적으로 User클래스의 Entity 속성을 user로 지정해주어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1627973263088&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity(name = &quot;user&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 맞닿은 에러 : 먼저 List&amp;lt;User&amp;gt;대신 User로 리턴을 했다가 매핑 오류가 났다. @ModelAttribute와 같이 지정해주는 줄 착각했다. 다음에는 해당하는 기능이 있는지 찾아보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 두번째로 Entity속성을 지정해주지않아서 오류가 났다. 지정해라!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 어느정도 구현이 완료되면 QueryDsl로 리팩토링해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Login 서비스 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드를 바로 보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973263089&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
@Slf4j
public class LoginService {
    @Autowired
    private final UserRepository userRepository;

    public String login(User user){
    
        List&amp;lt;User&amp;gt; lis = userRepository.finduser(user.getId(), user.getPassword());
        
        return &quot;redirect:/&quot;;
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;컨트롤러에서 LoginService의 login 메소드를 호출한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;호출된 login 메소드는 DB에 검색하여 해당하는 회원정보가 있는지 조회한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;그리고 홈으로 리다이렉트한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 회원정보가 검색되었을 경우 or 검색되지 않았을 경우를 나누어 구현을 완성해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 로그인 validation 처리도 하여야 한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Project/ADYB - 쇼핑몰</category>
      <category>ADYB</category>
      <category>login</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/151</guid>
      <comments>https://bestkingit.tistory.com/151#entry151comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:47:58 +0900</pubDate>
    </item>
    <item>
      <title>[Thymeleaf] BootStrap 템플릿 적용, 레이아웃 및 템플릿으로 나누기</title>
      <link>https://bestkingit.tistory.com/150</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 Thymeleaf에서 템플릿 조각, 레이아웃 나누기 기능을 공부해볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;부트스트랩 템플릿 구하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;템플릿 조각 나누기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;레이아웃 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;템플릿 조각과 레이아웃이란?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 적용을 하고, 무엇인지 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;부트스트랩 템플릿 구하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;부트스트랩에서 템플릿을 구해서 가져올 것이다. 먼저 아래의 링크로 가서 템플릿을 가져오자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://startbootstrap.com/&quot;&gt;https://startbootstrap.com/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1627973091395&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Free Bootstrap Themes, Templates, Snippets, and Guides&quot; data-og-description=&quot;Start Bootstrap develops free to download, open source Bootstrap 5 themes, templates, and snippets and creates guides and tutorials to help you learn more about designing and developing with Bootstrap.&quot; data-og-host=&quot;startbootstrap.com&quot; data-og-source-url=&quot;https://startbootstrap.com/&quot; data-og-url=&quot;https://startbootstrap.com&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oRSeN/hyKXXiRgL5/7ct4I15niUOsL2TouZiHSK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mzA0m/hyKX2YKXgO/HqeyIZSi0ZGdemxf9VCypk/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/lEIlB/hyKXQKL1GP/oiWBHLjcHpQVJilCFWwuA1/img.jpg?width=516&amp;amp;height=344&amp;amp;face=0_0_516_344&quot;&gt;&lt;a href=&quot;https://startbootstrap.com/&quot; data-source-url=&quot;https://startbootstrap.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oRSeN/hyKXXiRgL5/7ct4I15niUOsL2TouZiHSK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mzA0m/hyKX2YKXgO/HqeyIZSi0ZGdemxf9VCypk/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/lEIlB/hyKXQKL1GP/oiWBHLjcHpQVJilCFWwuA1/img.jpg?width=516&amp;amp;height=344&amp;amp;face=0_0_516_344');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Free Bootstrap Themes, Templates, Snippets, and Guides&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Start Bootstrap develops free to download, open source Bootstrap 5 themes, templates, and snippets and creates guides and tutorials to help you learn more about designing and developing with Bootstrap.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;startbootstrap.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 사용할 코드는 다음 페이지에 나와있는 템플릿이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://startbootstrap.com/theme/freelancer&quot;&gt;https://startbootstrap.com/theme/freelancer&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1627973091396&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Freelancer - One Page Theme&quot; data-og-description=&quot;A free one page Bootstrap portfolio theme for freelancers. All Start Bootstrap templates are free to download and open source.&quot; data-og-host=&quot;startbootstrap.com&quot; data-og-source-url=&quot;https://startbootstrap.com/theme/freelancer&quot; data-og-url=&quot;https://startbootstrap.com/theme/freelancer&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/z5LPn/hyKXUsQ9oZ/5vKn6E8Xp3kQqsjFjVHl0K/img.png?width=1200&amp;amp;height=630&amp;amp;face=556_208_634_292,https://scrap.kakaocdn.net/dn/M0gHr/hyKXPSDnFJ/LSRDqwsrfQYZjMUuTqOuU0/img.png?width=1200&amp;amp;height=628&amp;amp;face=549_200_637_295,https://scrap.kakaocdn.net/dn/bEcskq/hyKXUl7YaQ/ddttc2WlHlppfg2vHaGuaK/img.png?width=1500&amp;amp;height=1000&amp;amp;face=0_0_1500_1000&quot;&gt;&lt;a href=&quot;https://startbootstrap.com/theme/freelancer&quot; data-source-url=&quot;https://startbootstrap.com/theme/freelancer&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/z5LPn/hyKXUsQ9oZ/5vKn6E8Xp3kQqsjFjVHl0K/img.png?width=1200&amp;amp;height=630&amp;amp;face=556_208_634_292,https://scrap.kakaocdn.net/dn/M0gHr/hyKXPSDnFJ/LSRDqwsrfQYZjMUuTqOuU0/img.png?width=1200&amp;amp;height=628&amp;amp;face=549_200_637_295,https://scrap.kakaocdn.net/dn/bEcskq/hyKXUl7YaQ/ddttc2WlHlppfg2vHaGuaK/img.png?width=1500&amp;amp;height=1000&amp;amp;face=0_0_1500_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Freelancer - One Page Theme&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A free one page Bootstrap portfolio theme for freelancers. All Start Bootstrap templates are free to download and open source.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;startbootstrap.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;템플릿 조각 나누기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 나눌 코드는 Navigation, Footer, Config 이다. 조각 나누는 순서는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;fragment를 저장할 디렉터리를 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;새로만든 디렉터리에 나눌 fragment 코드 분리&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 템플릿에 있는 navigation, footer, config 부분을 빼내어 새로 만들어보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(부분 생략하였다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;navigation.html&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091397&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;

&amp;lt;body&amp;gt;
&amp;lt;nav th:fragment=&quot;navigation&quot; class=&quot;navbar navbar-expand-lg bg-secondary text-uppercase fixed-top&quot; id=&quot;mainNav&quot;&amp;gt;
    &amp;lt;!-- Navigation--&amp;gt;
&amp;lt;/nav&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;footer.html&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091398&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;

&amp;lt;body&amp;gt;
	&amp;lt;footer th:fragment=&quot;footer&quot; class=&quot;footer text-center&quot;&amp;gt;
		&amp;lt;!-- Footer--&amp;gt;
	&amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;config.html&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091398&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head th:fragment=&quot;config&quot;&amp;gt;
    &amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot; /&amp;gt;
    &amp;lt;meta name=&quot;description&quot; content=&quot;&quot; /&amp;gt;
    &amp;lt;meta name=&quot;author&quot; content=&quot;&quot; /&amp;gt;
    &amp;lt;title&amp;gt;Freelancer - Start Bootstrap Theme&amp;lt;/title&amp;gt;
    &amp;lt;!-- Favicon--&amp;gt;
    &amp;lt;link rel=&quot;icon&quot; type=&quot;image/x-icon&quot; href=&quot;assets/favicon.ico&quot; /&amp;gt;
    &amp;lt;!-- Font Awesome icons (free version)--&amp;gt;
    &amp;lt;script src=&quot;https://use.fontawesome.com/releases/v5.15.3/js/all.js&quot; crossorigin=&quot;anonymous&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;!-- Google fonts--&amp;gt;
    &amp;lt;link href=&quot;https://fonts.googleapis.com/css?family=Montserrat:400,700&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&amp;gt;
    &amp;lt;link href=&quot;https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&amp;gt;
    &amp;lt;!-- Core theme CSS (includes Bootstrap)--&amp;gt;
    &amp;lt;link href=&quot;css/styles.css&quot; rel=&quot;stylesheet&quot; /&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;fragment : 해당 부분을 fragment로 지정한다는 코드이다. 다른 코드에서 해당 fragment name을 통해 인식한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;레이아웃 생성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;먼저 레이아웃을 생성하자.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;template/layouts/base.html&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091398&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
	&amp;lt;html th:fragment=&quot;layout (title, content)&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
		&amp;lt;head&amp;gt;
    		&amp;lt;title th:replace=&quot;${title}&quot;&amp;gt;레이아웃 타이틀&amp;lt;/title&amp;gt;
		&amp;lt;/head&amp;gt;
		&amp;lt;body&amp;gt;

			&amp;lt;div th:replace=&quot;~{fragment/navigation :: navigation}&quot;&amp;gt;&amp;lt;/div&amp;gt;

			&amp;lt;section th:replace=&quot;${content}&quot; class=&quot;page-section&quot; id=&quot;contact&quot;&amp;gt;
    			&amp;lt;p&amp;gt;레이아웃 컨텐츠&amp;lt;/p&amp;gt;
			&amp;lt;/section&amp;gt;


			&amp;lt;div th:replace=&quot;~{fragment/footer :: footer}&quot;&amp;gt;&amp;lt;/div&amp;gt;
			&amp;lt;div th:replace=&quot;~{fragment/copyright :: copyright}&quot;&amp;gt;&amp;lt;/div&amp;gt;
			&amp;lt;div th:replace=&quot;~{fragment/config :: config}&quot;&amp;gt;&amp;lt;/div&amp;gt;

			&amp;lt;/div&amp;gt;

		&amp;lt;/body&amp;gt;
	&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;앞에서 생성한 fragment를 차례대로 불렀다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091399&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div th:replace=&quot;~{fragment/navigation :: navigation}&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 앞에서 생성한 navigation fragment를 replace한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627973091399&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;section th:replace=&quot;${content}&quot; class=&quot;page-section&quot; id=&quot;contact&quot;&amp;gt;
    &amp;lt;p&amp;gt;레이아웃 컨텐츠&amp;lt;/p&amp;gt;
&amp;lt;/section&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;레이아웃을 사용했을 때, 해당 부분은 customize 하도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;템플릿 조각과 레이아웃이란?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음의 그림을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5zO0s%2Fbtq97lWuTb3%2FLuaZAhiGHRU5N2MkPisMm0%2Fimg.jpg&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;586&quot; data-filename=&quot;KakaoTalk_20210721_213516991.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btgAth/btra8zLHC9P/A5ZoB68widu1HqZevQKvWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btgAth/btra8zLHC9P/A5ZoB68widu1HqZevQKvWk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btgAth/btra8zLHC9P/A5ZoB68widu1HqZevQKvWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5zO0s%2Fbtq97lWuTb3%2FLuaZAhiGHRU5N2MkPisMm0%2Fimg.jpg&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;586&quot; data-filename=&quot;KakaoTalk_20210721_213516991.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;페이지 3개를 만든다고 가정하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 그림을 보면 header, navbar, footer는 세 페이지에 공통으로 똑같이 적용된다는 것을 알 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 코드에 같은 코드가 들어간다면 유지보수 중에 너무나도 힘들 가능성이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;(※ 예를 들어, navbar에 한 글자를 바꾼다고하면 페이지 갯수만큼 수정을 해야한다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 다음과 같이 fragment를 생성하여 가져다 쓸 수 있게 하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 그림을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFIjOe%2FbtracZRHpme%2FBP45F6VkkLvQKXHJXHRne1%2Fimg.jpg&quot; width=&quot;485&quot; height=&quot;513&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1058&quot; data-filename=&quot;KakaoTalk_20210721_214849533.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvCnPC/btra35qXd3O/Gtx6YMcZh1VWz3paFfs8O1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvCnPC/btra35qXd3O/Gtx6YMcZh1VWz3paFfs8O1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvCnPC/btra35qXd3O/Gtx6YMcZh1VWz3paFfs8O1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFIjOe%2FbtracZRHpme%2FBP45F6VkkLvQKXHJXHRne1%2Fimg.jpg&quot; width=&quot;485&quot; height=&quot;513&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1058&quot; data-filename=&quot;KakaoTalk_20210721_214849533.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;board라는 페이지를 만든다고 가정하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;따로 header, navbar, footer를 생성해놓고 가져다 쓰는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;(※ 이 경우, 따로 생성해놓은 navbar만 고쳐주면 해당 navbar를 쓰는 모든 페이지가 수정될 것이다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발자는 content 내용만 각각 페이지에 다르게 설정해주면 코드중복없이(템플릿을 가져다 쓰는 코드는 중복될 수 있다.) 페이지를 생성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 레이아웃은 무엇인가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음 그림을 보면서 이해하자&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF7jsO%2Fbtrac792OmU%2FDLywQz5eQV4O2eGw2Q9iH0%2Fimg.jpg&quot; width=&quot;381&quot; height=&quot;490&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1286&quot; data-filename=&quot;KakaoTalk_20210721_214907339.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb9mrI/btra337DsQm/k3E7mUSWXVUZVGiNVaU7WK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb9mrI/btra337DsQm/k3E7mUSWXVUZVGiNVaU7WK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb9mrI/btra337DsQm/k3E7mUSWXVUZVGiNVaU7WK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF7jsO%2Fbtrac792OmU%2FDLywQz5eQV4O2eGw2Q9iH0%2Fimg.jpg&quot; width=&quot;381&quot; height=&quot;490&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1286&quot; data-filename=&quot;KakaoTalk_20210721_214907339.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 템플릿의 위치가 똑같고 페이지가 대부분 비슷할 경우, 모범 html(레이아웃)을 만들고 그것만 가져다 쓰면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;(※ 레이아웃에서 각 페이지마다 customize할 부분을 정해두어야 한다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이해가 쉽쥬!?&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/Thymeleaf</category>
      <category>FRONT</category>
      <category>Thymeleaf</category>
      <category>view</category>
      <category>web</category>
      <category>관심쟁이영호</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/150</guid>
      <comments>https://bestkingit.tistory.com/150#entry150comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:45:15 +0900</pubDate>
    </item>
    <item>
      <title>[Thymeleaf] 입력 폼 처리</title>
      <link>https://bestkingit.tistory.com/149</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은 내가 개발 공부를 하면서 가장 많이 사용했던 입력 폼 처리에 대해서 공부를 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;입력 폼 처리란&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;입력 폼 적용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;입력 폼 처리란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 개발공부를 하면서 Form 형태로 data를 주고받는 경우를 자주 볼 수 있다. Thymeleaf는 해당 폼 데이터를 주고받을 때, 많은 도움을 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;입력 폼 적용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음의 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627973046671&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;form action=&quot;item.html&quot; th:action th:object=&quot;${item}&quot; method=&quot;post&quot;&amp;gt;

 &amp;lt;div&amp;gt;
 &amp;lt;label for=&quot;itemName&quot;&amp;gt;상품명&amp;lt;/label&amp;gt;
 &amp;lt;input type=&quot;text&quot; id=&quot;itemName&quot; th:field=&quot;*{itemName}&quot; class=&quot;formcontrol&quot; placeholder=&quot;이름을 입력하세요&quot;&amp;gt;
 &amp;lt;/div&amp;gt;
 
 &amp;lt;div&amp;gt;
 &amp;lt;label for=&quot;price&quot;&amp;gt;가격&amp;lt;/label&amp;gt;
 &amp;lt;input type=&quot;text&quot; id=&quot;price&quot; th:field=&quot;*{price}&quot; class=&quot;form-control&quot;
placeholder=&quot;가격을 입력하세요&quot;&amp;gt;
 &amp;lt;/div&amp;gt;
 
 &amp;lt;div&amp;gt;
 &amp;lt;label for=&quot;quantity&quot;&amp;gt;수량&amp;lt;/label&amp;gt;
 &amp;lt;input type=&quot;text&quot; id=&quot;quantity&quot; th:field=&quot;*{quantity}&quot; class=&quot;formcontrol&quot; placeholder=&quot;수량을 입력하세요&quot;&amp;gt;
 &amp;lt;/div&amp;gt;
 
 &amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위 코드를 보면 1개의 폼을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;태그를 1개씩 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;th:object : 객체를 지정한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;*{~} : th:object에서 지정한 객체에 접근한다. *{itemName}이라고 하면 item.itemName이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;th:field : HTML 태그의 id, name, value 속성을 자동 처리해준다. &amp;lt;input type=&quot;text&quot; th:field=&quot;*{itemName}&quot; /&amp;gt;는 다음과 같이 렌더링 된다. &amp;lt;input type=&quot;text&quot; id=&quot;itemName&quot; name=&quot;itemName&quot; th:value=&quot;*{itemName} /&amp;gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;※ 위의 object에서 객체를 지정하기 위해서는 먼저 오브젝트에 대한 정보를 넘겨주어야 한다. 그래서 Controller에서 &quot;model.addAttribute(&quot;item&quot;, new Item())&quot;을 해주어 오브젝트를 model에 담아주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;※ *{itemName} = ${item.itemName} -&amp;gt; th:object로 객체를 지정했기 때문에 사용 가능&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/Thymeleaf</category>
      <category>form</category>
      <category>input</category>
      <category>Thymeleaf</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/149</guid>
      <comments>https://bestkingit.tistory.com/149#entry149comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:44:22 +0900</pubDate>
    </item>
    <item>
      <title>[Thymeleaf]#1 타임리프 기본 기능 ㅣ text, SpringEL, 기본 객체</title>
      <link>https://bestkingit.tistory.com/148</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;백엔드 공부를 하면서, 많은 고충이 있었다. 그중 가장 많이 맞닿은 문제는 뷰에서의 문제였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 구현한 내용을 눈으로 확인하고 싶지만 프론트에 대한 지식이 부족하여 발목이 많이 잡혔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맷돌에 손잡이가 없어서 맷돌을 사용하면 안되니까!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 기회에 확실하게 공부를 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf란?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf에 변수, 객체 넘기기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf 사용 선언&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf 간단한 표현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;text&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;SpringEL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URL 링크&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;속성 값 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;조건부 평가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thymeleaf란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에 기록을 하며 확실하게 정리하고 넘어가 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 먼저 &quot;템플릿 엔진&quot;에 대해서 알아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;템플릿 엔진&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 템플릿 엔진은 웹 문서를 출력하는 엔진이다. 개발을 진행하면서 자바 코드 - html 코드 간의 상이함을 최대한 줄여주기 위해서 나온 엔진이라고 생각하면 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 템플릿 엔진을 사용하면 html 문서 내에서 자바 코드를 사용할 수 있는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 그 외 연산, 객체 등등의 기능을 수행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thymeleaf&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- Thymeleaf는 수많은 템플릿 엔진 중에 하나이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 스프링 진영에서 가장 많이 쓰이는 엔진 중에 하나이다. 이유는 스프링에서 자체적으로 Thymeleaf에 대한 기능을 제공하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- Thymeleaf는 html의 모양을 최대한 유지하려는 특징이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;※ 나는 스프링을 공부할 거니까.. Thymeleaf를 공부하는 것! 더 이상 뷰 때문에 스트레스받고 싶지 않다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thymeelaf에 변수, 객체 넘기기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링에서는 model에 추가해놓으면, Thymeleaf가 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966479&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;User objectUser = new User()

Map&amp;lt;String, User&amp;gt; map = new HashMap&amp;lt;&amp;gt;();

int a;

//변수 담기
model.addAttribute(&quot;var&quot;, a);

//객체 담기
model.addAttribute(&quot;Object&quot;, ObjectUser);

//Map 담기
model.addAttribute(&quot;Map&quot;, map);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 model에 담고 템플릿을 리턴하면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 템플릿에서 model에서 변수, 객체, Map 등을 꺼내서 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thymeleaf 사용 선언&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf를 사용하기 위해서는 &amp;lt;html&amp;gt; 태그에 thymeleaf를 사용한다는 선언을 해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하는 법은 다음과 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966480&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;

&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thymeleaf 간단한 표현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;변수 표현식 : ${~}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;선택 변수 표현식: *{~}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;메시지 표현 : #{~}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;URL 표현: @{~}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;비교 : &amp;gt;, &amp;lt;, &amp;gt;=, &amp;lt;=, (gt, lt, ge, le)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;등이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래에서 다른 이론에 적용해보면서 익혀보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;text&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;텍스트를 출력하는 기능이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래와 같이 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966481&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div th:text=&quot;${data}&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 사용하면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Model에 담겨있는 &quot;data&quot;에 해당하는 값을 출력한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;SpringEL&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;타임리프에서는 변수 표현식을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와 같이 &quot;${~}&quot;를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Object에서의 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966482&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;Object

 &amp;lt;li&amp;gt;${user.username} = &amp;lt;span th:text=&quot;${user.username}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;${user['username']} = &amp;lt;span th:text=&quot;${user['username']}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;${user.getUsername()} = &amp;lt;span th:text=&quot;${user.getUsername()}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user.username : user의 username을 프로퍼티 접근법으로 접근한다. (user.getUsername())&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user ['username']: 위와 같은 방식으로 접근한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user.getUsername(): 직접 호출한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;List에서의 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966482&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;List

 &amp;lt;li&amp;gt;${users[0].username} = &amp;lt;span th:text=&quot;${users[0].username}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
 &amp;lt;li&amp;gt;${users[0]['username']} = &amp;lt;span th:text=&quot;${users[0]['username']}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
 &amp;lt;li&amp;gt;${users[0].getUsername()} = &amp;lt;span th:text=&quot;${users[0].getUsername()}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;

&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;users[0].username : users라는 리스트에서 0에 해당하는 index를 찾고 프로퍼티 접근을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나머지는 위의 Object와 같다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Map에서의 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966483&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;Map

 &amp;lt;li&amp;gt;${userMap['userA'].username} = &amp;lt;span th:text=&quot;${userMap['userA'].username}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
 &amp;lt;li&amp;gt;${userMap['userA']['username']} = &amp;lt;span th:text=&quot;${userMap['userA']['username']}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
 &amp;lt;li&amp;gt;${userMap['userA'].getUsername()} = &amp;lt;span th:text=&quot;${userMap['userA'].getUsername()}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
 
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;userMap['userA'].username : Map에서 userA를 찾고, 프로퍼티 접근을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나머지는 위의 Object와 같다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;URL 링크&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Thymeleaf에서는 @{~} 으로 url을 표현한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래의 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966483&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;li&amp;gt;&amp;lt;a th:href=&quot;@{/login}&quot;&amp;gt;basic url&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;

&amp;lt;li&amp;gt;&amp;lt;a th:href=&quot;@{/login(param1=${param1}, param2=${param2})}&quot;&amp;gt;hello queryparam&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;

&amp;lt;li&amp;gt;&amp;lt;a th:href=&quot;@{/login/{param1}/{param2}(param1=${param1}, param2=${param2})}&quot;&amp;gt;path variable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;

&amp;lt;li&amp;gt;&amp;lt;a th:href=&quot;@{/login/{param1}(param2=${param2})}&quot;&amp;gt;path + query param&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;코드 설명:&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;단순 URL : @{/login}으로 표현한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;쿼리 파라미터 : @{/login(param1=${param1}, param2=${param2})}는 /hello?param1=data&amp;amp;param2=data2로 변환된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;경로 변수: @{/login/{param1}/{param2}(param2}(param1=${param1}, param2=${param2})}는 /login/data1/data2로 변환된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;경로 변수 + 쿼리 파라미터 : @{/login/{param1}(param2=${param2})}는 /login/data1?param2=data2로 변환된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;속성 값 설정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;타임리프에서는 속성 값을 변경할 수 있다. 다음 코드를 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966484&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;속성 추가&amp;lt;/h1&amp;gt;

- th:attrappend = &amp;lt;input type=&quot;text&quot; class=&quot;text&quot; th:attrappend=&quot;class='large'&quot; /&amp;gt;&amp;lt;br/&amp;gt;

- th:classappend = &amp;lt;input type=&quot;text&quot; class=&quot;text&quot; th:classappend=&quot;large&quot; /&amp;gt;&amp;lt;br/&amp;gt;

- checked o &amp;lt;input type=&quot;checkbox&quot; name=&quot;active&quot; th:checked=&quot;true&quot; /&amp;gt;&amp;lt;br/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면 th로 설정한 내용대로 속성 값이 변경되거나 추가된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;조건부 평가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;if와 같다고 생각하자&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크게 if와 unless로 두 가지가 있다. unless는 if의 반대 문법이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972966485&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;span th:text=&quot;'미성년자'&quot; th:if=&quot;${user.age lt 20}&quot;&amp;gt;&amp;lt;/span&amp;gt;

&amp;lt;span th:text=&quot;'미성년자'&quot; th:unless=&quot;${user.age ge 20}&quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 조건이 false인 경우 렌더링 자체가 되지 않고 사라진다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘은&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기까지만 알아보고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추후에 더 알아보자!&lt;/span&gt;&lt;/p&gt;</description>
      <category>FRONT</category>
      <category>template engine</category>
      <category>Thymeleaf</category>
      <category>view</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/148</guid>
      <comments>https://bestkingit.tistory.com/148#entry148comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:43:06 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] 파일 업로드</title>
      <link>https://bestkingit.tistory.com/147</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오늘은 Spring Boot를 이용하여 파일 업로드에 대해서 공부할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;목차&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;HTML Form 전송 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;File 도메인 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;게시글 쓰기 Post Mapping 수정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;파일 올리기 Service 작성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;FileHanler 작성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;HTML 폼 전송 방식&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;파일을 서버와 주고받기 위해서는 가장 먼저, HTML Form 전송 방식을 알아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;두 가지의 전송 방식이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;multipart/form-data&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;application/x-www-form-urlencoded&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 해당 방식은 HTML 폼 데이터를 서버로 전송하는 가장 기본적인 방법이다. form 태그에 enctype 옵션을 넣어주지 않으면 브라우저는 헤더에 다음 내용을 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862486&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Content-Type: application/x-www-form-urlencoded&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;또한, 폼 내용을 HTTP Body에 A=10&amp;amp;B=13과 같이 &quot;&amp;amp;&quot;를 구분자로 이용하여 전송한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 파일을 업로드를 하기위해서는 문자가 아닌 바이너리 데이터를 전송해야 한다. 문자로는 파일을 전송하기가 어렵다. 근데 폼을 이용하여 파일을 전송해야 할 경우에는 파일뿐만 아니라 문자도 포함되어 있는 폼일 확률이 높다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위와 같은 이유때문에 단순히 구분자 &quot;&amp;amp;&quot;를 이용하는 application/x-www-form-urlencoded를 이용하기는 한계가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;multipart/form-data&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 해당 방식은 문자와 바이너리 데이터를 같이 보낼 수 있도록 하는 방식이다. 이것을 이용하기 위해서는 form에 enctype=&quot;multipart/form-data&quot;라는 속성을 추가해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 이 방식으로 생성한 HTTP 메시지는 각각 전송 항목이 구분되어있다. 위의 예에서는 A, B, File로 각각 분리되어서 전송된다. 문자는 문자 그대로 전송, 파일은 파일 이름과 Content-Type이 추가되고 바이너리 데이터가 전송된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;더 정확한 이해를 위해 실제 코드를 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;실제 코드&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;html form&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862487&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;form id=&quot;board&quot; action=&quot;/board_write&quot; method=&quot;post&quot; th:object=&quot;${board}&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label for=&quot;title&quot; class=&quot;h4&quot;&amp;gt;제목&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;title&quot; name=&quot;title&quot; placeholder=&quot;제목을 작성해주세요.&quot;&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;hr width = &quot;100%&quot; color = &quot;blue&quot; size = &quot;3&quot;&amp;gt;&amp;lt;br&amp;gt;

        &amp;lt;input type=&quot;file&quot; id=&quot;imageFiles&quot; name=&quot;imageFiles&quot; multiple=&quot;multiple&quot; accept=&quot;image/*&quot;&amp;gt;

        &amp;lt;hr width = &quot;100%&quot; color = &quot;blue&quot; size = &quot;3&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label for=&quot;content&quot; class=&quot;h4&quot;&amp;gt;내용&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;
            &amp;lt;textarea class=&quot;form-control&quot; id=&quot;content&quot; name=&quot;content&quot; rows=&quot;10&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;hr width = &quot;100%&quot; color = &quot;blue&quot; size = &quot;3&quot;&amp;gt; &amp;lt;br&amp;gt;

        &amp;lt;div class=&quot;text-center&quot;&amp;gt;

            &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot; style=&quot;color:white;&quot;&amp;gt;등록하기&amp;lt;/button&amp;gt;

            &amp;lt;button type=&quot;button&quot; class=&quot;btn btn-danger&quot; style=&quot;color:white;&quot; onclick=&quot;location.href='/board'&quot;&amp;gt;목록으로&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 다음과 같이 내용을 작성했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLoGau%2FbtraInLhh1z%2FK6GKXwvYkHXi98kDpajoU1%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;501&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elSlUc/btra4WGYUL5/xd1qkt0IG6fkBHWXeAVJOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elSlUc/btra4WGYUL5/xd1qkt0IG6fkBHWXeAVJOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elSlUc/btra4WGYUL5/xd1qkt0IG6fkBHWXeAVJOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLoGau%2FbtraInLhh1z%2FK6GKXwvYkHXi98kDpajoU1%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;501&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 HTTP 내용을 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ HTTP 요청 내용을 보기 위해서 application yml에 다음과 같은 로깅 코드를 추가했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862488&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;logging:
  level:
    org:
      apache:
        coyote:
          http11: debug&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 HTTP 내용을 보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862488&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;------WebKitFormBoundaryMVA4MPoFDDjKPJl2
Content-Disposition: form-data; name=&quot;title&quot;

this is title!
------WebKitFormBoundaryMVA4MPoFDDjKPJl2
Content-Disposition: form-data; name=&quot;image&quot;; filename=&quot;&amp;igrave;&amp;not;&amp;igrave;&amp;sect;.jpg&quot;
Content-Type: image/jpeg

... &amp;yuml;&amp;Oslash;&amp;yuml;&amp;agrave;&amp;middot;'j&amp;copy;?AG&amp;Ugrave;'&amp;igrave; &amp;yuml;&amp;Ugrave; ...
------WebKitFormBoundaryMVA4MPoFDDjKPJl2
Content-Disposition: form-data; name=&quot;content&quot;

this is content!
------WebKitFormBoundaryMVA4MPoFDDjKPJl2--&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;바이너리 코드가 너무 길어 생략했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;살펴보면 다음과 같은 구조를 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;---xxx&quot;로 영역 구분&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;Content-Dispositon: form-data; ~~&quot; : 영역의 시작(해당 영역에 대한 정보)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;---xxx--&quot;로 끝 명시&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;File 도메인 생성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;File 도메인을 새롭게 생성하는 이유는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;User 정보에서 올린 파일들을 조회할 수 있기 위해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;파일 또는 게시글 정보로만 양방향으로 접근할 수 있게 하기 위해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;사용자가 정해진 여러 개의 파일을 올릴 수 있게 하기 위해&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;File이라는 객체를 따로 도메인으로 생성해놓으면, 여러 가지 방면에서 좋은 점이 있을 것이라고 판단이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Board 내에 리스트로 만들어놓는 것보다 유연하다고 판단된다. 그리고 User 정보만으로도 File로 접근할 수 있고(리스트로 하면 Board를 거쳐야 한다.) File만으로도 User 및 Board에 접근할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 따로 관리하는 만큼 조금 더 복잡하겠지..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다음은 도메인을 생성한 코드이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862489&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Entity
@Table(name = &quot;user_file&quot;)
public class UserFile {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = &quot;file_id&quot;)
    private Long id;

    @ManyToOne
    @JoinColumn(name = &quot;boardId&quot;)
    private Board board;

    @Column(nullable = false)
    private String origFileName;  // 파일 원본명

    @Column(nullable = false)
    private String filePath;  // 파일 저장 경로

    @Column(nullable = false)
    private String savedName;

    private Long fileSize;

    @ManyToOne
    @JoinColumn(name = &quot;userId&quot;)
    private User user;

    @CreationTimestamp
    private Timestamp createDate;

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여러 가지의 내용이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;처음에는 관련 자료들을 찾아보다가 이해가 안 되었다. 그래서 다음 그림을 보면서 이해해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvL9to%2FbtraImmwTGa%2FjIhmOFKhq6c32wq7dKNJKK%2Fimg.jpg&quot; width=&quot;450&quot; height=&quot;480&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1365&quot; data-filename=&quot;ㅋㅌㅊㅍ.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/si4ZM/btraWvXMK5s/5aDYjLz6mXvwE24aHwEkfK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/si4ZM/btraWvXMK5s/5aDYjLz6mXvwE24aHwEkfK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/si4ZM/btraWvXMK5s/5aDYjLz6mXvwE24aHwEkfK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvL9to%2FbtraImmwTGa%2FjIhmOFKhq6c32wq7dKNJKK%2Fimg.jpg&quot; width=&quot;450&quot; height=&quot;480&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1365&quot; data-filename=&quot;ㅋㅌㅊㅍ.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실제 서버는 각종 파일들을 어떻게 관리할까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 실제 서버가 가지고 있는 DB에는 파일이 저장되어있는 디렉터리 정보만 저장되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 이후에 해당 파일을 접근해야 될 일이 있으면 DB의 디렉터리를 이용하여 접근한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이러한 이유로 파일 도메인은&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;directory, original name 등등 여러 가지의 필드가 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 외 나머지는 @ManyToOne 관계의 객체, 저장 시간, 시퀀스 등등이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;게시글 쓰기 Post Mapping 수정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이전에 사용한 post에서 파일을 받을 수 있게 수정해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;스프링에서는 파일을 주고받을 때, MultipartFile을 이용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드를 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862490&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; @PostMapping(&quot;/board_write&quot;)
    public String BoardWriter(@ModelAttribute Board board, @RequestParam(value=&quot;imageFiles&quot;, required=false) List&amp;lt;MultipartFile&amp;gt; files, @SessionAttribute(name = SessionConst.LOGIN_USER, required = false)
            User user) throws IOException {


        boardWriteService.write(board, user);
        boardUserFileService.userFilelRepository(fileHandler.UserFileUpload(files, user.getUserId()), board);
        return &quot;redirect:/board&quot;;

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@RequestParam을 이용하여 파라미터를 받는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;List인 이유는 사용자가 한 번의 요청으로 여러 개의 파일을 보낼 수가 있기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;파일 올리기 서비스 작성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드를 바로 살펴보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862491&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class BoardUserFileService {
    private final UserFileRepository userFileRepository;

    public void userFilelRepository(List&amp;lt;UserFile&amp;gt; userFileList, Board board){

        if(userFileList.isEmpty()){
            return;
        }
        for(UserFile userfile : userFileList){
            userfile.setBoard(board);
            userFileRepository.save(userfile);
        }
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;유저가 파일을 안 올렸을 경우에는 바로 리턴,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;파일을 올려주었을 경우에는 File과 해당 Board를 연결해주어야 한다. 그래서 File의 내용에 board객체를 set 해주는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 jpa를 이용하여 저장했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;FileHandler 작성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실제로 요청으로 오는 파일은 바이너리 값과 이름이다. 그래서 해당 바이너리를 디렉터리, 저장 이름 등을 설정해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;※ 여기서 디렉터리를 새롭게 생성해주거나 저장할 파일 이름(사용자가 입력한 거랑 다름!!) 그리고 MultipartFile -&amp;gt; File 객체로 변경해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다음 코드를 보자&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972862491&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
@RequiredArgsConstructor
@Slf4j
public class FileHandler {

    private final BoardUserFileService boardUserFileService;
    private final UserRepository userRepository;

    public List&amp;lt;UserFile&amp;gt; UserFileUpload(List&amp;lt;MultipartFile&amp;gt; files, String userId) throws IOException {

        // 반환할 파일 리스트
        List&amp;lt;UserFile&amp;gt; fileList = new ArrayList&amp;lt;&amp;gt;();
        User user = userRepository.findByUserId(userId);

        // 전달되어 온 파일이 존재할 경우
        if(!CollectionUtils.isEmpty(files)) {
            LocalDateTime now = LocalDateTime.now();
            DateTimeFormatter dateTimeFormatter =
                    DateTimeFormatter.ofPattern(&quot;yyyyMMdd&quot;);
            String current_date = now.format(dateTimeFormatter);

        for(MultipartFile multipartFile : files) {
            String path = &quot;C:/test&quot;+&quot;/&quot;+userId+&quot;/&quot;;

            String extension;
            String contentType = multipartFile.getContentType();

            if(ObjectUtils.isEmpty(contentType)) {
                break;
            }

            extension = FilenameUtils.getExtension(multipartFile.getOriginalFilename());

            String new_file_name = current_date + &quot;_&quot;+System.nanoTime() + &quot;.&quot; + extension;

            File file = new File(path + new_file_name); //파일 저장 경로 확인, 없으면 만든다.
            if (!file.exists()) {
                file.mkdirs();
            }
            UserFile userFile = new UserFile();


            userFile.setUser(user);
            userFile.setFilePath(path + new_file_name);
            userFile.setFileSize(multipartFile.getSize());
            userFile.setOrigFileName(multipartFile.getOriginalFilename());
            userFile.setSavedName(new_file_name);

            fileList.add(userFile);

            multipartFile.transferTo(file);

            file.setWritable(true);
            file.setReadable(true);
        }
            return fileList;
    }

        return null;

    }



};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;유저 id로 디렉터리 생성하였다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;날짜 + 나노 초를 통해서 파일 이름의 중복 문제를 해결했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;file을 저장해주고 File객체로 변경한 다음 List로 리턴해주었다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;List를 리턴해주면 Service에서 board와 연결할 것이다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>backend</category>
      <category>file</category>
      <category>Programming</category>
      <category>upload</category>
      <category>web</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/147</guid>
      <comments>https://bestkingit.tistory.com/147#entry147comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:41:47 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] 인터셉터 ㅣ intercepter</title>
      <link>https://bestkingit.tistory.com/146</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 스프링 부트에서 제공하는 필터와 인터셉터에 대해서 공부를 해볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터셉터란?&lt;/li&gt;
&lt;li&gt;스프링 인터셉터 인터페이스&lt;/li&gt;
&lt;li&gt;인터셉터 적용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터셉터란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 예시를 통해서 이해해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 Get 요청으로 로그인을 하지않은 상태에서 &quot;회원A의 정보 수정 페이지&quot;를 요청하면 해당 페이지가 나오지 않아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러기 위해서 인터셉터를 사용한다. 여기서 인터셉터는 해당 사용자가 &quot;회원 A&quot;로 로그인을 했는지 살펴봐야한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터셉터 흐름&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 요청 -&amp;gt; WAS -&amp;gt; 필터 -&amp;gt; 서블릿 -&amp;gt; 스프링 인터셉터 -&amp;gt; 컨트롤러&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터셉터는 서블릿이 컨트롤러를 호출하기 전에 호출된다는 것을 알아두자!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터셉터 체인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 요청 -&amp;gt; WAS -&amp;gt; 필터 -&amp;gt; 서블릿 -&amp;gt; 인터셉터1 -&amp;gt; 인터셉터2 -&amp;gt; 인터셉터3 -&amp;gt; ... -&amp;gt; 컨트롤러&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터셉터는 위와 같이 여러가지의 인터셉터를 연결하여 적용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터셉터 제한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예를 보면 인터셉터1에서 다음 인터셉터2가 적용하지 않을 수 있도록 막을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;스프링 인터셉터 인터페이스&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 인터셉터를 사용하기 위해서는 HandlerInterceptor를 완성하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972825325&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface HandlerInterceptor {

//preHandle
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
Object handler) throws Exception {}

//postHandle
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
@Nullable ModelAndView modelAndView) throws Exception {}

//afterCompletion
default void afterCompletion(HttpServletRequest request, HttpServletResponse response,
 Object handler, @Nullable Exception ex) throws Exception {}
 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 인터셉터 인터페이스에는 3가지의 메소드가 존재한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;preHandle&lt;/li&gt;
&lt;li&gt;postHandle&lt;/li&gt;
&lt;li&gt;afterCompletion&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각 호출되는 시점이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;호출 시점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;preHandle : 핸들러 어댑터가 호출되기 전&lt;/li&gt;
&lt;li&gt;postHandle : 컨트롤러 호출 다음인 핸들러 어댑터 호출 후&lt;/li&gt;
&lt;li&gt;afterCompletion : 뷰 렌더링 이후&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;예외&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정상적으로 통과가 된다면 더할 나위없이 좋겠지만, 인터셉터에서 예외가 터져버린다면 (아까와 같이 로그인이 되어있지 않은 상태에서 요청 시) 다음과 같이 호출된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;preHandle : 컨트롤러 호출 전에 호출&lt;/li&gt;
&lt;li&gt;postHandle: 컨트롤러에서 예외 발생시 postHandle은 호출되지 않음&lt;/li&gt;
&lt;li&gt;afterCompletion : 앞에서 예외가 발생해도 발생 -&amp;gt; 공통 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터셉터 적용하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Step 1. 뷰 생성하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 가장먼저 로그인 상태에서만 접근할 페이지를 생성하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;modify.html&lt;/p&gt;
&lt;pre id=&quot;code_1627972825327&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;회원 수정&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form action=&quot;/modify&quot; method=&quot;post&quot;&amp;gt;
        과거 아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;beforeId&quot; id=&quot;beforeId&quot;/&amp;gt;&amp;lt;br&amp;gt;
        과거 비밀번호 : &amp;lt;input type=&quot;text&quot; name=&quot;beforePassword&quot; id=&quot;beforePassword&quot;/&amp;gt;&amp;lt;br&amp;gt;
        아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;userId&quot; id=&quot;userId&quot;/&amp;gt;&amp;lt;br&amp;gt;
        비밀번호: &amp;lt;input type=&quot;text&quot; name=&quot;password&quot;/&amp;gt;&amp;lt;br&amp;gt;
        &amp;lt;input type=&quot;submit&quot; value=&quot;제출&quot; /&amp;gt; &amp;lt;br&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원 수정 페이지는 로그인이 되어있는 사람만 접근할 수 있도록 만들 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 인터셉터를 구현해보자. 인터셉터를 구현하기 위해선 몇가지의 절차가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;HandlerInterceptor 구현&lt;/li&gt;
&lt;li&gt;WebConfig에 구현한 인터셉터 등록&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Step 1. HandlerInterceptor 구현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ModifyInterceptor&lt;/p&gt;
&lt;pre id=&quot;code_1627972825327&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
public class ModifyInterceptor implements HandlerInterceptor {

    public static final String LOG_ID = &quot;logId&quot;;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        String uuid = UUID.randomUUID().toString();
        request.setAttribute(LOG_ID, uuid);
        
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler; 
        }
        
        log.info(&quot;REQUEST [{}][{}][{}]&quot;, uuid, requestURI, handler);
        return true; 
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info(&quot;postHandle [{}]&quot;, modelAndView);
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse
            response, Object handler, Exception ex) throws Exception {
        String requestURI = request.getRequestURI();
        String logId = (String)request.getAttribute(LOG_ID);
        log.info(&quot;RESPONSE [{}][{}]&quot;, logId, requestURI);
        if (ex != null) {
            log.error(&quot;afterCompletion error!!&quot;, ex);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Step 2. WebConfig에 인터셉터 등록&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972825327&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ModifyInterceptor())
                .order(1)
                .addPathPatterns(&quot;/**&quot;)
                .excludePathPatterns(&quot;/css/**&quot;, &quot;/*.ico&quot;, &quot;/error&quot;,&quot;/login&quot;);
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;코드 설명 :&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ModifyInterceptor에서 각각 부분에 넘어오는 정보를 log로 찍어보았다 로그는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- preHandle&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9876aa;&quot;&gt;log&lt;/span&gt;.info(&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;REQUEST [{}][{}]&quot;,&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;&amp;nbsp;&lt;/span&gt;requestURI&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;handler)&lt;span style=&quot;color: #cc7832;&quot;&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972825328&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;REQUEST [37a7ca18-d81c-4907-b1ca-115f4dce6a11][/signup][cyh.adyb.web.SignUpContoller#signup(Model)]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 Request에 대한 정보를 가지고 들어온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- postHandle&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9876aa;&quot;&gt;log&lt;/span&gt;.info(&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;postHandle [{}]&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;modelAndView)&lt;span style=&quot;color: #cc7832;&quot;&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972825328&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;postHandle [ModelAndView [view=&quot;/signup&quot;; model={user=User(sequenceId=null, userId=null, password=null), org.springframework.validation.BindingResult.user=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostHandle에서는 request 정보와 ModelAndView 정보를 가지고 온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- afterCompletion&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9876aa;&quot;&gt;log&lt;/span&gt;.info(&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;RESPONSE [{}][{}]&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;logId&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;requestURI)&lt;span style=&quot;color: #cc7832;&quot;&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972825328&quot; class=&quot;html xml&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;RESPONSE [37a7ca18-d81c-4907-b1ca-115f4dce6a11][/signup]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;afterCompletion에서는 response에 대한 정보, request 정보, 해당 Handler정보, Exception에 대한 정보를 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WebConfig&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebConfig에 인터셉터를 등록할 때, 여러가지의 속성을 정의할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- addInterceptor(&lt;span style=&quot;color: #cc7832;&quot;&gt;new&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ModifyInterceptor())&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ModifyInterceptor를 인터셉터로 등록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;- .order(&lt;span style=&quot;color: #6897bb;&quot;&gt;1&lt;/span&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서는 1번째로 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;- .addPathPatterns(&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;/**&quot;&lt;/span&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 URL에만 인터셉터를 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;- excludePathPatterns(&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;/css/**&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;/*.ico&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;/error&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc7832;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #6a8759;&quot;&gt;&quot;/login&quot;&lt;/span&gt;)&lt;span style=&quot;color: #cc7832;&quot;&gt;;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 URL은 인터셉터 처리를 제외한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 속성 설정을 할 수 있는데, 해당 사항은 문서를 확인해보자!&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/146</guid>
      <comments>https://bestkingit.tistory.com/146#entry146comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:40:41 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] 쿠키, 세션</title>
      <link>https://bestkingit.tistory.com/145</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 로그인에서 쿠키 및 세션을 적용해볼 것이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿠키란?&lt;/li&gt;
&lt;li&gt;쿠키구현&lt;/li&gt;
&lt;li&gt;쿠키의 한계&lt;/li&gt;
&lt;li&gt;세션이란?&lt;/li&gt;
&lt;li&gt;세션구현&lt;/li&gt;
&lt;li&gt;스프링에서의 세션&lt;/li&gt;
&lt;li&gt;세션의 한계&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;쿠키란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿠키는 서버측에서 사용자가 누구인지 알기위한 식별값이다.&lt;/li&gt;
&lt;li&gt;TCP/IP 위의 HTTP 통신이 지속성이 없기 때문에(한번 요청 - 한번 응답 끝) 사용자가 요청했을 때, 서버측에서는 그 사용자가 누구인지 모른다.&lt;/li&gt;
&lt;li&gt;서버는 사용자가 요청을하면 쿠키를 생성하여 응답에 포함하여 전달한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림으로 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 최초의 Request - Response&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnKas6%2Fbtq96FyZBIS%2FKQszDwGucSLinnyURaPVQ0%2Fimg.png&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;423&quot; data-filename=&quot;zxczxc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buePSj/btraXWheq7R/nTEVoBqGV3OcjCna8sS5mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buePSj/btraXWheq7R/nTEVoBqGV3OcjCna8sS5mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buePSj/btraXWheq7R/nTEVoBqGV3OcjCna8sS5mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnKas6%2Fbtq96FyZBIS%2FKQszDwGucSLinnyURaPVQ0%2Fimg.png&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;423&quot; data-filename=&quot;zxczxc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 서버측에 Post요청을 한다.&lt;/li&gt;
&lt;li&gt;서버는 회원 저장소에서 로그인 id에 맞는 정보가 있는지 확인한다.&lt;/li&gt;
&lt;li&gt;없어서 쿠키를 설정하고(Set-Cookie: id=abc) 응답한다.&lt;/li&gt;
&lt;li&gt;회원은 웹브라우저에 있는 쿠키 저장소에 쿠키를 저장한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 2번째 요청(쿠키가 유지되었을 때)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRXknO%2Fbtq9Zron7QW%2F0MXZ762POWU4kmJbvTVbRK%2Fimg.png&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;423&quot; data-filename=&quot;FFFFFFFFFFFFF.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cydLzY/btra8zLHoOo/JTIsLsdwbPcUMeT9sB4Jak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cydLzY/btra8zLHoOo/JTIsLsdwbPcUMeT9sB4Jak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cydLzY/btra8zLHoOo/JTIsLsdwbPcUMeT9sB4Jak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRXknO%2Fbtq9Zron7QW%2F0MXZ762POWU4kmJbvTVbRK%2Fimg.png&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;423&quot; data-filename=&quot;FFFFFFFFFFFFF.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자는 쿠키저장소에 저장되어있는 쿠키를 포함한 요청을 한다.&lt;/li&gt;
&lt;li&gt;서버는 해당 쿠키가 회원저장소에 있는지 살펴본다.&lt;/li&gt;
&lt;li&gt;회원저장소에 해당 쿠키가 존재하여 해당 회원에 대한 응답을 해준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 내용을 보면 서로 지속성이 없는대도 요청자가 누구인지 알 수 있게 되었다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Spring에서 해당 쿠키를 어떻게 구현하는지 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 가장 쉬운방법은 컨트롤러에서 쿠키를 생성하여 Response에 담아서 응답해주면 될 것이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드로 쿠키를 생성하여 응답하는 것을 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778425&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/login&quot;)
    public String loginId(@ModelAttribute User user, HttpServletResponse response) {
        if(!loginService.login(user)){
            return &quot;login&quot;;
        }
		
        //쿠키 생성
        Cookie idCookie = new Cookie(&quot;userId&quot;, String.valueOf(user.getUserId()));
        
        //응답에 쿠키 추가
        response.addCookie(idCookie);
        
        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778425&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Cookie idCookie = new Cookie(&quot;userId&quot;, String.valueOf(user.getUserId()));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Cookie를 key: &quot;userId&quot; / value: &quot;사용자가 입력한 id&quot; 로 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778425&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;reponse.addCookie(idCookie);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 응답에 쿠키를 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 쿠키가 정상적으로 브라우저에 포함이 된지 확인해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Response 내용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fog03T%2Fbtq94qB9wqc%2FgcxeJAN1SumFyX9yRphUKk%2Fimg.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;51&quot; data-filename=&quot;캡처.PNGffc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UuxKH/btrbe6IKg2z/NDvS66SWbrhHmhrmu8l9X1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UuxKH/btrbe6IKg2z/NDvS66SWbrhHmhrmu8l9X1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UuxKH/btrbe6IKg2z/NDvS66SWbrhHmhrmu8l9X1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fog03T%2Fbtq94qB9wqc%2FgcxeJAN1SumFyX9yRphUKk%2Fimg.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;51&quot; data-filename=&quot;캡처.PNGffc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키가 Response에 &quot;userId&quot;로 전달된 것이 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자가 깨지는 것은 필자가 한글로 쿠키를 전달했기 때문이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹브라우저 Cookie 저장소&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeG6R9%2Fbtq90m8N1YN%2FvJ1MOW3EHYrpUryjhJvNBK%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;235&quot; data-filename=&quot;ccccccccccccccccccccccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg2z59/btra34ZLOt9/kBtog5fEs5r9kVZoSkvuzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg2z59/btra34ZLOt9/kBtog5fEs5r9kVZoSkvuzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg2z59/btra34ZLOt9/kBtog5fEs5r9kVZoSkvuzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeG6R9%2Fbtq90m8N1YN%2FvJ1MOW3EHYrpUryjhJvNBK%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;235&quot; data-filename=&quot;ccccccccccccccccccccccc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Application -&amp;gt; Cookies에 들어가면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key: &quot;userId&quot; / value: &quot;영호&quot; / 그 외 기타 등등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이라는 내용의 쿠키가 저장된 것을 볼 수 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;쿠키의 한계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 알아온 쿠키는 엄청 큰 한계점이 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;만약 사용자가 쿠키의 value값을 '영호' -&amp;gt; '철수' 로 교체하여 보낸다면?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 철수가 들어온지 알고, 철수에 대한 응답을 할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞다. 쿠키는 사용자의 로컬에 저장되기 때문에 얼마든지 조작 및 변경이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 쿠키를 사용한다면 반드시 변경되어도 상관없는 정보만 포함하여야 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;세션이란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션은 쿠키의 한계점을 개선한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키가 사용자측에서 관리하는 요소라면, 세션은 서버에서 관리하는 요소라고 생각하면 된다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;어떻게 서버에서 관리할까?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 쉽다. 서버에서 쿠키값을 보내지 않고, 랜덤토큰을 생성하여 사용자에게 보낸다. 서버는 랜덤토큰에 대응하는 실제 값을 관리하는 테이블을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이제 &quot;abCCDCAD^^&amp;amp;#cd&quot;라는 토큰값을 임의로 고쳐도 다른 사람의 토큰과 겹칠 가능성이 현저히 줄어든다!(거의 0퍼)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림을 통해서 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSCSVc%2Fbtq97bkiLLt%2F1ZGy8o0ddV9GxmzQLoHgh1%2Fimg.png&quot; data-origin-width=&quot;953&quot; data-origin-height=&quot;607&quot; data-filename=&quot;hhhhhhh.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7rpYO/btra8ADPpam/NqkS7p144AldAFPVhizknk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7rpYO/btra8ADPpam/NqkS7p144AldAFPVhizknk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7rpYO/btra8ADPpam/NqkS7p144AldAFPVhizknk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSCSVc%2Fbtq97bkiLLt%2F1ZGy8o0ddV9GxmzQLoHgh1%2Fimg.png&quot; data-origin-width=&quot;953&quot; data-origin-height=&quot;607&quot; data-filename=&quot;hhhhhhh.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;살펴보자!&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 id와 password로 로그인한다.&lt;/li&gt;
&lt;li&gt;서버는 해당 id로 회원저장소를 조회한다.&lt;/li&gt;
&lt;li&gt;조회 내용을 토대로 회원값을 임의의 랜덤값을 만든다!&lt;/li&gt;
&lt;li&gt;랜덤값을 사용자에게 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;세션 구현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 세션을 구현해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전의 쿠키와 달라진 점은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;랜덤값 생성&lt;/li&gt;
&lt;li&gt;랜덤값과 userId 매핑 테이블 생성&lt;/li&gt;
&lt;li&gt;유저에게 랜덤값을 Response에 포함하여 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 살펴보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션 받기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778428&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 세션 관리
 */
@Component
public class SessionManager {
    public static final String SESSION_COOKIE_NAME = &quot;mySessionId&quot;;
    private Map&amp;lt;String, Object&amp;gt; sessionStore = new ConcurrentHashMap&amp;lt;&amp;gt;();
    /**
     * 세션 생성
     */
    public void createSession(Object value, HttpServletResponse response) {
        //세션 id를 생성하고, 값을 세션에 저장
        String sessionId = UUID.randomUUID().toString();
        sessionStore.put(sessionId, value);
        //쿠키 생성
        Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
        response.addCookie(mySessionCookie);
    }
    /**
     * 세션 조회
     */
    public Object getSession(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie == null) {
            return null;
        }
        return sessionStore.get(sessionCookie.getValue());
    }
    /**
     * 세션 만료
     */
    public void expire(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie != null) {
            sessionStore.remove(sessionCookie.getValue());
        }
    }
    private Cookie findCookie(HttpServletRequest request, String cookieName) {
        if (request.getCookies() == null) {
            return null;
        }
        return Arrays.stream(request.getCookies())
                .filter(cookie -&amp;gt; cookie.getName().equals(cookieName))
                .findAny()
                .orElse(null);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 3가지의 메소드가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;세션 생성&amp;nbsp;&lt;/li&gt;
&lt;li&gt;세션 찾기&lt;/li&gt;
&lt;li&gt;세션 제거&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션은 랜덤값을 생성해야 하기 때문에, uuid를 이용하여 생성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 uuid를 이용하여 &quot;sessionStore&quot;라는 매핑 테이블에 저장을 해주고, 사용자에게 쿠키로 넘긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778428&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/login&quot;)
    public String loginId(@ModelAttribute User user, HttpServletResponse response) {
        if(!loginService.login(user)){
            return &quot;login&quot;;
        }
        sessionManager.createSession(user, response);
        
        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 또한 복잡하다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 스프링에서 세션을 아주 편하게 사용할 수 있도록 기능을 제공한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;스프링에서의 세션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778429&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/&quot;)
public String homeLoginV3Spring(
 @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)
User loginUser,
 Model model) {
 //세션에 회원 데이터가 없으면 home
 if (loginUser == null) {
 return &quot;home&quot;;
 }
 //세션이 유지되면 로그인으로 이동
 model.addAttribute(&quot;user&quot;, loginuser);
 return &quot;loginhome&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@SessionAttribute를 이용하면 스프링에서 세션을 아주 편하게 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 해당 어노테이션은 세션을 생성하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@SessionAttribute를 이용하면 세션을 찾아주는 번거로운 과정을 알아서 해주는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 세션생성을 HTTP 서블릿에 구현되어있는 기능을 사용하거나 직접구현한 내용을 사용하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP 서블릿의 세션을 적용한 컨트롤러&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778429&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/login&quot;)
    public String loginId(@ModelAttribute User user, HttpServletRequest request) {
        if(!loginService.login(user)){
            return &quot;login&quot;;
        }

        HttpSession session = request.getSession();
        session.setAttribute(SessionConst.LOGIN_USER, user);

        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SeesionConst 내용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972778429&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class SessionConst {
    public static final String LOGIN_USER = &quot;loginUser&quot;;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;성공!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsmQ5f%2Fbtq92w4bYL5%2Fk4eNe2QBxYPFDb5BKlye3k%2Fimg.png&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;24&quot; data-filename=&quot;xxxxxxxxxxx.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYerWD/btra34S3pe9/79Mlc4tMFKPI7V9k1WmXm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYerWD/btra34S3pe9/79Mlc4tMFKPI7V9k1WmXm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYerWD/btra34S3pe9/79Mlc4tMFKPI7V9k1WmXm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsmQ5f%2Fbtq92w4bYL5%2Fk4eNe2QBxYPFDb5BKlye3k%2Fimg.png&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;24&quot; data-filename=&quot;xxxxxxxxxxx.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;세션의 한계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션또한 한계가 있다. 사용자들이 많아지면 서버는 세션 매핑테이블에 계속해서 저장을 해야하는데, 이 테이블 조차 엄청나게 무거워질 수 있다. 그래서 최근에는 JWT 토큰 정책을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용은 다음에 살펴보자!&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>cookie</category>
      <category>jwt</category>
      <category>Programming</category>
      <category>session</category>
      <category>spring</category>
      <category>token</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/145</guid>
      <comments>https://bestkingit.tistory.com/145#entry145comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:40:07 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot + JPA] 로그인 구현하기.</title>
      <link>https://bestkingit.tistory.com/144</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 기록은 Spring Boot와 JPA를 이용하여 로그인을 구현해볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그인 프론트 생성&lt;/li&gt;
&lt;li&gt;로그인 컨트롤러 매핑&lt;/li&gt;
&lt;li&gt;로그인 Service 구현&lt;/li&gt;
&lt;li&gt;기타&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;로그인 프론트 생성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 로그인을 받을 프론트를 생성하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 아주 간단하게 만들어 볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1627972724405&quot; class=&quot;html xml&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;

    &amp;lt;title&amp;gt;로그인&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
로그인입니다.

&amp;lt;form method=&quot;post&quot; action=&quot;/login&quot;&amp;gt;
    ID :&amp;lt;input type=&quot;text&quot; name=&quot;userId&quot;&amp;gt;&amp;lt;br&amp;gt;
    PASSWORD :&amp;lt;input type=&quot;text&quot; name=&quot;password&quot;&amp;gt;&amp;lt;br&amp;gt;
    &amp;lt;button type=&quot;submit&quot;&amp;gt;제출&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;180&quot; data-filename=&quot;cc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmoESb/btrbd0u2Drf/xSNeMz5uJUwFwalFCDyYH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmoESb/btrbd0u2Drf/xSNeMz5uJUwFwalFCDyYH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmoESb/btrbd0u2Drf/xSNeMz5uJUwFwalFCDyYH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmoESb%2Fbtrbd0u2Drf%2FxSNeMz5uJUwFwalFCDyYH1%2Fimg.png&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;180&quot; data-filename=&quot;cc.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;form 형태로 id와 password를 post 방식으로 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;로그인 컨트롤러 매핑&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매핑은 Get, Post 이렇게 2가지 방식으로 진행할 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Get 매핑 : &quot;login&quot; 템플릿을 response 한다.&lt;/li&gt;
&lt;li&gt;Post 매핑: 로그인 정보를 DB에서 조회하여 로직을 거친 다음, 성공 실패 여부를 정한다. 성공 시 HOME화면으로 이동하고 실패 시, login 템플릿을 다시 리턴한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 컨트롤러를 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972724406&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
@Slf4j
public class LoginController {

    @Autowired
    private final LoginService loginService;

    @GetMapping(&quot;/login&quot;)
    public String login() {
        return &quot;login&quot;;
    }

    @PostMapping(&quot;/login&quot;)
    public String loginId(@ModelAttribute User user) {
        if(loginService.login(user)){
            return &quot;redirect:/&quot;;
        }
        return &quot;login&quot;;
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Post 요청에 id와 password가 넘어올 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 loginService 클래스의 login 메소드를 실행한다. 인자는 폼에서 넘어온 User이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loginService에서 DB에 저장된 데이터와 비교를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교에서 성공하면 Home으로 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패하면 다시 login 화면이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;로그인 Service 구현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 먼저 보자!&lt;/p&gt;
&lt;pre id=&quot;code_1627972724407&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
@Slf4j
public class LoginService {
    @Autowired
    private final UserRepository userRepository;

    public boolean login(User user) {

        User findUser = userRepository.findByUserId(user.getUserId());

        if(findUser == null){
            return false;

        }

        if(!findUser.getPassword().equals(user.getPassword())){
            return false;
        }
        return true;

    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) Repository에서 해당 id로 DB에 저장된 데이터를 가지고 온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 해당 데이터가 없으면(NULL) &quot;false&quot;를 리턴한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 해당 데이터와 사용자가 입력한 password가 같지 않다면, &quot;false&quot;를 리턴한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) null이 아니거나 비밀번호가 일치하면 &quot;true&quot;를 리턴한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;기타&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 추후에 Spring Security를 사용하여 비밀번호를 암호화할 것이다. 그럼 Service 코드에 암호화, 복호화 코드가 추가될 것이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해놓자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 로그인이 실패한다면 사용자의 화면에 &quot;id 또는 password가 잘못되었습니다&quot; 표시를 해줄 것이다. 그러기 위해서는 thymeleaf 기능이 필요하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추후에 알아보자!&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/144</guid>
      <comments>https://bestkingit.tistory.com/144#entry144comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:39:13 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] Form 객체를 분리하여 검증 로직 다르게 적용</title>
      <link>https://bestkingit.tistory.com/143</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 기록은 Form 객체를 분리를 통해서 검증 로직을 서로 다르게 적용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말이 무슨 뜻인가!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 상황으로 이해해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&quot;회원 가입 시에는 id의 길이가 최대 10, 회원 정보 수정에는 id의 길이가 최대 15로 수정이 가능하게 해 주세요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 상황에 Form 객체를 분리하여 검증 로직을 다르게 적용한다는 말이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Form 객체 분리란?&lt;/li&gt;
&lt;li&gt;Form 객체 분리하기&lt;/li&gt;
&lt;li&gt;분리에 따른 후 처리&lt;/li&gt;
&lt;li&gt;번외 - 겪은 에러&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Form 객체 분리란?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Form 객체로 분리한다는 말이 무슨 뜻일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드로 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;User.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621251&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
@Entity(name = &quot;user&quot;)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long sequenceId;


    @NotNull
    @NotBlank
    @Column(length = 25, nullable = false)
    String userId;

    @NotNull
    @NotBlank
    @Column(nullable = false)
    String password;

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;SignupController.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621251&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/signup&quot;)
    public String signupForm(@Validated @ModelAttribute User user, BindingResult bindingResult, RedirectAttributes redirectAttributes){

        log.info(&quot;userid ={}&quot;, user.getUserId());
        if(bindingResult.hasErrors()){
            log.info(&quot;errors ={}&quot;, bindingResult);
            return &quot;/signup&quot;;
        }

        signUpService.signup(user);

        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 Post Mapping에서 user라는 객체를 사용한 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 user를 사용하지 않고 user를 가지고 있는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User sign Up Form, User Modify Form 객체로 나누어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따로따로 어노테이션을 설정할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Form 객체 분리하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지의 객체를 생성해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 검증 로직은 처음에 있던&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&quot;회원 가입 시에는 id의 길이가 10, 회원 정보 수정에는 id의 길이 15로 수정이 가능하게 해 주세요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 적용해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;UserSignUpForm.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621252&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
public class UserModifyForm {

    String beforeId;
    String beforePassword;

    @NotNull
    @NotBlank
    @Size(max = 15)
    String userId;

    @NotNull
    @NotBlank
    String password;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;UserModifyForm.java&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621252&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
public class UserSignUpForm {

    @NotNull
    @NotBlank
    @Size(max=10)
    String userId;

    @NotNull
    @NotBlank
    String password;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명 :&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User객체를 UserModifyForm과 UserSignUpForm객체로 나눈 이유는, 각각 다른 검증을 해주기 위해서이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Group을 사용하여 묶을 수도 있지만 그거 또한 한계가 있어서 차라리 관리하기 쉽게 두 가지의 폼으로 나누어 관리하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 JPA에 사용될 어노테이션은 모두 제거해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 회원 가입과 회원 수정에 각각 맞는 검증 어노테이션을 추가했다. (max=10, max=15)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;분리에 따른 후처리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리가 되었으니 제각각 코드를 바꿔주어야 할 것이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 어떤 코드를 바꿔야 할지 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Controller에 넘어오는 @ModelAttribute 부분의 객체를 바꿔주어야 한다.&lt;/li&gt;
&lt;li&gt;Service 부분에서 Form객체로 되어있는 값을 User 객체로 변환해주어야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 두 가지의 작업이 추가되었을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러와 서비스를 보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;SignUpController&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621254&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@Slf4j
@RequiredArgsConstructor
public class SignUpContoller {


    @Autowired
    private final SignUpService signUpService;

    @GetMapping(&quot;/signup&quot;)
    public String signup(Model model){

        model.addAttribute(&quot;user&quot;, new User());

        return &quot;/signup&quot;;
    }

    @PostMapping(&quot;/signup&quot;)
    public String signupForm(@Validated @ModelAttribute UserSignUpForm user, BindingResult bindingResult, RedirectAttributes redirectAttributes){

        log.info(&quot;userid ={}&quot;, user.getUserId());
        if(bindingResult.hasErrors()){
            log.info(&quot;errors ={}&quot;, bindingResult);
            return &quot;/signup&quot;;
        }

        User user2 = new User();
        user2.setUserId(user.getUserId());
        user2.setPassword(user.getPassword());
        signUpService.signup(user2);
        return &quot;redirect:/&quot;;
    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ModifyUserController&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621254&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
@Slf4j
public class ModifyUserController {

    private final ModifyUserService modifyUserService;

    @GetMapping(&quot;/modify&quot;)
    public String ModifyUser(){return &quot;/modify&quot;;}

    @PostMapping(&quot;/modify&quot;)
    public String ModifyUser(@Validated @ModelAttribute UserModifyForm userModifyForm, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return &quot;/modify&quot;;
        }
        modifyUserService.modifyUser(userModifyForm);
        return &quot;redirect:/&quot;;

    }

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;컨트롤러 코드 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;signup에서는 UserSignUpForm 객체가 넘어온다.&lt;/li&gt;
&lt;li&gt;modify에서는 UserModifyForm 객체가 넘어온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 점이 두 가지가 있는데 signup은 controller에서 user로 변환하였고, modify는 서비스에서 user로 변환을 해주었다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 서비스에서 하는 것이 올바르겠지!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 각각의 서비스를 보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;SignUpService&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621255&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class SignUpService {

    @Autowired
    private final UserRepository userRepository;

    public void signup(User user){
        userRepository.save(user);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ModifyUserService&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621255&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
@Slf4j
public class ModifyUserService {

    private final UserRepository userRepository;

    public void modifyUser(UserModifyForm userModifyForm){

       User user = userRepository.finduser(userModifyForm.getBeforeId(), userModifyForm.getBeforePassword());

       user.setUserId(userModifyForm.getUserId());
       user.setPassword(userModifyForm.getPassword());

        userRepository.save(user);

    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 완벽히 수행되는 것을 볼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;번외 - 겪은 문제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. JPA와 연동하면서 JPA Repository에 구현되어 있는 내용을 보니까 Long id(PK)로 getOne, findById가 수행되는 것을 볼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자들은 분명 자신의 id와 password를 입력할 건데, &quot;JpaRepository&quot;의 구현체에는 sequence로 등록된 id만 인자로 받는다.. 그럼 어떻게 조회를 해야 하나 ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 아래와 같이 인터페이스를 확장했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972621255&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {
    @Query(&quot;select m from user m where m.userId = ?1&quot;)
    User finduser(String id, String password);
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;해결 :&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Data JPA를 사용하면 정해진 규칙대로 인터페이스에 등록하면 간단한 쿼리문은 자동 구현된다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 구현 메서드명 규칙은 아래 글을 참고하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://minkwon4.tistory.com/130&quot;&gt;https://minkwon4.tistory.com/130&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1627972621256&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JPA] Spring Data JPA (2) - 메소드 네임 쿼리, @Query&quot; data-og-description=&quot;메소드 네임 쿼리 JPA는 기본적으로 JpaRepository&amp;lt;엔티티 타입, 식별자(PK)타입&amp;gt;을 상속 받음으로써 기본적인 CRUD를 할 수 있는 쿼리를 제공한다. 또한 이것과 별게로 추가적으로 규칙에 의한 메소드 &quot; data-og-host=&quot;minkwon4.tistory.com&quot; data-og-source-url=&quot;https://minkwon4.tistory.com/130&quot; data-og-url=&quot;https://minkwon4.tistory.com/130&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N2pUr/hyKVaRkKOj/1d75kJkJ6qjIAfvIcCxJLK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/lajy8/hyKU865ajo/tAkDBTMtomsxbmWfUbGZ90/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://minkwon4.tistory.com/130&quot; data-source-url=&quot;https://minkwon4.tistory.com/130&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N2pUr/hyKVaRkKOj/1d75kJkJ6qjIAfvIcCxJLK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/lajy8/hyKU865ajo/tAkDBTMtomsxbmWfUbGZ90/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JPA] Spring Data JPA (2) - 메소드 네임 쿼리, @Query&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;메소드 네임 쿼리 JPA는 기본적으로 JpaRepository&amp;lt;엔티티 타입, 식별자(PK)타입&amp;gt;을 상속 받음으로써 기본적인 CRUD를 할 수 있는 쿼리를 제공한다. 또한 이것과 별게로 추가적으로 규칙에 의한 메소드&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;minkwon4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 변경된 코드!&lt;/p&gt;
&lt;pre id=&quot;code_1627972621256&quot; class=&quot;java&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {

     //@Query(&quot;select m from user m where m.userId = ?1&quot;)
     //User finduser(String id, String password);


    User findByUserId(String id);
};&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1627972642534&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void modifyUser(UserModifyForm userModifyForm){

       //User user = userRepository.finduser(userModifyForm.getBeforeId(), userModifyForm.getBeforePassword());
       User user = userRepository.findByUserId(userModifyForm.getBeforeId());
       user.setUserId(userModifyForm.getUserId());
       user.setPassword(userModifyForm.getPassword());

        userRepository.save(user);

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>java</category>
      <category>spring boot</category>
      <category>관심쟁이</category>
      <category>백엔드</category>
      <category>프로그래밍</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/143</guid>
      <comments>https://bestkingit.tistory.com/143#entry143comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:38:23 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] Bean Validation 적용하기</title>
      <link>https://bestkingit.tistory.com/142</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 Bean Validation에 대해서 기록을 해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;목차&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Bean Validation 이란?&lt;/li&gt;
&lt;li&gt;Bean Validation Error 발생시키기&lt;/li&gt;
&lt;li&gt;Bean Validation 실행 내용 이해하기&lt;/li&gt;
&lt;li&gt;Bean Validation Object Error&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Bean Validation 이란?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 서버를 운영하면서, 사용자에게 여러 가지 입력을 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 사용자가 올바른 양식의 입력을 해주면 좋겠지만, 사용자도 사람인지라 올바르지 못한 입력을 할 가능성이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가령, 회원가입을 진행하면서 id를 공백으로 입력하는 경우를 말할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, Controller에서 if문을 이용하여 입력값을 검증할 수 있다. (고대 개발자들은 이렇게 했겠지..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 할 경우에는 Controller가 너무 길어지고, 코드의 구성이 복잡하여 코드를 읽는데 지장이 생길 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 중복되는 검증처리들이 존재하여 컨트롤러마다 똑같은 코드를 입력해야 하는 경우가 있을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 경우를 방지하기 위해서 스프링에서 Bean Validation 인터페이스를 미리 만들어 검증 처리를 하는데 도움을 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;한마디로, 검증 처리를 깔끔하고 간편하게 구현할 수 있도록 도와주는 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Bean Validation Error 발생시키기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Step. 1&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저, Bean Validation 라이브러리를 추가하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build.gradle에 다음 코드를 추가한 다음 새로고침! (나는 gradle기반 프로젝트다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972559014&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {

  // ...
implementation 'org.springframework.boot:spring-boot-starter-validation'

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jakarta.validation-api(인터페이스)와 hibernate-validator(구현체)가 설치된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Step. 2&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 검증을 적용할 도메인을 찾아보자! 필자는 User 클래스에 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1627972559014&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Data
@Entity(name = &quot;user&quot;)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long sequenceId;


    @NotNull
    @NotBlank
    @Column(length = 25, nullable = false)
    String userId;

    @NotNull
    @NotBlank
    @Column(nullable = false)
    String password;

};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두가지의 변수에 각 2가지씩 (총 4가지)의 검증을 추가했다. 내용은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;String userId의 &quot;@NotBlank&quot;, &quot;@NotNull&quot;&lt;/li&gt;
&lt;li&gt;String password의 &quot;@NotBlank&quot;, &quot;@NotNull&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 공백과 Null을 받지 않는다는 이야기다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Step. 3&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 해당 검증을 거칠 부분을 정해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정하는 방법은 &quot;@Validated&quot; 어노테이션을 추가하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 코드를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627972559015&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/signup&quot;)
    public String signupForm(@Validated @ModelAttribute User user, BindingResult bindingResult, RedirectAttributes redirectAttributes){

        log.info(&quot;userid ={}&quot;, user.getUserId());
        if(bindingResult.hasErrors()){
            log.info(&quot;errors ={}&quot;, bindingResult);
            return &quot;/signup&quot;;
        }

        signUpService.signup(user);

        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Signup 에서 &quot;@Validated&quot;를 추가한 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 user을 바인딩하면서 생기는 에러를 bindingResult에 담는다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Bean Validation 실행 내용 이해하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bean Validation이 어떻게 동작하는지 순서대로 살펴보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Bean Validation 라이브러리를 설치하면 스프링 부트는 그것을 감지하고 스프링에 통합한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당하는 Validator를 글로벌 Validator로 등록을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ModelAttribute가 타입 변환을 시도한다. 성공하면 Validator 수행, 실패하면 FieldError로 binding result에 추가!&amp;nbsp; &amp;nbsp;&amp;nbsp;※ 한마디로 타입 변환에 성공한 내용만 검증을 수행한다!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 Validator는 어노테이션을 살펴보고 검증을 수행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검증 오류가 발생하면 &quot;FieldError&quot;와 &quot;ObjectError&quot;를 생성해서 BindingResult에 담아준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Bean Validation Object Error&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 보았던 내용은 필드 자체에 오류이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다음과 같은 검증을 하고 싶을 때는 어떻게 해야 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;id의 길이와 비밀번호의 길이의 합은 100을 넘어선 안된다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지의 필드가 합쳐서 검증이 수행되어야 한다는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 해당 기능을 수행하기 위해서 &quot;@ScriptAssert&quot;라는 기능을 구현해놓긴 했는 데 사용하기에 한계가 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관심 있으면 찾아보자!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;이 경우에는, 컨트롤러에 직접 코드를 추가하자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;그래야 제약도 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 좋은 방법이 있을 것만 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 추후에 알게 된다면 포스팅을 하자!&lt;/p&gt;</description>
      <category>Bank-End/Spring Boot</category>
      <category>bean</category>
      <category>spring</category>
      <category>validation</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/142</guid>
      <comments>https://bestkingit.tistory.com/142#entry142comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:36:31 +0900</pubDate>
    </item>
    <item>
      <title>[#5] JPA를 이용한 DB insert</title>
      <link>https://bestkingit.tistory.com/141</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;JPA를 이용한 DB insert&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 JPA를 이용하여 DB에 회원가입 정보를 insert 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다루게될 목차는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sign Up 프론트 구현&lt;/li&gt;
&lt;li&gt;Sign Up 컨트롤러 구현&lt;/li&gt;
&lt;li&gt;User Repository 구현&lt;/li&gt;
&lt;li&gt;Sign Up 서비스 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Sign Up 프론트 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트 디자인은 신경쓰지 않고, 아주 간단하게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 구현된 화면은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxlVU%2Fbtq9PTK2ni5%2F6IYqRgO9hZMYf8ZHDFptQ1%2Fimg.png&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;362&quot; data-filename=&quot;1.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n7m1K/btraWwbepv5/2qtsIjLa2QB9YBG2KPykZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n7m1K/btraWwbepv5/2qtsIjLa2QB9YBG2KPykZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n7m1K/btraWwbepv5/2qtsIjLa2QB9YBG2KPykZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxlVU%2Fbtq9PTK2ni5%2F6IYqRgO9hZMYf8ZHDFptQ1%2Fimg.png&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;362&quot; data-filename=&quot;1.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxlVU/btq9PTK2ni5/6IYqRgO9hZMYf8ZHDFptQ1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;signup.html&quot;&gt;&lt;/span&gt;signup.html&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1627972479665&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;

    &amp;lt;title&amp;gt;회원가입&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
회원가입입니다.

&amp;lt;form action=&quot;/signup&quot; method=&quot;post&quot;&amp;gt;
   아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;id&quot;/&amp;gt;&amp;lt;br&amp;gt;
    비밀번호: &amp;lt;input type=&quot;text&quot; name=&quot;password&quot;/&amp;gt;&amp;lt;br&amp;gt;
    &amp;lt;input type=&quot;submit&quot; value=&quot;제출&quot; /&amp;gt; &amp;lt;br&amp;gt;
    &amp;lt;input type=&quot;reset&quot; value=&quot;clear&quot; /&amp;gt; &amp;lt;br&amp;gt;

&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;thymeleaf를 사용할 것이기 때문에, template 디렉토리에 &quot;signup.html&quot;을 생성해주었다.&lt;/li&gt;
&lt;li&gt;PostMapping을 해주기 위해서, form태그를 사용했다.&lt;/li&gt;
&lt;li&gt;id, password를 입력받는다.&lt;/li&gt;
&lt;li&gt;버튼은 총 2가지로 submit, clear 버튼이 있다.&lt;/li&gt;
&lt;li&gt;submit은 post로 http요청을 하는 것이다.&lt;/li&gt;
&lt;li&gt;clear은 해당 form의 모든 영역에 입력된 값들을 지워주는 버튼이다.&lt;/li&gt;
&lt;li&gt;submit을 하면, &quot;/signup&quot;으로 post 요청을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 개발을 진행하면서 필요한 내용을 추가할 예정이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Sign up 컨트롤러 구현&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 살펴보자!&lt;/p&gt;
&lt;pre id=&quot;code_1627972479665&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@Slf4j
@RequiredArgsConstructor
public class SignUpContoller {


    @Autowired
    private final SignUpService signUpService;
    @GetMapping(&quot;/signup&quot;)
    public String signup(){
        return &quot;/signup&quot;;
    }

    @PostMapping(&quot;/signup&quot;)
    public String signupForm(@ModelAttribute User user){

        signUpService.signup(user);
        
        return &quot;redirect:/&quot;;
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Get, Post 매핑 2가지가 있다.&lt;/li&gt;
&lt;li&gt;Get은 기본 회원가입 영역을 return 해주기위한 메소드이다.&lt;/li&gt;
&lt;li&gt;Post는 회원가입 시, Post 방식으로 오게 될 내용을 처리하는 메소드이다.&lt;/li&gt;
&lt;li&gt;Post 요청 시, User로 받고 &quot;signUpService&quot;의 &quot;signUp&quot;메소드를 통해 비즈니스 로직을 실행한다.&lt;/li&gt;
&lt;li&gt;비즈니스 로직 실행 후, 홈으로 리다이렉트한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;User Repository 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;User Repository는 실제로 DB에 엑세스하여 데이터를 다루는 중요한 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보자!&lt;/p&gt;
&lt;pre id=&quot;code_1627972479666&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {
	//내용없음
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적인 CRUD를 구현해놓은 JpaRepository를 사용하자!&lt;/li&gt;
&lt;li&gt;계속해서 기능을 확장할 예정이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 의문점 : 프로젝트가 엄청나게 커지면 User 기능을 확장하면서 코드량이 많아질텐데 그때는 User를 분해를 하는건가? 쓸때없는 걱정같기도 하다.. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Sign Up Service 구현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service는 실제 비즈니스 로직들을 가지고 있는 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Repository를 사용하며, DB-비즈니스 로직-컨트롤러 부분을 나누기 위함이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보자!&lt;/p&gt;
&lt;pre id=&quot;code_1627972479666&quot; class=&quot;java&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; word-break: break-all; white-space: pre-wrap; overflow-wrap: break-word; color: #000000; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class SignUpService {

    @Autowired
    private final UserRepository userRepository;

    public void signup(User user){
        userRepository.save(user);
    }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;코드 설명&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UserRepository를 @Autowired를 통해서 DI 받는다.&lt;/li&gt;
&lt;li&gt;signup 메소드를 통해서 insert를 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 로그인을 해보자!!&lt;/p&gt;</description>
      <category>jpa</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/141</guid>
      <comments>https://bestkingit.tistory.com/141#entry141comment</comments>
      <pubDate>Tue, 3 Aug 2021 15:35:22 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 인터페이스 ㅣ Interface</title>
      <link>https://bestkingit.tistory.com/135</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 인터페이스에 관해서 공부를 할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(출간된 &quot;자바의 정석&quot; 책을 참고했습니다.)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스란?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 추상 메서드의 집합이다. (추상 메서드 : 구현을 하지않은 메서드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 멤버가 public이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 구현된 내용이 하나도 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 추상클래스와 무엇이 다른가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상클래스는 구현된 메서드도 포함할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(인터페이스도 JDK 1.8 version 부터는 구현된 상수, static 메서드와 같은 멤버변수를 가질 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스 선언방법&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1621587420151&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface practice{
	public static final FIRST = 1;
	public abstract abc(int num);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 인터페이스를 선언할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스의 구현&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스를 구현한다는 것은 몸통부분을 완성해준다는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1621588250294&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Alive{
	public void breath();
    public void birth(int year);
}

class Human implements Alive{
	public void breath(){
    	System.out.println(&quot;숨을 쉰다!&quot;);
    }
    
    public void birth(int year){
    	System.out.println(year + &quot;년에 태어났다!&quot;);  
    }
}

class Practice{

	public static void main(String[] args) {
    	Human human = new Human();
        
        human.breath();
        human.birth();
    }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드처럼 구현하면 된다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스 특징&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터페이스의 조상은 인터페이스만 가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;다중 상속이 가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;인터페이스로 객체 생성이 불가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&quot;implements&quot; 라는 구현 키워드를 사용한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다중 상속해서 메서드나 변수가 겹치게 된다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 결론적으로 구현이 되어 있지 않아서 충돌에 걱정이 없다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;왜 인터페이스를 사용할까?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;두 대상(객체)를 연결하는 중간 역할을 한다!&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;선언과 구현을 분리시킬 수 있게 한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세히 알려면 다음 게시글을 보자!&lt;/p&gt;
&lt;figure id=&quot;og_1631535616427&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[#1 코드로 이해하는 객체지향 설계]  객체, 설계&quot; data-og-description=&quot;대망의 첫 장이다. 아 시작하기 전에, 저자님이 핵심적으로 전해주는 말이 있다. 해당 책은 프로그래밍 패러다임의 &amp;quot;객체지향 패러다임&amp;quot;에 대해서 설명하는 책이다. 객체지향 패러다임은 계속해&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/170&quot; data-og-url=&quot;https://bestkingit.tistory.com/170&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2e2P6/hyLzXpUIK5/rroXrKG6bl99DtTQ7Xqwok/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cP4mhh/hyLzXwGngj/9W6CwW1xkjQ9TCPy9KyPIK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/1Y0mJ/hyLBsPlYa1/lgHKFJ0BkeIn5f228KjoKk/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/170&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2e2P6/hyLzXpUIK5/rroXrKG6bl99DtTQ7Xqwok/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cP4mhh/hyLzXwGngj/9W6CwW1xkjQ9TCPy9KyPIK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/1Y0mJ/hyLBsPlYa1/lgHKFJ0BkeIn5f228KjoKk/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[#1 코드로 이해하는 객체지향 설계] 객체, 설계&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;대망의 첫 장이다. 아 시작하기 전에, 저자님이 핵심적으로 전해주는 말이 있다. 해당 책은 프로그래밍 패러다임의 &quot;객체지향 패러다임&quot;에 대해서 설명하는 책이다. 객체지향 패러다임은 계속해&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 변경에 유리한 코드가 될 수 있다. 아래의 코드로 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621592889683&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A{
	public void methodA(B b){
    	b.methodB();
    }
}

class B{
	public void methodB(){
    	System.out.println(&quot;methodB()&quot;);
    }
}

class InterfaceTest{
	public static void main(String args[]){
    	A a = new A();
        a.methodA(new B());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 인터페이스를 활용해서 다시 하면,&lt;/p&gt;
&lt;pre id=&quot;code_1621593099529&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A{
	public void methodA(I i){
    	i.methodB();
    }
}

interface I {
	void methodB();
}

class B implements I{
	public void methodB(){
    	System.out.println(&quot;methodB()&quot;);
    }
}

class InterfaceTest{
	public static void main(String args[]){
    	A a = new A();
        a.methodA(new B());
    }
}

    &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 나눌 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 경우는 인터페이스의 다형성 때문에 new B()로 넘기더라도 I i 에 속하기 때문에 넘어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하지만 i에서 인터페이스에 정의된 메서드 이외에&amp;nbsp; B메서드를 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 나중에 새로운 B class대신 C class를 써야한다면?&lt;/p&gt;
&lt;pre id=&quot;code_1621593176396&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class C implements I {
	public void methodB(){
    	System.out.println(&quot;methodB() is C&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스를 활용하지 않을 경우에는,&lt;/p&gt;
&lt;pre id=&quot;code_1621593281796&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A{
	//public void methodA(B b){ 에서
    public void methodA(C c){
    	b.methodB();
    }
}

class B{
	public void methodB(){
    	System.out.println(&quot;methodB()&quot;);
    }
}

class InterfaceTest{
	public static void main(String args[]){
    	A a = new A();
        
       // a.methodA(new B()); 에서
       a.methodA(new C());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- B b -&amp;gt; C c&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- new B() -&amp;gt; new C()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 두개를 변경해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스를 사용할 경우에는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new B() -&amp;gt; new C()만 바꾸어 주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(인터페이스 형태로 받기 때문이다! -&amp;gt; 인터페이스 다형성)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 별거아닌 일같아도 나중에 class가 엄청많아진다면 엄청나게 편리하다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;개발 시간을 단축할 수 있다!&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스만 알면 되기때문에, A를 개발하는 팀은 B가 완성이 되지 않아도 코드를 작성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;변경에 유리한 유연한 설계가 가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;표준화가 가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면, DB를 오라클을 사용한다고 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, 갑자기 오라클에서 MySql로 바꾼다면 코드를 엄청나게 고쳐야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이것을 해결하기 위해 JDBC를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클이나 MySql 회사에는 JDBC 인터페이스에 맞춰서 구현하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 JDBC 표준 인터페이스를 이용하기 때문에 따로 코드를 바꿀 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해가 안되면, 볼트와 너트 크기를 맞추기위해서 표준을 정해두는 것을 생각하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;서로 관계없는 클래스들을 묶을 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>학교공부/자바의 왕!</category>
      <category>interface</category>
      <category>java</category>
      <category>JDK</category>
      <category>OOP</category>
      <category>객체지향</category>
      <category>인터페이스</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/135</guid>
      <comments>https://bestkingit.tistory.com/135#entry135comment</comments>
      <pubDate>Sat, 22 May 2021 00:51:23 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA]추상클래스와 추상메서드에 대해서! ㅣ Abstract</title>
      <link>https://bestkingit.tistory.com/134</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 추상클래스와 추상메서드에 대해서 공부를 해볼 계획이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상클래스?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상클래스는 완성하지않은 메서드를 가지고 있는 클래스를 말한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한마디로, 몸통부분인 &quot;{}&quot;가 없는 것을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스에는 &quot;abstract&quot;라는 키워드가 필요하다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상메서드?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상메서드 또한 같다. 몸통부분 &quot;{}&quot;이 없는 메서드를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드에는 &quot;abstract&quot;라는 키워드가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드를 통해서 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1621578510526&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class MyClass{
	abstract void go(int num);
	abstract void stop(int result);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 보았듯이, 몸통부분이 없는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;왜 사용하는 걸까?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 클래스를 작성하는데 도움을 주기 위해서 사용한다!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 다음 코드를 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1621578654564&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class MyClass{
	abstract void go(int num);
	abstract void stop(int result);
	
}

class Student extends MyClass{

	@Override
	void go(int num) {
		// 이 부분을 통해서 구현을 완성해야 한다.
	}

	@Override
	void stop(int result) {
		// 이 부분을 통해서 구현을 완성해야 한다.
	}
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 보면 &quot;MyClass&quot;라는 추상클래스를 상속받아서 MyClass에 존재하는 추상메서드를 오버라이드하여 구현한 것을 볼 수 있다. 이런 식으로 추상클래스를 사전에 작성해놓으면 다른 클래스 작성을 하는데 도움을 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상클래스의 필요성-1&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 추상클래스가 왜 필요한지 실제 코드로 살펴보자!&lt;/p&gt;
&lt;pre id=&quot;code_1621579391120&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Car{
	String engine;
	int x, y;
	int wiper; // 와이퍼
	void move(int x, int y) {
		// x, y로 이동하라!
	}
	void stop() {
		//현재 위치 정지
	}
}
class Motorcycle{
	String engine;
	int x, y;
	void move(int x, int y) {
		// x, y로 이동하라!
	}
	void stop() {
		//현재 위치 정지
	}
}
class cycle{
	int x, y;
	void move(int x, int y) {
		// x, y로 이동하라!
	}
	void stop() {
		//현재 위치 정지
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 살펴보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동차, 오토바이, 자전거 클래스가 있다. 각 클래스에는 중복되는 코드가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상클래스를 이용하면 해당 코드들의 중복을 없앨 수 있다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 아래 코드를 통해서 코드의 중복을 없애보자!&lt;/p&gt;
&lt;pre id=&quot;code_1621579599911&quot; class=&quot;java&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class Vehicle{
	String engine;
	int x, y;
	abstract void move(int x, int y);
	void stop() {
		//현재 위치 멈추기
	}
}
class Car extends Vehicle{
	String engine;
	int wiper; // 와이퍼
	@Override
	void move(int x, int y) {
	}
}
class Motorcycle extends Vehicle{
	String engine;
	@Override
	void move(int x, int y) {
	}
}
class cycle extends Vehicle{
	@Override
	void move(int x, int y) {	
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통적으로 존재하는 부분은 추상클래스로 밀어넣고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전부 Vehicle을 상속받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 편해졌다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ stop 메서드는 몸통부분이 구현되어 있어서, 그냥 호출하면 바로 불러질 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상클래스의 필요성-2&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러가지의 객체 타입을 하나의 배열로 다루기 위해서이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드를 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1621579883321&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class AbstractClass{
	public static void main(String[] args) {
		ArrayList&amp;lt;Vehicle&amp;gt; arr = new ArrayList&amp;lt;Vehicle&amp;gt;();
		
		arr.add(new cycle());
		arr.add(new Motorcycle());
		arr.add(new Car());
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 코드를 짤 경우에! 각자 다른 객체를 다룰 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;※ 단점은 없을까..?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 당연히 있다. 위 배열을 다룰 때에는 Vehicle에 존재하는 함수와 변수만 사용할 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 객체 형변환을 하고 사용해야 cycle, Motocycle, Car만의 고유 기능을 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) arr.get(0).engine은 없을 것이다!!&lt;/p&gt;
&lt;pre id=&quot;code_1621580188024&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		Car c = (Car)arr.get(2);
		System.out.println(c.engine);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용해야 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점인지는 모르겠다.&lt;/p&gt;</description>
      <category>학교공부/자바의 왕!</category>
      <category>abstract</category>
      <category>class</category>
      <category>java</category>
      <category>Method</category>
      <category>OOP</category>
      <category>객체지향</category>
      <category>인터페이스</category>
      <category>자바</category>
      <category>추상메서드</category>
      <category>추상클래스</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/134</guid>
      <comments>https://bestkingit.tistory.com/134#entry134comment</comments>
      <pubDate>Fri, 21 May 2021 15:57:50 +0900</pubDate>
    </item>
    <item>
      <title>[React #4] JSX 문법 ㅣ UserState</title>
      <link>https://bestkingit.tistory.com/133</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 UserState에 대해서 공부를 해보자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 아래의 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620144755205&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; let number = 1;
const add = () =&amp;gt;{
  number++;
  console.log('add', number);
}
  
  return (
  &amp;lt;div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;숫자 : {number}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={add}&amp;gt;더하기&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;local:3000 으로 접속해서&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;더하기&quot; 버튼을 클릭하면 console로 number 값을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1.PNG&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;193&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CTEOo/btq4cuDIJvu/6ViW1L8Yir1gJkvSKDyaE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CTEOo/btq4cuDIJvu/6ViW1L8Yir1gJkvSKDyaE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CTEOo/btq4cuDIJvu/6ViW1L8Yir1gJkvSKDyaE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCTEOo%2Fbtq4cuDIJvu%2F6ViW1L8Yir1gJkvSKDyaE1%2Fimg.png&quot; data-filename=&quot;1.PNG&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;193&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;2.PNG&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;155&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbensA/btq4bnyLgwF/49O7rRjQqtoa2jPcw3NB91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbensA/btq4bnyLgwF/49O7rRjQqtoa2jPcw3NB91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbensA/btq4bnyLgwF/49O7rRjQqtoa2jPcw3NB91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbensA%2Fbtq4bnyLgwF%2F49O7rRjQqtoa2jPcw3NB91%2Fimg.png&quot; data-filename=&quot;2.PNG&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;155&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 숫자: {number}인데&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;number 값을 +1을 해주어도&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;숫자 : 1&quot; 에서 1이 바뀌지 않는다 왜그럴까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태 값이 변경되었다는 신호를 보내야 한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리액트는 아무 변수나 상태 값으로 생각하지않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 &quot;이 변수를 상태 값으로 설정할게!&quot; 라고 해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 값이 변하면 &quot;상태 값이 변경되었어!&quot; 라고 말해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떻게 하는 걸까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래의 코드를 통해서 수정된 모습을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1620145150554&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//let number = 1;
  const [number, setNumber] = useState(1);

const add = () =&amp;gt;{
  setNumber(number + 1);
  console.log('add', number);
}
  
  return (
  &amp;lt;div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;숫자 : {number}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={add}&amp;gt;더하기&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면 성공적으로 UI 변경이 일어나는 모습을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;3.PNG&quot; data-origin-width=&quot;142&quot; data-origin-height=&quot;124&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NwsKU/btq4bK770I9/7NS9CNBnQDSyuHQTLvi9wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NwsKU/btq4bK770I9/7NS9CNBnQDSyuHQTLvi9wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NwsKU/btq4bK770I9/7NS9CNBnQDSyuHQTLvi9wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNwsKU%2Fbtq4bK770I9%2F7NS9CNBnQDSyuHQTLvi9wk%2Fimg.png&quot; data-filename=&quot;3.PNG&quot; data-origin-width=&quot;142&quot; data-origin-height=&quot;124&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;4.PNG&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;202&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lO14a/btq4c1aacA3/jIMwMIzzAPbJUBUKikvj91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lO14a/btq4c1aacA3/jIMwMIzzAPbJUBUKikvj91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lO14a/btq4c1aacA3/jIMwMIzzAPbJUBUKikvj91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlO14a%2Fbtq4c1aacA3%2FjIMwMIzzAPbJUBUKikvj91%2Fimg.png&quot; data-filename=&quot;4.PNG&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;202&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;바뀐 것을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;let number = 1; --------&amp;gt; const [number, setNumber] = useState(1);&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;useState()를 통해서 해당하는 number를 상태 값으로 설정한다는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;setNumber 부분은 해당하는 number의 값이 변경되었다는 것을 알려주는 메소드의 이름을 설정하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;setNumber(number + 1); 의 부분을 보면 알 수 있듯이,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태값 number의 값이 바뀌었다는 것을 알 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 자동으로 변경 감지를 해서 &lt;span style=&quot;color: #333333;&quot;&gt;UI가&amp;nbsp;&lt;/span&gt;변경되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것은 React안에 hooks 라이브러리 상태값이 되는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;응용해보자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620146741883&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const[users, setUsers] = useState([]);

  const download = () =&amp;gt;{
    let sample = [
      {id:1, name:&quot;유재석&quot;},
      {id:2, name:&quot;강호동&quot;},
      {id:3, name:&quot;이수근&quot;},
      {id:4, name:&quot;신동엽&quot;},
    ]

    setUsers(sample);
  }

  
  return (
  &amp;lt;div&amp;gt;
    &amp;lt;button onClick={download}&amp;gt;다운로드&amp;lt;/button&amp;gt;
    {users.map((u) =&amp;gt; (
      &amp;lt;h1&amp;gt;
        {u.id}, {u.name}
      &amp;lt;/h1&amp;gt;
    ))}
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 코드를 보면&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;users 배열은 처음에는 아무 값도 없다가&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;다운로드&quot; 버튼을 클릭하면 download 함수가 실행되고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;users에 object들이 들어가고 상태 값이 변경(정확히는 레퍼런스가 변경)되어 ui가 변경되는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;953&quot; data-filename=&quot;5.PNG&quot; width=&quot;548&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGM4HK/btq4cFFbzXi/s6q4r6J0QEAIP26WIkwMSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGM4HK/btq4cFFbzXi/s6q4r6J0QEAIP26WIkwMSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGM4HK/btq4cFFbzXi/s6q4r6J0QEAIP26WIkwMSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGM4HK%2Fbtq4cFFbzXi%2Fs6q4r6J0QEAIP26WIkwMSK%2Fimg.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;953&quot; data-filename=&quot;5.PNG&quot; width=&quot;548&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;682&quot; data-filename=&quot;6.PNG&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wyoTD/btq4cFLVTDX/OcbueY7MnFBrkUTkDW9ag1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wyoTD/btq4cFLVTDX/OcbueY7MnFBrkUTkDW9ag1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wyoTD/btq4cFLVTDX/OcbueY7MnFBrkUTkDW9ag1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwyoTD%2Fbtq4cFLVTDX%2FOcbueY7MnFBrkUTkDW9ag1%2Fimg.png&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;682&quot; data-filename=&quot;6.PNG&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 아래와 같이 처음부터&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;똑같은 Object들이 들어있다면&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다운로드를 클릭했을 때, 똑같이 렌더링이 된 것일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(다시 페이지를 불러온 것일까?)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그것을 확인하기 위해서 Console을 찍어보았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620146663081&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
  console.log(&quot;App 실행됨&quot;);
  const[users, setUsers] = useState([
    {id:1, name:&quot;유재석&quot;},
    {id:2, name:&quot;강호동&quot;},
    {id:3, name:&quot;이수근&quot;},
    {id:4, name:&quot;신동엽&quot;},
  ]);

  const download = () =&amp;gt;{
    let sample = [
      {id:1, name:&quot;유재석&quot;},
      {id:2, name:&quot;강호동&quot;},
      {id:3, name:&quot;이수근&quot;},
      {id:4, name:&quot;신동엽&quot;},
    ]

    setUsers([...sample]);
  }

  
  return (
  &amp;lt;div&amp;gt;
    &amp;lt;button onClick={download}&amp;gt;다운로드&amp;lt;/button&amp;gt;
    {users.map((u) =&amp;gt; (
      &amp;lt;h1&amp;gt;
        {u.id}, {u.name}
      &amp;lt;/h1&amp;gt;
    ))}
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;7.PNG&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;369&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDn8Mq/btq4bDahUxO/Yr0z2tWRXk9iOdn03Qr1fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDn8Mq/btq4bDahUxO/Yr0z2tWRXk9iOdn03Qr1fK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDn8Mq/btq4bDahUxO/Yr0z2tWRXk9iOdn03Qr1fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDn8Mq%2Fbtq4bDahUxO%2FYr0z2tWRXk9iOdn03Qr1fK%2Fimg.png&quot; data-filename=&quot;7.PNG&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;369&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;페이지를 처음 열면, users에 정보가 있기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Object들이 화면에 그려져 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;다운로드&quot; 버튼을 클릭해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;8.PNG&quot; data-origin-width=&quot;1017&quot; data-origin-height=&quot;183&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dU0jFH/btq4bXTHN9v/a7fsyYckkpE22whvWkVG20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dU0jFH/btq4bXTHN9v/a7fsyYckkpE22whvWkVG20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dU0jFH/btq4bXTHN9v/a7fsyYckkpE22whvWkVG20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdU0jFH%2Fbtq4bXTHN9v%2Fa7fsyYckkpE22whvWkVG20%2Fimg.png&quot; data-filename=&quot;8.PNG&quot; data-origin-width=&quot;1017&quot; data-origin-height=&quot;183&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맨 처음에 그릴 때,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;console인 &quot;App 실행됨&quot;이 실행된 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데 &quot;다운로드&quot;를 클릭했을 때,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;새로 App 실행됨이 실행된 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;왜일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태값은 똑같은 값인데, 왜 렌더링이 새롭게 되는것일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이유는 &quot;sample&quot;에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;sample에서 새로운 레퍼런스를 받게 되고, 그것이 할당되기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태 값이 변경된 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결과적으로, &quot;다운로드&quot;를 클릭할 때마다 상태 값은 변한게 없지만&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ui를 새로 그린 것을 알 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #f89009;&quot;&gt;해결 : download에서 sample을 빼낸다. 그럼 download 함수가 실행될 때마다, 새롭게 sample을 할당하지 않을테니까.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 그럼 이 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620147532132&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let sample = [
  {id:1, name:&quot;유재석&quot;},
  {id:2, name:&quot;강호동&quot;},
  {id:3, name:&quot;이수근&quot;},
  {id:4, name:&quot;신동엽&quot;},
]
function App() {
  console.log(&quot;App 실행됨&quot;);
  const[users, setUsers] = useState(sample);
  

  const download = () =&amp;gt;{
    
    sample.push({id: 5, name :'김흥국'});
    console.log(sample);
    setUsers(sample);
  }

  
  return (
  &amp;lt;div&amp;gt;
    &amp;lt;button onClick={download}&amp;gt;다운로드&amp;lt;/button&amp;gt;
    {users.map((u) =&amp;gt; (
      &amp;lt;h1&amp;gt;
        {u.id}, {u.name}
      &amp;lt;/h1&amp;gt;
    ))}
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;다운로드&quot; 버튼을 클릭할 때마다,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;{id: 5, name: '김흥국'}이라는 Object를 push 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 다운로드를 누를 때 마다, Object가 추가되고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UI에 추가되어야 한다고 예상할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만, 변경되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;9.PNG&quot; data-origin-width=&quot;1913&quot; data-origin-height=&quot;384&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFHNDw/btq4ddBwcfs/VbAiMNuXgz5DhWuKbIq9TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFHNDw/btq4ddBwcfs/VbAiMNuXgz5DhWuKbIq9TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFHNDw/btq4ddBwcfs/VbAiMNuXgz5DhWuKbIq9TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFHNDw%2Fbtq4ddBwcfs%2FVbAiMNuXgz5DhWuKbIq9TK%2Fimg.png&quot; data-filename=&quot;9.PNG&quot; data-origin-width=&quot;1913&quot; data-origin-height=&quot;384&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 sample 배열에 Object는 추가된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 UI는 변경이 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이유는 레퍼런스의 변경이 없기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 어떻게 해결해야할까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;concat을 사용하자!&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1620147754826&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const download = () =&amp;gt;{
    
    const b = sample.concat({id: 5, name :'김흥국'});
    
    setUsers(b);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위 코드처럼 바꾸면 성공적으로 ui가 변경되는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>web</category>
      <category>관심쟁이영호</category>
      <category>리액트</category>
      <category>웹 개발</category>
      <category>프론트엔드</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/133</guid>
      <comments>https://bestkingit.tistory.com/133#entry133comment</comments>
      <pubDate>Sat, 8 May 2021 01:05:10 +0900</pubDate>
    </item>
    <item>
      <title>[React #3] JSX 문법을 익혀보자! ㅣ concat, filter, map, spread, slice, forEach</title>
      <link>https://bestkingit.tistory.com/132</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅에서는 concat, filter, map, slice, 스프레드(전개) 연산자에 대해서 살펴볼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;스프레드 연산자&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프레드 연산자는 깊은 복사를 실시하는 연산자이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620142681228&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = [1,2,3]
const b = [...a];

b.push(4);

// a???&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 했을 때, a의 값은 어떻게 될까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정답은 [1,2,3] 그대로다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것이 깊은 복사이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;a의 모든 값을 복사하여 새로운 메모리를 할당한 배열 b에 저장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 b에 새로운 값을 푸쉬해도 a에는 아무런 영향을 주지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;concat&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;concat 함수는 추가하는 함수라고 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620142807902&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = [1,2,3];
const b = a.concat(4);

// b???&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 때의 b값은 1,2,3,4 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;filter&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;filter는 걸러내는 함수라고 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;filter 속에는 함수를 넣어주어야 한다. 함수에서 true값 나오는 것들만 배열에 남게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620142942555&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = [1,2,3]
const b = a.filter((n) =&amp;gt; { return n != 1});

// b???&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 때의 b값은 2,3 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;a의 값을 n으로 순차적으로 받아오고 1만 false 나머지는 true여서 2, 3 만 남게되는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;slice&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;slice는 잘라내는 함수이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620143031985&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = [1,2,3];
const b = a.slice(0, 2);

// b???&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 때의 b값은 1,2 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;forEach, map&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;forEach, map은 반복하는 것이라고 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;차이점은 forEach는 return이 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;map은 return이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 보면서 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620143283364&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a = [1,2,3]

a5.forEach((n) =&amp;gt; { console.log}(n);}); // 리턴 x

const b = a5.map((n) =&amp;gt; n); // 리턴 o&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;n은 n이다. 라고 했기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;b는 [1, 2, 3]이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(const b = [...a])&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;forEach는 연산이나 콘솔을 찍을 때, 주로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>JSX</category>
      <category>react</category>
      <category>관심쟁이영호</category>
      <category>리액트</category>
      <category>백엔드</category>
      <category>웹개발</category>
      <category>프로그래밍</category>
      <category>프론트엔드</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/132</guid>
      <comments>https://bestkingit.tistory.com/132#entry132comment</comments>
      <pubDate>Fri, 7 May 2021 01:51:18 +0900</pubDate>
    </item>
    <item>
      <title>[React #2] JSX 문법을 익혀보자!</title>
      <link>https://bestkingit.tistory.com/131</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 시간은 JSX 문법을 익혀볼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;React의 기본만 다루는 것이 목표기 때문에, 자세히 들여다보진 말자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #ee2323;&quot;&gt;JS문법에 HTML 문법을 넣을 수 있다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1620140091564&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
  &amp;lt;div&amp;gt;
    안녕
&amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;일반적으로 JS문법에서는 &quot;&amp;lt;div&amp;gt; 안녕 &amp;lt;/div&amp;gt;&quot; 이렇게 &quot;&quot; 사이에 html 구문을 입력한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JSX에서는 &quot;&quot;를 표시할 필요가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #f89009;&quot;&gt;※ return이 무엇인지 모르는 사람이 있을 수 있다. 리액트는 설정에서 index.js를 실행하도록 설정이 되어있다. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #f89009;&quot;&gt;index.js는 아래의 코드가 있다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620140437291&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ReactDOM.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;,
  document.getElementById('root')
);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;lt;App /&amp;gt; 는 App.js의 function App()을 실행하라는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;document.getElementById('root')는 index.html에서 root라는 id값을 찾으라는 말이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 index.html을 가보면 root라는 div 태그가 있다. 그리고 해당 태그에 return을 해서 적용이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하나의 태그만 return 한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래와 같이 return을 하게 되면 오류가 난다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620140639018&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
	하이
&amp;lt;/div&amp;gt; 
&amp;lt;h1&amp;gt;
	하이2
&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 어떻게 해야하나?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그냥 태그 하나 더 씌워주자!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1620140683078&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt; 
	&amp;lt;div&amp;gt; 
    	하이 
    &amp;lt;/div&amp;gt; 
    &amp;lt;h1&amp;gt; 
    	하이2
    &amp;lt;/h2&amp;gt; 
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면 return은 1개의 태그이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;{}로 변수 표시가 가능하다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;if는 사용 불가능하다. 대신 삼항 연산자를 사용한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1620140850994&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let a = 20;
  return (
  &amp;lt;div&amp;gt;
  
    &amp;lt;div style = {mystyle}&amp;gt;
        안녕{a === 10 ? '10입니다' : '10아닙니다.'}
    &amp;lt;/div&amp;gt;
    
  &amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;조건&amp;nbsp;?&amp;nbsp;값(true)&amp;nbsp;:&amp;nbsp;값&amp;nbsp;(false) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;css 디자인을 입힐 수 있다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내부 디자인, 외부 디자인, 라이브러리&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3가지의 방법이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내부 디자인은 사용하지 않기로 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외부 디자인은 어떻게 하나?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;App.css 파일에서 기존에 css를 입력한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 똑같이 태그에 입력해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>ajax</category>
      <category>javascript</category>
      <category>JSX</category>
      <category>react</category>
      <category>리액트</category>
      <category>싱글페이지</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/131</guid>
      <comments>https://bestkingit.tistory.com/131#entry131comment</comments>
      <pubDate>Wed, 5 May 2021 06:13:29 +0900</pubDate>
    </item>
    <item>
      <title>[React #1] 리액트가 무엇인가?</title>
      <link>https://bestkingit.tistory.com/130</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 개발에 관심이 있는 사람이라면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;리액트&quot;라는 단어를 한번쯤은 보았을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 단어가 왜 많은 사람들에게서 언급이 되는 것일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오늘의 포스팅에서는 리액트의 전반적인 개요를 둘러볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;리액트란?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 이해한 수준에서 명쾌하게 말을 하자면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리액트는 싱글 페이지 어플리케이션을 개발하는데 도움을 주는 프레임워크라고 생각이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇다면 싱글 페이지 어플리케이션이란 무엇인가?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;싱글 페이지 어플리케이션?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;싱글 페이지 어플리케이션이란, html 파일은 1개 뿐이다. 필요한 부분의 View만 새롭게 그린다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;통째로 html을 받아올 필요가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발되기 전에 웹 개발 상황을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클라이언트가 서버에게 웹 페이지를 요청한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버는 클라이언트에게 HTML 화면 통째로 보내준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클라이언트가 화면에 어느 부분을 클릭한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버가 클라이언트에게 HTML 화면 통째로 다시 보내준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ajax를 이용해서 부분 화면을 그리는 방법도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 페이스북과 같은 웹뷰는 매우매우 복잡해서 ajax로 그리기가 매우 복잡하다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 리액트가 등장했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;리액트 특징&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 여기서 리액트가 무엇을 하는 것인가?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리액트는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ajax를 이용한 데이터 변경감지 -&amp;gt;UI가 자동 업데이트 되도록 프로그래밍이 가능&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 때, 변경을 감지하는 엔진은 Demon이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;항상 변경을 감지해야하기 때문에, 계속해서 서버처럼 돌고있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 서버는 nodejs로 이루어져있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다시 말해서, 리액트는 UI를 &lt;span style=&quot;color: #333333;&quot;&gt;Demon엔진을 통해서 지켜보고 있다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;변경이 필요한 부분은 해당 부분만 UI를 새롭게 그려준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리액트를 이용하면 html 페이지는 1개이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;수시로 태그부분이 바뀐다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JSX 문법을 이용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이정도만 이해하자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;리액트 공부해야하는 것!&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;엔진에게 어떠한 부분만 변경하도록 지칭하는 공부!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지칭을 넘어서서 효율적으로 UI를 재구성하는 공부!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JSX 문법 익히기&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정도로만 공부하는 것을 목표로 하자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>react</category>
      <category>singlepage</category>
      <category>개발자</category>
      <category>관심쟁이</category>
      <category>리액트</category>
      <category>백엔드</category>
      <category>프론트엔드</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/130</guid>
      <comments>https://bestkingit.tistory.com/130#entry130comment</comments>
      <pubDate>Tue, 4 May 2021 23:51:50 +0900</pubDate>
    </item>
    <item>
      <title>[#19] Spring Boot ㅣ 완성 코드 분석 ㅣ 주문 취소 살펴보기</title>
      <link>https://bestkingit.tistory.com/127</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/roi4Q/btq17beLeR4/GXPimxsvNz4u2KAppvJmT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/roi4Q/btq17beLeR4/GXPimxsvNz4u2KAppvJmT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/roi4Q/btq17beLeR4/GXPimxsvNz4u2KAppvJmT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Froi4Q%2Fbtq17beLeR4%2FGXPimxsvNz4u2KAppvJmT1%2Fimg.jpg&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 주문취소에 대해서 살펴볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주문취소를 보는 이유는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB에서 값을 가져와서 데이터를 변경해주는 작업이기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 문제가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;만약, 물품이 10개가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;A라는 사람이 1개의 물품을 주문함과 동시에&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;B라는 사람이 10개의 물품을 주문할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 된다면, DB에도 문제가 생기고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결제서비스와 같은 직접 돈과 연관되어 있는 문제면 엄청난 파장이 생길 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어쨌든 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;주문하기.PNG&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;733&quot; width=&quot;432&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dy0UfS/btq12vrQW9G/ezAMUMppFxKVDDiWfBO7dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dy0UfS/btq12vrQW9G/ezAMUMppFxKVDDiWfBO7dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dy0UfS/btq12vrQW9G/ezAMUMppFxKVDDiWfBO7dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdy0UfS%2Fbtq12vrQW9G%2FezAMUMppFxKVDDiWfBO7dk%2Fimg.png&quot; data-filename=&quot;주문하기.PNG&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;733&quot; width=&quot;432&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;홈화면에서 &quot;주문 내역&quot;을 눌러준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;주문상태.PNG&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;908&quot; width=&quot;544&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YYRvq/btq11M1Fu5u/0IjdOKfKY95wRY8noWfpfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YYRvq/btq11M1Fu5u/0IjdOKfKY95wRY8noWfpfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YYRvq/btq11M1Fu5u/0IjdOKfKY95wRY8noWfpfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYYRvq%2Fbtq11M1Fu5u%2F0IjdOKfKY95wRY8noWfpfk%2Fimg.png&quot; data-filename=&quot;주문상태.PNG&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;908&quot; width=&quot;544&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그러면 위와같은 페이지가 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;페이지에 해당하는 매핑 컨트롤러로 가보자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;페이지는 &quot;http://localhost:8080/orders&quot; 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617809500659&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// OrderController.class

@Controller
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    private final MemberService memberService;
    private final ItemService itemService;
    
    @GetMapping(value = &quot;/orders&quot;)
    public String orderList(@ModelAttribute(&quot;orderSearch&quot;) OrderSearch
                                    orderSearch, Model model) {
        List&amp;lt;Order&amp;gt; orders = orderService.findOrders(orderSearch);
        model.addAttribute(&quot;orders&quot;, orders);
        return &quot;order/orderList&quot;;
    }

   
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@GetMapping으로 구성되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 DB에서 모든 order을 가지고 온다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 이전 블로그에 다루지 않았던, db를 들고오는 것을 한번 짚고가자.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;OrderService에서 Repository의 메소드를 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;영속성 컨텍스트를 다루는 Repository를 접근하는 것은 당연할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617809619578&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// OrderRepository.class

@Repository
@RequiredArgsConstructor
public class OrderRepository {

    private final EntityManager em;

    public Order findOne(Long id) {
        return em.find(Order.class, id);
    }

    // public List&amp;lt;Order&amp;gt; findAll(OrderSearch ordersearch){}
    public List&amp;lt;Order&amp;gt; findAllByCriteria(OrderSearch orderSearch) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery&amp;lt;Order&amp;gt; cq = cb.createQuery(Order.class);
        Root&amp;lt;Order&amp;gt; o = cq.from(Order.class);
        Join&amp;lt;Order, Member&amp;gt; m = o.join(&quot;member&quot;, JoinType.INNER); //회원과 조인
        List&amp;lt;Predicate&amp;gt; criteria = new ArrayList&amp;lt;&amp;gt;();
        //주문 상태 검색
        if (orderSearch.getOrderStatus() != null) {
            Predicate status = cb.equal(o.get(&quot;status&quot;),
                    orderSearch.getOrderStatus());
            criteria.add(status);
        }
        //회원 이름 검색
        if (StringUtils.hasText(orderSearch.getMemberName())) {
            Predicate name =
                    cb.like(m.&amp;lt;String&amp;gt;get(&quot;name&quot;), &quot;%&quot; +
                            orderSearch.getMemberName() + &quot;%&quot;);
            criteria.add(name);
        }
        cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()])));
        TypedQuery&amp;lt;Order&amp;gt; query = em.createQuery(cq).setMaxResults(1000); //최대1000건
        return query.getResultList();


    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;findOne, findAll 두개의 메소드가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1개를 찾아오는 것, 전부를 찾아오는 것이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 List에 담을 모든 order을 불러와야 하기때문에, findall을 살펴볼 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당하는 부분에 Criteria 방식으로 db를 조회하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데, Criteria라는 방식에 대해서 정확한 설명을 듣지못해서 확실하게 기록할 수가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이유는, 실무에서는 다른방식을 사용하신다고 하셔서 제대로 안들었다..ㅋㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어쨋든 여기에서 검색 text가 입력되어있다면 해당하는 정보만 조회,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;없다면 모든 정보를 조회할 수 있도록 만들어놓은 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;cb에 em.getCritiriaBuilder를 넣어주고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것에다가 만드는 느낌이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다시 돌아가면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이런식으로 join하고 조회를 해와서 해당값을 리턴해주고, 그것을 리스트에 담아준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;취소는 어떻게 되는건가?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이건 먼저 html문서를 봐야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이유는 버튼 클릭 액션이 일어나고, 거기서 해당하는 요청을 해야하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;html을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617809998323&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- OrderList.html --&amp;gt;

&amp;lt;!DOCTYPE HTML&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head th:replace=&quot;fragments/header :: header&quot;/&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div class=&quot;container&quot;&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/bodyHeader :: bodyHeader&quot;/&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;
            &amp;lt;form th:object=&quot;${orderSearch}&quot; class=&quot;form-inline&quot;&amp;gt;
                &amp;lt;div class=&quot;form-group mb-2&quot;&amp;gt;
                    &amp;lt;input type=&quot;text&quot; th:field=&quot;*{memberName}&quot; class=&quot;formcontrol&quot; placeholder=&quot;회원명&quot;/&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class=&quot;form-group mx-sm-1 mb-2&quot;&amp;gt;
                    &amp;lt;select th:field=&quot;*{orderStatus}&quot; class=&quot;form-control&quot;&amp;gt;
                        &amp;lt;option value=&quot;&quot;&amp;gt;주문상태&amp;lt;/option&amp;gt;
                        &amp;lt;option th:each=
                                        &quot;status : ${T(jpashop.jpashop.domain.OrderStatus).values()}&quot;
                                th:value=&quot;${status}&quot;
                                th:text=&quot;${status}&quot;&amp;gt;option
                        &amp;lt;/option&amp;gt;
                    &amp;lt;/select&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-primary mb-2&quot;&amp;gt;검색&amp;lt;/button&amp;gt;
            &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;table class=&quot;table table-striped&quot;&amp;gt;
            &amp;lt;thead&amp;gt;
            &amp;lt;tr&amp;gt;
                &amp;lt;th&amp;gt;#&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;회원명&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;대표상품 이름&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;대표상품 주문가격&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;대표상품 주문수량&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;상태&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;일시&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;
            &amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
            &amp;lt;tbody&amp;gt;
            &amp;lt;tr th:each=&quot;item : ${orders}&quot;&amp;gt;
                &amp;lt;td th:text=&quot;${item.id}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.member.name}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.orderItems[0].item.name}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.orderItems[0].orderPrice}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.orderItems[0].count}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.status}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td th:text=&quot;${item.orderDate}&quot;&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td&amp;gt;
                    &amp;lt;a th:if=&quot;${item.status.name() == 'ORDER'}&quot; href=&quot;#&quot;
                       th:href=&quot;'javascript:cancel('+${item.id}+')'&quot;
                       class=&quot;btn btn-danger&quot;&amp;gt;CANCEL&amp;lt;/a&amp;gt;
                &amp;lt;/td&amp;gt;
            &amp;lt;/tr&amp;gt;
            &amp;lt;/tbody&amp;gt;
        &amp;lt;/table&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/footer :: footer&quot;/&amp;gt;
&amp;lt;/div&amp;gt; &amp;lt;!-- /container --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script&amp;gt;
 function cancel(id) {
 var form = document.createElement(&quot;form&quot;);
 form.setAttribute(&quot;method&quot;, &quot;post&quot;);
 form.setAttribute(&quot;action&quot;, &quot;/orders/&quot; + id + &quot;/cancel&quot;);
 document.body.appendChild(form);
 form.submit();
 }
&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 cancel하면 해당하는 주문이 사라져야해서, 자바스크립트가 실행된 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바스크립트 공부가 아니니, 다음에 짚어보자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 코드에서 해당하는 주문의 영속성 컨텍스트를 삭제해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드가 어떻게 움직일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기도 form이 있고, action과 post방식으로 넘겨주고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당하는 url을 보내는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;/orders/&quot; + id + &quot;/cancel&quot; &amp;lt;- 이렇게 표시되어 있는 곳과 매핑되어있는 곳을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617810179437&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// OrderController

 @PostMapping(value = &quot;/orders/{orderId}/cancel&quot;)
    public String cancelOrder(@PathVariable(&quot;orderId&quot;) Long orderId) {
        orderService.cancelOrder(orderId);
        return &quot;redirect:/orders&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와같다. {}중괄호는 자바스크립트 쪽인거 같으니까 다음에 짚어보고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당하는 값이 id와 같이 넘어온다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 Service.cancelOrder 메서드를 불러온다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;orderService 클래스를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617810256894&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// OrderService.class

//취소
    @Transactional
    public void cancelOrder(Long orderId){

        // 주문 엔티티 조회
        Order order = orderRepository.findOne(orderId);

        // 주문 취소
        order.cancel();


    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당하는 id를 DB와 직접연결된 Repository 클래스에 넘겨준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 Repository에서 찾아온 값을 cancel 메서드를 호출하여 삭제해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617810370781&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void cancel(){
        if(delivery.getStatus() == DeliveryState.COMP){ //COMP 는 이미 배송이 완료된 상품이다.
            throw new IllegalStateException(&quot;이미 배송완료된 상품은 취소가 불가능합니다.&quot;);
        }

        this.setStatus(OrderStatus.CANCEL);

        for(OrderItem orderItem: orderItems){
            //주문에 담은 각 상품들에 cancel을 날려주어 상품도메인에 각 상품에 갯수를 + 해주어야 한다.
            orderItem.cancel();
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;cancel 메소드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 배송이 완료되었는지, 확인을 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;배송이 완료되었으면 취소불가하다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;배송이 완료되지 않았으면 상품주문을 취소하고 해당상품의 재고를 1개 늘려주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 orderItem.cancel을 불러준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 orderitem.cancel을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617810483260&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void cancel() { //재고를 늘려주는게 목표이다,
        getItem().addStock(count);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주문 취소를 했으니, 당연히 재고는 늘어날 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;getItem은 해당 item 객체를 받아오는 것이고, 해당 객체의 addStock 메서드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617810635701&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; public void addStock(int quantity){
        this.stockQuantity += quantity;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;수량이 늘어난 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게하면 영속성 컨텍스트에 포함되어 있는 객체의 값이 변경될 것이고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JPA는 영속성 컨텍스트의 데이터 변경감지를 알아차리고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DB테이블과 매칭시켜 데이터를 바꾸어줄 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-filename=&quot;로고.jpg&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VQkhF/btq18n6SjY9/W0bJ2QOSpM1A8bRkgqOzyK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VQkhF/btq18n6SjY9/W0bJ2QOSpM1A8bRkgqOzyK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VQkhF/btq18n6SjY9/W0bJ2QOSpM1A8bRkgqOzyK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVQkhF%2Fbtq18n6SjY9%2FW0bJ2QOSpM1A8bRkgqOzyK%2Fimg.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-filename=&quot;로고.jpg&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Bank-End/인프런- Spring 공부</category>
      <category>jpa</category>
      <category>Order</category>
      <category>ORM</category>
      <category>spring boot</category>
      <category>관심쟁이영호</category>
      <category>대학생</category>
      <category>주문</category>
      <category>취업준비</category>
      <category>컴공</category>
      <category>코딩</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/127</guid>
      <comments>https://bestkingit.tistory.com/127#entry127comment</comments>
      <pubDate>Mon, 3 May 2021 01:52:46 +0900</pubDate>
    </item>
    <item>
      <title>[#18] Spring Boot ㅣ 완성된 코드 분석 ㅣ 주문하기 살펴보기!</title>
      <link>https://bestkingit.tistory.com/126</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NKgYe/btq13z1N0hK/qNlworkS7h9SVjSUpOHSrk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NKgYe/btq13z1N0hK/qNlworkS7h9SVjSUpOHSrk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NKgYe/btq13z1N0hK/qNlworkS7h9SVjSUpOHSrk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNKgYe%2Fbtq13z1N0hK%2FqNlworkS7h9SVjSUpOHSrk%2Fimg.jpg&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;이번에는 &quot;주문하기&quot;에 대한 코드를 살펴보자.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주문하기는 Member, item, order 등등 모든 테이블과 엔티티가 엮어있기 때문에 조금더 생각을 해야한다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어쨋든, 홈화면에서 주문하기 버튼을 클릭해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;432&quot; height=&quot;NaN&quot; data-filename=&quot;주문하기.PNG&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;733&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blMJpb/btq16PW58GD/PknUMGKwAW2BrYMLkVnYwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blMJpb/btq16PW58GD/PknUMGKwAW2BrYMLkVnYwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blMJpb/btq16PW58GD/PknUMGKwAW2BrYMLkVnYwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblMJpb%2Fbtq16PW58GD%2FPknUMGKwAW2BrYMLkVnYwK%2Fimg.png&quot; width=&quot;432&quot; height=&quot;NaN&quot; data-filename=&quot;주문하기.PNG&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;733&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇게 되면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;localhost:8080/order로 넘어가게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;화면은 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;주문.PNG&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;542&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rcoHQ/btq18DV820N/ULPEkIDLy6aTB8ah1Qvr50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rcoHQ/btq18DV820N/ULPEkIDLy6aTB8ah1Qvr50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rcoHQ/btq18DV820N/ULPEkIDLy6aTB8ah1Qvr50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrcoHQ%2Fbtq18DV820N%2FULPEkIDLy6aTB8ah1Qvr50%2Fimg.png&quot; data-filename=&quot;주문.PNG&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;542&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 Controller에 매핑이 되어있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 url이 매핑되어 있는곳으로 가보자!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #f89009; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;※ 주문 회원, 상품명을 클릭하면 리스트가 콥보박스처럼 드롭다운된다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617803426358&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    private final MemberService memberService;
    private final ItemService itemService;
    
    @GetMapping(value = &quot;/order&quot;)
    public String createForm(Model model) {
        List&amp;lt;Member&amp;gt; members = memberService.findMembers();
        List&amp;lt;Item&amp;gt; items = itemService.findItems();
        model.addAttribute(&quot;members&quot;, members);
        model.addAttribute(&quot;items&quot;, items);
        return &quot;order/orderForm&quot;;
    }
   
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;확실히 코드가 많다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 GetMapping을 했으니, @GetMapping부분을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 member와 item을 전부 찾아와서, List에 담아준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 model에 담아준다음, orderForm.html을 불러준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이유는, 주문 페이지에서 등록된 상품들을 주문해야하니, item을 불러오고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;member를 입력해주어야 하니 member를 다 불러오도록 만든 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 여기서 model에 담아준 attribute들을 orderForm에서 어떻게 받는지 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;orderForm.html을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617803810298&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head th:replace=&quot;fragments/header :: header&quot; /&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div class=&quot;container&quot;&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/bodyHeader :: bodyHeader&quot;/&amp;gt;
    &amp;lt;form role=&quot;form&quot; action=&quot;/order&quot; method=&quot;post&quot;&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label for=&quot;member&quot;&amp;gt;주문회원&amp;lt;/label&amp;gt;
            &amp;lt;select name=&quot;memberId&quot; id=&quot;member&quot; class=&quot;form-control&quot;&amp;gt;
                &amp;lt;option value=&quot;&quot;&amp;gt;회원선택&amp;lt;/option&amp;gt;
                &amp;lt;option th:each=&quot;member : ${members}&quot;
                        th:value=&quot;${member.id}&quot;
                        th:text=&quot;${member.name}&quot; /&amp;gt;
            &amp;lt;/select&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label for=&quot;item&quot;&amp;gt;상품명&amp;lt;/label&amp;gt;
            &amp;lt;select name=&quot;itemId&quot; id=&quot;item&quot; class=&quot;form-control&quot;&amp;gt;
                &amp;lt;option value=&quot;&quot;&amp;gt;상품선택&amp;lt;/option&amp;gt;
                &amp;lt;option th:each=&quot;item : ${items}&quot;
                        th:value=&quot;${item.id}&quot;
                        th:text=&quot;${item.name}&quot; /&amp;gt;
            &amp;lt;/select&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label for=&quot;count&quot;&amp;gt;주문수량&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;number&quot; name=&quot;count&quot; class=&quot;form-control&quot; id=&quot;count&quot;
                   placeholder=&quot;주문 수량을 입력하세요&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
    &amp;lt;br/&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/footer :: footer&quot; /&amp;gt;
&amp;lt;/div&amp;gt; &amp;lt;!-- /container --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;html을 상세히모르지만 model을 넘겨주어서 orderForm을 생성하는 거 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;똑같이 form에 action과 method로 설정되어 있다. &lt;span style=&quot;color: #333333;&quot;&gt;submit을 클릭하게 되면, 폼에 저장한다음, &lt;/span&gt;&amp;nbsp;&quot;/order&quot;로 post방식으로 정보를 넘겨주게 될 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 그것을 받은 매핑으로 가보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617804138514&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; // OrderController.class
 
 @PostMapping(value = &quot;/order&quot;)
    public String order(@RequestParam(&quot;memberId&quot;) Long memberId,
                        @RequestParam(&quot;itemId&quot;) Long itemId, @RequestParam(&quot;count&quot;) int count) {
        orderService.order(memberId, itemId, count);
        return &quot;redirect:/orders&quot;;
    }
   &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;OrderController에 다음과 같이 매핑되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;근데 여기서는 Form 객체로 받지않고, 각각에 key - value로 받고있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것은 html문법인지 jpa 제공기능인지 정확하게는 모르겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;html 공부를 할 때, 찾아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어쨋든 해당하는 데이터를 이용해서&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;orderService의 order 메서드를 실행해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래는 orderService이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617804318019&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final MemberRepository memberRepository;
    private final ItemRepository itemRepository;
    //주문
    @Transactional
    public Long order(Long memberId, Long itemId, int count){

        //엔티티 조회
        Member member = memberRepository.findOne(memberId);
        Item item = itemRepository.findOne(itemId);

        //배송정보 생성
        Delivery delivery = new Delivery();
        delivery.setAddress(member.getAddress());

        //주문 상품 생성
        OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);

        //주문 생성
        Order order = Order.createOrder(member, delivery, orderItem);

        //주문 저장
        orderRepository.save(order);

        return order.getId();

    }
    
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;OrderService에서 해당하는 엔티티를 찾아주고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;금액 계산, 주문목록 생성 등등 로직을 거친 다음,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최종적으로 영속성 컨텍스트 저장을 위해서 넘겨준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 되면 orderRepository에서 save 메서드를 거치고 저장이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 다음에는 주문 취소에 대해서 공부를 해보자!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9UFoy/btq17a1dFdM/Q6HnrfHOPgeYrgdxeupeDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9UFoy/btq17a1dFdM/Q6HnrfHOPgeYrgdxeupeDK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9UFoy/btq17a1dFdM/Q6HnrfHOPgeYrgdxeupeDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9UFoy%2Fbtq17a1dFdM%2FQ6HnrfHOPgeYrgdxeupeDK%2Fimg.jpg&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Bank-End/인프런- Spring 공부</category>
      <category>Controller</category>
      <category>Entity</category>
      <category>HTML</category>
      <category>jpa</category>
      <category>Order</category>
      <category>ORM</category>
      <category>repository</category>
      <category>springboot</category>
      <category>관심쟁이영호</category>
      <category>주문</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/126</guid>
      <comments>https://bestkingit.tistory.com/126#entry126comment</comments>
      <pubDate>Sun, 2 May 2021 01:08:04 +0900</pubDate>
    </item>
    <item>
      <title>[#17] Spring Boot ㅣ JPA로 테이블에 insert하기 ㅣ 완성 코드 분석하기</title>
      <link>https://bestkingit.tistory.com/125</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R3kev/btq11y3vq7e/BYcj5QOR0m2uJ4chPM8yFk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R3kev/btq11y3vq7e/BYcj5QOR0m2uJ4chPM8yFk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R3kev/btq11y3vq7e/BYcj5QOR0m2uJ4chPM8yFk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR3kev%2Fbtq11y3vq7e%2FBYcj5QOR0m2uJ4chPM8yFk%2Fimg.jpg&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이전 시간에는 데이터베이스에 테이블을 어떻게 생성하는지 살펴보았다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이번 시간에는 웹에서 데이터를 생성할 때를 살펴보자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;회원가입을 해보자.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;회원가입.PNG&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;612&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PedfZ/btq107kFnu6/rPeMA2BqZbiZcYD1k9hDik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PedfZ/btq107kFnu6/rPeMA2BqZbiZcYD1k9hDik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PedfZ/btq107kFnu6/rPeMA2BqZbiZcYD1k9hDik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPedfZ%2Fbtq107kFnu6%2FrPeMA2BqZbiZcYD1k9hDik%2Fimg.png&quot; data-filename=&quot;회원가입.PNG&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;612&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 그림과 같이 생성했다.&lt;/p&gt;
&lt;p&gt;&quot;Submit&quot; 버튼을 눌렀을 때, 어떤일이 일어날까!?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;- 먼저 해당화면을 구성하는 html을 살펴보자.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617802036757&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head th:replace=&quot;fragments/header :: header&quot; /&amp;gt;
&amp;lt;style&amp;gt;
 .fieldError {
 border-color: #bd2130;
 }
&amp;lt;/style&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div class=&quot;container&quot;&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/bodyHeader :: bodyHeader&quot;/&amp;gt;
    &amp;lt;form role=&quot;form&quot; action=&quot;/members/new&quot; th:object=&quot;${memberForm}&quot;
          method=&quot;post&quot;&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label th:for=&quot;name&quot;&amp;gt;이름&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;text&quot; th:field=&quot;*{name}&quot; class=&quot;form-control&quot;
                   placeholder=&quot;이름을 입력하세요&quot;
                   th:class=&quot;${#fields.hasErrors('name')}? 'form-control
fieldError' : 'form-control'&quot;&amp;gt;
            &amp;lt;p th:if=&quot;${#fields.hasErrors('name')}&quot;
               th:errors=&quot;*{name}&quot;&amp;gt;Incorrect date&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label th:for=&quot;city&quot;&amp;gt;도시&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;text&quot; th:field=&quot;*{city}&quot; class=&quot;form-control&quot;
                   placeholder=&quot;도시를 입력하세요&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label th:for=&quot;street&quot;&amp;gt;거리&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;text&quot; th:field=&quot;*{street}&quot; class=&quot;form-control&quot;
                   placeholder=&quot;거리를 입력하세요&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
            &amp;lt;label th:for=&quot;zipcode&quot;&amp;gt;우편번호&amp;lt;/label&amp;gt;
            &amp;lt;input type=&quot;text&quot; th:field=&quot;*{zipcode}&quot; class=&quot;form-control&quot;
                   placeholder=&quot;우편번호를 입력하세요&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
    &amp;lt;br/&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/footer :: footer&quot; /&amp;gt;
&amp;lt;/div&amp;gt; &amp;lt;!-- /container --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 구성되었다.&lt;/p&gt;
&lt;p&gt;여기서 &amp;lt;form&amp;gt;태그에 주목을 하면,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&quot;&amp;lt;form role=&quot;form&quot; action=&quot;/members/new&quot; th:object=&quot;${memberForm}&quot; method=&quot;post&quot;&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;이렇게 코드가 짜여져 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;자세한 이해를 하고 싶다면, html의 form태그의 기능을 살펴보자!&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;action 으로 &quot;/members/new&quot;라고 적혀있다. &quot;/members/new&quot;라고 매핑이 되어있는 곳으로 해당 폼정보를 던진다는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;method는 폼정보를 post형태로 던진다는 뜻이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇게 던지면, MemberController에서 해당하는 요청 매핑이 된다.&lt;/p&gt;
&lt;p&gt;아래의 매핑코드를 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1617802458388&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(value = &quot;/members/new&quot;)
    public String create(@Valid MemberForm form, BindingResult result) {
        if (result.hasErrors()) {
            return &quot;members/createMemberForm&quot;; //에러가 있으면 BindingResult에서 스프링이 해당 값을 사용할 수 있도록 해준다.
        }
        Address address = new Address(form.getCity(), form.getStreet(),
                form.getZipcode());
        Member member = new Member();
        member.setName(form.getName());
        member.setAddress(address);
        memberService.join(member);
        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;해당 값으로 넘어온다.&lt;/p&gt;
&lt;p&gt;파라미터로 &quot;MemberForm form&quot;이 넘어온다.&lt;/p&gt;
&lt;p&gt;html에서 던져준 폼을 받은 것이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;컨트롤러에서는 폼에서의 정보를 전부 member객체에 set해준다.&lt;/p&gt;
&lt;p&gt;그리고 memberService의 join 메소드를 호출하여 set해준 member를 던져준다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래는 memberService 코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1617802593515&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@Transactional(readOnly = true) //데이터 변경은 기본적으로 트랜잭션안에 있어야 한다.
@RequiredArgsConstructor // 자동 주입
public class MemberService {


    //@Autowird를 추가한다면,
    //EntityManager의 @PersistenceContext와 똑같이 자동 주입을 위함이겠지?
    // 스프링 Bean에 등록되어있는 MemberRepository를 주입해줄 것이다!!

    private final MemberRepository memberRepository;



    @Transactional
    //회원가입
    public Long join(Member member){

        validateDuplicateMember(member); //중복 회원 검증
        memberRepository.save(member);

        return member.getId();
    }
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;join을 받아서 중복회원을 검증하고, 영속성 컨텍스트를 관리하고있는 memberRepository에 던져준다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;※ validateDuplicateMember 안에 예외처리를 해두어서, 예외가 발생할 경우 save까지 넘어오지 않는다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래는 memberRepository이다.&lt;/p&gt;
&lt;pre id=&quot;code_1617802679070&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
@RequiredArgsConstructor
public class MemberRepository {

     // @PersistenceContext // 1. JPA 사용 표준 어노테이션
    private final EntityManager em; // 2. 이렇게 해주면 스프링이 자동으로 엔티티 매니저를 만들어서 em에 주입시켜준다.

    public void save(Member member){ //저장
        em.persist(member);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;여기서 EntityManager 타입의 em이 있다.&lt;/p&gt;
&lt;p&gt;이것을 통해서 우리는 영속성 컨텍스트를 다룰 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여기까지 넘어온 member 객체는 모든 과정을 통과한 정보라서 DB에 저장해주어도 된다.&lt;/p&gt;
&lt;p&gt;em.persist를 통해서 영속성 컨텍스트에 추가해준다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇게하면 JPA가 알아서 해당 객체를 테이블에 매칭하여 추가해준다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이것뿐만 아니라, 다른 &quot;item&quot; 항목에도 해당하는 로직과 똑같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그럼 이 다음에는 주문에 해당하는 로직을 살펴보자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhlaoz/btq17Hdqt01/nLVFPwJuN14DmwCb8cceK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhlaoz/btq17Hdqt01/nLVFPwJuN14DmwCb8cceK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhlaoz/btq17Hdqt01/nLVFPwJuN14DmwCb8cceK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhlaoz%2Fbtq17Hdqt01%2FnLVFPwJuN14DmwCb8cceK1%2Fimg.jpg&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Bank-End/인프런- Spring 공부</category>
      <category>Action</category>
      <category>Entity</category>
      <category>form</category>
      <category>get</category>
      <category>HTML</category>
      <category>Method</category>
      <category>POST</category>
      <category>springboot</category>
      <category>validate</category>
      <category>회원가입</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/125</guid>
      <comments>https://bestkingit.tistory.com/125#entry125comment</comments>
      <pubDate>Sat, 1 May 2021 01:30:59 +0900</pubDate>
    </item>
    <item>
      <title>[#17] Spring Bootㅣ 코드 분해하기 ㅣ Entity클래스? JPA?</title>
      <link>https://bestkingit.tistory.com/124</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0T65D/btq14ZMQhMZ/JLKJRstY449LvDTXX6KgV1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0T65D/btq14ZMQhMZ/JLKJRstY449LvDTXX6KgV1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0T65D/btq14ZMQhMZ/JLKJRstY449LvDTXX6KgV1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0T65D%2Fbtq14ZMQhMZ%2FJLKJRstY449LvDTXX6KgV1%2Fimg.jpg&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 시간에는 웹사이트에서 요청했을때, 어떤방식으로 인식하고 넘어가는지 살펴보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 이번시간에는 회원가입을 했을때, 데이터가 어떻게 넘어가고 어떻게 내부에서 움직이는지 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Spring이 시작이 되면, 테이블을 생성한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;어디에서 테이블을 생성하라는 코드가 있을까?&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이것을 알기 위해서는 먼저 JPA에 대한 지식이 있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JPA에 대한 지식은 다른 글에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/106&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bestkingit.tistory.com/106&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1617799135937&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Spring Boot ㅣ JPA, ORM에 관해서&quot; data-og-description=&quot;ORM? ORM은 Object Relational Mapping이다. 데이터베이스에 저장된 테이블 형식의 데이터를 모델링하여 자바에서 사용할 수 있도록 클래스로 바꿔주는 것이다!! 거꾸로도 가능하다! ]ORM를 알아보기 전에,&quot; data-og-host=&quot;bestkingit.tistory.com&quot; data-og-source-url=&quot;https://bestkingit.tistory.com/106&quot; data-og-url=&quot;https://bestkingit.tistory.com/106&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/MxDDx/hyJPoHIyRH/8nMXCx5KJ3vjdJT52kjA2k/img.jpg?width=400&amp;amp;height=300&amp;amp;face=0_0_400_300,https://scrap.kakaocdn.net/dn/n71lI/hyJNZQkFi8/3LymzxiZp8W5gh8qhYltKk/img.jpg?width=400&amp;amp;height=300&amp;amp;face=0_0_400_300,https://scrap.kakaocdn.net/dn/p7YIY/hyJNW0mV1H/KLTQlMHXjxkBPOaKvNsKCK/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://bestkingit.tistory.com/106&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bestkingit.tistory.com/106&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/MxDDx/hyJPoHIyRH/8nMXCx5KJ3vjdJT52kjA2k/img.jpg?width=400&amp;amp;height=300&amp;amp;face=0_0_400_300,https://scrap.kakaocdn.net/dn/n71lI/hyJNZQkFi8/3LymzxiZp8W5gh8qhYltKk/img.jpg?width=400&amp;amp;height=300&amp;amp;face=0_0_400_300,https://scrap.kakaocdn.net/dn/p7YIY/hyJNW0mV1H/KLTQlMHXjxkBPOaKvNsKCK/img.jpg?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;Spring Boot ㅣ JPA, ORM에 관해서&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;ORM? ORM은 Object Relational Mapping이다. 데이터베이스에 저장된 테이블 형식의 데이터를 모델링하여 자바에서 사용할 수 있도록 클래스로 바꿔주는 것이다!! 거꾸로도 가능하다! ]ORM를 알아보기 전에,&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;bestkingit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트를 시작할 때, 우리는 spring web, hibernate 등등의 라이브러리를 다운로드 받아주었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면, 자동으로 의존성이 추가된 상태로 프로젝트가 만들어지고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;필요한 라이브러리가 다운로드 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 때, 설치된 것 중 하나가 Spring JPA Pakage가 있다. 그리고 이것을 사용하기 위해서는 구현체가 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그것이 바로 hibernate이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 어디서 그러한 설정이 되어있는지 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- gradle로 가보자.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617798828271&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation 'org.springframework.boot:spring-boot-starter-data-jpa'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 jpa를 설치한 것이 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;- hibernate는 어디에?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;hibernate.PNG&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;79&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csTi0T/btq106F1rt5/FnKKSB6Vz0moV4gtTxkbKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csTi0T/btq106F1rt5/FnKKSB6Vz0moV4gtTxkbKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csTi0T/btq106F1rt5/FnKKSB6Vz0moV4gtTxkbKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsTi0T%2Fbtq106F1rt5%2FFnKKSB6Vz0moV4gtTxkbKk%2Fimg.png&quot; data-filename=&quot;hibernate.PNG&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;79&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외부 라이브러리에 설치되어 있는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;JPA는 어떻게 테이블을 생성할까?&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트를 Run하게 되면, JPA는 @Entity들을 스캔해서 영속성 컨텍스트에 담게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;영속성 컨텍스트에 대해서는 다른 포스팅에 있다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서의 Entity는 자바에서 1개의 클래스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 해당하는 클래스는 데이터베이스에 테이블에 매칭된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래의 그림을 보자&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;엔티티클래스.PNG&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;567&quot; width=&quot;322&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh7cHy/btq16zUsvTw/6QDeakOnbhrXsS5hdbf7nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh7cHy/btq16zUsvTw/6QDeakOnbhrXsS5hdbf7nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh7cHy/btq16zUsvTw/6QDeakOnbhrXsS5hdbf7nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh7cHy%2Fbtq16zUsvTw%2F6QDeakOnbhrXsS5hdbf7nk%2Fimg.png&quot; data-filename=&quot;엔티티클래스.PNG&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;567&quot; width=&quot;322&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게하면 테이블은 아래와 같이 만들어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;테이블2.jpg&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;85&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsxPrj/btq11MHmOAx/lhhj0Imo3sgDcN5s9Ls091/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsxPrj/btq11MHmOAx/lhhj0Imo3sgDcN5s9Ls091/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsxPrj/btq11MHmOAx/lhhj0Imo3sgDcN5s9Ls091/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsxPrj%2Fbtq11MHmOAx%2Flhhj0Imo3sgDcN5s9Ls091%2Fimg.jpg&quot; data-filename=&quot;테이블2.jpg&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;85&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(현실성 있게 하다가, 나의 개인정보가 있어서.. 지웠다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #f3c000; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;※ 각각 테이블의 필드가 되었다. 그래고 어노테이션을 지정해준 것에 따라서 Primary Key가 되고, Foriegn Key가 되었다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음 시간에는, 웹에서 회원가입을 했을 때, 데이터들이 어떻게 움직이는 지, 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3VMVP/btq17by0qPL/N6wjbrCSk7sy6In17OZJT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3VMVP/btq17by0qPL/N6wjbrCSk7sy6In17OZJT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3VMVP/btq17by0qPL/N6wjbrCSk7sy6In17OZJT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3VMVP%2Fbtq17by0qPL%2FN6wjbrCSk7sy6In17OZJT1%2Fimg.jpg&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Bank-End/인프런- Spring 공부</category>
      <category>database</category>
      <category>Entity</category>
      <category>jpa</category>
      <category>ORM</category>
      <category>springboot</category>
      <category>Table</category>
      <category>관심쟁이영호</category>
      <category>백엔드</category>
      <category>영속성컨텍스트</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/124</guid>
      <comments>https://bestkingit.tistory.com/124#entry124comment</comments>
      <pubDate>Fri, 30 Apr 2021 01:22:42 +0900</pubDate>
    </item>
    <item>
      <title>[#16] Spring Boot ㅣ 완성한 프로젝트 기초부터 전부 뜯어보기</title>
      <link>https://bestkingit.tistory.com/123</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZaD3J/btq13y9DrF7/CU4h9KDvi0yNnkk3kuWsc0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZaD3J/btq13y9DrF7/CU4h9KDvi0yNnkk3kuWsc0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZaD3J/btq13y9DrF7/CU4h9KDvi0yNnkk3kuWsc0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZaD3J%2Fbtq13y9DrF7%2FCU4h9KDvi0yNnkk3kuWsc0%2Fimg.jpg&quot; data-filename=&quot;16.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제부터는 모든 코드를 하나하나 뜯어보고, 어떤일이 일어나있는 지, 왜 그렇게 되는지 완벽하게 분해분석을 할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;1. H2 서버를 시작해주고, 프로젝트를 실행해준다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- 해당 내용에 대한 설정은, application.yml에 표시되어 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617795388614&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/jpashop
    username: sa
    password:
    driver-class-name: org.h2.Driver&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;- 여기서 url로 설정되어 있다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;2. url : localhost:8080으로 접속해준다. 그럼 홈화면이 뜬다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;-&amp;nbsp; 왜 localhost:8080인가?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 이유는 yml에 설정이 되어 있기 때문이다. yml에 server.port에 대한 설정이 없으면 기본 루트 값인, 8080포트로 향하도록 설정이 된다. 설정을 바꾸려면 아래와 같이 yml에 표시해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617795635148&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server:
  port: 8081
  context-path: /book&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 설정하면 우리는 localhost:8080이 아닌&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;localhost:8081/book&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 해야 홈화면을 접속할 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- 접속했을 때, 왜 홈화면이 나오는가?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 이유는 localhost:8080에 해당하는 url에 RequestMapping을 해놓았기 때문이다. 아래의 코드를 보면 알 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617795807612&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
@Slf4j
public class HomeController {

    @RequestMapping(&quot;/&quot;)
    public String home(){
        log.info(&quot;home controller&quot;);
        return &quot;home&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 RequestMapping(&quot;/&quot;)이 무슨 말이냐면,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Serif KR';&quot;&gt;서버에게 요청이 &quot;localhost:8080/&quot;으로 올 경우&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Serif KR';&quot;&gt;resource폴더에 있는 home.html을 리턴해주라는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;controller-home관계.PNG&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;655&quot; width=&quot;231&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzkil4/btq16zmy2Nw/P74eEws4VznKcyUmEQcVJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzkil4/btq16zmy2Nw/P74eEws4VznKcyUmEQcVJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzkil4/btq16zmy2Nw/P74eEws4VznKcyUmEQcVJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzkil4%2Fbtq16zmy2Nw%2FP74eEws4VznKcyUmEQcVJ1%2Fimg.png&quot; data-filename=&quot;controller-home관계.PNG&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;655&quot; width=&quot;231&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring은 해당 폴더를 접근하도록 기본 설정이 되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;templates의 home.html을 찾아서 리턴해주게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(static을 찾아가도록 설정되어있다고 들었는데, 음.. 여기는 공부를 해야겠다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3. 각 버튼을 누르면 이동된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;- 그럼 어디에 이동하도록 설정되어 있나?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;먼저 이것은 home.html을 살펴보아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617796056948&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head th:replace=&quot;fragments/header :: header&quot;&amp;gt;
    &amp;lt;title&amp;gt;Hello&amp;lt;/title&amp;gt;
    &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div class=&quot;container&quot;&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/bodyHeader :: bodyHeader&quot; /&amp;gt;
    &amp;lt;div class=&quot;jumbotron&quot;&amp;gt;
        &amp;lt;h1&amp;gt;HELLO SHOP&amp;lt;/h1&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;회원 기능&amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-secondary&quot; href=&quot;/members/new&quot;&amp;gt;회원 가입&amp;lt;/a&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-secondary&quot; href=&quot;/members&quot;&amp;gt;회원 목록&amp;lt;/a&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;상품 기능&amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-dark&quot; href=&quot;/items/new&quot;&amp;gt;상품 등록&amp;lt;/a&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-dark&quot; href=&quot;/items&quot;&amp;gt;상품 목록&amp;lt;/a&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p class=&quot;lead&quot;&amp;gt;주문 기능&amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-info&quot; href=&quot;/order&quot;&amp;gt;상품 주문&amp;lt;/a&amp;gt;
            &amp;lt;a class=&quot;btn btn-lg btn-info&quot; href=&quot;/orders&quot;&amp;gt;주문 내역&amp;lt;/a&amp;gt;
        &amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div th:replace=&quot;fragments/footer :: footer&quot; /&amp;gt;
&amp;lt;/div&amp;gt; &amp;lt;!-- /container --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 모든 버튼들이 선언되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대표적으로 회원가입 버튼을 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;회원가입 버튼은 href=&quot;/members/new&quot; 라고 설정되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 버튼을 누르면 서버에 기본설정값 + &quot;/members/new&quot;라고 요청이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;http://localhost:8080/members/new &amp;lt;- 이렇게 요청이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- 요청은 어디에 매핑이 되어있나?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 요청은 회원가입에 해당하는 Controller에 매핑이 되어 있을 것이다. 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617796240924&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private final MemberService memberService;

    @GetMapping(value = &quot;/members/new&quot;)
    public String createForm(Model model) {
        model.addAttribute(&quot;memberForm&quot;, new MemberForm());
        return &quot;members/createMemberForm&quot;;
    }

    @PostMapping(value = &quot;/members/new&quot;)
    public String create(@Valid MemberForm form, BindingResult result) {
        if (result.hasErrors()) {
            return &quot;members/createMemberForm&quot;; //에러가 있으면 BindingResult에서 스프링이 해당 값을 사용할 수 있도록 해준다.
        }
        Address address = new Address(form.getCity(), form.getStreet(),
                form.getZipcode());
        Member member = new Member();
        member.setName(form.getName());
        member.setAddress(address);
        memberService.join(member);
        return &quot;redirect:/&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 코드를 보면 GetMapping과 PostMapping 2개가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각각 다른 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;회원가입이니까 1개는 회원가입 페이지를 표시, 다른 1개는 회원가입 정보를 입력하고 확인버튼 눌렀을 때의 정보를 넘겨줄 Post매핑일 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;앞에 코드에서 RequestMapping을 사용한 것을 살펴볼 수 있다. 근데 @GetMapping과 @PostMapping이 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 여기서 RequestMapping, GetMapping, PostMapping이 무엇일까?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;- RequestMapping, GetMapping, PostMapping 차이&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@RequestMapping은 @GetMapping, @PostMapping이 나오기 전에 먼저 있던 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래의 코드를 줄일 수 있는 역할이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@RequestMapping(value=&quot;/&quot;, method = { RequestMethod.GET}) -&amp;gt; @GetMapping(&quot;/&quot;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@RequestMapping(value=&quot;/&quot;, method = {RequestMethod.POST}) -&amp;gt; @PostMapping(&quot;/&quot;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 줄일 수 있게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;둘 중 아무거나 사용해도 상관없는데, 뒤에 최신버전으로 나온 것이 더욱 최적화가 잘되어있을 것이다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 개발자입장에서도 구분하기 편하다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 다음 시간에는 데이터베이스에 테이블들이 어떻게 생성되는지 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwarUm/btq13zUWSAc/WvIOqgpWgmyUciwksNvQw1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwarUm/btq13zUWSAc/WvIOqgpWgmyUciwksNvQw1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwarUm/btq13zUWSAc/WvIOqgpWgmyUciwksNvQw1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwarUm%2Fbtq13zUWSAc%2FWvIOqgpWgmyUciwksNvQw1%2Fimg.jpg&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Bank-End/인프런- Spring 공부</category>
      <category>get</category>
      <category>HTML</category>
      <category>POST</category>
      <category>springboot</category>
      <category>관심쟁이영호</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/123</guid>
      <comments>https://bestkingit.tistory.com/123#entry123comment</comments>
      <pubDate>Thu, 29 Apr 2021 01:25:46 +0900</pubDate>
    </item>
    <item>
      <title>[HTML #4] HTML 옵션값 ui, li, ol, br,</title>
      <link>https://bestkingit.tistory.com/122</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;4.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuYfqk/btq1WgIRUBu/WQHtEiOsX0iDzG1cCjpXq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuYfqk/btq1WgIRUBu/WQHtEiOsX0iDzG1cCjpXq0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuYfqk/btq1WgIRUBu/WQHtEiOsX0iDzG1cCjpXq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuYfqk%2Fbtq1WgIRUBu%2FWQHtEiOsX0iDzG1cCjpXq0%2Fimg.jpg&quot; data-filename=&quot;4.jpg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;li&gt;li&lt;/li&gt;
&lt;li&gt;ol&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ui와 ol은 리스트 형태로 보여주는 것이다.&lt;/p&gt;
&lt;p&gt;li는 해당 리스트에 값을 넣어주는 것이다.&lt;/p&gt;
&lt;p&gt;화면으로 살펴보자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;코드는&lt;/p&gt;
&lt;pre id=&quot;code_1617722724037&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
	&amp;lt;li&amp;gt;쇼핑&amp;lt;/li&amp;gt;
    	&amp;lt;li&amp;gt;고기&amp;lt;/li&amp;gt;
    	&amp;lt;li&amp;gt;화장품&amp;lt;/li&amp;gt;
	&amp;lt;li&amp;gt;장난감&amp;lt;/li&amp;gt;
   	&amp;lt;li&amp;gt;전자기기&amp;lt;/li&amp;gt;
   	&amp;lt;li&amp;gt;신발&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;ol&amp;gt;
	&amp;lt;li&amp;gt;일번&amp;lt;/li&amp;gt;
	&amp;lt;li&amp;gt;이번&amp;lt;/li&amp;gt;
	&amp;lt;li&amp;gt;삼번&amp;lt;/li&amp;gt;
	&amp;lt;li&amp;gt;사번&amp;lt;/li&amp;gt;
	&amp;lt;li&amp;gt;오번&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;화면은&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;a.PNG&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;370&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0T4bK/btq12wCY8Bc/oMLlsixfhv66Wgszh60nPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0T4bK/btq12wCY8Bc/oMLlsixfhv66Wgszh60nPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0T4bK/btq12wCY8Bc/oMLlsixfhv66Wgszh60nPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0T4bK%2Fbtq12wCY8Bc%2FoMLlsixfhv66Wgszh60nPk%2Fimg.png&quot; data-filename=&quot;a.PNG&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;370&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이렇다.&lt;/p&gt;
&lt;p&gt;이미지파일, 버튼 그냥 싹다 넣을 수 있다!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;br&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 것은 줄을 한번 개행 시켜주는 것이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그 외에는 많은 태그가 있다.&lt;/p&gt;
&lt;p&gt;하나하나 짚고 넘어가기가 힘들다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 다음에 html을 사용할 때, 필요하면 w3school.com에 가서 찾아보도록 하자!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MnSEN/btq1WKcaUh9/yAfKQqtztKximdboc98FV1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MnSEN/btq1WKcaUh9/yAfKQqtztKximdboc98FV1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MnSEN/btq1WKcaUh9/yAfKQqtztKximdboc98FV1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMnSEN%2Fbtq1WKcaUh9%2FyAfKQqtztKximdboc98FV1%2Fimg.jpg&quot; data-filename=&quot;로고.jpg&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;300&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Front-End/HTML</category>
      <author>관심쟁이 영호</author>
      <guid isPermaLink="true">https://bestkingit.tistory.com/122</guid>
      <comments>https://bestkingit.tistory.com/122#entry122comment</comments>
      <pubDate>Wed, 28 Apr 2021 01:35:54 +0900</pubDate>
    </item>
  </channel>
</rss>