<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>보안 전공생의 공부</title>
    <link>https://jonnastudy.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 21 Jul 2026 09:35:42 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>수잉</managingEditor>
    <image>
      <title>보안 전공생의 공부</title>
      <url>https://tistory1.daumcdn.net/tistory/4452504/attach/14ad69eea1e744b7b7be350058dd6737</url>
      <link>https://jonnastudy.tistory.com</link>
    </image>
    <item>
      <title>수정하고 저장소에 저장하기 + 브랜치</title>
      <link>https://jonnastudy.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;참조 : &lt;a href=&quot;https://git-scm.com/book/ko/v2/Git%EC%9D%98-%EA%B8%B0%EC%B4%88-%EC%88%98%EC%A0%95%ED%95%98%EA%B3%A0-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://git-scm.com/book/ko/v2&lt;/a&gt;, &lt;a href=&quot;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=zxy826&amp;amp;logNo=220488261345&quot;&gt;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=zxy826&amp;amp;logNo=220488261345&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시물 (&lt;a href=&quot;https://jonnastudy.tistory.com/109&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.12.29 - [개발/풀스택 스터디 공부 정리] - Git - git 저장소 만들기&lt;/a&gt;)에서 git 저장소를 만들었고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;working directory&lt;/span&gt;(작업자의 현재 시점-&amp;gt;작업자의 작업 트리)에&lt;span style=&quot;color: #009a87;&quot;&gt; checkout&lt;/span&gt;(작업자의 작업트리를 저장소의 특정 시점과 일치하도록 하는 작업)을 하였다.&lt;/p&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;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;span style=&quot;color: #009a87;&quot;&gt;tracked(관리대상o) / untracked(관리대상x)&lt;/span&gt;으로 나눈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;tracked&lt;/b&gt; 파일 : 이미 스냅샷에 포함되어 있던 파일 &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt; git이 알고 있는 파일&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;unmodified&lt;/b&gt;(수정x) / &lt;b&gt;modified&lt;/b&gt;(수정o) / &lt;b&gt;staged&lt;/b&gt;(커밋으로 저장소에 기록할)&lt;/span&gt; 상태 중 하나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;untracked&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;최초로 저장소를 clone하면 &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; 모든 파일은 tracked이면서&lt;b&gt; unmodified&lt;/b&gt;상태이다. 파일을 checkout하고 나서 아무것도 수정&lt;span style=&quot;color: #ee2323;&quot;&gt;x&lt;/span&gt; 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 커밋 이후 아무것도 수정&lt;span style=&quot;color: #ee2323;&quot;&gt;x&lt;/span&gt; 상태에서 파일을 수정하면&lt;span style=&quot;color: #ee2323;&quot;&gt; -&amp;gt;&lt;/span&gt; git은 그 파일을&lt;b&gt; modified&lt;/b&gt;상태로 인식한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 커밋을 하기 위해서는 이 수정한 파일을&lt;b&gt; staged&lt;/b&gt;상태로 만들고, &lt;b&gt;staged&lt;/b&gt;상태의 파일을 커밋한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;=&amp;gt; 이러한 라이프사이클 계속 반복&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;330&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BceWJ/btrpuslMUX9/WHe6plPYFn5QjoItq2LxNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BceWJ/btrpuslMUX9/WHe6plPYFn5QjoItq2LxNK/img.png&quot; data-alt=&quot;파일의 라이프 사이클&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BceWJ/btrpuslMUX9/WHe6plPYFn5QjoItq2LxNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBceWJ%2FbtrpuslMUX9%2FWHe6plPYFn5QjoItq2LxNK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;330&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;330&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;b&gt;&amp;middot; 파일 상태 확인&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;141&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p8yYa/btrpvTiUQro/cdkhNKERdmTETkuUuXOOS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p8yYa/btrpvTiUQro/cdkhNKERdmTETkuUuXOOS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p8yYa/btrpvTiUQro/cdkhNKERdmTETkuUuXOOS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp8yYa%2FbtrpvTiUQro%2FcdkhNKERdmTETkuUuXOOS1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;692&quot; height=&quot;166&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;141&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일의 상태 확인하기 위해서는 &lt;b&gt;git status&lt;/b&gt; 명령이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clone한 후 바로 이 명령을 실행하면 위의 메시지가 뜬다.&lt;/p&gt;
&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;tracked 파일은 하나도 수정되지 않았다는 의미이다. untracked 파일은 아직 없어서 목록에 나타나지 않는다.&lt;/p&gt;
&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;span style=&quot;color: #009a87;&quot;&gt;master&lt;/span&gt;이기 때문에 현재 브랜치 이름이 'master'로 나온다.&lt;/p&gt;
&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;&amp;middot; 파일 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 README 파일을 만들기 위해 gitbash에 아래와 같은 명령어를 입력한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L8Wxr/btrpJRxEuYX/nBdJXG8dzUzmoihLJqT6TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L8Wxr/btrpJRxEuYX/nBdJXG8dzUzmoihLJqT6TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L8Wxr/btrpJRxEuYX/nBdJXG8dzUzmoihLJqT6TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL8Wxr%2FbtrpJRxEuYX%2FnBdJXG8dzUzmoihLJqT6TK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;235&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;README 파일은 새로 만든 파일이기 때문에 status를 실행하면 위와 같은 문구가 출력된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- README 파일은 &lt;span style=&quot;color: #009a87;&quot;&gt;Untracked&lt;/span&gt; 상태라는 것을 나타내고 있다. git은 &lt;span style=&quot;color: #009a87;&quot;&gt;untracked&lt;/span&gt; 파일을 아직 스냅샷(커밋)에 넣어지지 않은 파일로 인식한다 (파일이 &lt;span style=&quot;color: #009a87;&quot;&gt;tracked&lt;/span&gt; 상태가 되기 전까지 git은 절대 그 파일을 커밋하지 않는다)&lt;/p&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;README 파일을 직접 &lt;span style=&quot;color: #009a87;&quot;&gt;tracked&lt;/span&gt; 상태로 만들기 위해&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPWSrW/btrpKlefTTu/YxoNN5aSHxK9KgT9RLkrY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPWSrW/btrpKlefTTu/YxoNN5aSHxK9KgT9RLkrY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPWSrW/btrpKlefTTu/YxoNN5aSHxK9KgT9RLkrY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPWSrW%2FbtrpKlefTTu%2FYxoNN5aSHxK9KgT9RLkrY0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;292&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;git add&lt;/b&gt; 명령으로 README 파일을 추적한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;git status&lt;/b&gt; 명령을 다시 실행하면 README 파일이 &lt;span style=&quot;color: #009a87;&quot;&gt;tracked&lt;/span&gt; 상태이면서 커밋에 추가될 &lt;span style=&quot;color: #009a87;&quot;&gt;staged &lt;/span&gt;상태임&lt;span style=&quot;color: #ee2323;&quot;&gt;(&amp;lt;-changes to be committed)&lt;/span&gt;을 확인할 수 있다. 커밋하면 &lt;b&gt;git add&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;2) modified 상태의 파일을 stage 하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- README 파일을 수정하고 다시 &lt;b&gt;git status &lt;/b&gt;명령을 실행하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lmLm6/btrpLuB02f8/P8lwQvqDkSd2do2090XOM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lmLm6/btrpLuB02f8/P8lwQvqDkSd2do2090XOM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lmLm6/btrpLuB02f8/P8lwQvqDkSd2do2090XOM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlmLm6%2FbtrpLuB02f8%2FP8lwQvqDkSd2do2090XOM0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;708&quot; height=&quot;239&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- README 파일은 &lt;span style=&quot;color: #009a87;&quot;&gt;tracked&lt;/span&gt;한 상태이지만 아직&lt;span style=&quot;color: #009a87;&quot;&gt; staged&lt;/span&gt;가 안된 상태임&lt;span style=&quot;color: #ee2323;&quot;&gt;(&amp;lt;-changes not staged for commit)&lt;/span&gt;을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; staged 상태로 만들려면 &lt;b&gt;git add&lt;/b&gt; 명령을 실행해야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;▷ git add : 파일을 새로 추적할 때 &amp;amp; 수정한 파일을 staged 상태로 만들 때 사용 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;+ merge할 때 충돌난 상태의 파일을 resolve할 때도 사용&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0BTli/btrpMQEP8L0/LNoXu9eZrafoB8gk2XrP30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0BTli/btrpMQEP8L0/LNoXu9eZrafoB8gk2XrP30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0BTli/btrpMQEP8L0/LNoXu9eZrafoB8gk2XrP30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0BTli%2FbtrpMQEP8L0%2FLNoXu9eZrafoB8gk2XrP30%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;301&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git add &lt;/b&gt;명령을 실행해 README파일을 &lt;span style=&quot;color: #009a87;&quot;&gt;staged&lt;/span&gt; 상태로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git status&lt;/b&gt; 명령으로 파일이&lt;span style=&quot;color: #009a87;&quot;&gt; staged&lt;/span&gt; 상태임을 확인할 수 있다.&lt;/p&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HgjOn/btrpLtiXLXp/pVZrqn6tUskuWNZRQCxwX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HgjOn/btrpLtiXLXp/pVZrqn6tUskuWNZRQCxwX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HgjOn/btrpLtiXLXp/pVZrqn6tUskuWNZRQCxwX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHgjOn%2FbtrpLtiXLXp%2FpVZrqn6tUskuWNZRQCxwX1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;661&quot; height=&quot;180&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;165&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;staged&lt;/span&gt; 상태가 된 파일을 커밋하기 위해 &lt;b&gt;git commit&lt;/b&gt;을 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 &lt;span style=&quot;color: #ee2323;&quot;&gt;'Aborting commit due to empty commit message'&lt;/span&gt; 라는 오류가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vscode로 파일이 열려있어서 생긴 오류인 것으로 예상했다. 그래서 vscode를 종료하고 다시 -m 옵션을 사용하여 메시지를 첨부하였더니 커밋이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련 참고 자료 : &lt;a href=&quot;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1641253103955&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;Associating text editors with Git - GitHub Docs&quot; data-og-description=&quot;Associating text editors with Git Use a text editor to open and edit your files with Git. MacWindowsLinux Using Atom as your editor Install Atom. For more information, see &amp;quot;Installing Atom&amp;quot; in the Atom documentation. Open TerminalTerminalGit Bash. Type thi&quot; data-og-host=&quot;docs.github.com&quot; data-og-source-url=&quot;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&quot; data-og-url=&quot;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2Gi3q/hyMXATvRgx/aw04uOdxOVz39ykRZfcLFK/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200&quot;&gt;&lt;a href=&quot;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2Gi3q/hyMXATvRgx/aw04uOdxOVz39ykRZfcLFK/img.png?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200');&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;Associating text editors with Git - GitHub Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Associating text editors with Git Use a text editor to open and edit your files with Git. MacWindowsLinux Using Atom as your editor Install Atom. For more information, see &quot;Installing Atom&quot; in the Atom documentation. Open TerminalTerminalGit Bash. Type thi&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.github.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;color: #006dd7;&quot;&gt;커밋을 통해 확인할 수 있는 정보&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;-&amp;gt; &lt;u&gt;master&lt;/u&gt; 브랜치에 커밋했고, 체크섬은 &lt;u&gt;f8518ff&lt;/u&gt; 이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;그리고 수정한 파일은 &lt;u&gt;1개&lt;/u&gt;이고, &lt;u&gt;추가&lt;/u&gt;된 라인은 &lt;u&gt;1개&lt;/u&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;&amp;middot; staging area 생략&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 &lt;b&gt;git add&lt;/b&gt; 명령을 실행하여 파일이 &lt;span style=&quot;color: #009a87;&quot;&gt;staged&lt;/span&gt; 상태가 되게 한 후, &lt;b&gt;git commit&lt;/b&gt; 명령을 통해 커밋을 해야 되는 과정이 귀찮을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git commit&lt;/b&gt; 명령을 실행할 때 &lt;b&gt;-a&lt;/b&gt; 옵션을 추가하면 git은&lt;span style=&quot;color: #009a87;&quot;&gt; tracked&lt;/span&gt;상태의 파일을 자동으로 staging area로 넣기 때문에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git add&lt;/b&gt; 명령을 실행할 필요가 &lt;u&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;b&gt;&amp;middot; 파일 삭제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git rm&lt;/b&gt; 명령으로 &lt;span style=&quot;color: #009a87;&quot;&gt;tracked&lt;/span&gt; 상태의 파일을 삭제한 후&lt;span style=&quot;color: #006dd7;&quot;&gt;(staging area에서 삭제하는 것)&lt;/span&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;git 명령을 사용하지 않고 단순히 워킹 디렉토리에서 README 파일을 삭제하고 &lt;b&gt;git status&lt;/b&gt; 명령으로 상태를 확인하면 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UvL1R/btrpIx7xbyg/tAiPUl0oWbEGxzKWdxCAfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UvL1R/btrpIx7xbyg/tAiPUl0oWbEGxzKWdxCAfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UvL1R/btrpIx7xbyg/tAiPUl0oWbEGxzKWdxCAfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUvL1R%2FbtrpIx7xbyg%2FtAiPUl0oWbEGxzKWdxCAfK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;653&quot; height=&quot;216&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Changes not staged for commit&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt; (-&amp;gt;unstaged)&lt;/span&gt; 상태라고 표시를 하고 있다.&lt;/p&gt;
&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;git rm&lt;/b&gt; 명령을 실행하면 삭제된 파일은 &lt;span style=&quot;color: #009a87;&quot;&gt;staged&lt;/span&gt; 상태가 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Urcrm/btrpOxSIjKY/KieKHYCswiO3ox6bf9CTlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Urcrm/btrpOxSIjKY/KieKHYCswiO3ox6bf9CTlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Urcrm/btrpOxSIjKY/KieKHYCswiO3ox6bf9CTlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUrcrm%2FbtrpOxSIjKY%2FKieKHYCswiO3ox6bf9CTlK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;70&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;70&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;b&gt;git status&lt;/b&gt;로 상태를 확인해보면 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BkxU2/btrpOyc03ys/44AYpoyr1ka34YcUmnTKCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BkxU2/btrpOyc03ys/44AYpoyr1ka34YcUmnTKCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BkxU2/btrpOyc03ys/44AYpoyr1ka34YcUmnTKCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBkxU2%2FbtrpOyc03ys%2F44AYpoyr1ka34YcUmnTKCk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;636&quot; height=&quot;199&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 git은 이 파일을 더 추적하지 않는다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; 브랜치&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;&amp;middot; Git이 데이터를 저장하는 방법&lt;/b&gt; : git은 데이터를 change set이나 변경사항(diff)으로 기록하지 않고, &lt;u&gt;일련의 스냅샷&lt;/u&gt;으로 기록한다.&amp;nbsp;&lt;br /&gt;커밋하면 git은&lt;b&gt; 커밋 개체&lt;/b&gt;(object)를 저장한다 &lt;span style=&quot;color: #009a87;&quot;&gt;(-&amp;gt; 현 staging area에 있는 데이터의 스냅샷에 대한 포인터 등)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초 커밋을 제외한 나머지 커밋은 이전 커밋 포인터가 적어도 하나씩 있고, 브랜치를 합친 merge커밋 같은 경우에는 이전 커밋 포인터가 여러 개 있다.&lt;/p&gt;
&lt;p data-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;ex)&lt;/b&gt;&amp;nbsp;파일 3개 있는 디렉토리 하나가 있고, 이 파일을 staging area에 저장하고 커밋&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;1) staging area에 저장&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 파일을 &lt;b&gt;stage&lt;/b&gt;하면 git 저장소에 파일을 저장하고&lt;span style=&quot;color: #ee2323;&quot;&gt;(&lt;b&gt;Blob&lt;/b&gt;)&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;b&gt;staging area&lt;/b&gt;에 해당 파일의 체크섬을 저장한다 (SHA-1 사용)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;2) 커밋&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1641188358722&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git add README LICENSE test.rb
$ git commit -m 'The initial commit of my project'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;span style=&quot;background-color: #333333; color: #ffffff;&quot;&gt;git commit&lt;/span&gt; 으로 커밋 &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; 루트 디렉토리와 각 하위 디렉토리의 트리 개체를 체크섬과 함께 저장소에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;b&gt;커밋 개체&lt;/b&gt; 생성&lt;span style=&quot;color: #009a87;&quot;&gt; (&amp;lt;- 메타데이터, 루트 디렉토리 트리 개체를 가리키는 포인터 정보 넣음)&lt;/span&gt;&lt;/p&gt;
&lt;p data-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;&quot;&gt;Git 저장소에는 5개의 데이터 객체가 생긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;각 파일에 대한 Blob 3개, 파일과 디렉토리 구조가 들어 있는 트리 개체 1개, 커밋 개체 1개&lt;/u&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5sPN8/btrpu2zVA0i/8rEK5rZrcsRDaK3fOtXK61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5sPN8/btrpu2zVA0i/8rEK5rZrcsRDaK3fOtXK61/img.png&quot; data-alt=&quot;커밋&amp;amp;amp;amp;amp;트리데이터(5개의 데이터 객체)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5sPN8/btrpu2zVA0i/8rEK5rZrcsRDaK3fOtXK61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5sPN8%2Fbtrpu2zVA0i%2F8rEK5rZrcsRDaK3fOtXK61%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;443&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;커밋&amp;amp;amp;amp;트리데이터(5개의 데이터 객체)&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CvQeC/btrpGzw5cR2/NaYvgwlEpxhKQfq5t4kGEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CvQeC/btrpGzw5cR2/NaYvgwlEpxhKQfq5t4kGEK/img.png&quot; data-alt=&quot;커밋&amp;amp;amp;amp;amp;이전 커밋&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CvQeC/btrpGzw5cR2/NaYvgwlEpxhKQfq5t4kGEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCvQeC%2FbtrpGzw5cR2%2FNaYvgwlEpxhKQfq5t4kGEK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;265&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;커밋&amp;amp;amp;amp;이전 커밋&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;b&gt;브랜치&lt;/b&gt;는 커밋과 커밋 사이를 이동할 수 있는 &lt;b&gt;포인터&lt;/b&gt; 같은 것이라고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 git은 master 브랜치를 만든다. 처음 커밋하면 이 &lt;u&gt;master 브랜치가 생성된 커밋&lt;/u&gt;을 가리킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 커밋을 만들면 master 브랜치는 자동으로 &lt;u&gt;가장 마지막 커밋&lt;/u&gt;을 가리킨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXTVVP/btrpJRKLPVY/krrB98AqxTXmvJd4v2b5W0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXTVVP/btrpJRKLPVY/krrB98AqxTXmvJd4v2b5W0/img.png&quot; data-alt=&quot;master 브랜치 &amp;amp;amp;amp;amp; 커밋 히스토리 -&amp;amp;amp;amp;gt; master 브랜치는 가장 최신 커밋을 가리킴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXTVVP/btrpJRKLPVY/krrB98AqxTXmvJd4v2b5W0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXTVVP%2FbtrpJRKLPVY%2FkrrB98AqxTXmvJd4v2b5W0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;430&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;430&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;master 브랜치 &amp;amp;amp;amp; 커밋 히스토리 -&amp;amp;amp;gt; master 브랜치는 가장 최신 커밋을 가리킴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; 새 브랜치 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~/Documents/asdf1파일에 testing 브랜치를 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4no0P/btrpKkMLTzS/yxz9Hs60KXtgVAn6SXeOa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4no0P/btrpKkMLTzS/yxz9Hs60KXtgVAn6SXeOa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4no0P/btrpKkMLTzS/yxz9Hs60KXtgVAn6SXeOa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4no0P%2FbtrpKkMLTzS%2Fyxz9Hs60KXtgVAn6SXeOa1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;533&quot; height=&quot;57&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;57&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;b&gt;git branch&lt;/b&gt;명령어는 브랜치를 새로 만들기만 하기 때문에, git은 아직 maser 브랜치를 가리키고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 확인하는 방법은 git의 HEAD포인터를 이용하면 된다. 이 포인터는 지금 작업하고 있는 로컬 브랜치를 가리킨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git log&lt;/b&gt; 명령에&lt;b&gt; --decorate&lt;/b&gt; 옵션을 사용하면 브랜치가 어떤 커밋을 가리키는지 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kNfKw/btrpD09DEhk/koc9hw3apMIqCzmenGhE9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kNfKw/btrpD09DEhk/koc9hw3apMIqCzmenGhE9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kNfKw/btrpD09DEhk/koc9hw3apMIqCzmenGhE9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkNfKw%2FbtrpD09DEhk%2Fkoc9hw3apMIqCzmenGhE9K%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;574&quot; height=&quot;66&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4gctV/btrpu28fInV/n72bKOYNEAzm8XxTPuuKZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4gctV/btrpu28fInV/n72bKOYNEAzm8XxTPuuKZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4gctV/btrpu28fInV/n72bKOYNEAzm8XxTPuuKZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4gctV%2Fbtrpu28fInV%2Fn72bKOYNEAzm8XxTPuuKZ0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;272&quot; height=&quot;274&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;master 브랜치를 가리키고 있는 것을 확인할 수 있다.&lt;/p&gt;
&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;&amp;middot; 브랜치 이동하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git checkout&lt;/b&gt; 명령으로 다른 브랜치로 이동할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b50eem/btrpyjITeXE/W3RC0igHhMeNkPskP1V6C0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b50eem/btrpyjITeXE/W3RC0igHhMeNkPskP1V6C0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b50eem/btrpyjITeXE/W3RC0igHhMeNkPskP1V6C0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb50eem%2FbtrpyjITeXE%2FW3RC0igHhMeNkPskP1V6C0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;574&quot; height=&quot;65&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;60&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;testing 브랜치로 바꾸었다. 이렇게 하면 HEAD는 testing 브랜치를 가리킨다.&lt;/p&gt;
&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;git log&lt;/b&gt; 명령어를 이용하여 HEAD가 가리키는 브랜치를 확인하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vdu7w/btrpvR0qp12/n5r1nkdQnk5ezrUtkO5zV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vdu7w/btrpvR0qp12/n5r1nkdQnk5ezrUtkO5zV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vdu7w/btrpvR0qp12/n5r1nkdQnk5ezrUtkO5zV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVdu7w%2FbtrpvR0qp12%2Fn5r1nkdQnk5ezrUtkO5zV0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;559&quot; height=&quot;67&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w3qzH/btrpJRYomTP/VlXtUZzANALkWNNHG8oDeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w3qzH/btrpJRYomTP/VlXtUZzANALkWNNHG8oDeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w3qzH/btrpJRYomTP/VlXtUZzANALkWNNHG8oDeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw3qzH%2FbtrpJRYomTP%2FVlXtUZzANALkWNNHG8oDeK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;342&quot; height=&quot;325&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;testing 브랜치로 변경된 것을 확인할 수 있다.&lt;/p&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;there4; git은 브랜치가 필요할 때 프로젝트를 전체 복사하지 않기 때문에, 복사하는 작업이 순식간이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 커밋할 때마다 이전 커밋의 정보를 저장하기 때문에 merge할 때 어디서부터&lt;span style=&quot;color: #009a87;&quot;&gt;(merge base)&lt;/span&gt; 합쳐야 하는지 안다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 개발자들이 수시로 브랜치를 만들어 사용한다.&lt;/p&gt;</description>
      <category>SCM/GIT</category>
      <category>GIT</category>
      <category>gitbash</category>
      <category>브랜치</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/110</guid>
      <comments>https://jonnastudy.tistory.com/110#entry110comment</comments>
      <pubDate>Tue, 4 Jan 2022 08:59:29 +0900</pubDate>
    </item>
    <item>
      <title>git 저장소 만들기</title>
      <link>https://jonnastudy.tistory.com/109</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;출처 : &lt;a href=&quot;https://git-scm.com/book/ko/v2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://git-scm.com/book/ko/v2&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 밑의 두 가지 방법 중 하나로 git 저장소를 쓰기 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;&amp;gt; 아직 버전 관리를 하지 않는 로컬 디렉토리 하나를 선택해서 git 저장소를 적용하는 방법&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;&amp;gt; 다른 어딘가에서 git 저장소를 clone하는 방법&lt;/i&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;1. 아직 버전 관리를 하지 않는 로컬 디렉토리 하나를 선택해서 git 저장소를 적용하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 프로젝트의 디렉토리로 들어가서 git bash를 실행시킨다&lt;span style=&quot;color: #009a87;&quot;&gt;(마우스 우클릭 &amp;gt; git bash 실행)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러면 굳이 cmd에서 디렉토리 이동을 하지 않아도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-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;git init&lt;/span&gt; 명령을 실행한다. 이 명령만으로는 프로젝트의 어떤 파일도 관리하지 않는다. 대신 &lt;b&gt;.git&lt;/b&gt;이라는 하위 디렉토리를 만들 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bV569v/btrpgyq6l5j/UltT6lwUr90sdxNqUaUrt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bV569v/btrpgyq6l5j/UltT6lwUr90sdxNqUaUrt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bV569v/btrpgyq6l5j/UltT6lwUr90sdxNqUaUrt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbV569v%2Fbtrpgyq6l5j%2FUltT6lwUr90sdxNqUaUrt1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;518&quot; height=&quot;160&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.git 디렉토리에는 저장소에 필요한 뼈대파일&lt;span style=&quot;color: #009a87;&quot;&gt;(skeleton)&lt;/span&gt;이 들어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git이 파일을 관리하게 하려면 저장소에 파일을 추가하고 commit 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git add&lt;/span&gt; 명령으로 파일을 추가하고 &lt;span style=&quot;color: #006dd7;&quot;&gt;git commit&lt;/span&gt; 명령으로 commit한다.&lt;/p&gt;
&lt;pre id=&quot;code_1640703511617&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git add .
$ git add &amp;lt;filename&amp;gt;or&amp;lt;foldername&amp;gt;
$ git commit
$ git commit -m &quot;commit message&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;&amp;gt; &lt;a href=&quot;https://jonnastudy.tistory.com/107&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.12.28 - [개발/풀스택 스터디 공부 정리] - Git - git 최초설정, git 레파지토리 생성 및 소스 올리기 (git bash)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640705355367&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;Git - git 최초설정, git 레파지토리 생성 및 소스 올리기 (git bash)&quot; data-og-description=&quot;github에서 원격 저장소를 만들고 난 후 , git bash로 push 하는 방법을 사용한다. 참조 : https://coding-factory.tistory.com/244 [Git] Git 레파지토리 생성 &amp;amp; 소스 올리기 (Git Bash활용) GitHub에서 원격저장..&quot; data-og-host=&quot;jonnastudy.tistory.com&quot; data-og-source-url=&quot;https://jonnastudy.tistory.com/107&quot; data-og-url=&quot;https://jonnastudy.tistory.com/107&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/z5W8g/hyMS5GfO2l/ULCY2gvaNviEx6kdBPrri0/img.png?width=800&amp;amp;height=456&amp;amp;face=0_0_800_456,https://scrap.kakaocdn.net/dn/cDg52x/hyMSTMzs9G/1jOQoekH85FKNYlZlSH6s0/img.png?width=800&amp;amp;height=456&amp;amp;face=0_0_800_456,https://scrap.kakaocdn.net/dn/lzjcp/hyMS4USfra/shxKrfD86N0PA5u4Uxn7h1/img.jpg?width=669&amp;amp;height=669&amp;amp;face=0_0_669_669&quot;&gt;&lt;a href=&quot;https://jonnastudy.tistory.com/107&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jonnastudy.tistory.com/107&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/z5W8g/hyMS5GfO2l/ULCY2gvaNviEx6kdBPrri0/img.png?width=800&amp;amp;height=456&amp;amp;face=0_0_800_456,https://scrap.kakaocdn.net/dn/cDg52x/hyMSTMzs9G/1jOQoekH85FKNYlZlSH6s0/img.png?width=800&amp;amp;height=456&amp;amp;face=0_0_800_456,https://scrap.kakaocdn.net/dn/lzjcp/hyMS4USfra/shxKrfD86N0PA5u4Uxn7h1/img.jpg?width=669&amp;amp;height=669&amp;amp;face=0_0_669_669');&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;Git - git 최초설정, git 레파지토리 생성 및 소스 올리기 (git bash)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;github에서 원격 저장소를 만들고 난 후 , git bash로 push 하는 방법을 사용한다. 참조 : https://coding-factory.tistory.com/244 [Git] Git 레파지토리 생성 &amp;amp; 소스 올리기 (Git Bash활용) GitHub에서 원격저장..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jonnastudy.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;b&gt;2. 다른 어딘가에서 git 저장소를 clone하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 프로젝트에 참여하거나&lt;span style=&quot;color: #009a87;&quot;&gt;(contribute)&lt;/span&gt; git 저장소를 복사하고 싶을 때 git clone 명령을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git은 서버에 있는 거의 모든 데이터를 복사한다. git clone을 실행하면 프로젝트 히스토리를 전부 받아온다.&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: #006dd7;&quot;&gt;git clone &amp;lt;url&amp;gt;&lt;/span&gt;으로 저장소를 clone 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 example 라이브러리 소스코드를 clone하려면 아래처럼 명령하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1640704890660&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git clone https://github.com/example/example&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령은 example이라는 디렉토리를 만들고 그 안에 &lt;b&gt;.git&lt;/b&gt;이라는 디렉토리를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 저장소의 데이터를 모두 가져와 자동으로 최신 버전을 checkout 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;example 디렉토리로 이동하면 checkout으로 생성한 파일을 볼 수 있고 작업을 시작할 수 있다.&lt;/p&gt;
&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;/u&gt;을 입력하면된다.&lt;/p&gt;
&lt;pre id=&quot;code_1640705199330&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git clone https://github.com/example/example example2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디렉토리 이름이 example2가 된다.&lt;/p&gt;</description>
      <category>SCM/GIT</category>
      <category>GIT</category>
      <category>git저장소</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/109</guid>
      <comments>https://jonnastudy.tistory.com/109#entry109comment</comments>
      <pubDate>Wed, 29 Dec 2021 00:30:52 +0900</pubDate>
    </item>
    <item>
      <title>중간 정리</title>
      <link>https://jonnastudy.tistory.com/108</link>
      <description>&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-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20211222_143752771.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9gaca/btroDva8m5w/ennGqpyf6hYk0ZaRi3bT5K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9gaca/btroDva8m5w/ennGqpyf6hYk0ZaRi3bT5K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9gaca/btroDva8m5w/ennGqpyf6hYk0ZaRi3bT5K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9gaca%2FbtroDva8m5w%2FennGqpyf6hYk0ZaRi3bT5K%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1018&quot; data-filename=&quot;KakaoTalk_20211222_143752771.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20211222_143753158.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbpRzx/btroABpFhXp/CUgYKkktJdrJbVt1ntzsUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbpRzx/btroABpFhXp/CUgYKkktJdrJbVt1ntzsUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbpRzx/btroABpFhXp/CUgYKkktJdrJbVt1ntzsUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbpRzx%2FbtroABpFhXp%2FCUgYKkktJdrJbVt1ntzsUk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1018&quot; data-filename=&quot;KakaoTalk_20211222_143753158.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20211222_143753774.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GnGyv/btroAAxvlWO/kHQHk5ZeLfYnxYTow344T0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GnGyv/btroAAxvlWO/kHQHk5ZeLfYnxYTow344T0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GnGyv/btroAAxvlWO/kHQHk5ZeLfYnxYTow344T0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGnGyv%2FbtroAAxvlWO%2FkHQHk5ZeLfYnxYTow344T0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1018&quot; data-filename=&quot;KakaoTalk_20211222_143753774.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20211222_143754790.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0UaUp/btrozwoztzx/BH8qNzk3GWpEgEqoRn76Ck/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0UaUp/btrozwoztzx/BH8qNzk3GWpEgEqoRn76Ck/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0UaUp/btrozwoztzx/BH8qNzk3GWpEgEqoRn76Ck/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0UaUp%2Fbtrozwoztzx%2FBH8qNzk3GWpEgEqoRn76Ck%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1018&quot; data-filename=&quot;KakaoTalk_20211222_143754790.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20211222_143755324.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwYeOV/btroDhqGpHr/qLeopkRhUsfwTpQ2euFTH1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwYeOV/btroDhqGpHr/qLeopkRhUsfwTpQ2euFTH1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwYeOV/btroDhqGpHr/qLeopkRhUsfwTpQ2euFTH1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwYeOV%2FbtroDhqGpHr%2FqLeopkRhUsfwTpQ2euFTH1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1018&quot; data-filename=&quot;KakaoTalk_20211222_143755324.jpg&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1018&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;그리고 그 땐 어려웠던 함수가 한 눈에 정리하고 보니&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>WEB/Node</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/108</guid>
      <comments>https://jonnastudy.tistory.com/108#entry108comment</comments>
      <pubDate>Tue, 28 Dec 2021 20:03:53 +0900</pubDate>
    </item>
    <item>
      <title>git 최초설정, git 레파지토리 생성 및 소스 올리기 (git bash)</title>
      <link>https://jonnastudy.tistory.com/107</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;github에서 원격 저장소를 만들고 난 후 , git bash로 push 하는 방법을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조 : &lt;a href=&quot;https://coding-factory.tistory.com/244&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://coding-factory.tistory.com/244&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640616343315&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;[Git] Git 레파지토리 생성 &amp;amp; 소스 올리기 (Git Bash활용)&quot; data-og-description=&quot;GitHub에서 원격저장소를 만든 뒤 Git Bash를 활용하여 Push하는 방법입니다. Git Repository생성 깃허브 바로가기 1. 위에 링크된 깃허브 사이트에가서 로그인을 합니다. (회원이 아니라면 회원가입을 해&quot; data-og-host=&quot;coding-factory.tistory.com&quot; data-og-source-url=&quot;https://coding-factory.tistory.com/244&quot; data-og-url=&quot;https://coding-factory.tistory.com/244&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/coAugi/hyMRxDb0iX/GKbp3od3u51sltJ170vs81/img.png?width=317&amp;amp;height=228&amp;amp;face=0_0_317_228,https://scrap.kakaocdn.net/dn/s4Oel/hyMRxb5vFH/svy23GrMKmX7Lk2c4JnbgK/img.png?width=317&amp;amp;height=228&amp;amp;face=0_0_317_228,https://scrap.kakaocdn.net/dn/bwTbY7/hyMRxXsiSt/WgXGkq7OqtivsAi8aQMgv1/img.png?width=651&amp;amp;height=537&amp;amp;face=0_0_651_537&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/244&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://coding-factory.tistory.com/244&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/coAugi/hyMRxDb0iX/GKbp3od3u51sltJ170vs81/img.png?width=317&amp;amp;height=228&amp;amp;face=0_0_317_228,https://scrap.kakaocdn.net/dn/s4Oel/hyMRxb5vFH/svy23GrMKmX7Lk2c4JnbgK/img.png?width=317&amp;amp;height=228&amp;amp;face=0_0_317_228,https://scrap.kakaocdn.net/dn/bwTbY7/hyMRxXsiSt/WgXGkq7OqtivsAi8aQMgv1/img.png?width=651&amp;amp;height=537&amp;amp;face=0_0_651_537');&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;[Git] Git 레파지토리 생성 &amp;amp; 소스 올리기 (Git Bash활용)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GitHub에서 원격저장소를 만든 뒤 Git Bash를 활용하여 Push하는 방법입니다. Git Repository생성 깃허브 바로가기 1. 위에 링크된 깃허브 사이트에가서 로그인을 합니다. (회원이 아니라면 회원가입을 해&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;coding-factory.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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. github 가입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640150376874&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub: Where the world builds software&quot; data-og-description=&quot;GitHub is where over 73 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/&quot; data-og-url=&quot;https://github.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cGNpco/hyMN6R5bMS/TvCny1KGkurhK5XM6bDqJk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dLjwbS/hyMN8h4ydf/kClBdpDx2FqhgbG5ILWZS0/img.png?width=2496&amp;amp;height=1480&amp;amp;face=0_0_2496_1480,https://scrap.kakaocdn.net/dn/bRt8VK/hyMOevPgiC/kLKhZL6YbdrrHrlktDbaF1/img.jpg?width=1238&amp;amp;height=1404&amp;amp;face=0_0_1238_1404&quot;&gt;&lt;a href=&quot;https://github.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cGNpco/hyMN6R5bMS/TvCny1KGkurhK5XM6bDqJk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dLjwbS/hyMN8h4ydf/kClBdpDx2FqhgbG5ILWZS0/img.png?width=2496&amp;amp;height=1480&amp;amp;face=0_0_2496_1480,https://scrap.kakaocdn.net/dn/bRt8VK/hyMOevPgiC/kLKhZL6YbdrrHrlktDbaF1/img.jpg?width=1238&amp;amp;height=1404&amp;amp;face=0_0_1238_1404');&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;GitHub: Where the world builds software&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GitHub is where over 73 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCKYzS/btro8wHals7/PdXLhpbjC9qzwWJOaeCnb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCKYzS/btro8wHals7/PdXLhpbjC9qzwWJOaeCnb1/img.png&quot; data-alt=&quot;new repository&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCKYzS/btro8wHals7/PdXLhpbjC9qzwWJOaeCnb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCKYzS%2Fbtro8wHals7%2FPdXLhpbjC9qzwWJOaeCnb1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;388&quot; height=&quot;402&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;new repository&lt;/figcaption&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;practice 레파토리지를 이용할거다 !&lt;/p&gt;
&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. git 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://git-scm.com/download/win&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://git-scm.com/download/win&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640158073226&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;Git - Downloading Package&quot; data-og-description=&quot;Downloading Git Now What? Now that you have downloaded Git, it's time to start using it.&quot; data-og-host=&quot;git-scm.com&quot; data-og-source-url=&quot;https://git-scm.com/download/win&quot; data-og-url=&quot;https://git-scm.com/download/win&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://git-scm.com/download/win&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://git-scm.com/download/win&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;Git - Downloading Package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Downloading Git Now What? Now that you have downloaded Git, it's time to start using it.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;git-scm.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cM3QlK/btrox2hkQRt/bQq6NHKLnKiU1nbbTRZVD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cM3QlK/btrox2hkQRt/bQq6NHKLnKiU1nbbTRZVD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cM3QlK/btrox2hkQRt/bQq6NHKLnKiU1nbbTRZVD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcM3QlK%2Fbtrox2hkQRt%2FbQq6NHKLnKiU1nbbTRZVD1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;402&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 IDE로 VSCode를 사용하기 때문에 이렇게 설정해주었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본으로 설정된 Vim을 그대로 설정해도 상관없다.&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; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5gOzh/btroYjoCHO5/ATYkbJTZ26hnHWBvHHQeK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5gOzh/btroYjoCHO5/ATYkbJTZ26hnHWBvHHQeK1/img.png&quot; data-alt=&quot;git 설치완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5gOzh/btroYjoCHO5/ATYkbJTZ26hnHWBvHHQeK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5gOzh%2FbtroYjoCHO5%2FATYkbJTZ26hnHWBvHHQeK1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;89&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;git 설치완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git이 설치가 완료되면 이렇게 Git 파일이 생긴다.&lt;/p&gt;
&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;3. git 최초 설정&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640693281599&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;Git - Git 최초 설정&quot; data-og-description=&quot;Vim과 Emacs, Notepad++은 꽤 인기 있는 편집기로 개발자들이 즐겨 사용한다. Mac이나 Linux 같은 Unix 시스템, Windows 시스템에서 사용 가능하다. 여기서 소개하는 편집기들이 불편해서 다른 편집기를 사&quot; data-og-host=&quot;git-scm.com&quot; data-og-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-Git-%EC%B5%9C%EC%B4%88-%EC%84%A4%EC%A0%95&quot; data-og-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-Git-%EC%B5%9C%EC%B4%88-%EC%84%A4%EC%A0%95&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-Git-%EC%B5%9C%EC%B4%88-%EC%84%A4%EC%A0%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-Git-%EC%B5%9C%EC%B4%88-%EC%84%A4%EC%A0%95&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;Git - Git 최초 설정&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vim과 Emacs, Notepad++은 꽤 인기 있는 편집기로 개발자들이 즐겨 사용한다. Mac이나 Linux 같은 Unix 시스템, Windows 시스템에서 사용 가능하다. 여기서 소개하는 편집기들이 불편해서 다른 편집기를 사&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;git-scm.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git config&lt;/b&gt;라는 도구로 git의 환경 설정 내용을 확인하고 변경할 수 있다.&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;b&gt;(1) /etc/gitconfig 파일&lt;/b&gt; : 시스템의 &lt;u&gt;모든&lt;/u&gt; 사용자와 &lt;u&gt;모든&lt;/u&gt; 저장소에 적용되는 설정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #006dd7;&quot;&gt;git config --System&lt;/span&gt; 옵션으로 이 파일을 읽고 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; (&lt;span&gt;&amp;nbsp;&lt;/span&gt;※시스템 전체 설정파일이기 때문에 수정하려면 관리자 권한이 필요 )&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2mzIK/btro8wVwGMC/o2UVmKIHwnxaReGUbw0tm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2mzIK/btro8wVwGMC/o2UVmKIHwnxaReGUbw0tm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2mzIK/btro8wVwGMC/o2UVmKIHwnxaReGUbw0tm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2mzIK%2Fbtro8wVwGMC%2Fo2UVmKIHwnxaReGUbw0tm0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;350&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;350&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;b&gt;(2) ~/.gitconfig, ~/.config/git/config 파일&lt;/b&gt; : &lt;u&gt;특정&lt;/u&gt; 사용자&lt;span style=&quot;color: #009a87;&quot;&gt;(현재 사용자)&lt;/span&gt;에게만 적용되는 설정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #006dd7;&quot;&gt;git config --global&lt;/span&gt; 옵션으로 이 파일을 읽고 쓸 수 있다. &lt;u&gt;특정&lt;/u&gt; 사용자의 &lt;u&gt;모든&lt;/u&gt; 저장소 설정에 적용된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;515&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYPmON/btrpaI2xsGS/jtKE2iSz6hr8kMmKeiYH6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYPmON/btrpaI2xsGS/jtKE2iSz6hr8kMmKeiYH6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYPmON/btrpaI2xsGS/jtKE2iSz6hr8kMmKeiYH6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYPmON%2FbtrpaI2xsGS%2FjtKE2iSz6hr8kMmKeiYH6K%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;157&quot; data-origin-width=&quot;515&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3) .git/config 파일&lt;/b&gt; : git디렉토리에 존재하고, 특정 저장소&lt;span style=&quot;color: #009a87;&quot;&gt;(현재 작업중인 프로젝트)&lt;/span&gt;에만 적용되는 설정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #006dd7;&quot;&gt;--local &lt;/span&gt;옵션을 사용하면 이 파일을 사용하도록 지정할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TXZmQ/btrpeItVcp8/IWRifnSJ0d8ej5ggKUdeMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TXZmQ/btrpeItVcp8/IWRifnSJ0d8ej5ggKUdeMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TXZmQ/btrpeItVcp8/IWRifnSJ0d8ej5ggKUdeMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTXZmQ%2FbtrpeItVcp8%2FIWRifnSJ0d8ej5ggKUdeMK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;626&quot; height=&quot;283&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 설정의 우선 순위 : (3) &lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;gt;&lt;/span&gt; (2) &lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;gt;&lt;/span&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;b&gt;4. git bash 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git bash는&amp;nbsp;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;i&gt;내가 github에 올리고자 하는 폴더(소스폴더)&lt;/i&gt;&lt;/span&gt;에서 실행시키면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blzbvU/btrpeIHuruL/CINgxFtIjWCCoxcPt9jBB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blzbvU/btrpeIHuruL/CINgxFtIjWCCoxcPt9jBB0/img.png&quot; data-alt=&quot;화질 뎨동&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blzbvU/btrpeIHuruL/CINgxFtIjWCCoxcPt9jBB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblzbvU%2FbtrpeIHuruL%2FCINgxFtIjWCCoxcPt9jBB0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;313&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;313&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;b&gt;Git Bash Here&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctYhDU/btro8x0lgUg/VThB0879imk206vKUJSaSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctYhDU/btro8x0lgUg/VThB0879imk206vKUJSaSK/img.png&quot; data-alt=&quot;깃 버전 확인(설치 확인)&amp;amp;amp;nbsp;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctYhDU/btro8x0lgUg/VThB0879imk206vKUJSaSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctYhDU%2Fbtro8x0lgUg%2FVThB0879imk206vKUJSaSK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;586&quot; height=&quot;226&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;깃 버전 확인(설치 확인)&amp;amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git --version &lt;/span&gt;명령어를 이용해 git이 제대로 설치되었는지 확인한다.&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;git을 설치하고 나서 가장 먼저 해야되는 것은 &lt;u&gt;사용자이름과 이메일 주소를 설정&lt;/u&gt;하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git은 commit 할 때마다 이 정보를 사용한다. 한 번 커밋한 후에는 정보를 &lt;u&gt;변경할 수 없다&lt;/u&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #000000; color: #ffffff;&quot;&gt;$git config --global user.name &quot;suinee&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #000000; color: #ffffff;&quot;&gt;$git config --global user.email suinee@example.com&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--global&lt;/span&gt; 옵션으로 설정하는 것은 딱 한 번만 하면 된다는 것이다. 만약 프로젝트마다 다른 이름과 이메일 주소를 사용하고 싶으면 이 옵션을 빼고 명령을 실행하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 &lt;u&gt;github와 동일한&lt;/u&gt; 사용자이름과 이메일 주소를 설정해주면 github와 연동된다.&lt;/p&gt;
&lt;p data-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;git config --list &lt;/span&gt;명령어를 통해 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLHw4x/btrpffSJomb/SKkPhkxcTTV32kdHVtCj9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLHw4x/btrpffSJomb/SKkPhkxcTTV32kdHVtCj9k/img.png&quot; data-alt=&quot;ㅇcmd창으로도 git 명령어 사용 가능 !&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLHw4x/btrpffSJomb/SKkPhkxcTTV32kdHVtCj9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLHw4x%2FbtrpffSJomb%2FSKkPhkxcTTV32kdHVtCj9k%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;349&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ㅇcmd창으로도 git 명령어 사용 가능 !&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git config &amp;lt;key&amp;gt;&lt;/span&gt;명령으로 특정 key에 대해 어떤 값을 사용하는지 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfpu8d/btrpcQzfEXb/bu2qpi0jewuoEX57QMSl61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfpu8d/btrpcQzfEXb/bu2qpi0jewuoEX57QMSl61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfpu8d/btrpcQzfEXb/bu2qpi0jewuoEX57QMSl61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfpu8d%2FbtrpcQzfEXb%2Fbu2qpi0jewuoEX57QMSl61%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;394&quot; height=&quot;58&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;58&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;b&gt;(1) $git init&lt;/b&gt; - 로컬 저장소 만들기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c433zm/btroTd36Yxm/pShiVD0mZ3PL6y6HcyGojk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c433zm/btroTd36Yxm/pShiVD0mZ3PL6y6HcyGojk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c433zm/btroTd36Yxm/pShiVD0mZ3PL6y6HcyGojk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc433zm%2FbtroTd36Yxm%2FpShiVD0mZ3PL6y6HcyGojk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;55&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2) $git status&lt;/b&gt; - 올라갈 파일이 있는지 현재 폴더에 있는 파일들을 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdDVVL/btro3095o0d/jG2kzhgcB8J5Bx7HKfqF1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdDVVL/btro3095o0d/jG2kzhgcB8J5Bx7HKfqF1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdDVVL/btro3095o0d/jG2kzhgcB8J5Bx7HKfqF1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdDVVL%2Fbtro3095o0d%2FjG2kzhgcB8J5Bx7HKfqF1k%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;633&quot; height=&quot;67&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 두번째 시도여서 지금은 commit할 게 없다고 뜨지만,&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;(3) $git add .&lt;/b&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;(&amp;lt;-add와 . 사이에 &lt;b&gt;공백&lt;/b&gt;있음) &lt;span style=&quot;color: #000000;&quot;&gt;- 로컬 저장소에 파일을 올려준다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/INysw/btro8wNVYaw/fFXxtz1kjVnVCv55N8iPuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/INysw/btro8wNVYaw/fFXxtz1kjVnVCv55N8iPuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/INysw/btro8wNVYaw/fFXxtz1kjVnVCv55N8iPuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FINysw%2Fbtro8wNVYaw%2FfFXxtz1kjVnVCv55N8iPuK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;689&quot; height=&quot;33&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 파일을 push 할 것이기 때문에 . 을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 파일만 업로드 하고 싶으면 -&amp;gt; &lt;b&gt;add [파일명]or[폴더명]&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;(4) $git commit -m &quot;init commit&quot;&lt;/b&gt; - push시 원하는 메시지(init commit)를 등록하고 &lt;span style=&quot;color: #ee2323;&quot;&gt;commit&lt;/span&gt; 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;417&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkZ8wp/btro9H2OHNM/Q9KiDMIiRCyiWEUtcgFl0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkZ8wp/btro9H2OHNM/Q9KiDMIiRCyiWEUtcgFl0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkZ8wp/btro9H2OHNM/Q9KiDMIiRCyiWEUtcgFl0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkZ8wp%2Fbtro9H2OHNM%2FQ9KiDMIiRCyiWEUtcgFl0k%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;653&quot; height=&quot;32&quot; data-origin-width=&quot;417&quot; data-origin-height=&quot;32&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;b&gt;(5) $git remote add origin [레퍼토리지 주&lt;b&gt;소]&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSjLk6/btroXMY5hNS/X7EABNTWWA2XSrbSrgqut0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSjLk6/btroXMY5hNS/X7EABNTWWA2XSrbSrgqut0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSjLk6/btroXMY5hNS/X7EABNTWWA2XSrbSrgqut0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSjLk6%2FbtroXMY5hNS%2FX7EABNTWWA2XSrbSrgqut0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;641&quot; height=&quot;33&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pC4Ux/btro8v9j0iL/aOZ59G4rhKVl3wYvfwBly0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pC4Ux/btro8v9j0iL/aOZ59G4rhKVl3wYvfwBly0/img.png&quot; data-alt=&quot;깃허브에서 레퍼토리지 주소 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pC4Ux/btro8v9j0iL/aOZ59G4rhKVl3wYvfwBly0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpC4Ux%2Fbtro8v9j0iL%2FaOZ59G4rhKVl3wYvfwBly0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1866&quot; height=&quot;386&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;386&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;&lt;b&gt;(6) $git remote -v&lt;/b&gt; - 로컬 저장소가 원격 저장소로 연결된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CVsNO/btro31gP44Q/duGAnd2oMKFIJxn1NrjqY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CVsNO/btro31gP44Q/duGAnd2oMKFIJxn1NrjqY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CVsNO/btro31gP44Q/duGAnd2oMKFIJxn1NrjqY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCVsNO%2Fbtro31gP44Q%2FduGAnd2oMKFIJxn1NrjqY0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;626&quot; height=&quot;96&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;96&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;b&gt;(7) git push origin master&lt;/b&gt; - 아까&lt;span style=&quot;color: #ee2323;&quot;&gt; commit&lt;/span&gt;한 파일들을 원격저장소에 올린다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cB2UFi/btroT5dYser/mnk9P5WxxVJuyp77aXK6mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cB2UFi/btroT5dYser/mnk9P5WxxVJuyp77aXK6mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cB2UFi/btroT5dYser/mnk9P5WxxVJuyp77aXK6mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcB2UFi%2FbtroT5dYser%2Fmnk9P5WxxVJuyp77aXK6mK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;172&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;172&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;( + 추가적인 git 명령어에 대한 도움말 : &lt;a href=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&lt;/a&gt; )&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640700541526&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;Git - 도움말 보기&quot; data-og-description=&quot;도움말은 언제 어디서나 볼 수 있다. 오프라인으로도 볼 수 있다. 도움말과 이 책으로 부족하면 다른 사람의 도움을 받는 것이 필요하다. Freenode IRC 서버(irc.freenode.net)에 있는 #git 이나 #github 채널&quot; data-og-host=&quot;git-scm.com&quot; data-og-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&quot; data-og-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%8F%84%EC%9B%80%EB%A7%90-%EB%B3%B4%EA%B8%B0&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;Git - 도움말 보기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;도움말은 언제 어디서나 볼 수 있다. 오프라인으로도 볼 수 있다. 도움말과 이 책으로 부족하면 다른 사람의 도움을 받는 것이 필요하다. Freenode IRC 서버(irc.freenode.net)에 있는 #git 이나 #github 채널&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;git-scm.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;color: #009a87;&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;&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;[does not have a commit cheked out 에러]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밑의 사이트를 이용하여 해결한 에러이다.&lt;/p&gt;
&lt;figure id=&quot;og_1640614443977&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;깃허브) does not have a commit checked out 에러 해결방법&quot; data-og-description=&quot;이 에러는 해당 로컬 리포지토리 안의 다른 디렉토리(폴더)에 .git이 있기 때문에 발생하는 현상입니다 흔히 한개의 폴더 안에 여러 개의 프로젝트를 넣어서 관리하는데 이때 최상위 폴터에 로컬&quot; data-og-host=&quot;mmol.tistory.com&quot; data-og-source-url=&quot;https://mmol.tistory.com/entry/%EA%B9%83%ED%97%88%EB%B8%8C-does-not-have-a-commit-checked-out-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95&quot; data-og-url=&quot;https://mmol.tistory.com/entry/%EA%B9%83%ED%97%88%EB%B8%8C-does-not-have-a-commit-checked-out-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bfLXfR/hyMRE3lWqt/neLBzhLba88YdQwZjFKYxK/img.png?width=800&amp;amp;height=89&amp;amp;face=0_0_800_89,https://scrap.kakaocdn.net/dn/lVbKC/hyMREWBR42/2z0xDBdM2xucgMKpKlacQk/img.png?width=800&amp;amp;height=89&amp;amp;face=0_0_800_89&quot;&gt;&lt;a href=&quot;https://mmol.tistory.com/entry/%EA%B9%83%ED%97%88%EB%B8%8C-does-not-have-a-commit-checked-out-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mmol.tistory.com/entry/%EA%B9%83%ED%97%88%EB%B8%8C-does-not-have-a-commit-checked-out-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bfLXfR/hyMRE3lWqt/neLBzhLba88YdQwZjFKYxK/img.png?width=800&amp;amp;height=89&amp;amp;face=0_0_800_89,https://scrap.kakaocdn.net/dn/lVbKC/hyMREWBR42/2z0xDBdM2xucgMKpKlacQk/img.png?width=800&amp;amp;height=89&amp;amp;face=0_0_800_89');&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;깃허브) does not have a commit checked out 에러 해결방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 에러는 해당 로컬 리포지토리 안의 다른 디렉토리(폴더)에 .git이 있기 때문에 발생하는 현상입니다 흔히 한개의 폴더 안에 여러 개의 프로젝트를 넣어서 관리하는데 이때 최상위 폴터에 로컬&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mmol.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 처음에 git bash를 소스코드에서 실행해야하는 것을 모르고 여기저기서 시작하다 보니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치된 .git 파일들이 많다 ㅋㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숨김파일까지 보이도록 설정한 다음에 .git 을 검색한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cz7BTz/btroXOigcyV/pKyE2fNU5oPY338sBlmCNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cz7BTz/btroXOigcyV/pKyE2fNU5oPY338sBlmCNk/img.png&quot; data-alt=&quot;보기&amp;amp;amp;gt;표시/숨기기&amp;amp;amp;gt;숨김항목 체크 후 검색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cz7BTz/btroXOigcyV/pKyE2fNU5oPY338sBlmCNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcz7BTz%2FbtroXOigcyV%2FpKyE2fNU5oPY338sBlmCNk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1027&quot; height=&quot;363&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보기&amp;amp;gt;표시/숨기기&amp;amp;gt;숨김항목 체크 후 검색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 사용할 소스코드 외의 다른 위치에 있는 .git을 제거해준다.&lt;/p&gt;
&lt;p data-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;[origin does not appear to be a git repository 에러]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;밑의 사이트를 이용하여 에러를 해결하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 에러 발생의 원인은...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기억이 안난다... 따흑.. 시간이 좀 지난 거여서 ..&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1640616463284&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;git push error : fatal: 'origin' does not appear to be a git repository ...&quot; data-og-description=&quot;노트북 여러대로 커밋을 하다 보니 (주기적 포멧도 진행) 해당 오류가 너무 많이나와 글로 남깁니다. fatal: 'origin' does not appear to be a git repository fatal: Could not read from remote repository. P..&quot; data-og-host=&quot;integer-ji.tistory.com&quot; data-og-source-url=&quot;https://integer-ji.tistory.com/312&quot; data-og-url=&quot;https://integer-ji.tistory.com/312&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dFZ7lz/hyMRJRbwgn/sP67G9eodq3u1VfVvXL8Mk/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346,https://scrap.kakaocdn.net/dn/b6kauQ/hyMRJRbwiG/JAJPnmjiUeR39GhG8ZUXT1/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346,https://scrap.kakaocdn.net/dn/c6eBuZ/hyMRz16dTZ/fAa8We5uTX4EwrtJKof2H0/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346&quot;&gt;&lt;a href=&quot;https://integer-ji.tistory.com/312&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://integer-ji.tistory.com/312&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dFZ7lz/hyMRJRbwgn/sP67G9eodq3u1VfVvXL8Mk/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346,https://scrap.kakaocdn.net/dn/b6kauQ/hyMRJRbwiG/JAJPnmjiUeR39GhG8ZUXT1/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346,https://scrap.kakaocdn.net/dn/c6eBuZ/hyMRz16dTZ/fAa8We5uTX4EwrtJKof2H0/img.png?width=736&amp;amp;height=346&amp;amp;face=0_0_736_346');&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;git push error : fatal: 'origin' does not appear to be a git repository ...&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;노트북 여러대로 커밋을 하다 보니 (주기적 포멧도 진행) 해당 오류가 너무 많이나와 글로 남깁니다. fatal: 'origin' does not appear to be a git repository fatal: Could not read from remote repository. P..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;integer-ji.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;b&gt;&amp;lt;결과&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1283&quot; data-origin-height=&quot;732&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lJaP9/btroYjhSr7z/oNw46eaOuuUeK2VrXuJpDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lJaP9/btroYjhSr7z/oNw46eaOuuUeK2VrXuJpDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lJaP9/btroYjhSr7z/oNw46eaOuuUeK2VrXuJpDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlJaP9%2FbtroYjhSr7z%2FoNw46eaOuuUeK2VrXuJpDk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1283&quot; height=&quot;732&quot; data-origin-width=&quot;1283&quot; data-origin-height=&quot;732&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레파토리지에 파일들이 잘 업로드 된 것을 확인할 수 있다 :)&lt;/p&gt;</description>
      <category>SCM/GIT</category>
      <category>GIT</category>
      <category>gitbash</category>
      <category>github</category>
      <category>깃레퍼토리지</category>
      <category>깃명령어</category>
      <category>깃설정</category>
      <category>깃시작하기</category>
      <category>깃허브</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/107</guid>
      <comments>https://jonnastudy.tistory.com/107#entry107comment</comments>
      <pubDate>Tue, 28 Dec 2021 00:26:32 +0900</pubDate>
    </item>
    <item>
      <title>버전 관리, Git 기초</title>
      <link>https://jonnastudy.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;출처 : pro git - &lt;a href=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639920417478&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;Git - 버전 관리란?&quot; data-og-description=&quot;1.1 시작하기 - 버전 관리란? 이 장에서 설명하는 것은 Git을 처음 접하는 사람에게 필요한 내용이다. 먼저 버전 관리 도구에 대한 이해와 Git을 설치하는 방법을 설명하고 마지막으로 Git 서버를 설&quot; data-og-host=&quot;git-scm.com&quot; data-og-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&quot; data-og-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F&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;Git - 버전 관리란?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1.1 시작하기 - 버전 관리란? 이 장에서 설명하는 것은 Git을 처음 접하는 사람에게 필요한 내용이다. 먼저 버전 관리 도구에 대한 이해와 Git을 설치하는 방법을 설명하고 마지막으로 Git 서버를 설&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;git-scm.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;b&gt;▶&amp;nbsp;버전 관리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;버전 관리 시스템&lt;/b&gt;(&lt;span style=&quot;color: #009a87;&quot;&gt;Version Control System, VCS&lt;/span&gt;)은 파일의 변화를 시간에 따라 기록하여 과거 특정 시점의 버전을 다시 불러올 수 있는 시스템이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- VCS를 사용하면 개별 파일or프로젝트 전체를 이전 상태로 되돌리거나 시간에 따른 변경 사항을 검토 가능하고, 파일을 쉽게 복구할 수 있다.&lt;/p&gt;
&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;&amp;middot; 로컬 버전 관리 시스템&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;- 어느 디렉토리에서 작업하고 있었는지 까먹고 엉뚱한 파일을 덮어쓰거나 의도치 않았던 위치로 복사하는 실수를 해결해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파일을 관리하는 서버가 별도로 있고, 클라이언트가 중앙 서버에서 파일을 받아서 사용(&lt;span style=&quot;color: #009a87;&quot;&gt;checkout&lt;/span&gt;)한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oj98d/btronKzhfgb/CM6R58DOyvjnCTWFsgbeD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oj98d/btronKzhfgb/CM6R58DOyvjnCTWFsgbeD0/img.png&quot; data-alt=&quot;로컬 버전 관리 (출처: https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oj98d/btronKzhfgb/CM6R58DOyvjnCTWFsgbeD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOj98d%2FbtronKzhfgb%2FCM6R58DOyvjnCTWFsgbeD0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;683&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로컬 버전 관리 (출처: https://git-scm.com/book/ko/v2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 많이 쓰는 VCS 도구 중 &lt;b&gt;RCS&lt;/b&gt;(&lt;span style=&quot;color: #009a87;&quot;&gt;Revision Contrl System&lt;/span&gt;) : 각 revision들 간의 &lt;span style=&quot;color: #009a87;&quot;&gt;patch 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;b&gt;&amp;middot; 중앙집중식 버전 관리(CVCS)&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;- 모두 누가 무엇을 하고 있는지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 클라이언트의 로컬 데이터베이스를 관리&lt;span style=&quot;color: #ee2323;&quot;&gt; &amp;lt;&lt;/span&gt;&amp;nbsp; VCS 하나를 관리&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WzGxX/btrogvX0C5D/hingEv3zReMVkoPMzZN2dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WzGxX/btrogvX0C5D/hingEv3zReMVkoPMzZN2dk/img.png&quot; data-alt=&quot;&amp;amp;nbsp;중앙집중식 버전 관리 (출처:https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WzGxX/btrogvX0C5D/hingEv3zReMVkoPMzZN2dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWzGxX%2FbtrogvX0C5D%2FhingEv3zReMVkoPMzZN2dk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;556&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;nbsp;중앙집중식 버전 관리 (출처:https://git-scm.com/book/ko/v2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; 분산 버전 관리 시스템 (DVCS)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라이언트는 히스토리를 포함한 저장소를 &lt;u&gt;전부&lt;/u&gt; 복제하여 checkout한다.&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;span style=&quot;color: #009a87;&quot;&gt;clone&lt;/span&gt;은 모든 데이터를 가진 진정한 백업이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 대부분의 DVCS 환경에서는 리모트 저장소가 존재한다 &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; 협업 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;color: #006dd7;&quot;&gt;git, mecurial, bazaar, darcs&lt;/span&gt; 등&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAWkF1/btrokrAx3KS/lGNxo6JyIlqBtBcBXKM0Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAWkF1/btrokrAx3KS/lGNxo6JyIlqBtBcBXKM0Gk/img.png&quot; data-alt=&quot;분산버전관리 시스템 (출처: https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAWkF1/btrokrAx3KS/lGNxo6JyIlqBtBcBXKM0Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAWkF1%2FbtrokrAx3KS%2FlGNxo6JyIlqBtBcBXKM0Gk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;668&quot; height=&quot;800&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;분산버전관리 시스템 (출처: https://git-scm.com/book/ko/v2)&lt;/figcaption&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;b&gt;▶ Git 기초&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;&amp;middot; VCS시스템의 대부분&lt;/b&gt;(&lt;span style=&quot;color: #006dd7;&quot;&gt;CVS,&amp;nbsp; Subversion, Preforce, Bazaar&lt;/span&gt; 등)&lt;b&gt;의&amp;nbsp;데이터를 다루는 방법&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;- 각 파일의 변화를 시간순으로 관리하면서 파일들의 집합을 관리한다(&lt;span style=&quot;color: #009a87;&quot;&gt;델타 기반&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/epffLF/btroezfkkHF/aEf6kTKIQqU8keTiVnpXb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/epffLF/btroezfkkHF/aEf6kTKIQqU8keTiVnpXb0/img.png&quot; data-alt=&quot;대부분의 VCS시스템&amp;amp;nbsp;(출처: https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/epffLF/btroezfkkHF/aEf6kTKIQqU8keTiVnpXb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FepffLF%2FbtroezfkkHF%2FaEf6kTKIQqU8keTiVnpXb0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;310&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;대부분의 VCS시스템&amp;nbsp;(출처: https://git-scm.com/book/ko/v2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot;&lt;span&gt; Git의&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&amp;nbsp;데이터를 다루는 방법&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;- &lt;a title=&quot;commit&quot; href=&quot;https://backlog.com/git-tutorial/kr/intro/intro1_3.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;&lt;/a&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;u&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckaTk4/btrogwvPFtI/Q1zk4Ec9W29WYqGPxIzzKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckaTk4/btrogwvPFtI/Q1zk4Ec9W29WYqGPxIzzKK/img.png&quot; data-alt=&quot;Git&amp;amp;nbsp;(출처: https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckaTk4/btrogwvPFtI/Q1zk4Ec9W29WYqGPxIzzKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckaTk4%2FbtrogwvPFtI%2FQ1zk4Ec9W29WYqGPxIzzKK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;305&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Git&amp;nbsp;(출처: https://git-scm.com/book/ko/v2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot;&lt;span&gt;&lt;span&gt; Git 브랜치를 사용하면 얻게 되는 이득&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&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;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; 오프라인 상태이거나 VPN에 연결하지 못해도 작업을 할 수 있고, &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;도 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;무결성&lt;/b&gt; : 데이터를 저장하기 전에 항상 &lt;a title=&quot;checksum&quot; href=&quot;https://ko.wikipedia.org/wiki/%EC%B2%B4%ED%81%AC%EC%84%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;checksum&lt;/span&gt;&lt;/a&gt;(40자 길이의 16진수 문자열)을 구하고 그 &lt;span style=&quot;color: #009a87;&quot;&gt;checksum&lt;/span&gt;으로 데이터를 관리한다. SHA-1해시&lt;span style=&quot;color: #006dd7;&quot;&gt;(ex.24b9da6552252987aa493b52f8696cd6d3b00373)&lt;/span&gt;를 사용하여 파일내용이나 디렉토리 구조를 이용해 &lt;span style=&quot;color: #009a87;&quot;&gt;checksum&lt;/span&gt;을 구한다. git에서 사용하는 가장 기본적인 데이터 단위이자 기본철학이 &lt;span style=&quot;color: #009a87;&quot;&gt;checksum&lt;/span&gt;이기 때문에, 이것 없이는 어떠한 파일이나 디렉토리로 변경 할 수 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;데이터의 추가만&lt;/b&gt; : git으로 무엇을 하든 데이터베이스에 데이터가 &lt;u&gt;추가&lt;/u&gt;된다(데이터를 삭제할 방법 &lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt;) 일단 스냅샷을 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;하고 나면 데이터를 잃어비리기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;세가지 상태&lt;/span&gt;&lt;/b&gt; : git은 파일을 세 가지 상태(-&amp;gt;&lt;span style=&quot;color: #009a87;&quot;&gt;committed, modified, staged&lt;/span&gt;)로 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; (1) &lt;b&gt;committed&lt;/b&gt; : 데이터가 로컬 데이터베이스에 안전하게 저장됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; (2) &lt;b&gt;modified&lt;/b&gt; : 수정한 파일을 아직 로컬 데이터베이스에 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;하지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; (3) &lt;b&gt;staged&lt;/b&gt; : 현재 수정한 파일을 곧 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;할 거라고 표시한 상태&lt;/p&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;u&gt;git 프로젝트의 세가지 단계&lt;/u&gt;(-&amp;gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git 디렉토리, 워킹 트리, staging area&lt;/span&gt;)와 연결되어 있다.&lt;/p&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;b&gt;▷git 프로젝트 세 단계&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; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pMO9S/btrolTqeatC/NOUAO3TH8gdg0MlSlAkgjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pMO9S/btrolTqeatC/NOUAO3TH8gdg0MlSlAkgjk/img.png&quot; data-alt=&quot;git 프로젝트의 세가지 단계 (출처: https://git-scm.com/book/ko/v2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pMO9S/btrolTqeatC/NOUAO3TH8gdg0MlSlAkgjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpMO9S%2FbtrolTqeatC%2FNOUAO3TH8gdg0MlSlAkgjk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;441&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;441&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;git 프로젝트의 세가지 단계 (출처: https://git-scm.com/book/ko/v2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - &lt;b&gt;git 디렉토리&lt;/b&gt; : git이 프로젝트의 메타데이터와 객체데이터베이스를 저장하는 곳. git의 핵심이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 다른 컴퓨터에 있는 저장소를 &lt;span style=&quot;color: #009a87;&quot;&gt;clone&lt;/span&gt;할 때 만들어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -&lt;b&gt;&amp;nbsp;워킹 트리&lt;/b&gt; : 프로젝트의 특정 버전을 &lt;span style=&quot;color: #009a87;&quot;&gt;checkout&lt;/span&gt;한 것.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt; -&amp;gt;&lt;/span&gt; git 디렉토리는 &lt;u&gt;지금 작업하는 디스크&lt;/u&gt;에 있고, 그 디렉토리 안에 압축된 데이터베이스에서 파일을 가져와서 워킹트리를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - &lt;b&gt;staging area&lt;/b&gt; : git 디렉토리에 있다. 단순한 파일이다. 곧 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&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;b&gt;▷git이 기본적으로 하는 일&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;워킹 트리&lt;/span&gt;&lt;/b&gt;에서 파일을 수정한다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;gt;modified&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;staging area&lt;/span&gt;&lt;/b&gt;에 파일을 stage해서 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;할 스냅샷을 만든다(모든 파일 추가 &lt;span style=&quot;color: #ee2323;&quot;&gt;or&lt;/span&gt; 선택하여 추가) &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;gt;staged&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;staging area&lt;/span&gt;&lt;/b&gt;에 있는 파일들을 &lt;span style=&quot;color: #009a87;&quot;&gt;commit&lt;/span&gt;해서 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git 디렉토리&lt;/span&gt;&lt;/b&gt;에 영구적인 스냅샷으로 저장한다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;gt;committed&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;</description>
      <category>SCM/GIT</category>
      <category>GIT</category>
      <category>git기초</category>
      <category>버전관리</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/106</guid>
      <comments>https://jonnastudy.tistory.com/106#entry106comment</comments>
      <pubDate>Mon, 20 Dec 2021 13:59:17 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기 - Post-User 관계 만들기 (1) 게시물에 작성자 만들기</title>
      <link>https://jonnastudy.tistory.com/105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;게시물과 사용자 사이에 관계(relationship)을 만들어서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시물(document)에 작성자(document 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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; schema 수정&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceiEWQ/btrocTZerqy/AwCeUjbvjCCYP2KTgi0tv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceiEWQ/btrocTZerqy/AwCeUjbvjCCYP2KTgi0tv1/img.png&quot; data-alt=&quot;post schema&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceiEWQ/btrocTZerqy/AwCeUjbvjCCYP2KTgi0tv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceiEWQ%2FbtrocTZerqy%2FAwCeUjbvjCCYP2KTgi0tv1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;901&quot; height=&quot;380&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;post schema&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post schema에 &lt;b&gt;author&lt;/b&gt;을 추가하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ref: 'user'&lt;/b&gt;를 통해 이 항목의 데이터가 user collection의 id와 연결됨을 mongoose에 알린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user의 user.id와 post의 post.author가 연결되어 user과 post의 relationship이 형성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 참조하기 좋은 글 : &lt;a href=&quot;https://catnap-jo.tistory.com/entry/Mongoose-%EB%AA%A8%EB%A5%B4%EB%8A%94-%EA%B2%83-%EC%B1%84%EC%9B%8C%EB%86%93%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://catnap-jo.tistory.com/entry/Mongoose-%EB%AA%A8%EB%A5%B4%EB%8A%94-%EA%B2%83-%EC%B1%84%EC%9B%8C%EB%86%93%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639900497171&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;Mongoose - 모르는 것  채워놓기&quot; data-og-description=&quot;스키마의 옵션(Schema's option) mongoose에서 스키마를 선언하는 과정에서 사용할 수 있는 옵션들이 존재한다. autoIndex bufferCommands capped collection emitIndexErrors id [id](#id) minimize read safe sh..&quot; data-og-host=&quot;catnap-jo.tistory.com&quot; data-og-source-url=&quot;https://catnap-jo.tistory.com/entry/Mongoose-%EB%AA%A8%EB%A5%B4%EB%8A%94-%EA%B2%83-%EC%B1%84%EC%9B%8C%EB%86%93%EA%B8%B0&quot; data-og-url=&quot;https://catnap-jo.tistory.com/19&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cutKpz/hyMKPpxfQG/tAkYkc94jTh2Iimi6Q5zpk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/T8A4O/hyMKHSy42g/kgIDfhV4HSM2CpeME1RXZk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://catnap-jo.tistory.com/entry/Mongoose-%EB%AA%A8%EB%A5%B4%EB%8A%94-%EA%B2%83-%EC%B1%84%EC%9B%8C%EB%86%93%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://catnap-jo.tistory.com/entry/Mongoose-%EB%AA%A8%EB%A5%B4%EB%8A%94-%EA%B2%83-%EC%B1%84%EC%9B%8C%EB%86%93%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cutKpz/hyMKPpxfQG/tAkYkc94jTh2Iimi6Q5zpk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/T8A4O/hyMKHSy42g/kgIDfhV4HSM2CpeME1RXZk/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;Mongoose - 모르는 것 채워놓기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스키마의 옵션(Schema's option) mongoose에서 스키마를 선언하는 과정에서 사용할 수 있는 옵션들이 존재한다. autoIndex bufferCommands capped collection emitIndexErrors id [id](#id) minimize read safe sh..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;catnap-jo.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;b&gt;&amp;middot; post.js 수정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1639901403933&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//routes/post.js

const express  = require('express');
const router = express.Router();
const Post = require('../models/Post');
const util=require('../util');

// Index 
router.get('/', function(req, res){
  Post.find({})       
  .populate('author')
  .sort('-createdAt')            
  .exec(function(err, posts){    
    if(err) return res.json(err);
    res.render('posts/index', {posts:posts});
  });
});

// New
router.get('/new', function(req, res){
  const post=req.flash('post')[0]||{};
  const errors=req.flash('errors')[0]||{};
  res.render('posts/new',{post:post, errors:errors});
});

// create
router.post('/', function(req, res){
  req.body.author = req.user._id;
  Post.create(req.body, function(err, post){
    if(err){
      req.flash('post',req.body);
      req.flash('errors',util.parseError(err));
      return res.redirect('/posts/new');
    }
    res.redirect('/posts');
  });
});

// show
router.get('/:id', function(req, res){
  Post.findOne({_id:req.params.id})
  .populate('author')            
  .exec(function(err, post){     
    if(err) return res.json(err);
    res.render('posts/show', {post:post});
  });
});

// edit
router.get('/:id/edit', function(req, res){
  const post=req.flash('post')[0];
  const errors=req.flash('errors')[0]||{};
  if(!post){
    Post.findOne({_id:req.params.id},function(err,post){
      if(err) return res.json(err);
      res.render('post/edit',{post:post, errors:errors});
    })
  }
  else{
    post._id=req.params.id;
    res.render('posts/edit',{post:post, errors:errors});
  }
});

// update
router.put('/:id', function(req, res){
  req.body.updatedAt = Date.now();
  Post.findOneAndUpdate({_id:req.params.id}, req.body, {runValidators:true}, function(err, post){
    if(err) {
      req.flash('post',req.body)
      req.flash('errors',util.parseError(err))
      return res.redirect('/posts'+req.params.id+'/edit')
    }
    res.redirect(&quot;/posts/&quot;+req.params.id);
  });
});

// destroy
router.delete('/:id', function(req, res){
  Post.deleteOne({_id:req.params.id}, function(err){
    if(err) return res.json(err);
    res.redirect('/posts');
  });
});

module.exports = router;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Post(Model)&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;populate&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'author'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Model.population( )&lt;/b&gt;함수는 relationship이 형성되어 있는 항목의 값을 생성해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;현재 post의 author에는 user의 id가 기록되어 있는데, 이 값을 바탕으로 실제 user의 값을 author에 생성하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- index와 show에 추가하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;_id&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 글을 작성할 때 req.user._id를 가져와서 post의 author에 기록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; req.user는 로그인을 하면 passport에서 자동으로 생성해준다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;lt;- &lt;a href=&quot;https://jonnastudy.tistory.com/102&quot;&gt;2021.12.07 - [개발/node.js] - 게시판 만들기 / login 기능 - passport package&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639902323203&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;게시판 만들기 / login 기능 - passport package&quot; data-og-description=&quot;passport package를 사용해 login 기능을 만든다. &amp;middot; passport : node.js에서 user authentication(사용자 인증, login)을 만들기 위해 사용하는 package 단독으로 사용 X , passport strategy package와 함꼐 사..&quot; data-og-host=&quot;jonnastudy.tistory.com&quot; data-og-source-url=&quot;https://jonnastudy.tistory.com/102&quot; data-og-url=&quot;https://jonnastudy.tistory.com/102&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cknn2R/hyMKJ3V3x9/8GDRUkjPxi0Kw9DPvKKCdK/img.png?width=629&amp;amp;height=417&amp;amp;face=0_0_629_417,https://scrap.kakaocdn.net/dn/pRXBX/hyMKHSACBi/sosmnt2KtKzR1gGMkOqVN1/img.png?width=629&amp;amp;height=417&amp;amp;face=0_0_629_417,https://scrap.kakaocdn.net/dn/5opwl/hyMKLgnOZh/TKIJSHyey5SNSOPQIlc1n0/img.png?width=877&amp;amp;height=602&amp;amp;face=0_0_877_602&quot;&gt;&lt;a href=&quot;https://jonnastudy.tistory.com/102&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jonnastudy.tistory.com/102&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cknn2R/hyMKJ3V3x9/8GDRUkjPxi0Kw9DPvKKCdK/img.png?width=629&amp;amp;height=417&amp;amp;face=0_0_629_417,https://scrap.kakaocdn.net/dn/pRXBX/hyMKHSACBi/sosmnt2KtKzR1gGMkOqVN1/img.png?width=629&amp;amp;height=417&amp;amp;face=0_0_629_417,https://scrap.kakaocdn.net/dn/5opwl/hyMKLgnOZh/TKIJSHyey5SNSOPQIlc1n0/img.png?width=877&amp;amp;height=602&amp;amp;face=0_0_877_602');&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;게시판 만들기 / login 기능 - passport package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;passport package를 사용해 login 기능을 만든다. &amp;middot; passport : node.js에서 user authentication(사용자 인증, login)을 만들기 위해 사용하는 package 단독으로 사용 X , passport strategy package와 함꼐 사..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jonnastudy.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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; index.ejs 수정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1639902671530&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- views/posts/index.ejs --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

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

      &amp;lt;h2 class=&quot;mb-3&quot;&amp;gt;Board&amp;lt;/h2&amp;gt;

      &amp;lt;table class=&quot;board-table table table-sm border-bottom&quot;&amp;gt;

        &amp;lt;thead class=&quot;thead-light&quot;&amp;gt;
          &amp;lt;tr&amp;gt;
            &amp;lt;th scope=&quot;col&quot;&amp;gt;Title&amp;lt;/th&amp;gt;
            &amp;lt;th scope=&quot;col&quot;&amp;gt;Author&amp;lt;/th&amp;gt;
            &amp;lt;th scope=&quot;col&quot; class=&quot;date&quot;&amp;gt;Date&amp;lt;/th&amp;gt;
          &amp;lt;/tr&amp;gt;
        &amp;lt;/thead&amp;gt;

        &amp;lt;tbody&amp;gt;
          &amp;lt;% if(posts == null || posts.length == 0){ %&amp;gt;
            &amp;lt;tr&amp;gt;
              &amp;lt;td colspan=2&amp;gt; 보여줄게 없쪙 ㅠ &amp;lt;/td&amp;gt;
            &amp;lt;/tr&amp;gt;
          &amp;lt;% } %&amp;gt;
          &amp;lt;% posts.forEach(function(post) { %&amp;gt;
            &amp;lt;tr&amp;gt;
              &amp;lt;td&amp;gt;
                &amp;lt;a href=&quot;/posts/&amp;lt;%= post._id %&amp;gt;&quot;&amp;gt;&amp;lt;div class=&quot;ellipsis&quot;&amp;gt;&amp;lt;%= post.title %&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/a&amp;gt;
              &amp;lt;/td&amp;gt;
              &amp;lt;td class=&quot;author&quot;&amp;gt;
                &amp;lt;div class=&quot;ellipsis&quot;&amp;gt;&amp;lt;%= post.author ? post.author.username : &quot;&quot; %&amp;gt;&amp;lt;/div&amp;gt;
              &amp;lt;/td&amp;gt;
              &amp;lt;td class=&quot;date&quot;&amp;gt;
                &amp;lt;span data-date=&quot;&amp;lt;%= post.createdAt %&amp;gt;&quot;&amp;gt;&amp;lt;/span&amp;gt;
              &amp;lt;/td&amp;gt;
            &amp;lt;/tr&amp;gt;
          &amp;lt;% }) %&amp;gt;
        &amp;lt;/tbody&amp;gt;

      &amp;lt;/table&amp;gt;

      &amp;lt;div&amp;gt;
        &amp;lt;a class=&quot;btn btn-primary&quot; href=&quot;/posts/new&quot;&amp;gt;New&amp;lt;/a&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;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;Author&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;th&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;table의 theader에 author 항목을 추가하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;td&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ellipsis&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;%= post.author ? post.author.username : &quot;&quot; %&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;td&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;table의 tbody에도 author 항목을 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;author가 있는 경우-&amp;gt;author의 username을 표시한다.&lt;/p&gt;
&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;&amp;middot; show.ejs 수정&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1053&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vA7Ux/btroi4SBhR9/kQ1e7u7kpKg3YNyBLh8sh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vA7Ux/btroi4SBhR9/kQ1e7u7kpKg3YNyBLh8sh0/img.png&quot; data-alt=&quot;views/posts/show.ejs&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vA7Ux/btroi4SBhR9/kQ1e7u7kpKg3YNyBLh8sh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvA7Ux%2Fbtroi4SBhR9%2FkQ1e7u7kpKg3YNyBLh8sh0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1053&quot; height=&quot;270&quot; data-origin-width=&quot;1053&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;views/posts/show.ejs&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;show에도 author 항목을 추가하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;author가 있는 경우-&amp;gt;author의 username을 표시한다.&lt;/p&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;size18&quot;&gt;&lt;b&gt;&amp;lt;실행결과&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bClQ9a/btrodR7QNc5/FPpgaTpQLnfkleD4eyWkK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bClQ9a/btrodR7QNc5/FPpgaTpQLnfkleD4eyWkK0/img.png&quot; data-alt=&quot;ㄱ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bClQ9a/btrodR7QNc5/FPpgaTpQLnfkleD4eyWkK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbClQ9a%2FbtrodR7QNc5%2FFPpgaTpQLnfkleD4eyWkK0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;992&quot; height=&quot;750&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;750&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;르그인하여 글을 작성하면 author가 기록된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmZd6/btrocCXdS5G/2yZSypLMRtuxLmxKmeD9R0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmZd6/btrocCXdS5G/2yZSypLMRtuxLmxKmeD9R0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmZd6/btrocCXdS5G/2yZSypLMRtuxLmxKmeD9R0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmZd6%2FbtrocCXdS5G%2F2yZSypLMRtuxLmxKmeD9R0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1003&quot; height=&quot;648&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시판에 author 항목이 생겨서 작성자를 확인할 수 있게 되었다.&lt;/p&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;619&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nCbCE/btrogwB5p1d/fJpKoEMmJg2EgYHody2MJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nCbCE/btrogwB5p1d/fJpKoEMmJg2EgYHody2MJ1/img.png&quot; data-alt=&quot;mongoDB의 post 데이터&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nCbCE/btrogwB5p1d/fJpKoEMmJg2EgYHody2MJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnCbCE%2FbtrogwB5p1d%2FfJpKoEMmJg2EgYHody2MJ1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1430&quot; height=&quot;619&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;619&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mongoDB의 post 데이터&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post의 author에는 user id가 기록되며, 이 값을 바탕으로 실제 user의 값을 author에 생성할 수 있다고 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user의 고유 아이디가 author에 기록되어 있다는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mongoDB의 post 데이터에 들어가보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작성자의 user데이터의 id(mongodb object id)만 기록되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 post의 author를 populate하면 author가 &lt;u&gt;단순히 user의 id만 가지고 있는게 아니라&lt;/u&gt;, &lt;b&gt;user object로 변환&lt;/b&gt;돼서 name, email등을 가지게 되고, post.author.email과 같은 방식으로 값을 읽을 수 있게 된다.&lt;/p&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;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639904396167&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;Node JS 첫걸음/게시판 만들기: 게시판 - Post-User 관계(relationship) 만들기 - A MEAN Blog&quot; data-og-description=&quot;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&quot; data-og-host=&quot;www.a-mean-blog.com&quot; data-og-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; data-og-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-User-%EA%B4%80%EA%B3%84-relationship-%EB%A7%8C%EB%93%A4%EA%B8%B0&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;Node JS 첫걸음/게시판 만들기: 게시판 - Post-User 관계(relationship) 만들기 - A MEAN Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.a-mean-blog.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;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;아 이것저것 공부하고 활동하다 보니까 공부했던 게 다 가물가물하고 헷갈려졌다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;오늘 밤은 다시 다 정리하고 점검하면서 전체적인 이해도를 높이게따..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB/Node</category>
      <category>backend</category>
      <category>Express</category>
      <category>nodeJS</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/105</guid>
      <comments>https://jonnastudy.tistory.com/105#entry105comment</comments>
      <pubDate>Sun, 19 Dec 2021 18:00:15 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기 - post error</title>
      <link>https://jonnastudy.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;routes/userjs에서 사용한 parseError함수를 post에서도 사용하여 post의 error를 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 여러 파일에서 사용하게 될 함수들을 하나의 module로 분리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1638856014178&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// util.js

const util = {};

util.parseError = function(errors){
  const parsed = {};
  if(errors.name == 'ValidationError'){
    for(const name in errors.errors){
      const validationError = errors.errors[name];
      parsed[name] = { message:validationError.message };
    }
  } 
  else if(errors.code == '11000' &amp;amp;&amp;amp; errors.errmsg.indexOf('username') &amp;gt; 0) {
    parsed.username = { message:'This username already exists!' };
  } 
  else {
    parsed.unhandled = JSON.stringify(errors);
  }
  return parsed;
}

module.exports = util;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;routes/users.js에 있던 parseError함수를 module로 만들어 util.js파일로 분리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;util.js&lt;/b&gt; &lt;span style=&quot;color: #009a87;&quot;&gt;&amp;lt;- 여러 곳에서 공통으로 쓰게 될 함수들을 기록&lt;/span&gt;&lt;/p&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;middot; user.js 수정&lt;/p&gt;
&lt;pre id=&quot;code_1638858869787&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// routes/users.js

const express = require('express');
const router = express.Router();
const User = require('../models/User');
const util=require('../util');

// Index
router.get('/', function(req, res){
  User.find({})
    .sort({username:1})
    .exec(function(err, users){
      if(err) return res.json(err);
      res.render('users/index', {users:users});
    });
});

// New
router.get('/new', function(req, res){
  const user = req.flash('user')[0] || {};
  const errors = req.flash('errors')[0] || {};
  res.render('users/new', { user:user, errors:errors });
});

// create
router.post('/', function(req, res){
  User.create(req.body, function(err, user){
    if(err){
      req.flash('user', req.body);
      req.flash('errors', util.parseError(err));
      return res.redirect('/users/new');
    }
    res.redirect('/users');
  });
});


// show
router.get('/:username', function(req, res){
  User.findOne({username:req.params.username}, function(err, user){
    if(err) return res.json(err);
    res.render('users/show', {user:user});
  });
});

// edit
router.get('/:username/edit', function(req, res){
  const user = req.flash('user')[0];
  const errors = req.flash('errors')[0] || {};
  if(!user){
    User.findOne({username:req.params.username}, function(err, user){
      if(err) return res.json(err);
      res.render('users/edit', { username:req.params.username, user:user, errors:errors });
    });
  }
  else {
    res.render('users/edit', { username:req.params.username, user:user, errors:errors });
  }
});

// update
router.put('/:username', function(req, res, next){
  User.findOne({username:req.params.username})
    .select('password')
    .exec(function(err, user){
      if(err) return res.json(err);

      // update user object
      user.originalPassword = user.password;
      user.password = req.body.newPassword? req.body.newPassword : user.password;
      for(var p in req.body){
        user[p] = req.body[p];
      }

      // save updated user
      user.save(function(err, user){
        if(err){
          req.flash('user', req.body);
          req.flash('errors', util.parseError(err));
          return res.redirect('/users/'+req.params.username+'/edit');
        }
        res.redirect('/users/'+user.username);
      });
  });
});


// destroy
router.delete('/:username', function(req, res){
  User.deleteOne({username:req.params.username}, function(err){
    if(err) return res.json(err);
    res.redirect('/users');
  });
});

module.exports = router;

// functions
function parseError(errors){
  const parsed = {};
  if(errors.name == 'ValidationError'){
    for(const name in errors.errors){
      const validationError = errors.errors[name];
      parsed[name] = { message:validationError.message };
    }
  }
  else if(errors.code == '11000' &amp;amp;&amp;amp; errors.errmsg.indexOf('username') &amp;gt; 0) {
    parsed.username = { message:'This username already exists!' };
  }
  else {
    parsed.unhandled = JSON.stringify(errors);
  }
  return parsed;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #4fc1ff;&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #ce9178;&quot;&gt;'../util'&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;util을 require했다.&lt;/p&gt;
&lt;p data-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: #6a9955; letter-spacing: 0px; background-color: #333333;&quot;&gt;// create&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'errors'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;parseError&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #6a9955; letter-spacing: 0px; background-color: #333333;&quot;&gt;// update // save updated user&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'errors'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;parseError&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parseError -&amp;gt; util.parseError로 변경했다.&lt;/p&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;middot; Post.js 수정&lt;/p&gt;
&lt;pre id=&quot;code_1638864256256&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//models/Post.js
const mongoose = require('mongoose');
const postSchema = mongoose.Schema({
  title:{type:String, required:[true,'Title is required']},
  body:{type:String, required:[true,'Body is required']},
  createdAt:{type:Date, default:Date.now},
  updatedAt:{type:Date},
});

const Post = mongoose.model('post', postSchema);
module.exports = Post;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post schema의 custom error message를 추가한다.&lt;/p&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;middot; posts.js 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;a style=&quot;background-color: #f6e199;&quot; href=&quot;https://jonnastudy.tistory.com/100&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.12.01 - [개발/node.js] - 게시판 만들기 / User 생성, 수정 시 error 처리 (1)&lt;/a&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_1638864911037&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//routes/posts.js

const express  = require('express');
const router = express.Router();
const Post = require('../models/Post');
const util=require('../util');

// Index 
router.get('/', function(req, res){
  Post.find({})
  .sort('-createdAt')
  .exec(function(err, posts){
    if(err) return res.json(err);
    res.render('posts/index', {posts:posts});
  });
});

// New
router.get('/new', function(req, res){
  const post=req.flash('post')[0]||{};
  const errors=req.flash('errors')[0]||{};
  res.render('posts/new',{post:post, errors:errors});
});

// create
router.post('/', function(req, res){
  Post.create(req.body, function(err, post){
    if(err){
      req.flash('post',req.body);
      req.flash('errors',util.parseError(err));
      return res.redirect('/posts/new');
    }
    res.redirect('/posts');
  });
});

// show
router.get('/:id', function(req, res){
  Post.findOne({_id:req.params.id}, function(err, post){
    if(err) return res.json(err);
    res.render('posts/show', {post:post});
  });
});

// edit
router.get('/:id/edit', function(req, res){
  const post=req.flash('post')[0];
  const errors=req.flash('errors')[0]||{};
  if(!post){
    Post.findOne({_id:req.params.id},function(err,post){
      if(err) return res.json(err);
      res.render('post/edit',{post:post, errors:errors});
    })
  }
  else{
    post._id=req.params.id;
    res.render('posts/edit',{post:post, errors:errors});
  }
});

// update
router.put('/:id', function(req, res){
  req.body.updatedAt = Date.now(); 
  Post.findOneAndUpdate({_id:req.params.id}, req.body, {runValidators:true}, function(err, post){
    if(err) {
      req.flash('post',req.body)
      req.flash('errors',util.parseError(err))
      return res.redirect('/posts'+req.params.id+'/edit')
    }
    res.redirect(&quot;/posts/&quot;+req.params.id);
  });
});

// destroy
router.delete('/:id', function(req, res){
  Post.deleteOne({_id:req.params.id}, function(err){
    if(err) return res.json(err);
    res.redirect('/posts');
  });
});

module.exports = router;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #4fc1ff;&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #ce9178;&quot;&gt;'../util'&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;util을 require했다.&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWPxTT/btrngO4KXQN/kByO455EaNw299RLBHnTRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWPxTT/btrngO4KXQN/kByO455EaNw299RLBHnTRK/img.png&quot; data-alt=&quot;new route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWPxTT/btrngO4KXQN/kByO455EaNw299RLBHnTRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWPxTT%2FbtrngO4KXQN%2FkByO455EaNw299RLBHnTRK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;154&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;new route&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post 생성시 에러가 있는 경우 new페이지에 에러와 기존에 입력했던 값들을 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이때, 이 값들은 create route에서 생성된 flash로부터 받아옴)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flash는&lt;b&gt; 배열&lt;/b&gt;이 오는데 이 프로그램에서는 하나 이상의 값이 저장되는 경우가 없고 ,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;있더라도 오류이므로 무조건&lt;span style=&quot;color: #009a87;&quot;&gt; [0]&lt;/span&gt;의 값을 읽어오게 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;값이 없으면(처음 new페이지에 들어온 경우)&lt;/u&gt;에는 &lt;span style=&quot;background-color: #333333; color: #ffffff;&quot;&gt;| | { }&lt;/span&gt;를 사용해 빈 오브젝트를 넣어 posts/new페이지 생성한다.&lt;/p&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;b&gt;req.flash(&lt;span style=&quot;color: #f89009;&quot;&gt;문자열&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;저장할 값&lt;/span&gt;)&lt;/b&gt;형태로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;저장할 값&lt;/span&gt;(숫자, 문자열, 오브젝트 등 가능)을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;해당 문자열&lt;/span&gt;에 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;배열&lt;/u&gt;로 저장되기 때문에 같은 문자열을 중복해서 사용하면 순서대로 배열에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;req.flash(&lt;span style=&quot;color: #f89009;&quot;&gt;문자열&lt;/span&gt;)&lt;/b&gt;인 경우 -&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;해당 문자열&lt;/span&gt;에 저장된 값들을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;배열&lt;/u&gt;로 불러온다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;- 저장된 값이 없으면 빈 배열(&lt;span style=&quot;color: #ee2323;&quot;&gt;[ ]&lt;/span&gt;)을 return&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHlKxp/btrnbVD7fOT/KN2gPoVNKTOntXI16EFLK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHlKxp/btrnbVD7fOT/KN2gPoVNKTOntXI16EFLK0/img.png&quot; data-alt=&quot;create route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHlKxp/btrnbVD7fOT/KN2gPoVNKTOntXI16EFLK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHlKxp%2FbtrnbVD7fOT%2FKN2gPoVNKTOntXI16EFLK0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;272&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;create route&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post 생성시 오류가 있으면 post, error flash를 만들고 new페이지로 redirect한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post 생성시 발생하는 오류는&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mWC28/btrndmBnXlR/AgQfKgPVykLNxyKqL6Bsb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mWC28/btrndmBnXlR/AgQfKgPVykLNxyKqL6Bsb1/img.png&quot; data-alt=&quot;update route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mWC28/btrndmBnXlR/AgQfKgPVykLNxyKqL6Bsb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmWC28%2FbtrndmBnXlR%2FAgQfKgPVykLNxyKqL6Bsb1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;981&quot; height=&quot;313&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;update route&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Post.findOneAndUpdate에 &lt;b&gt;{runValidators:true}&lt;/b&gt;가 기존 코드에서 추가되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;findOneAndUpdate&lt;/b&gt;는 기본설정이 schema에 있는 validation이 작동하지 &lt;u&gt;않도록&lt;/u&gt; 되어있어 이 option을 통해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;middot; edit.ejs &amp;amp; new.ejs 수정&lt;/p&gt;
&lt;pre id=&quot;code_1639892579879&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- views/posts/edit.ejs --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

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

      &amp;lt;nav aria-label=&quot;breadcrumb&quot;&amp;gt;
        &amp;lt;ol class=&quot;breadcrumb p-1 pl-2 pr-2&quot;&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item&quot;&amp;gt;&amp;lt;a href=&quot;/&quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item&quot;&amp;gt;&amp;lt;a href=&quot;/posts&quot;&amp;gt;Board&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item&quot;&amp;gt;&amp;lt;a href=&quot;/posts/&amp;lt;%= post._id %&amp;gt;&quot;&amp;gt;&amp;lt;%= post.title %&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item active&quot; aria-current=&quot;page&quot;&amp;gt;Edit Post&amp;lt;/li&amp;gt;
        &amp;lt;/ol&amp;gt;
      &amp;lt;/nav&amp;gt;

      &amp;lt;form action=&quot;/posts/&amp;lt;%= post._id %&amp;gt;?_method=put&quot; method=&quot;post&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;title&quot;&amp;gt;Title&amp;lt;/label&amp;gt;
          &amp;lt;input type=&quot;text&quot; id=&quot;title&quot; name=&quot;title&quot; value=&quot;&amp;lt;%= post.title %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.title)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
          &amp;lt;% if(errors.title){ %&amp;gt;
            &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.title.message %&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;% } %&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;body&quot;&amp;gt;Body&amp;lt;/label&amp;gt;
           &amp;lt;textarea id=&quot;body&quot; name=&quot;body&quot; rows=&quot;5&quot; class=&quot;form-control &amp;lt;%= (errors.body)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;&amp;lt;%= post.body %&amp;gt;&amp;lt;/textarea&amp;gt;
          &amp;lt;% if(errors.body){ %&amp;gt;
            &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.body.message %&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;% } %&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;% if(errors.unhandled){ %&amp;gt;
          &amp;lt;div class=&quot;invalid-feedback d-block&quot;&amp;gt;
            &amp;lt;%= errors.unhandled %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;% } %&amp;gt;
        
        &amp;lt;div&amp;gt;
          &amp;lt;a class=&quot;btn btn-primary&quot; href=&quot;/posts/&amp;lt;%= post._id %&amp;gt;&quot;&amp;gt;Back&amp;lt;/a&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;/div&amp;gt;
      &amp;lt;/form&amp;gt;

    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;%= (errors.항목이름)?'is-invalid':'' %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 항목의 form-group class가 있는 div에 위의 코드를 추가하였다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;% if(errors.title){ %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;invalid-feedback&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;%= errors.title.message %&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;% } %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 error가 있다면 bootstrap의 invalid-feedback class를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;% if(errors.unhandled){ %&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;alert alert-danger&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;%= errors.unhandled %&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;% } %&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;error.unhandled는 따로 표시한다.&lt;/p&gt;
&lt;pre id=&quot;code_1639892957754&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- views/posts/new.ejs --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

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

      &amp;lt;nav aria-label=&quot;breadcrumb&quot;&amp;gt; 
        &amp;lt;ol class=&quot;breadcrumb p-1 pl-2 pr-2&quot;&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item&quot;&amp;gt;&amp;lt;a href=&quot;/&quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item&quot;&amp;gt;&amp;lt;a href=&quot;/posts&quot;&amp;gt;Board&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
          &amp;lt;li class=&quot;breadcrumb-item active&quot; aria-current=&quot;page&quot;&amp;gt;New Post&amp;lt;/li&amp;gt;
        &amp;lt;/ol&amp;gt;
      &amp;lt;/nav&amp;gt;

      &amp;lt;form action=&quot;/posts&quot; method=&quot;post&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;title&quot;&amp;gt;Title&amp;lt;/label&amp;gt;
          &amp;lt;input type=&quot;text&quot; id=&quot;title&quot; name=&quot;title&quot; value=&quot;&amp;lt;%= post.title %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.title)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
          &amp;lt;% if(errors.title){ %&amp;gt;
            &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.title.message %&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;% } %&amp;gt;
        &amp;lt;/div&amp;gt;
        
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;body&quot;&amp;gt;Body&amp;lt;/label&amp;gt;
          &amp;lt;textarea id=&quot;body&quot; name=&quot;body&quot; rows=&quot;5&quot; class=&quot;form-control &amp;lt;%= (errors.body)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;&amp;lt;%= post.body %&amp;gt;&amp;lt;/textarea&amp;gt;
          &amp;lt;% if(errors.body){ %&amp;gt;
            &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.body.message %&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;% } %&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;% if(errors.unhandled){ %&amp;gt;
          &amp;lt;div class=&quot;invalid-feedback d-block&quot;&amp;gt;
            &amp;lt;%= errors.unhandled %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;% } %&amp;gt;

        &amp;lt;div&amp;gt;
          &amp;lt;a class=&quot;btn btn-primary&quot; href=&quot;/posts&quot;&amp;gt;Back&amp;lt;/a&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;/div&amp;gt;

      &amp;lt;/form&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;위의 edit.ejs와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;lt;실행결과&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post 작성시 Title과 Body를 작성하지 않고 Submit하면 이렇게 error message가 뜬다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;945&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mDyql/btroi4SuGbs/EawmMVhJHeW5keM7DIkTx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mDyql/btroi4SuGbs/EawmMVhJHeW5keM7DIkTx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mDyql/btroi4SuGbs/EawmMVhJHeW5keM7DIkTx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmDyql%2Fbtroi4SuGbs%2FEawmMVhJHeW5keM7DIkTx0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1007&quot; height=&quot;945&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;945&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처 및 참조 : &lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639897759676&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;Node JS 첫걸음/게시판 만들기: 게시판 - Post Error 처리 - A MEAN Blog&quot; data-og-description=&quot;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&quot; data-og-host=&quot;www.a-mean-blog.com&quot; data-og-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&quot; data-og-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Post-Error-%EC%B2%98%EB%A6%AC&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;Node JS 첫걸음/게시판 만들기: 게시판 - Post Error 처리 - A MEAN Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.a-mean-blog.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;</description>
      <category>WEB/Node</category>
      <category>Express</category>
      <category>nodeJS</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/104</guid>
      <comments>https://jonnastudy.tistory.com/104#entry104comment</comments>
      <pubDate>Sun, 19 Dec 2021 16:10:01 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기 / login 기능 - passport package</title>
      <link>https://jonnastudy.tistory.com/102</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;passport package&lt;/span&gt;를 사용해 login 기능을 만든다.&lt;/p&gt;
&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;&amp;middot; passport&lt;/b&gt; : node.js에서 &lt;u&gt;user authentication&lt;/u&gt;(사용자 인증, login)을 만들기 위해 사용하는 package&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 단독으로 사용 &lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt; , &lt;span style=&quot;color: #006dd7;&quot;&gt;passport strategy package&lt;/span&gt;와 함꼐 사용해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; passport strategy&lt;/b&gt; : 구체적인 인증 방법을 구현하는 package&lt;/p&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;gt; 인증 방법별로 수십가지(Facebook strategy, Twitter strategy, Naver strategy 등)가 존재하기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;package가 나눠지게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 한 사이트에서 사용하는 strategy는 이 중 몇 개밖에 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 사이트에 필요한 인증밥법만 설치하기 위해 package를 분리한 것이다.&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;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;[로그인 기본 원리]&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; server와 client 간의 정보교환 : &lt;span style=&quot;color: #006dd7;&quot;&gt;단발성&lt;/span&gt;(어떤 일이 단 한 번 만으로 그치는성질)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 사용자의 browser(client)d에서 주소 입력 &lt;span style=&quot;color: #ee2323;&quot;&gt;or&lt;/span&gt; link가 click 되면 server로 요청(request) 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-&amp;gt;&lt;/span&gt; server는 요청에 맞는 결과를 응답(response)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; =&amp;gt; server-client간의 통신은 연결을 유지 &lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;client를 구별하기 위해서는 각각의 request에 &lt;u&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;&amp;nbsp; 이 때, 식별코드는 사이트에 처음 접속한 순간 생성되어 client의 브라우저에 저장되고, server에 요청할 때마다 server로 전달됨 / server에서는 식별코드가 session에 저장되어 어느 client로부터 요청이 오는지 구별할 수 있게 됨&lt;/p&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;로그인 성공하면 server의 session에 기록되고, 다음번 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;&amp;nbsp; &lt;span style=&quot;color: #f89009;&quot;&gt;로그인 == DB에 이미 등록된 user을 찾는 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- &lt;b&gt;serialize(직렬화)&lt;/b&gt; : &lt;span style=&quot;color: #006dd7;&quot;&gt;로그인&lt;/span&gt; 시, DB로부터 user을 찾아 session에 user 정보의 일부(전부)를 등록하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- &lt;b&gt;deserialize(역직렬화)&lt;/b&gt; :&amp;nbsp; session에 등록된 user 정보로부터 해당 user를 oject로 만드는 것 -&amp;gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;server에 요청 올 때&lt;/span&gt;마다 거치는 과정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbcBgZ/btrmZmngpN1/ACBg8Oy5q5hKdG0UomM4CK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbcBgZ/btrmZmngpN1/ACBg8Oy5q5hKdG0UomM4CK/img.png&quot; data-alt=&quot;https://www.geeksforgeeks.org/serialization-in-java/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbcBgZ/btrmZmngpN1/ACBg8Oy5q5hKdG0UomM4CK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbcBgZ%2FbtrmZmngpN1%2FACBg8Oy5q5hKdG0UomM4CK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;629&quot; height=&quot;417&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.geeksforgeeks.org/serialization-in-java/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 필요한 package를 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;717&quot; data-origin-height=&quot;28&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clvywi/btrmZ2aXdrQ/Z7WGT7uPzdO5mzM9vyid21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clvywi/btrmZ2aXdrQ/Z7WGT7uPzdO5mzM9vyid21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clvywi/btrmZ2aXdrQ/Z7WGT7uPzdO5mzM9vyid21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fclvywi%2FbtrmZ2aXdrQ%2FZ7WGT7uPzdO5mzM9vyid21%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;717&quot; height=&quot;28&quot; data-origin-width=&quot;717&quot; data-origin-height=&quot;28&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;2. 코드 수정, 추가&lt;/p&gt;
&lt;pre id=&quot;code_1638682877608&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js

const express=require('express')//모듈 가져오기
const mongoose=require('mongoose')
const methodOverride = require('method-override')
const flash=require(&quot;connect-flash&quot;)
const session=require(&quot;express-session&quot;)
const passport=require(&quot;./config/passport&quot;)
const app = express()//어플리케이션 생성

// DB setting
mongoose.connect(process.env.MONGO_DB);
const db = mongoose.connection; 

db.once('open', function(){
  console.log('DB connected');
})
db.on('error', function(err){
  console.log('DB ERROR : ', err);
});

//other setting
app.set('view engine','ejs')//템플릿 엔진
app.use(express.json());
app.use(express.static('public'));
app.use(express.urlencoded({extended:true}));
app.use(methodOverride('_method'));
app.use(flash());
app.use(session({secret:'MySecret', resave:true, saveUninitialized:true}));
app.use(passport.initialize())
app.use(passport.session())

//custom middlewares
app.use(function(req,res,next){
  res.locals.isAuthenticated = req.isAuthenticated();
  res.locals.currentUser = req.user;
  next();
})

//routes
app.use('/', require('./routes/home'));
app.use('/posts', require('./routes/posts'))
app.use('/contacts', require('./routes/contacts'));
app.use('/home', require('./routes/home'))
app.use('/users', require('./routes/users'))

//port setting
const server=app.listen(3000, ()=&amp;gt;{
  console.log('Start Server : localhost:3000')
})&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;./config/passport&quot;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: passport 말고 config/passport module을 변수 passport에 담았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;passport와 passport-local package는 index.js에 require되지 않고, config의 passport.js에서 require된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;initialize&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;())&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: passport를 초기화시키는 함수&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;session&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;())&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: passport와 session을 연결해주는 함수&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;- session을 이용하기 위해 앞서 user error처리를 하기위해 작성한 아래 코드가 &lt;u&gt;반드시&lt;/u&gt; 필요함&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;session&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;express-session&quot;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #4fc1ff;&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;session&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;secret&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'MySecret'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;resave&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;saveUninitialized&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;}));&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;//custom middlewares&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;locals&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isAuthenticated&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;isAuthenticated&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;locals&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;currentUser&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;})&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: app.use에 함수를 넣은 것 = &lt;b&gt;middleware&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app.use에 있는 함수는 request가 올 때마다 &lt;u&gt;route에 상관없이 무조건&lt;/u&gt; 해당 함수가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;위치&lt;/u&gt;가 중요하다 ( ∵ 위에 있는 것부터 순차적으로 실행됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;route에 들어가는 함수와 동일하게 3개의 parameter( &lt;i&gt;req, res, next &lt;/i&gt;)를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 안에 &lt;u&gt;반드시&lt;/u&gt; &lt;b&gt;next()&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;req.isAuthenticated()&lt;/b&gt; - passport에서 제공하는 함수 (현재 로그인이 되어있으면 true, 아니면 false를 return)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;req.user&lt;/b&gt; - passport에서 추가하는 항목. 로그인 되면 session으로부터 user를 deserialize하여 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;res.locals&lt;/b&gt; - 위의 두가지를 담고 있다. res.lcals에 담긴 변수는 &lt;span style=&quot;color: #ee2323;&quot;&gt;ejs에서 바로 사용가능&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;res.locals.isAuthenticated : ejs에서 user의 로그인 유무를 확인하는 데 사용됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;res.localse.currentUser : 로그인된 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;&lt;span style=&quot;color: #ee2323;&quot;&gt;[error]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sMMe5/btrnbJJYeA3/uWQYYmStFDZKJbMsN0xw31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sMMe5/btrnbJJYeA3/uWQYYmStFDZKJbMsN0xw31/img.png&quot; data-alt=&quot;error&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sMMe5/btrnbJJYeA3/uWQYYmStFDZKJbMsN0xw31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsMMe5%2FbtrnbJJYeA3%2FuWQYYmStFDZKJbMsN0xw31%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1298&quot; height=&quot;351&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;error&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 error가 발생하였는데, custom middlewares 코드의 위치 문제때문이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;routes 뒤에 custom middlewares를 위치시켰더니 위의 error가 발생하여,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;custom middlewares를 routes 앞으로 옮겼더니 해결되었다.&lt;/p&gt;
&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;routes에 있는 루트 경로에 대한 라우팅(&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #4fc1ff;&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #ce9178;&quot;&gt;'/'&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #ce9178;&quot;&gt;'./routes/home'&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;) 이후에 custom middlewares가 로드되면,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트 경로의 라우트 핸들러가 요청-응답 주기를 종료하므로 요청은 절대 custom middlewares로 도달하지 못하게 되며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 error가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 앞으로도 index.js에 추가할 middleware는 routes 앞에 위치시켜야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(route에 상관없이 무조건 해당 함수가 실행되어야 하므로)&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;a href=&quot;https://expressjs.com/ko/guide/writing-middleware.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://expressjs.com/ko/guide/writing-middleware.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1638852218372&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;Express 앱에서 사용하기 위한 미들웨어 작성&quot; data-og-description=&quot;Express 앱에서 사용하기 위한 미들웨어 작성 개요 미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트 (res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 액세스 권한&quot; data-og-host=&quot;expressjs.com&quot; data-og-source-url=&quot;https://expressjs.com/ko/guide/writing-middleware.html&quot; data-og-url=&quot;https://expressjs.com/ko/guide/writing-middleware.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://expressjs.com/ko/guide/writing-middleware.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://expressjs.com/ko/guide/writing-middleware.html&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;Express 앱에서 사용하기 위한 미들웨어 작성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Express 앱에서 사용하기 위한 미들웨어 작성 개요 미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트 (res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 액세스 권한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;expressjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1638688659948&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//config/passport.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');

// serialize &amp;amp; deserialize User
passport.serializeUser(function(user, done) {
  done(null, user.id);
});
passport.deserializeUser(function(id, done) {
  User.findOne({_id:id}, function(err, user) {
    done(err, user);
  });
});

// local strategy
passport.use('local-login',
  new LocalStrategy({
      usernameField : 'username', 
      passwordField : 'password', 
      passReqToCallback : true
    },
    function(req, username, password, done) {
      User.findOne({username:username})
        .select({password:1})
        .exec(function(err, user) {
          if (err) return done(err);

          if (user &amp;amp;&amp;amp; user.authenticate(password)){
            return done(null, user);
          }
          else {
            req.flash('username', username);
            req.flash('errors', {login:'The username or password is incorrect.'});
            return done(null, false);
          }
        });
    }
  )
);

module.exports = passport;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;LocalStrategy&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'passport-local'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Strategy&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: strategy들은 대부분 require 다음에 .Strategy가 붙는다 (.Strategy없이 사용해도 되는 것들도 있음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;serializeUser&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: login시 DB에서 발견한 user를 어떻게 session에 저장할지 정하는 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;user정보 전체를 session에 저장할 수 있지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;session에 저장되는 정보가 과다하면 사이트 성능이 하락할 수 있고, 전체 user정보가 session에 저장되어 있으므로 &amp;nbsp;user object를 변경하면(회원정보수정)&amp;nbsp; 해당 부분을 변경해줘야 하는 문제들이 있으므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;user의 id만 session에 저장한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;deserializeUser&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;findOne&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;_id&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; });&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: request시에 session에서 어떻게 user object를 만들지를 정하는 부분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;매번 request마다 user정보를 DB에서 새로 읽어오는데, user가 변경되면 바로 변경된 정보가 반영된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;+) done함수의 첫번째 parameter는 항상 error를 담는다. error가 없다면 null을 담는다.&lt;/span&gt;&lt;/p&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 정보를 전부 session에 저장하여 DB접촉 감소&lt;span style=&quot;color: #ee2323;&quot;&gt; -&amp;gt;&lt;/span&gt; session에 저장되는 정보가 과다해 사이트 성능 하락할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;request마다 user를 DB에서 읽어와서 데이터의 일관성을 확보 &lt;span style=&quot;color: #ee2323;&quot;&gt;-&amp;gt;&lt;/span&gt; 매 request마다 DB에서 user을 읽어와야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;=&amp;gt; 상황에 맞게 선택&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;usernameField&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'username'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;passwordField&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'password'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 form의 username과 password항목의 이름을 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;findOne&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;}) //DB에서 해당 user를 찾음&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;})&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;exec&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authenticate&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'username'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'errors'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, {&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;login&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'The username or password is incorrect.'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 시에 호출되는 함수&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPd9bX/btrnbIJt7zN/ytukh8RYiKZdWSUXzzRoZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPd9bX/btrnbIJt7zN/ytukh8RYiKZdWSUXzzRoZ1/img.png&quot; data-alt=&quot;user model&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPd9bX/btrnbIJt7zN/ytukh8RYiKZdWSUXzzRoZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPd9bX%2FbtrnbIJt7zN%2Fytukh8RYiKZdWSUXzzRoZ1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;123&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;user model&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user model에서 정의한 user.authenticate 함수를 사용해 입력받은 password와 DB에 저장된 해당 user의 password(user.password) hash를 비교해서 값이 일치하면 해당 user를 done에 담아 return한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지 않으면 username flash, error flash를 생성하고 false를 done에 담아 return한다.&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;pre id=&quot;code_1638765828120&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//routes/home.js

const express=require('express')
const router=express.Router()
const passport=require('../config/passport')

router.get('/', function(req, res){
  res.render('home/main');
});

router.get('/about', function(req, res){
  res.render('home/about');
});

router.get('/login',function(req,res){
  const username=req.flash('username')[0];
  const errors=req.flash('errors')[0]||{};
  res.render('home/login',{
    username:username,
    errors:errors
  })
})

router.post('/login',
  function(req,res,next){
    const errors = {};
    const isValid = true;

    if(!req.body.username){
      isValid = false;
      errors.username = 'Username is required!';
    }
    if(!req.body.password){
      isValid = false;
      errors.password = 'Password is required!';
    }

    if(isValid){
      next();
    }
    else {
      req.flash('errors',errors);
      res.redirect('/login');
    }
  },
  passport.authenticate('local-login', {
    successRedirect : '/posts',
    failureRedirect : '/login'
  }
));

// Logout
router.get('/logout', function(req, res) {
  req.logout();
  res.redirect('/');
});

module.exports=router;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;./config/passport&quot;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: passport 말고 config/passport module을 변수 passport에 담았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;passport와 passport-local package는 home.js에 require되지 않고, config의 passport.js에서 require된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;(index.js와 동일)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;router&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/login'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'username'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'errors'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;]||{};&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'home/login'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;errors&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; })&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;})&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;login view를 보여주는 route&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;router&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/login'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = {};&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(!&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'Username is required!'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(!&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'Password is required!'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;flash&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'errors'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;redirect&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/login'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; },&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;passport&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authenticate&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'local-login'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;successRedirect&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/posts'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;failureRedirect&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/login'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;));&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;login form에서 보내진 post request를 처리해 주는 route&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 개의 callback 중 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫번째 callback은 보내진 form의 validation을 위한 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에러가 있으면( &lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;; &lt;/span&gt;&lt;/span&gt;) &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;flash를 만들고 login view로 redirect한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두번째 callback은 passport local strategy를 호출해서 authentiction(로그인)을 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eF13UY/btrnc22AfRd/XeyjVPtstGqVgcV6tYU74k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eF13UY/btrnc22AfRd/XeyjVPtstGqVgcV6tYU74k/img.png&quot; data-alt=&quot;config/passport.js&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eF13UY/btrnc22AfRd/XeyjVPtstGqVgcV6tYU74k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeF13UY%2Fbtrnc22AfRd%2FXeyjVPtstGqVgcV6tYU74k%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;877&quot; height=&quot;602&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config/passport.js&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(참조 : &lt;a href=&quot;http://www.passportjs.org/docs/login/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.passportjs.org/docs/login/&lt;/a&gt;)&lt;/p&gt;
&lt;figure id=&quot;og_1638771865812&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;Documentation: Log In&quot; data-og-description=&quot;Log In Passport exposes a login() function on req (also aliased as logIn()) that can be used to establish a login session. req.login(user, function(err) { if (err) { return next(err); } return res.redirect('/users/' + req.user.username); }); When the login&quot; data-og-host=&quot;www.passportjs.org&quot; data-og-source-url=&quot;http://www.passportjs.org/docs/login/&quot; data-og-url=&quot;http://www.passportjs.org/docs/login/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cYVqIb/hyMApsA3iZ/ioSskTgnn5QpJN0i5lYeU1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260&quot;&gt;&lt;a href=&quot;http://www.passportjs.org/docs/login/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.passportjs.org/docs/login/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cYVqIb/hyMApsA3iZ/ioSskTgnn5QpJN0i5lYeU1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260');&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;Documentation: Log In&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Log In Passport exposes a login() function on req (also aliased as logIn()) that can be used to establish a login session. req.login(user, function(err) { if (err) { return next(err); } return res.redirect('/users/' + req.user.username); }); When the login&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.passportjs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;// Logout&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;router&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/logout'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;logout&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;redirect&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'/'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;logout을 해주는 route&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;passport에서 제공된 req.logout함수를 사용하여 로그아웃하고 &quot;/&quot;로 redirect한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-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;&quot;&gt;(참조 : &lt;a href=&quot;http://www.passportjs.org/docs/logout/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.passportjs.org/docs/logout/&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1638771820156&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;Documentation: Log Out&quot; data-og-description=&quot;Log Out Passport exposes a logout() function on req (also aliased as logOut()) that can be called from any route handler which needs to terminate a login session. Invoking logout() will remove the req.user property and clear the login session (if any). app&quot; data-og-host=&quot;www.passportjs.org&quot; data-og-source-url=&quot;http://www.passportjs.org/docs/logout/&quot; data-og-url=&quot;http://www.passportjs.org/docs/logout/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bZQIt7/hyMB3VJa2J/hbjxOV3yNN2OIV827Ce5g1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/bab1Py/hyMB1Q8FmQ/Uk70VwxAy6gNRyTgkTC2P0/img.png?width=3010&amp;amp;height=1612&amp;amp;face=0_0_3010_1612&quot;&gt;&lt;a href=&quot;http://www.passportjs.org/docs/logout/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.passportjs.org/docs/logout/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bZQIt7/hyMB3VJa2J/hbjxOV3yNN2OIV827Ce5g1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/bab1Py/hyMB1Q8FmQ/Uk70VwxAy6gNRyTgkTC2P0/img.png?width=3010&amp;amp;height=1612&amp;amp;face=0_0_3010_1612');&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;Documentation: Log Out&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Log Out Passport exposes a logout() function on req (also aliased as logOut()) that can be called from any route handler which needs to terminate a login session. Invoking logout() will remove the req.user property and clear the login session (if any). app&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.passportjs.org&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;color: #000000;&quot;&gt;-login view-&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1638782006239&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- views/home/login.ejs --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

    &amp;lt;div class=&quot;container&quot;&amp;gt;

      &amp;lt;h3 class=&quot;mb-3&quot;&amp;gt;Login&amp;lt;/h3&amp;gt;

      &amp;lt;form class=&quot;user-form&quot; action=&quot;/login&quot; method=&quot;post&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;username&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Username&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; value=&quot;&amp;lt;%= username %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.username)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.username){ %&amp;gt;
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.username %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;password&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Password&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.password)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.password){ %&amp;gt;
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.password %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;% if(errors.login){ %&amp;gt;
          &amp;lt;div class=&quot;invalid-feedback d-block&quot;&amp;gt;&amp;lt;%= errors.login %&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;% } %&amp;gt;

        &amp;lt;div class=&quot;mt-3&quot;&amp;gt;
          &amp;lt;input class=&quot;btn btn-primary&quot; type=&quot;submit&quot; value=&quot;Submit&quot;&amp;gt;
        &amp;lt;/div&amp;gt;

      &amp;lt;/form&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-nav.ejs-&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1638855058400&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

    &amp;lt;div class=&quot;container contact contact-new&quot;&amp;gt;
      &amp;lt;h2&amp;gt;New&amp;lt;/h2&amp;gt;
      &amp;lt;form class=&quot;cotact-form&quot; action=&quot;/contacts&quot; method=&quot;post&quot;&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;name&quot;&amp;gt;Name&amp;lt;/label&amp;gt;
          &amp;lt;input type=&quot;text&quot; id=&quot;name&quot; name=&quot;name&quot; value=&quot;&quot; class=&quot;form-control&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;email&quot;&amp;gt;Email&amp;lt;/label&amp;gt;
          &amp;lt;input type=&quot;text&quot; id=&quot;email&quot; name=&quot;email&quot; value=&quot;&quot; class=&quot;form-control&quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group&quot;&amp;gt;
          &amp;lt;label for=&quot;phone&quot;&amp;gt;Phone&amp;lt;/label&amp;gt;
          &amp;lt;input type=&quot;text&quot; id=&quot;phone&quot; name=&quot;phone&quot; value=&quot;&quot; class=&quot;form-control&quot;&amp;gt;
        &amp;lt;/div&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;/div&amp;gt;
      &amp;lt;/form&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kRlXa/btrnbJ3Fjza/nnkphEUehuNx7ZyozoEFTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kRlXa/btrnbJ3Fjza/nnkphEUehuNx7ZyozoEFTk/img.png&quot; data-alt=&quot;변경 전 navbar-nav ml-auto&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kRlXa/btrnbJ3Fjza/nnkphEUehuNx7ZyozoEFTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkRlXa%2FbtrnbJ3Fjza%2FnnkphEUehuNx7ZyozoEFTk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;808&quot; height=&quot;96&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경 전 navbar-nav ml-auto&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;998&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn8ZkS/btrndHcUtBi/4E3ZtNuutiChru0qBc5SX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn8ZkS/btrndHcUtBi/4E3ZtNuutiChru0qBc5SX1/img.png&quot; data-alt=&quot;변경 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn8ZkS/btrndHcUtBi/4E3ZtNuutiChru0qBc5SX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn8ZkS%2FbtrndHcUtBi%2F4E3ZtNuutiChru0qBc5SX1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;827&quot; height=&quot;153&quot; data-origin-width=&quot;998&quot; data-origin-height=&quot;184&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y7g31/btrnfA6fr8B/05dDBEeTSxiwZNf7Myk0kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y7g31/btrnfA6fr8B/05dDBEeTSxiwZNf7Myk0kk/img.png&quot; data-alt=&quot;변경 후&amp;amp;amp;nbsp;변경 전 navbar-nav ml-auto&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y7g31/btrnfA6fr8B/05dDBEeTSxiwZNf7Myk0kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy7g31%2FbtrnfA6fr8B%2F05dDBEeTSxiwZNf7Myk0kk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1132&quot; height=&quot;212&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경 후&amp;amp;nbsp;변경 전 navbar-nav ml-auto&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4plD5/btrndHktTsg/nOKtGwWEwdKEKzCxE7mB60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4plD5/btrndHktTsg/nOKtGwWEwdKEKzCxE7mB60/img.png&quot; data-alt=&quot;변경 후 ( isAuthenticated ==false )&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4plD5/btrndHktTsg/nOKtGwWEwdKEKzCxE7mB60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4plD5%2FbtrndHktTsg%2FnOKtGwWEwdKEKzCxE7mB60%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;184&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경 후 ( isAuthenticated ==false )&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1065&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ch1ZkJ/btrnc3auc0x/QRaZ4K9zs3nbchd4T8JtkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ch1ZkJ/btrnc3auc0x/QRaZ4K9zs3nbchd4T8JtkK/img.png&quot; data-alt=&quot;변경 후 ( isAuthenticated == true )&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ch1ZkJ/btrnc3auc0x/QRaZ4K9zs3nbchd4T8JtkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fch1ZkJ%2Fbtrnc3auc0x%2FQRaZ4K9zs3nbchd4T8JtkK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1065&quot; height=&quot;189&quot; data-origin-width=&quot;1065&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변경 후 ( isAuthenticated == true )&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;b&gt;※ 로그인이 일어날 때 코드 진행순서&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Login 버튼 클릭 -&amp;gt; routes/home.js의 &lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #4fc1ff;&quot;&gt;router&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #dcdcaa;&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #ce9178;&quot;&gt;'/login'&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d4d4d4;&quot;&gt;, ~)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;가 실행&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;1) login route 실행&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;(첫번째 callback)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;2)&amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;passport local strategy (config/passport.js)를 호출해서 로그인 진행&lt;span style=&quot;color: #006dd7;&quot;&gt; (두번째 callback)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 로그인이 성공하면 config/passport.js의 serialize 코드 실행&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. routes/home.js의 passport.authenticate의 succssRedirect route로 redirect&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 로그인 된 이후 모든 request가 config/passport.js의 deserialize코드를 거치게 됨&lt;/span&gt;&lt;/p&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;출처및참조 : &lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1638855327916&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;Node JS 첫걸음/게시판 만들기: 게시판 - Login 기능 추가 - A MEAN Blog&quot; data-og-description=&quot;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&quot; data-og-host=&quot;www.a-mean-blog.com&quot; data-og-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&quot; data-og-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-Login-%EA%B8%B0%EB%8A%A5-%EC%B6%94%EA%B0%80&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;Node JS 첫걸음/게시판 만들기: 게시판 - Login 기능 추가 - A MEAN Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.a-mean-blog.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;</description>
      <category>WEB/Node</category>
      <category>Deserialize</category>
      <category>login</category>
      <category>logout</category>
      <category>node.js</category>
      <category>Passport</category>
      <category>serialize</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/102</guid>
      <comments>https://jonnastudy.tistory.com/102#entry102comment</comments>
      <pubDate>Tue, 7 Dec 2021 14:34:04 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기 / User 생성, 수정 시 error 처리 (2)</title>
      <link>https://jonnastudy.tistory.com/101</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; edit.ejs 수정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1638340707210&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&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

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

      &amp;lt;h3 class=&quot;mb-3&quot;&amp;gt;Edit User&amp;lt;/h3&amp;gt;

      &amp;lt;form action=&quot;/users/&amp;lt;%= username %&amp;gt;?_method=put&quot; method=&quot;post&quot;&amp;gt; 

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;currentPassword&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Current Password*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9 col-sm-offset-3&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;currentPassword&quot; name=&quot;currentPassword&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.currentPassword)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.currentPassword){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.currentPassword.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;hr&amp;gt;&amp;lt;/hr&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;username&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Username*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; value=&quot;&amp;lt;%= user.username %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.username)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.username){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.username.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;name&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Name*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;name&quot; name=&quot;name&quot; value=&quot;&amp;lt;%= user.name %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.name)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.name){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.name.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;email&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Email&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;email&quot; name=&quot;email&quot; value=&quot;&amp;lt;%= user.email %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.email)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.email){ %&amp;gt;
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.email.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;newPassword&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;New Password&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9 col-sm-offset-3&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;newPassword&quot; name=&quot;newPassword&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.newPassword)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.newPassword){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.newPassword.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;passwordConfirmation&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Password Confirmation&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9 col-sm-offset-3&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;passwordConfirmation&quot; name=&quot;passwordConfirmation&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.passwordConfirmation)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.passwordConfirmation){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.passwordConfirmation.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;p&amp;gt;
          &amp;lt;small&amp;gt;*Required&amp;lt;/small&amp;gt;
        &amp;lt;/p&amp;gt;

        &amp;lt;% if(errors.unhandled){ %&amp;gt;
          &amp;lt;div class=&quot;alert alert-danger&quot;&amp;gt;
            &amp;lt;%= errors.unhandled %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;% } %&amp;gt;

        &amp;lt;div class=&quot;buttons&quot;&amp;gt;
          &amp;lt;a class=&quot;btn btn-primary&quot; href=&quot;/users/&amp;lt;%= user.username %&amp;gt;&quot;&amp;gt;Back&amp;lt;/a&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;/div&amp;gt;

      &amp;lt;/form&amp;gt;

    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;form&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;action&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;/users/&lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;%= username %&amp;gt;?_method=put&quot;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;user.username 대신 router에서 받은 username 사용&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;form-control &lt;/span&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;%= (errors.항목이름)?'is-invalid':' ' %&amp;gt;&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 항목의 form-group class가 있는 div에 위 코드가 추가되었다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에러가 있으면 bootstrap의 invalid-feedback class를 사용한다. &lt;u&gt;서버 측&lt;/u&gt;에서 유효성 검사를 사용한 것이다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;( 참조하기 좋은 글 : &lt;a href=&quot;https://getbootstrap.kr/docs/5.0/forms/validation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://getbootstrap.kr/docs/5.0/forms/validation/&lt;/a&gt; )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #f44747;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;% if(errors.username){ %&amp;gt; &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;input 밑에 위 코드를 추가하여 에러메세지를 보여주게 하였다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;&amp;middot; new.ejs 수정&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1638342165069&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&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;%- include('../partials/head') %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%- include('../partials/nav') %&amp;gt;

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

      &amp;lt;h3 class=&quot;contentBoxTop mb-3&quot;&amp;gt;New User&amp;lt;/h3&amp;gt;

      &amp;lt;form action=&quot;/users&quot; method=&quot;post&quot;&amp;gt;

        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;username&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Username*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; value=&quot;&amp;lt;%= user.username %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.username)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.username){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.username.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;name&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Name*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;name&quot; name=&quot;name&quot; value=&quot;&amp;lt;%= user.name %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.name)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.name){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.name.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;email&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Email&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;text&quot; id=&quot;email&quot; name=&quot;email&quot; value=&quot;&amp;lt;%= user.email %&amp;gt;&quot; class=&quot;form-control &amp;lt;%= (errors.email)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.email){ %&amp;gt;
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.email.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;password&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Password*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.password)?'is-invalid':'' %&amp;gt;&quot;&amp;gt; 
            &amp;lt;% if(errors.password){ %&amp;gt; 
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.password.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;form-group row&quot;&amp;gt;
          &amp;lt;label for=&quot;passwordConfirmation&quot; class=&quot;col-sm-3 col-form-label&quot;&amp;gt;Password Confirmation*&amp;lt;/label&amp;gt;
          &amp;lt;div class=&quot;col-sm-9 col-sm-offset-3&quot;&amp;gt;
            &amp;lt;input type=&quot;password&quot; id=&quot;passwordConfirmation&quot; name=&quot;passwordConfirmation&quot; value=&quot;&quot; class=&quot;form-control &amp;lt;%= (errors.passwordConfirmation)?'is-invalid':'' %&amp;gt;&quot;&amp;gt;
            &amp;lt;% if(errors.passwordConfirmation){ %&amp;gt;
              &amp;lt;span class=&quot;invalid-feedback&quot;&amp;gt;&amp;lt;%= errors.passwordConfirmation.message %&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;% } %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;small&amp;gt;*Required&amp;lt;/small&amp;gt;
        &amp;lt;/p&amp;gt;

        &amp;lt;% if(errors.unhandled){ %&amp;gt; 
          &amp;lt;div class=&quot;alert alert-danger&quot;&amp;gt;
            &amp;lt;%= errors.unhandled %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;% } %&amp;gt;

        &amp;lt;div class=&quot;form-group&quot;&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;/div&amp;gt;
      &amp;lt;/form&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;--edit.ejs와 같다--&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;i&gt;&amp;lt;실행결과&amp;gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SrmfC/btrmKCC6i8C/ju5XEePKdHphKRKYzszIA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SrmfC/btrmKCC6i8C/ju5XEePKdHphKRKYzszIA0/img.png&quot; data-alt=&quot;create 과정에서의 error ( new 페이지로 route간 이동이 발생함)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SrmfC/btrmKCC6i8C/ju5XEePKdHphKRKYzszIA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSrmfC%2FbtrmKCC6i8C%2Fju5XEePKdHphKRKYzszIA0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;726&quot; height=&quot;652&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;create 과정에서의 error ( new 페이지로 route간 이동이 발생함)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjLMsn/btrmEEPWHR0/U7ITi0rcVZbiLlJcSklYQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjLMsn/btrmEEPWHR0/U7ITi0rcVZbiLlJcSklYQK/img.png&quot; data-alt=&quot;update 과정에서의 error error ( edit 페이지로 route간 이동이 발생함)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjLMsn/btrmEEPWHR0/U7ITi0rcVZbiLlJcSklYQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjLMsn%2FbtrmEEPWHR0%2FU7ITi0rcVZbiLlJcSklYQK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;764&quot; height=&quot;741&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;update 과정에서의 error error ( edit 페이지로 route간 이동이 발생함)&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;user 생성, 수정에서 error가 일어나는 경우 사이트에서 error들을 표시해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;route간의 이동&lt;/u&gt;이 일어나는데 이 때 route간의 정보 전달을 위해 &lt;b&gt;flash&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;출처및참조 : &lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1638342806008&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;Node JS 첫걸음/게시판 만들기: 게시판 - User Error 처리 - A MEAN Blog&quot; data-og-description=&quot;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&quot; data-og-host=&quot;www.a-mean-blog.com&quot; data-og-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; data-og-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&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;Node JS 첫걸음/게시판 만들기: 게시판 - User Error 처리 - A MEAN Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.a-mean-blog.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;</description>
      <category>WEB/Node</category>
      <category>Express</category>
      <category>Flash</category>
      <category>nodeJS</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/101</guid>
      <comments>https://jonnastudy.tistory.com/101#entry101comment</comments>
      <pubDate>Wed, 1 Dec 2021 16:13:53 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기 / User 생성, 수정 시 error 처리 (1)</title>
      <link>https://jonnastudy.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; flash&lt;/b&gt; : 변수처럼 이름과 값(문자열, 숫자, 배열, 객체 등 어떠한 형태의 값이라도 사용 가능)을 저장할 수 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번 생성되면 사용될 때까지 서버 메모리상에 저장이 되어 있다가 한 번 사용되면 사라지는 형태의 data&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&amp;nbsp; -&amp;gt; connect-flash package를 이용하여 flash&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;&lt;b&gt;&amp;middot; regex(Regular Expression, 정규 표현식)&lt;/b&gt; : 특정규칙을 가진 문자열의 집할을 표현하는 데 사용하는 형식 언어&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;(출처 :&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D&lt;/a&gt;)&lt;/p&gt;
&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;&amp;nbsp; -&amp;gt;User의 username, password, name, email 항목들이 특정한 형식의 값만 저장할 수 있도록 함&lt;/i&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot;&lt;span&gt; package 설치&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;27&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQdUeC/btrlSkDollB/UOMkXBvFkruvOeJZdn8b80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQdUeC/btrlSkDollB/UOMkXBvFkruvOeJZdn8b80/img.png&quot; data-alt=&quot;express-session package&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQdUeC/btrlSkDollB/UOMkXBvFkruvOeJZdn8b80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQdUeC%2FbtrlSkDollB%2FUOMkXBvFkruvOeJZdn8b80%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;27&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;27&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;express-session package&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;27&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vLJOx/btrlFlqj0bT/xpuGsCFsekudekf5yLiUZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vLJOx/btrlFlqj0bT/xpuGsCFsekudekf5yLiUZK/img.png&quot; data-alt=&quot;connect-falsh package&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vLJOx/btrlFlqj0bT/xpuGsCFsekudekf5yLiUZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvLJOx%2FbtrlFlqj0bT%2FxpuGsCFsekudekf5yLiUZK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;27&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;27&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;connect-falsh package&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;express-session&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;connect-flash&lt;/b&gt;&lt;/span&gt;를 실행하기 위해 필요한 package이다.&lt;/p&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;&amp;middot;&amp;nbsp;User.js 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- User schema&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NTY9h/btrlPoTAold/bfcqlyVVcekAl0s2DAvn20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NTY9h/btrlPoTAold/bfcqlyVVcekAl0s2DAvn20/img.png&quot; data-alt=&quot;수정 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NTY9h/btrlPoTAold/bfcqlyVVcekAl0s2DAvn20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNTY9h%2FbtrlPoTAold%2FbfcqlyVVcekAl0s2DAvn20%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;801&quot; height=&quot;192&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;수정 전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G3OlD/btrlGIMQZy9/JgFetpOEUYOSzwMSpIk891/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G3OlD/btrlGIMQZy9/JgFetpOEUYOSzwMSpIk891/img.png&quot; data-alt=&quot;수정 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G3OlD/btrlGIMQZy9/JgFetpOEUYOSzwMSpIk891/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG3OlD%2FbtrlGIMQZy9%2FJgFetpOEUYOSzwMSpIk891%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;485&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;659&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;&lt;b&gt;trim&lt;/b&gt;은 문자열 앞뒤에 빈칸이 있는 경우 제거해주는 옵션&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;match&lt;/b&gt;에 regex가 들어가서 값이 regex에 부합하지 않으면 에러메시지를 낸다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;p data-ke-size=&quot;size16&quot;&gt;1. 정규식 리터럴(&quot;/&quot;로 감싸는 패턴) 사용&lt;/p&gt;
&lt;pre id=&quot;code_1637638903864&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/^.{4,12}$/
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 스크립트가 불러와질 때 컴파일됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -&amp;gt; 정규식이 상수일 때 사용&lt;/p&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. RegExp객체의 생성자 함수 호출&lt;/p&gt;
&lt;pre id=&quot;code_1637638907685&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;RegExp(&quot;^.{4,12}$&quot;)
RegExp(&quot;^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$&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; -&amp;gt; 정규식의 패턴이 변경될 수 있는 경우 or 사용자 입력과 같이 다른 출처로부터 패턴을 가져와야 하는 경우에 사용&lt;/p&gt;
&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;^ : 문자열의 시작 위치에 대응(줄 바꿈 문자 바로 다음 부분과도 대응)&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;{n} : 앞 표현식이 n번 나타나는 부분에 대응 (n은 반드시 양의 정수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ex) /a{2}/ -&amp;gt;caandy의 a에 대응O , candy의 a에 대응X&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;\w : 영숫자 문자에 대응&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[A-Za-z0-9_]와 동일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[xyz] : 문자셋(Character set)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 괄호 안의 어떤 문자(escape sequence까지 포함)와도 대응&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 하이픈(-)으로 문자의 범위 지정 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ex) [a-d] -&amp;gt;[abcd]와 똑같이 작동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 출처 : &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1637638810866&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;정규 표현식 - JavaScript | MDN&quot; data-og-description=&quot;정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해&amp;nbsp;사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.&amp;nbsp; 이 패턴들은&amp;nbsp;RegExp의 exec 메소드와 test 메소드&amp;nbsp; ,&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions&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;정규 표현식 - JavaScript | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해&amp;nbsp;사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.&amp;nbsp; 이 패턴들은&amp;nbsp;RegExp의 exec 메소드와 test 메소드&amp;nbsp; ,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&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;style5&quot; /&gt;
&lt;div&gt;regex(/^.{4,12}$/) : 문자열의 시작 위치에 길이 4이상 12이하인 문자열이 있고, 바로 다음이 문자열의 끝이여야 함&lt;/div&gt;
&lt;div&gt;regex(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/) &amp;nbsp;:&amp;nbsp; 문자열의 시작위치에 영문자, 숫자, 특수문자( . , _ , % , +, - ) 중에서 최소 1자 이상의 문자열+&quot;@&quot;+영문자, 숫자, 특수문자( . , - ) 중에서 최소 1자 이상의 문자열 +&quot;.&quot;+ 영문자 최소 2자 이상의 문자열이 끝이여야 함&lt;/div&gt;
&lt;div&gt;- 참조 :&amp;nbsp; &lt;a href=&quot;https://jamesdreaming.tistory.com/196&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://jamesdreaming.tistory.com/196&lt;/a&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;- password validation&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1005&quot; data-origin-height=&quot;695&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ALP9r/btrl8mO18fK/mLHwZdi8ObjewNPEHIFk21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ALP9r/btrl8mO18fK/mLHwZdi8ObjewNPEHIFk21/img.png&quot; data-alt=&quot;수정 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ALP9r/btrl8mO18fK/mLHwZdi8ObjewNPEHIFk21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FALP9r%2Fbtrl8mO18fK%2FmLHwZdi8ObjewNPEHIFk21%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1005&quot; height=&quot;695&quot; data-origin-width=&quot;1005&quot; data-origin-height=&quot;695&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;pre id=&quot;code_1637822195288&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// password validation
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16}$/;
const passwordRegexErrorMessage = 'Should be minimum 8 characters of alphabet and number combination!';
userSchema.path('password').validate(function(v) {
  var user = this;

  // create user
  if(user.isNew){
    if(!user.passwordConfirmation){
      user.invalidate('passwordConfirmation', 'Password Confirmation is required.');
    }

    if(!passwordRegex.test(user.password)){
      user.invalidate('password', passwordRegexErrorMessage);
    }
    else if(user.password !== user.passwordConfirmation) {
      user.invalidate('passwordConfirmation', 'Password Confirmation does not matched!');
    }
  }

  // update user
  if(!user.isNew){
    if(!user.currentPassword){
      user.invalidate('currentPassword', 'Current Password is required!');
    }
    else if(!bcrypt.compareSync(user.currentPassword, user.originalPassword)){
      user.invalidate('currentPassword', 'Current Password is invalid!');
    }

    if(user.newPassword &amp;amp;&amp;amp; !passwordRegex.test(user.newPassword)){
      user.invalidate(&quot;newPassword&quot;, passwordRegexErrorMessage);
    }
    else if(user.newPassword !== user.passwordConfirmation) {
      user.invalidate('passwordConfirmation', 'Password Confirmation does not matched!');
    }
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;passwordRegex&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;(?=&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #d7ba7d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;A-Za-z&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;])(?=&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #d7ba7d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;\d&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;A-Za-z\d&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #d7ba7d;&quot;&gt;{8,16}&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #d16969;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;8-16자리의 문자열 중에 숫자랑 영문자가 반드시 하나 이상 존재해야 함&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;background-color: #333333;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;passwordRegexErrorMessage&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;'Should be minimum 8 characters of alphabet and number combination!'&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;에러메세지-&amp;gt;변수로 선언&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sIZZf/btrl6J40aK1/3zDTDWysnOQaKh9K4seAP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sIZZf/btrl6J40aK1/3zDTDWysnOQaKh9K4seAP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sIZZf/btrl6J40aK1/3zDTDWysnOQaKh9K4seAP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsIZZf%2Fbtrl6J40aK1%2F3zDTDWysnOQaKh9K4seAP1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;528&quot; height=&quot;67&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 정규표현식을 변수 passwordRegex로 선언하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정규표현식.test(문자열)함수&lt;/b&gt; : 문자열에 정규표현식을 통과하는 부분이 있으면 -&amp;gt; &lt;span style=&quot;color: #009a87;&quot;&gt;true&lt;/span&gt;,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;아니면&lt;span style=&quot;color: #009a87;&quot;&gt; false&lt;/span&gt;를 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;false가 반환되면 model.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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;middot; index.js 수정&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buTW5f/btrl54H6Uad/U6QsMhod5hJK4wl4ET93qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buTW5f/btrl54H6Uad/U6QsMhod5hJK4wl4ET93qK/img.png&quot; data-alt=&quot;index.js&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buTW5f/btrl54H6Uad/U6QsMhod5hJK4wl4ET93qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuTW5f%2Fbtrl54H6Uad%2FU6QsMhod5hJK4wl4ET93qK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;858&quot; height=&quot;618&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;index.js&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로 설치한 package로부터 flash, session을 선언하였다.&lt;/p&gt;
&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;req.flash(&lt;span style=&quot;color: #f89009;&quot;&gt;문자열&lt;/span&gt;, &lt;span style=&quot;color: #006dd7;&quot;&gt;저장할 값&lt;/span&gt;)&lt;/b&gt;형태로 &lt;span style=&quot;color: #006dd7;&quot;&gt;저장할 값&lt;/span&gt;(숫자, 문자열, 오브젝트 등 가능)을 &lt;span style=&quot;color: #f89009;&quot;&gt;해당 문자열&lt;/span&gt;에 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 &lt;u&gt;배열&lt;/u&gt;로 저장되기 때문에 같은 문자열을 중복해서 사용하면 순서대로 배열에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;req.flash(&lt;span style=&quot;color: #f89009;&quot;&gt;문자열&lt;/span&gt;)&lt;/b&gt;인 경우 - &lt;span style=&quot;color: #f89009;&quot;&gt;해당 문자열&lt;/span&gt;에 저장된 값들을 &lt;u&gt;배열&lt;/u&gt;로 불러온다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;- 저장된 값이 없으면 빈 배열(&lt;span style=&quot;color: #ee2323;&quot;&gt;[ ]&lt;/span&gt;)을 return&lt;/p&gt;
&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;sesssion&lt;/b&gt;은 서버에서 접속자를 &lt;u&gt;구분&lt;/u&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;span style=&quot;background-color: #333333; color: #ffffff;&quot;&gt;{secret:'MySecret', resave:true, saveUninitialized:true}&lt;/span&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&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: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; -&amp;gt; &lt;b&gt;secret :&lt;/b&gt;&amp;nbsp;session을 hash화하는 데 사용되는 값(일종의 비밀번호) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;아무값이나 넣으면 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt; resave&lt;/b&gt; : 재저장을 계속 할 것인지에 대한 옵션&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;매 request마다 세션에 변동이 있든 없든 무조건 다시 저장하는 것&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;u&gt;default : true&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;saveUninitialized&lt;/b&gt; :&amp;nbsp; 세션이 세션store에 저장되기 전 &lt;span style=&quot;color: #009a87;&quot;&gt;uninitialized&lt;span style=&quot;color: #000000;&quot;&gt;한 상태&lt;/span&gt;(request가 들어올 때, 해당 request에서 새로 생성된 session에 아무 작업이 이루어지지 않은 상황)&lt;/span&gt;의 session을 강제 저장&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;아무 내용 없는 session이 계속 저장될 수 있음&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;u&gt;default : true&lt;/u&gt;-&amp;gt; client의 서버 방문 횟수에 따라 등급을 구분 짓는 기능 구현 가능&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;(참조 : &lt;a href=&quot;https://dalkomit.tistory.com/72&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dalkomit.tistory.com/72&lt;/a&gt; , &lt;a href=&quot;https://fierycoding.tistory.com/36&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://fierycoding.tistory.com/36&lt;/a&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;&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;&amp;middot; user.js 수정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1638332993564&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// routes/users.js

const express = require('express');
const router = express.Router();
const User = require('../models/User');

// Index
router.get('/', function(req, res){
  User.find({})
    .sort({username:1})
    .exec(function(err, users){
      if(err) return res.json(err);
      res.render('users/index', {users:users});
    });
});

// New
router.get('/new', function(req, res){
  const user = req.flash('user')[0] || {};
  const errors = req.flash('errors')[0] || {};
  res.render('users/new', { user:user, errors:errors });
});

// create
router.post('/', function(req, res){
  User.create(req.body, function(err, user){
    if(err){
      req.flash('user', req.body);
      req.flash('errors', parseError(err));
      return res.redirect('/users/new');
    }
    res.redirect('/users');
  });
});


// show
router.get('/:username', function(req, res){
  User.findOne({username:req.params.username}, function(err, user){
    if(err) return res.json(err);
    res.render('users/show', {user:user});
  });
});

// edit
router.get('/:username/edit', function(req, res){
  const user = req.flash('user')[0];
  const errors = req.flash('errors')[0] || {};
  if(!user){
    User.findOne({username:req.params.username}, function(err, user){
      if(err) return res.json(err);
      res.render('users/edit', { username:req.params.username, user:user, errors:errors });
    });
  }
  else {
    res.render('users/edit', { username:req.params.username, user:user, errors:errors });
  }
});

// update
router.put('/:username', function(req, res, next){
  User.findOne({username:req.params.username})
    .select('password')
    .exec(function(err, user){
      if(err) return res.json(err);

      // update user object
      user.originalPassword = user.password;
      user.password = req.body.newPassword? req.body.newPassword : user.password;
      for(const p in req.body){
        user[p] = req.body[p];
      }

      // save updated user
      user.save(function(err, user){
        if(err){
          req.flash('user', req.body);
          req.flash('errors', parseError(err));
          return res.redirect('/users/'+req.params.username+'/edit');
        }
        res.redirect('/users/'+user.username);
      });
  });
});


// destroy
router.delete('/:username', function(req, res){
  User.deleteOne({username:req.params.username}, function(err){
    if(err) return res.json(err);
    res.redirect('/users');
  });
});

module.exports = router;

// functions
function parseError(errors){
  const parsed = {};
  if(errors.name == 'ValidationError'){
    for(const name in errors.errors){
      const validationError = errors.errors[name];
      parsed[name] = { message:validationError.message };
    }
  }
  else if(errors.code == '11000' &amp;amp;&amp;amp; errors.errmsg.indexOf('username') &amp;gt; 0) {
    parsed.username = { message:'This username already exists!' };
  }
  else {
    parsed.unhandled = JSON.stringify(errors);
  }
  return parsed;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd01rM/btrmEjEzCwe/dyk543Y2kEue5YvIvNZjKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd01rM/btrmEjEzCwe/dyk543Y2kEue5YvIvNZjKk/img.png&quot; data-alt=&quot;new route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd01rM/btrmEjEzCwe/dyk543Y2kEue5YvIvNZjKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd01rM%2FbtrmEjEzCwe%2Fdyk543Y2kEue5YvIvNZjKk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;656&quot; height=&quot;150&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;new route&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user 생성 시에 에러가 있는 경우 new페이지에 에러와 기존에 입력했던 값을 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( 이때, 이 값들은 create route에서 생성된 flash로부터 받아옴 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flash는 배열이 오는데 이 프로그램에서는 하나 이상의 값이 저장되는 경우가 없고, 있더라도 오류이므로 무조건 &lt;span style=&quot;color: #009a87;&quot;&gt;[0]&lt;/span&gt;의 값을 읽어오게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;값이 없다면 (처음 new 페이지에 들어온 경우)&lt;/u&gt; &lt;span style=&quot;color: #ffffff; background-color: #333333;&quot;&gt;| | { }&lt;/span&gt;을 사용하여 빈 오브젝트를 넣어 user/new 페이지를 생성한다.&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b19UqO/btrmJkig9LE/nUzrDu33k2kKOm9KSk7kVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b19UqO/btrmJkig9LE/nUzrDu33k2kKOm9KSk7kVK/img.png&quot; data-alt=&quot;create route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b19UqO/btrmJkig9LE/nUzrDu33k2kKOm9KSk7kVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb19UqO%2FbtrmJkig9LE%2FnUzrDu33k2kKOm9KSk7kVK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;613&quot; height=&quot;273&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;create route&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user 생성시 &lt;span style=&quot;color: #ee2323;&quot;&gt;오류&lt;/span&gt;가 있으면 user, error flash를 만들고 new페이지로 redirect 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;user 생성시 발생하는 오류&lt;/u&gt;는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. User model의 userSchema에 설정해둔 validation을 통과하지 못한 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. mongoDB에서 오류를 내는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;-&amp;gt; 두 경우의 error객체의 형식은 상이하므로 &lt;b&gt;parseError&lt;/b&gt;라는 함수를 따로 만들어서 err을 분석하고 일정한 형식으로 만든다&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLfqg7/btrmCBMWtcG/X4OCLofupAZydAlTl9jXj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLfqg7/btrmCBMWtcG/X4OCLofupAZydAlTl9jXj0/img.png&quot; data-alt=&quot;edit route&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLfqg7/btrmCBMWtcG/X4OCLofupAZydAlTl9jXj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLfqg7%2FbtrmCBMWtcG%2FX4OCLofupAZydAlTl9jXj0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;995&quot; height=&quot;336&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;edit route&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user flash가 있으면 -&amp;gt; 1. update에서 오류가 생겨 edit으로 다시 돌아온 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(그래서 &lt;u&gt;기존에 입력했던 값&lt;/u&gt;으로 form에 값들을 생성해야 함 -&amp;gt;&lt;span style=&quot;background-color: #333333; color: #ffffff;&quot;&gt; | | { } &lt;/span&gt;사용 &lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt; )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 없으면 -&amp;gt; 2. 처음 들어온 경우로 가정&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;b&gt;req.flash(&lt;span style=&quot;color: #f89009;&quot;&gt;문자열&lt;/span&gt;)&lt;/b&gt;인 경우 -&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;해당 문자열&lt;/span&gt;에 저장된 값들을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;배열&lt;/u&gt;로 불러온다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;- 저장된 값이 없으면 빈 배열(&lt;span style=&quot;color: #ee2323;&quot;&gt;[ ]&lt;/span&gt;)을 return&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;2. 처음 접속하는 경우 (!user : user 변수에 값이 없음) -&amp;gt; DB에서 값을 찾아 form에 기본 값을 생성(=form을 user의 DB값들로 채움)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. update에서 오류가 생겨 edit 페이지로 돌아온 경우 -&amp;gt; user 변수의 값을 flash에서 받아옴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user을 사용해 값을 생성함(=update에서 입력했던 값으로 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;span style=&quot;color: #99cefa; background-color: #333333;&quot;&gt;username : req.params.username&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render시 username을 따로 req.params.username로 보내준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user.username이 (1) 해당 user의 username일수도, (2) user flash에서 받는 username일수도 있기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;username은 주소에서 찾은 username을 따로 보내준다.&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H2xUj/btrmHDQfi6X/W93kEyAMkbqPzJsMyR2gj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H2xUj/btrmHDQfi6X/W93kEyAMkbqPzJsMyR2gj0/img.png&quot; data-alt=&quot;function&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H2xUj/btrmHDQfi6X/W93kEyAMkbqPzJsMyR2gj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH2xUj%2FbtrmHDQfi6X%2FW93kEyAMkbqPzJsMyR2gj0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;828&quot; height=&quot;411&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;function&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mongoose에서 내는 에러와 mongoDB에서 내는 에러의 형태가 다르기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러의 형태를 &lt;span style=&quot;color: #ef5369;&quot;&gt;항목이름: { message: &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;if - mongoose의 model validation error&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;else if - mongoDB에서 username이 중복되는 error&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error code 11000 : key값이 중복될 때 발생하는 error)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;else - 그 외의 error을 처리함&lt;/p&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;출처및참조 : &lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1638340317429&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;Node JS 첫걸음/게시판 만들기: 게시판 - User Error 처리 - A MEAN Blog&quot; data-og-description=&quot;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&quot; data-og-host=&quot;www.a-mean-blog.com&quot; data-og-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; data-og-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.a-mean-blog.com/ko/blog/Node-JS-%EC%B2%AB%EA%B1%B8%EC%9D%8C/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EA%B2%8C%EC%8B%9C%ED%8C%90-User-Error-%EC%B2%98%EB%A6%AC&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;Node JS 첫걸음/게시판 만들기: 게시판 - User Error 처리 - A MEAN Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소스코드 이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.a-mean-blog.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;</description>
      <category>WEB/Node</category>
      <category>Express</category>
      <category>Flash</category>
      <category>nodeJS</category>
      <category>Regex</category>
      <category>정규표현식</category>
      <author>수잉</author>
      <guid isPermaLink="true">https://jonnastudy.tistory.com/100</guid>
      <comments>https://jonnastudy.tistory.com/100#entry100comment</comments>
      <pubDate>Wed, 1 Dec 2021 15:33:28 +0900</pubDate>
    </item>
  </channel>
</rss>