<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>매일 매일, 꾸준함의 힘</title>
    <link>https://devjooj.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 10 Jun 2026 15:59:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>데브쥬쥬</managingEditor>
    <item>
      <title>[AWS] CloudFront 캐싱 무효화 하는 방법</title>
      <link>https://devjooj.tistory.com/49</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;디자인팀에서 기존 s3에 올려놨던 이미지 파일을 변경해 달라고 요청이 들어왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일명은 같아서 기존 파일을 덮어씌우는 형태로 변경 후&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'변경완료했습니다~' 하고 피드백을 드렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왠걸? 주신 파일 그대로 변경했는데 변경이 안되었다고 연락이 왔고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'엥 난 변경했는데??' 생각하면서 이슈 확인이 시작되었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 30분 내로 원인 + 해결까지 완료&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 같은 파일명으로 변경 후, 변경 전 파일이 캐싱되어 있으면 캐싱이 만료되기 전까지는 변경 전 파일을 바라보게 된다는 점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 네트워크 응답 헤더를 통해 cloudfront를 통해 캐싱되었는지 확인할 수 있는 태그가 있다는 점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. cloudFront를 폴더별, 파일별로 무효화시키는 명령어가 있다는 점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해당 파일이 cloudFront에 의해 캐싱되어있는지 확인하는 방법&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 curl 명령어를 통해 확인했음. (브라우저 개발자 도구의 이미지 객체로도 확인 가능함)&lt;/p&gt;
&lt;pre class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;$ curl -I &amp;lt;cloudFront로 된 파일 경로&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-11-08 at 4.13.19 PM.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mhSbY/btsKAZpuw6H/E0GxwcpIJebYNalBRaZ8c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mhSbY/btsKAZpuw6H/E0GxwcpIJebYNalBRaZ8c0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mhSbY/btsKAZpuw6H/E0GxwcpIJebYNalBRaZ8c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmhSbY%2FbtsKAZpuw6H%2FE0GxwcpIJebYNalBRaZ8c0%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;635&quot; height=&quot;215&quot; data-filename=&quot;Screenshot 2024-11-08 at 4.13.19 PM.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;215&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;x-cache 태그에 `Hit From cloudfront` 라고 되어있으면 cloudFront 캐싱되어 있는다는 의미이다.&lt;/p&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;cloudFront 캐싱 무효화 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 로그인 후 안전하게 s3의 상단 clounShell(터미널 모양 아이콘) 클릭 후 접근한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 터미널에서 아래 명령어 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무효화 하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731050212420&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ aws cloudfront create-invalidation --distribution-id &amp;lt;cloudFront id&amp;gt; --paths &amp;lt;파일 또는 폴더 경로&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;cloudFront id:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AWS cloudFront의 배포 ID&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단일 파일 날리고 싶을 경우&lt;/b&gt;: cloudFront Url을 제외한 파일 경로 작성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;폴더 자체를 날리고 싶을 경우&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;/폴더명/* 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;결과: status: inProgress이면 성공&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무효화 확인하기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;$ aws cloudfront list-invalidations --distribution-id &amp;lt;cloudFront id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;결과: status== Completed이면 성공&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Server/AWS</category>
      <category>AWS</category>
      <category>CloudFront</category>
      <category>cloudfront캐싱무효화</category>
      <category>오블완</category>
      <category>티스토리챌린지</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/49</guid>
      <comments>https://devjooj.tistory.com/49#entry49comment</comments>
      <pubDate>Fri, 8 Nov 2024 16:24:50 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Global Accelarator 적용 후기</title>
      <link>https://devjooj.tistory.com/48</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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 적용 계기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근엔 프리랜서로 올해 글로벌 서비스 앱 런칭도 준비하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 개발자가 나혼자라 다양한 시도를 하며 고군분투 중이다. 어느새 6개월이 되어가고 있네 시간이 엄청 빠르다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 시드 투자를 받기 위해 투자자 미팅이 많은데,&amp;nbsp;대표님께서 미국 투자자 미팅 일정이 잡혀 갑자기 당장 내일 모레 뉴욕을 간다고 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한창 개발 중이라 운영 서버도 구축이 안되어있고,&amp;nbsp; 개발 서버도 서울 리전에 있는데, 뉴욕에서 성능이 괜찮을지 걱정이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서울&amp;nbsp; -&amp;gt; 서울리전 서버는 트래픽 성능이 좋겠지만, 뉴욕 -&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;기존에 이미지 최적화를 위해 CloudFront를 적용해놨지만, CloudFront는 정적 콘텐츠를 캐싱해주고, 캐싱되지 않은 데이터는 오리진으로 요청한다.&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;그래서 AWS에서 제공하는 서비스를 찾던 중 괜찮은 서비스를 발견했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Global Accelarator라는 서비스인데, 2개의 글로벌 정적 IP를 제공해준다. 이 IP를 우리 서버의 로드밸런서와 연결하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;사용자가 요청하는 위치와 가까운 엔드포인트로 자동 라우팅해줘서 letancy, 패킷 손실 같은 이슈를 방지해주는 최적화를 해주는 기능이다.&lt;/span&gt;&lt;/p&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;amp; 적용을 진행했다.&lt;/p&gt;
&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;기존 Client -&amp;gt; ALB -&amp;gt; EC2&amp;nbsp; 경로인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 후 Client -&amp;gt; Global Accelartor -&amp;gt; ALB -&amp;gt; EC2 경로로 적용했다.&lt;/p&gt;
&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-11-01 at 3.18.04 PM.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;1278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQQ8e4/btsKsyE951D/e7U9bkQvQEXRou1o5euYS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQQ8e4/btsKsyE951D/e7U9bkQvQEXRou1o5euYS0/img.png&quot; data-alt=&quot;노션에 정리해둔 서비스 적용 방법..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQQ8e4/btsKsyE951D/e7U9bkQvQEXRou1o5euYS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQQ8e4%2FbtsKsyE951D%2Fe7U9bkQvQEXRou1o5euYS0%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;303&quot; height=&quot;578&quot; data-filename=&quot;Screenshot 2024-11-01 at 3.18.04 PM.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;1278&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 테스트&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뉴욕에서 가시기 전에, 잘 적용되었는지 확인하고 싶은데 확인할 길이 없네?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 검색해본 결과 요즘 세상이 좋아져셔 미국 VPN 가상 서버로 우회하여 뉴욕에서 요청하는 것처럼 테스트가 가능했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷 검색하면 다양한 VPN 사이트를 찾을 수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, AWS 공식 사이트에서도 속도 분석 도구를 지원해주는데, 약 53% 향상된 결과로 나온다고 알려준다. &lt;a style=&quot;color: #000000;&quot; contenteditable=&quot;false&quot; href=&quot;https://speedtest.globalaccelerator.aws/#/&quot; data-token-index=&quot;1&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;AWS Global Accelerator Speed Comparison&lt;/span&gt;&lt;/span&gt;&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-11-01 at 3.29.36 PM.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m9mB6/btsKsYcPhf4/kNvlQqYkAMOdX4DKvpqtg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m9mB6/btsKsYcPhf4/kNvlQqYkAMOdX4DKvpqtg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m9mB6/btsKsYcPhf4/kNvlQqYkAMOdX4DKvpqtg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm9mB6%2FbtsKsYcPhf4%2FkNvlQqYkAMOdX4DKvpqtg0%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;670&quot; height=&quot;493&quot; data-filename=&quot;Screenshot 2024-11-01 at 3.29.36 PM.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 예상 비용&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타트업이라 한푼한푼 소중하기 때문에 비용도 고려하여 해당 서비스를 적용할지 결정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 대기업 계열사에서 근무할 때는 비용 관련된 고려를 해본 적이 없는데 인프라 비용 최적화의 중요성을 확실히 배우고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 약 1주일정도의 출장이셔서 1주일 사용 비용을 측정했는데 괜찮은 비용이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일주일 동안의 비용: 총 약 &lt;b&gt;$28.70&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고정요금: 168시간 x $0.025 = &lt;b&gt;$4.20&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간당 $0.025&lt;/li&gt;
&lt;li&gt;24시간 x 7일 = 168시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;미국 &amp;rarr; 서울 리전으로 데이터 전송 요금 (7일 * 24시간) : &lt;b&gt;$24.50&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;700GB x $0.035/GB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 결과&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표님께서 한국 시간으로 새벽 도착이셨음에도 불구하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 서버 성능이 좋지 않을까 걱정돼서 기다리다가 도착 슬랙 알림 울리자마자 앱 속도는 괜찮은지 여쭤봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄청 빠르다고 한 대표님의 안심되는 답변을 듣자마자 한시름 덜고 딥슬립... zZ&lt;/p&gt;</description>
      <category>Server/AWS</category>
      <category>AWS</category>
      <category>global accelarator</category>
      <category>백엔드</category>
      <category>인프라</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/48</guid>
      <comments>https://devjooj.tistory.com/48#entry48comment</comments>
      <pubDate>Fri, 1 Nov 2024 15:40:57 +0900</pubDate>
    </item>
    <item>
      <title>[Mac] MySQL root 비밀번호 변경하기</title>
      <link>https://devjooj.tistory.com/47</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;이슈&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- root 계정 비밀번호 까먹어서 접근 불가...&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&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;size14&quot;&gt;1. 혹시라도 mysql 서버가 켜져있지 않다면 실행시켜 주기&lt;/p&gt;
&lt;pre id=&quot;code_1712752653553&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ mysql.server start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;아래와 같이 뜨면 정상적으로 실행됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2024-04-10 at 9.39.05 PM.png&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BUvCF/btsGwc6BIfz/vxAR3kckpTuxQgYsPT3dkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BUvCF/btsGwc6BIfz/vxAR3kckpTuxQgYsPT3dkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BUvCF/btsGwc6BIfz/vxAR3kckpTuxQgYsPT3dkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBUvCF%2FbtsGwc6BIfz%2FvxAR3kckpTuxQgYsPT3dkK%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;530&quot; height=&quot;32&quot; data-filename=&quot;Screen Shot 2024-04-10 at 9.39.05 PM.png&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;2. 비밀번호 없이 root 계정에 접근하기&lt;/p&gt;
&lt;pre id=&quot;code_1712752712797&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ mysql - u root&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;size14&quot;&gt;3. database [mysql]에 접속&lt;/p&gt;
&lt;pre id=&quot;code_1712752879821&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ use mysql;&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;size14&quot;&gt;4. 새로운 비밀번호 변경 쿼리&lt;/p&gt;
&lt;pre id=&quot;code_1712752931346&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ alter user 'root'@'localhost' identified with mysql_native_password by '변경할 비밀번호 작성';&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;size14&quot;&gt;5. 현재 사용 중인 MySQL 새로운 설정을 적용 (ID, 패스워드 추가 &amp;amp; 수정될 경우는 환경 설정이 변경되었기 때문에 필요함)&lt;/p&gt;
&lt;pre id=&quot;code_1712753035395&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ flush privileges;&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;6. 확인하기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2024-04-10 at 9.44.36 PM.png&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ykJVR/btsGyfHYiYi/h62kBOo2T307mVoGowdfDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ykJVR/btsGyfHYiYi/h62kBOo2T307mVoGowdfDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ykJVR/btsGyfHYiYi/h62kBOo2T307mVoGowdfDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FykJVR%2FbtsGyfHYiYi%2Fh62kBOo2T307mVoGowdfDk%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;116&quot; height=&quot;166&quot; data-filename=&quot;Screen Shot 2024-04-10 at 9.44.36 PM.png&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <category>root계정비밀번호</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/47</guid>
      <comments>https://devjooj.tistory.com/47#entry47comment</comments>
      <pubDate>Wed, 10 Apr 2024 21:50:33 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Kinesis Data Streams 1분 요약 (개념, 예시, 그 외 비슷한 서비스 종류)</title>
      <link>https://devjooj.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;최근 면접 볼 일이 많았는데, 그중 프리랜서 면접 본 곳에서 AWS Kinesis를 통해 데이터 스트림 처리 관련 업무를 맡게 되는 곳이 있었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;(Kinesis라는 용어조차 처음 들었더니 발음을 잘 모르겠어서 AWS에 데이터 스트림 서비스라고 검색해 본 건 안 비밀...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;그만큼 모르는 분야였어서 이번 기회에 간략하게 정리해 보았다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;나와 비슷한 경험이 있는 사람들이 빠르게 아는 척하기에 딱 훑기 좋은 글이 되길 바라면서.. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  AWS Kinesis 개념&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 실시간 비디오 및 데이터 스트림을 수집, 처리 및 분석할 수 있는 완전관리형 AWS 서비스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;데이터 스트림을 일상생활에 비유를 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;내가 카페에 앉아 있고 주변에서 일어나는 모든 대화를 실시간으로 듣고 있다고 가정하면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;여기서 일어나는 각 대화들은 데이터 스트림으로 볼 수 있고, 내 뇌는 이 데이터를 실시간으로 처리하고, 중요한 정보를 분류하고 반응한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;뇌와 비슷한 역할을 하는 서비스가 AWS Kinesis라고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2024-04-07 at 4.08.50 PM.png&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kGOiX/btsGso6dueb/EqEx5P3zLkhpkcNM9hMYx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kGOiX/btsGso6dueb/EqEx5P3zLkhpkcNM9hMYx1/img.png&quot; data-alt=&quot; Kinesis Data Streams High-Level Architecture (출처: AWS 공식홈)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kGOiX/btsGso6dueb/EqEx5P3zLkhpkcNM9hMYx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkGOiX%2FbtsGso6dueb%2FEqEx5P3zLkhpkcNM9hMYx1%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;1154&quot; height=&quot;514&quot; data-filename=&quot;Screen Shot 2024-04-07 at 4.08.50 PM.png&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Kinesis Data Streams High-Level Architecture (출처: AWS 공식홈)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p id=&quot;terminology&quot; style=&quot;background-color: #ffffff; color: #16191f; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;Kinesis Data Streams 용어&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;size14&quot;&gt;*데이터 레코드(Data record)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;Kinesis 데이터 스트림에 저장되는 단위&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;데이터 레코드는 시퀀스 번호, 파티션 키 및 변경할 수 없는 바이트 시퀀스인 데이터 blob(최대 1MB)으로 구성됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*용량모드(Capacity mode)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;데이터 스트림 용량 모드는 용량이 관리되는 방식과 데이터 스트림 사용에 대한 요금이 청구되는 방식으로 결정됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;온디맨드 모드, 프로비저닝 모드 중에서 선택 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;온디맨드 모드 - 필요한 처리량을 제공하기 위해 샤드를 자동으로 관리 (사용한 실제 처리량에 대해서만 요금이 부과됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;프로비저닝 모드 - 데이터 스트림의 샤드 수를 지정해야 함, 데이터 스트림의 총용량은 해당 샤드 용량의 합계(샤드 수에 대해 시간당 요금 부과)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*보존 기간(Retention period)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;데이터 레코드를 스트림에 추가한 후 데이터 레코드에 엑세스할 수 있는 기간&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;기본: 24시간&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;최대 8760시간(365일) 가능(&lt;a style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; href=&quot;https://docs.aws.amazon.com/kinesis/latest/APIReference/API_IncreaseStreamRetentionPeriod.html&quot;&gt;IncreaseStreamRetentionPeriod&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;최소 24시간(&lt;a style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; href=&quot;https://docs.aws.amazon.com/kinesis/latest/APIReference/API_DecreaseStreamRetentionPeriod.html&quot;&gt;DecreaseStreamRetentionPeriod&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*생산자(Producer)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;레코드를 AWS Kinesis Data Streams에 저장하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;예를 들어, 스트림에 로그 데이터를 보내는 웹서버가 생산자&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*소비자(Consumer)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;AWS Kinesis Data Streams의 레코드를 가져와서 처리하는데, 이 소비자를 AWS Kinesis Data Streams 애플리케이션이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*AWS Kinesis Data Streams Applications&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;EC2 인스턴스의 플릿에서 공통적으로 실행되는 스트림의 소비자&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Kinesis Data Streams 애플리케이션의 출력은 다른 스트림의 입력이 될 수 있으며 실시간으로 데이터를 처리하는 복잡한 토폴로지를 생성할 수 있도록 해줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;또한, 애플리케이션은 다양한 다른 AWS 서비스에 데이터를 보낼 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;스트림 하나에 여러 애플리케이션이 있을 수 있으며 각 애플리케이션이 동시에 독집적으로 스트림의 데이터를 소비할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*샤드(Shard):&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스트림의 기본 데이터 처리 유닛&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;데이터 스트림으로부터 데이터 수집, 저장 처리하는 데 사용.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스트림의 처리량(Capacity)과 병철 처리 능력은 스트림에 포함된 샤드의 수에 결정된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;필요한 처리량에 따라 적절한 수의 샤드를 구성하여 스트림을 최적화할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;읽기의 경우 초당 최대 5개의 트랜잭션, 초당 최대 2MB의 총 데이터 읽기 속도&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;쓰기의 경우 초당 최대 1,000개의 레코드, 초당 최대 1MB의 총 데이터 쓰기 속도를 지원할 수 있음&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스트림의 데이터 용량은 스트림에 지정하는 샤드 수의 함수&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스트림의 총용량은 해당 샤드의 용량의 합계&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;*파티션 키(Partition Key)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스트림 내의 샤드에서 데이터를 그룹화하는 데 사용됨&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;최대 길이 제한 256자인 유니코드 문자열&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;파티션 키를 128비트 정수 값에 매핑하고, 샤드의 해시 키 범위를 사용하여 연결된 데이터 레코드를 샤드에 매핑하기 위해 MD5 해시 함수 사용&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;*시퀀스 번호(Sequence Number)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;각 데이터 레코드에는 샤드 내 파티션 키별로 고유한 시퀀스 번호가 있음&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;같은 파트션 키의 시퀀스 번호는 일반적으로 시간이 지나면서 증가, 쓰기 요청 간의 기간이 길수록 시퀀스 번호 커짐&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;  작동 방식 요약&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;1. 데이터 수집 (Input -&amp;gt; AWS Kinesis)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 여러 출처로부터 데이터가 Kinesis로 흘러들어오는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이 데이터들은 웹사이트 클릭, 센서 데이터, 금융 거래, 로그 파일 등 다양한 연속적인 데이터 스트림일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;(내가 면접 본 곳은 IoT 관련된 곳이었다 ㅎㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;2. 데이터 처리 및 분석 (&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;AWS Kinesis)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 흘러들어온 데이터는 Kinesis 시스템 내에서 처리되는데, &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;특정 조건을 충족하는 데이터를 필터링하거나, 데이터 조각(개별 레코드 또는 이벤트 등) 들을 합쳐서 더 큰 의미를 찾으며 분석한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 예를 들어, 데이터 스트림에서 직접 적용할 수 있는 간단한 데이터 변환, 집계 작업도 포함 가능(시간대별로 데이터를 집계하여 평균값을 계산한다는 등의 작업)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;3. 데이터 저장 및 사용(AWS Kinesis -&amp;gt; AWS s3, ElasticSearch, RedShift 등 서비스 -&amp;gt; Output)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 처리된 데이터는 분석을 위해 AWS의 다른 저장 서비스로 전송될 수 있다. &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;또한, 이 데이터를 사용하여 대시보드를 업데이트하거나, 알림을 보내는 등의 액션을 취할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 예를 들어, AWS S3에 저장된 데이터를 기반으로 Amazone Athena를 사용하여 SQL 쿼리를 실행하거나, Amazon QuickSight를 사용하여 대시보드를 생성하여 데이터를 시각화를 수행할 수 있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;*AWS RedShift: &lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;petaByte 규모의 데이터 웨어하우스 완전관리형 AWS 서비스, 복잡한 쿼리와 대량의 데이터 분석 작업을 빠르게 처리할 수 있음 (구조화된 데이터에 대한 분석 지원)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;*AWS ElasticSearch: 오픈 소스 검색 및 분석 엔진을 기반으로 하는 완전 관리형 AWS 서비스, &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;대규모 데이터셋에 대해 빠른 검색, 실시간 분석, 복잡한 쿼리, 로그 분석, 데이터 시각화 기능 제공(비구조화된 데이터인 텍스트, 로그 등의 검색과 분석을 위해 JSON형식의 쿼리를 사용)&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;  왜&amp;nbsp; AWS Kinesis를 사용하는가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;1) 다양한 데이터 소스와 유형 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Kinesis는 GA 같은 분석 시스템과 다르게 더 넓은 범위의 데이터 소스와 유형을 처리할 수 있다. IoT장비 데이터, 서버 로그, 소셜 미디어 피드 등 다양한 형태의 실시간 데이터를 처리하는데 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;2) 고성능 실시간 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 대량의 데이터를 실시간으로 처리하고 분석해야 하는 경우, Kinesis는 높은 처리량과 낮은 지연 시간을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;3) 맞춤형 데이터 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Kinesis를 사용하면 데이터 스트림 맞춤 설정하며, 특정 비즈니스 요구 사항이나 로직에 맞게 데이터를 처리하고 분석할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;  AWS Kinesis와 비슷한 다른 서비스들&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;1) Apache Kafka&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Apache Kafka는 고성능, 고신뢰성을 가진 분산 스트리밍 플랫폼이다. 대량의 데이터 스트림을 실시간으로 처리하고, 데이터를 저장하며, 여러 시스템과 데이터를 통합할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 높은 처리량, 빌트인 파티셔닝, 복제, 서버 간 밸런스 조정 등을 지원하고, 대규모 메시지 처리가 필요한 애플리케이션에 사용됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Kinesis와 차이점:&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;1. Kinesis는 완전 관리형 서비스지만, Kafka는 오픈 소스 플랫폼으로 사용자가 직접 설치, 설정, 운영 등 커스터마이징 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;2. Kinesis는 데이터 처리량, 샤드의 수, 저장 데이터의 양에 따라 비용이 결정되지만, Kafka는 소프트웨어 자체는 무료, 자체 서버 관련 인프라 비용이 발생함&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;3. Kinesis는 당연하게도 AWS 생태계 적극 활용 가능하여 다른 AWS 서비스와의 연동이 용이함, Kafka는 브로커(개별서버) 시스템을 통한 확장이 용이하여, 다양한 플러그인, 커뮤니티 지원을 통해 거의 모든 데이터 소스와 시스템에 연결할 수 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;결론은 Kinesis 서비스는 AWS 환경에서 빠르고 쉽게 스트림 처리 기능 구현하고 싶으면 사용하고, Kafka는 좀 섬세한 커스터마이징이 필요하고, 복잡한 스트림 처리 로직을 구현해야 하는 대규모 프로젝트에 적합할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* 빌트인 파티셔닝: 큰 데이터 스트림을 관리 가능한 작은 부분으로 세분화하는 작업&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;* 복제: 데이터의 안전을 위해 백업해 주는 것&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;* 서버 간 밸런스 조정(Load Balancing): 시스템의 부하를 고르게 분배하는 부하 분산 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2) Apache Flink&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 복잡한 데이터 스트림 처리를 위한 분산 처리 엔진, 실시간 스트리밍 데이터 처리뿐만 아니라, 배치 데이터 처리도 지원&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 고성능, 정확한 시간 관리, 고장 내성 등을 제공&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 스트림 처리의 정확성과 실시간 처리 능력이 핵심&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;3) Google&lt;/span&gt; Cloud Pub/Sub&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Google Cloud에서 제공하는 실시간 메시징 서비스&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 데이터 스트림을 쉽게 수집, 분석, 분산시키고 다양한 Google Cloud 서비스와 통합할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 글로벌 분산, 높은 가용성, 대규모 이벤트 스트림의 신속한 처리를 지원하고, 서버리스 아키텍처를 사용하여 관리가 용이함&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;4)&amp;nbsp;Microsoft Azure Event Hubs&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Azure Event Hubs는 Microsoft Azure에서 제공하는 대규모 이벤트 스트림 데이터 수집 서비스&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 높은 처리량의 이벤트나 데이터를 처리할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 수백만 개의 이벤트를 초당 처리할 수 있는 능력, 데이터 분석과 저장을 위한 실시간 스트림 처리 기능 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;5) Apache Pulsar&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Apache Pulsar는 분산 메시지 및 스트리밍 플랫폼&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- Kafka와 비교 시 멀티 테넌시, 지연 시간이 짧은 메시징, 서버리스 클라우드 네이티브 스트리밍, 분산된 영속성이 장점이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*멀티 테넌시&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;(Multi-tenancy): 단일 인스턴스의 소프트웨어 애플리케이션이나 서비스가 여러 사용자 또는 고객(테넌트)에게 서비스를 제공할 수 있는 아키텍처를 말함. 리소스 공유, 데이터 격리, 유연한 스케일링, 중앙에서의 효율적인 관리와 업데이트 가능&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;*메시지: 시스템, 서비스, 애플리케이션 간에 데이터를 실시간으로 교환하는 모든 형태의 메시징을 포함&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;오호,, 간략하게 요약해 봤는데, 굉장히 재미있는 내용이었던 걸 새삼 깨달았다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;역시나 이런 플랫폼을 경험해보지 못한 게 너무 아쉽다.. 꼭 앞으로는 경험해서 블로그에 실제 후기 작성하는 날이 오기를... &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Server/AWS</category>
      <category>AWS</category>
      <category>aws kinesis</category>
      <category>Kinesis</category>
      <category>데이터스트림처리</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/46</guid>
      <comments>https://devjooj.tistory.com/46#entry46comment</comments>
      <pubDate>Sun, 7 Apr 2024 16:35:47 +0900</pubDate>
    </item>
    <item>
      <title>[리눅스마스터 1급] 2023년 필기 합격 후기 &amp;amp; 시험 공부 방법</title>
      <link>https://devjooj.tistory.com/45</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  개요&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✍  시험을 보게 된 계기&lt;/b&gt;&lt;br&gt;회사에서 &lt;b&gt;AWS 업무를 배우게 되면서 다소 작은 장애들은 내 선에서 대응해야 할 일들이 생겼다.&lt;/b&gt;&lt;br&gt;&lt;b&gt;현재 생성된 인스턴스들의 os는 모두 ubuntu로 올라가 있는 상황&lt;/b&gt;이었다.&lt;br&gt;문제가 생겼을 시 당연히 리눅스 명령어 사용하여 원인 파악을 해야 하는지라&lt;br&gt;리눅스 지식이 어느 정도 필요해졌음을 느끼게 되었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이전에 알고 있던 명령어는 cd, cat, vi와 같이 정말 기본적인 명령어였기 때문에&lt;br&gt;예를 들어 out of memory라는 이슈가 생겨서 서버가 뻗었을 경우,&amp;nbsp; 어떤 명령어로 어떻게 찾아야 하는 건지 그때그때 구글링을 해서 급급하게 찾아보는 상황이었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이러저러한 이유로, 리눅스 기본기를 다지자 라는 마음으로 그냥 공부하려다가&amp;nbsp;&lt;br&gt;이왕이면 &lt;b&gt;관리자 영역까지 공부할 수 있는 리눅스 마스터 1급을 찾아봤다.&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;마침 &lt;b&gt;1년에 두 번 있는 리눅스 마스터 1급 올해 마지막 회차 접수기간이었고,&lt;/b&gt;&amp;nbsp;에라 모르겠다! 하고 저질러버렸다..&lt;br&gt;회사에서 지원도 해준다고 해서 그래! 공부하는 김에 성취감을 자격증으로 느껴보자..!! 싶은 마음에 시험을 준비했다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✍  시험의 필요성&lt;/b&gt;&lt;br&gt;실제로 필기에서 공부한 내용들이&amp;nbsp;실무 미팅에서 들리는 게 조금씩 많아졌고,&lt;br&gt;최근 AWS 시니어 개발자분들과 미팅 시에도 필기 공부할 때 학습한 단어들이 나와서 공부 전이었다면,&amp;nbsp; 응?? 무슨 소리지 ㅠ 했을 법한데,&lt;br&gt;바로 어떤 개념인지 알아들을 수 있어서 &lt;b&gt;역시 공부는 버릴 게 하나도 없구나 싶었다..&lt;/b&gt;&lt;br&gt;퇴근하고 잠도 못 자고 공부하니까 아 그냥 포기할까 라는 생각을 하고 있었는데, 저런 순간들이 나에게 동기부여, 힘이 되어주었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;혹시라도 리눅스 마스터 1급이 도움이 될까 의문을 품으신다면, &lt;b&gt;개발자라면 무조건 도움이 된다.&lt;/b&gt;라고 말씀드리고 싶다..&lt;br&gt;&lt;b&gt;아는 게 힘&lt;/b&gt;이라는 말처럼&lt;b&gt; 리눅스 마스터 1급을 공부하기 전과 후로 들리고 보이는 게 많아질 것&lt;/b&gt;이라고 분명 장담한다!&lt;br&gt; 특히&lt;b&gt; AWS관련 업무 시작하시는 리눅스초보자라면...!!&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  시험 정보&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✔️시험 일정&lt;/b&gt;&lt;br&gt;매년 2회의 시험이 있다.&lt;br&gt;2023년 리눅스 마스터 1차 시험은 이제 끝났고, 다음 1차 시험은 2024년 아마 상반기에 있을 예정이다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;1534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9eiaq/btstG9z6ps7/c346B8c9RIVkx3AvVvZpe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9eiaq/btstG9z6ps7/c346B8c9RIVkx3AvVvZpe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9eiaq/btstG9z6ps7/c346B8c9RIVkx3AvVvZpe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9eiaq%2FbtstG9z6ps7%2Fc346B8c9RIVkx3AvVvZpe0%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;639&quot; height=&quot;1534&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;1534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합격자 발표는 한 달 뒤에 난다.&lt;br&gt;하지만 문제지도 가지고 나올 수 있고, 가답안 공개를 시험 보고 3일 뒤에 알려주기 때문에 거의 미리 합격 여부를 판단할 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;또, 3일 뒤에 가답안이 공개되긴 하지만,&amp;nbsp;&lt;br&gt;오픈채팅방이 있어서 시험 끝나자마자 시험 본 사람들끼리 가답안을 맞춰보는데, 이 가답안이 거의 정답률 95%로 라고 한다&lt;br&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(리눅스 마스터는 워낙 문제 오류로 답이 바뀌는 경우가 많기 때문에 100%라고는 할 수 없다.)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;✔️ 시험 접수 비용&lt;/b&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1차 55000원, 2차 77000원 비싸다.&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt; (카드로 하면 카드수수료도 몇백 원 붙음)&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WQQxF/btstsQbOaLb/AJ46Oz2cjVOvYJZnauopZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WQQxF/btstsQbOaLb/AJ46Oz2cjVOvYJZnauopZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WQQxF/btstsQbOaLb/AJ46Oz2cjVOvYJZnauopZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWQQxF%2FbtstsQbOaLb%2FAJ46Oz2cjVOvYJZnauopZK%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;593&quot; height=&quot;316&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✔️ 시험과목&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tH1eQ/btstyjjcuZK/UQEzS4qTNgzuoF8LyNvsWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tH1eQ/btstyjjcuZK/UQEzS4qTNgzuoF8LyNvsWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tH1eQ/btstyjjcuZK/UQEzS4qTNgzuoF8LyNvsWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtH1eQ%2FbtstyjjcuZK%2FUQEzS4qTNgzuoF8LyNvsWK%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;561&quot; height=&quot;916&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험과목에 과락이 있다.. 100문제 중 60문 제 만 맞추면 되는데, 기출에서 70% + 신유형 30% 비율이라&lt;br&gt;기출문제를 최대한 많이 풀어봐서 최소 65%는 안정적으로 맞춘다는 생각으로 가야 한다.&lt;br&gt;최근 CentOS 7으로 버전이 변경된 지 얼마 안 돼서 더 힘들 것 같긴 하다..&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  시험 준비 기간&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;약 3주 동안 &lt;b&gt;-&amp;gt;&amp;nbsp; &lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;퇴근 후 &lt;/b&gt;&lt;/span&gt;&lt;u&gt;&lt;b&gt;주 3일 평균 2~3시간 &lt;/b&gt;&lt;/u&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;+ &lt;/b&gt;&lt;/span&gt;&lt;u&gt;&lt;b&gt;시험 2주 전부터의 주말은 7~8시간 정도 공부&lt;/b&gt;&lt;/u&gt;&lt;br&gt;시험은 접수일 마지막에 접수했고, 약 한 달이라는 기간 동안 준비했다.&lt;br&gt;회사를 다니면서 했고, 한 달 동안 업무, 회식, 문화데이도 겹쳐서&lt;br&gt;실제 공부 기간은 3주였고, 퇴근 후 주 3일 평균 2~3시간 + 시험 2주 전부터의 주말은 7~8시간 정도 공부하면서 준비했던 것 같다.&lt;br&gt;외울 것도 많고, 기출문제에서 많이 출제된다 해서 기출문제도 최소 2 회독은 추천한다고 하여 공부할 양이 정말 많았다..&lt;br&gt;2급은 안 봐서 모르겠지만, 리눅스를 처음 다루는 사람 입장에서 1급은 결코 만만한 시험이 아니었다..&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  시험공부 방법&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 도서 구매&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lrC77/btstx4s4jjB/n97gDlyMvj8a2HdyPM2PZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lrC77/btstx4s4jjB/n97gDlyMvj8a2HdyPM2PZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lrC77/btstx4s4jjB/n97gDlyMvj8a2HdyPM2PZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlrC77%2Fbtstx4s4jjB%2Fn97gDlyMvj8a2HdyPM2PZ1%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;246&quot; height=&quot;1150&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로는 잘 구매했다고 생각한다.&lt;br&gt;이 책은 다른 블로그 후기들에서 굳이 필요 없다고 해서 안 사려다가 회사에서 도서 지원 해줘서 그냥 구매했다.&lt;br&gt;기출문제 풀다가 부족한 개념 부분들은 책 보면서 개념정리를 다시 했기 때문에 나는 많은 도움이 된 책이다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✅ 기출문제 2 회독 &lt;/b&gt;&lt;b&gt;(2015년도 ~ 2023년도)&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;br&gt;&lt;b&gt;- 1 회독&lt;/b&gt;&lt;br&gt;1. 그냥 풀었다.&lt;br&gt;2. 틀린 부분 개념 학습 + 정답이 아닌 선택지들에 대한 개념까지 정리&lt;br&gt;3. 1번, 2번을 기출문제 3개 정도 풀면 다음 기출문제 풀 때부터는 맞는 개수들이 점차 늘어났다.&lt;br&gt;나의 공부 루틴: [개념정리-요약본] 한번 보기 -&amp;gt; 기출문제 1회 풀기 -&amp;gt; 틀린 문제 개념 학습 &amp;amp; 정리 -&amp;gt; [개념정리 - 요약본]&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;- 2 회독&lt;/b&gt;&lt;br&gt;&lt;b&gt;1. &lt;/b&gt;&lt;a href=&quot;https://www.comcbt.com/xe/r1&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;&lt;b&gt;최강 자격증 기출문제라는 사이트&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;b&gt;에서 7개년도 문제 랜덤 출제 기능 사용&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이렇게 내 이름으로 등록해서 풀면 기출문제 원하는 출제 연도 선택해서 100문제 랜덤으로 돌린 모의고사 기능을 제공해 준다!&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2548&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/us8pw/btstwjdseKf/2vkNy7yBJpooAAbS5dtu40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/us8pw/btstwjdseKf/2vkNy7yBJpooAAbS5dtu40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/us8pw/btstwjdseKf/2vkNy7yBJpooAAbS5dtu40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fus8pw%2FbtstwjdseKf%2F2vkNy7yBJpooAAbS5dtu40%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;565&quot; height=&quot;752&quot; data-origin-width=&quot;2548&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 틀린 문제에 대한 해설도 잘 되어있어서 그때그때 부족한 개념 추가 공부하기 좋다&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(그리고 해설 작성자들이 나처럼 일반인들이라, 외우기 힘든 개념들은 외우기 좋은 방식도 가끔 남겨줘서 이런 게 은근 도움이 되었다)&lt;/span&gt;&lt;br&gt;&lt;br&gt;아래 기출문제 빈출유형 정리하면서 명령어 옵션 진짜 다 외우기 벅차서 외우고 갈 곳과 버리고 갈 곳을 구분했는데,&lt;br&gt;아래와 같이 2과목은 웬만하면 다 명령어라... 주룩...&lt;br&gt;개념 공부할 때 아래 빈출되는 개념들을 위주로 공부했다!&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;1344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxDw8/btstxlIBjFg/ffVOEjmaY4bswlaH51E7pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxDw8/btstxlIBjFg/ffVOEjmaY4bswlaH51E7pk/img.png&quot; data-alt=&quot;기출문제 7개년도 하면서 평균치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxDw8/btstxlIBjFg/ffVOEjmaY4bswlaH51E7pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxDw8%2FbtstxlIBjFg%2FffVOEjmaY4bswlaH51E7pk%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;496&quot; height=&quot;1344&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;1344&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기출문제 7개년도 하면서 평균치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✅ 개념정리&lt;/b&gt;&lt;br&gt;&lt;b&gt;개념정리 시 꿀팁!이라고&lt;/b&gt; 하기엔 뭐 없지만..&lt;b&gt;.&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;1) 2과목 명령어 외울 때 무작정 외우기보다는 그 명령어가 어떤 단어를 축약해 놓은 건지? 생각하면서 외우기&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp; &amp;gt;&amp;gt; 예를 들어 삭제할 때&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;u&gt;옵션이 -d 이면&amp;nbsp;&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;u&gt;&lt;b&gt;delete&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;u&gt;를 줄여서 -d이다.&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이렇게 외우면 잘 외워지고&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp;&amp;gt;&amp;gt; 같은 삭제 옵션인데&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;u&gt;각 명령어마다 -r (remove) , -d(delete) 이렇게 다르게 쓰는 경우&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;가 있다.&lt;/span&gt;&lt;br&gt;시험에도 이 허점을 노려서 잘 나오니 이런 옵션들은 더 주의 깊게 외워야 한다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;2) 다른 사람의 요약본을 보더라도 꼭! 자기만의 스타일로 한번 정리하기&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #333333;&quot;&gt;마지막 한주동안은&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;u&gt;&lt;b&gt;요약본 +&amp;nbsp; 없는 개념 별도로 정리한 최종 정리본만&lt;/b&gt;&lt;/u&gt; 훑었다.&lt;br&gt;&amp;gt;&amp;gt; 2022년, 2023년 최신 기출문제 학습하면서 자기 스스로 추가로 개념정리를 해야 한다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;인터넷에 1차 필기 요약본 잘 정리된 게 정말 많다. 어쩜 그리 다들 정리를 잘하시는지..&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;아래 블로그 분 요약본&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(약 2021년까지의 개념을 정리)&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;으로 추가 공부했는데,&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt; 개념별로 출제된 년도 부분도 표시해 주셔서 너무 좋았다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;나는 나중에 시험 1주 전에 개념정리를 다 공부하고 나서 보게 된 케이스라,&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;나중에 쓱-한번 빠르게 훑는 용도로 잘 썼지만,&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;리눅스 마스터 1급은 매년 새로운 문제가 30% 정도 출제되는데 &lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;아래 요약본은 2021년도까지의 내용만 정리되어 있어서&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;최신 문제에 대한 개념 &amp;amp; 보안 관련 개념은 별도로 정리하거나 다른 요약본을 찾으시길...&lt;/span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=is_king&amp;amp;logNo=221383568264&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=is_king&amp;amp;logNo=221383568264&lt;/span&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;리눅스마스터 1급 1차(필기) 정리 요약집&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;리눅스마스터 1급 정리(수정-200226)...&quot; data-og-host=&quot;blog.naver.com&quot; data-og-source-url=&quot;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=is_king&amp;amp;logNo=221383568264&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eWsAw/hyTSu6ZmZQ/JjM8yLrFCtKS0eZPkwX2M1/img.png?width=270&amp;amp;height=270&amp;amp;face=0_0_270_270&quot; data-og-url=&quot;https://blog.naver.com/is_king/221383568264&quot;&gt;&lt;a href=&quot;https://blog.naver.com/is_king/221383568264&quot; target=&quot;_blank&quot; data-source-url=&quot;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=is_king&amp;amp;logNo=221383568264&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eWsAw/hyTSu6ZmZQ/JjM8yLrFCtKS0eZPkwX2M1/img.png?width=270&amp;amp;height=270&amp;amp;face=0_0_270_270')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;리눅스마스터 1급 1차(필기) 정리 요약집&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;리눅스마스터 1급 정리(수정-200226)...&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;blog.naver.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;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  시험 후기&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 시험 장소&lt;/b&gt;&lt;br&gt;인천바이오과학고등학교에서 시험을 봤다.&lt;br&gt;주차가 안 돼서 근처로 주차했다.. 집에서 차로 약 30분 거리인데, 지하철로 1시간 넘게 걸려서 차를 타고 갔다.&lt;br&gt;주차가 안된다는 게 조금 당황스러웠지만, 바로 앞 상가 주차장이 꽤 크고, 심지어 무료여서 다행이었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(대신 나는 1시에 차를 대서 주차장에 자리가 있었지만 시험 시작 시간이 다가올수록 주차장에 자리가 없을 것 같은 느낌이었다.)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✅ 필수 준비물: 신분증 &amp;amp; 컴퓨터용 사인펜&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;신분증 없으면 시험 못 본다. (수험표는 없어도 된다.)&lt;/b&gt;&lt;/span&gt;&lt;br&gt;컴퓨터용 사인펜 없으면 감독관님께 요청해야 하는데, 우리 시험장 감독관님께서는 갖고 계셔서 다행히 누군가 빌리셨지만&lt;br&gt;없으시면 곤란할 것 같다.&lt;br&gt;&amp;nbsp;&lt;br&gt;안 갖고 오신 분은 학교 앞 상가 문구점에서 구매하려고 했지만, 당일 품절이라 못 사셨다고 한다.&lt;br&gt;이런 경우도 있어서 동네에서 사 갖고 오면 안전할 것 같다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✅ 퇴실&lt;/b&gt;&lt;br&gt;- 중도 퇴실 (14:50분부터 가능)&lt;br&gt;- 문제지 갖고 나가기 가능&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;✅ 시험 최종 후기&lt;/b&gt;&lt;br&gt;- 기출문제만 제대로 보고 가면 60점 이상은 맞을 수 있을 것 같다.&lt;br&gt;- 서브넷 관련 문제가 2개나 나와서 당혹스러웠다(나는 버리고 간 문제라..)&lt;br&gt;- 이번엔 명령어 중에 -l, -L 이렇게 소문자 대문자 헷갈리는&amp;nbsp; 명령어들이 많이 나왔다.. 무려 3문제나 나옴.. &lt;br&gt;&lt;br&gt;✅ &lt;b&gt;결과는 합격…&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kAHnT/btsyuiNuili/uHkCi42PInFsMnwfNYYcpK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kAHnT/btsyuiNuili/uHkCi42PInFsMnwfNYYcpK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kAHnT/btsyuiNuili/uHkCi42PInFsMnwfNYYcpK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkAHnT%2FbtsyuiNuili%2FuHkCi42PInFsMnwfNYYcpK%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;838&quot; height=&quot;519&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 2차는 다음에 준비할 것 같다…&lt;br&gt;일단은 aws자격증이 중요하기 때문에…..&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
      <category>자격증/리눅스마스터 1급</category>
      <category>리눅스마스터</category>
      <category>리눅스마스터1급</category>
      <category>시험후기</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/45</guid>
      <comments>https://devjooj.tistory.com/45#entry45comment</comments>
      <pubDate>Sun, 10 Sep 2023 16:14:37 +0900</pubDate>
    </item>
    <item>
      <title>[리눅스마스터 1급] 16/03/12 기출 - 3과목 정리</title>
      <link>https://devjooj.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp;파일 공유를 위한 서비스 및 프로토콜 -&lt;/b&gt; SAMBA, NFS(Network File System), FTP(File Transport Protocol)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;&lt;b&gt;SAMBA&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GPL 기반의 자유 소프트웨어로 리눅스와 윈도우 간 디렉토리, 파일,, 프린터 등 공유에 사용&lt;/li&gt;
&lt;li&gt;TCP/IP 기반으로 NetBIOS상에 동작하는 SMB(Server Message Block) 프로토콜 이용&lt;/li&gt;
&lt;li&gt;삼바에서 설정한 그룹과 호스트명이 윈도우의 Network Neighborhood에 컴퓨터 이름으로 표시된다, 또한 삼바를 이용하면 상대의 호스트의 IP 주소 대신 컴퓨터 이름을 이용하여 접속 가능 (WINS- Windows Internet Name Service)&lt;/li&gt;
&lt;li&gt;CIFS(Common Internet File System)은 SMB를 인터넷까지 확장한 표준 프로토콜, 유닉스와 윈도우 환경 동시 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;삼바 서버&lt;/b&gt; 구성 요소&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;nmbd
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UDp 137, 138 포트 이용&lt;/li&gt;
&lt;li&gt;WINS 서비스를 위한 데몬&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;smbd
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삼바 프로토콜의 주요 기능 담당&lt;/li&gt;
&lt;li&gt;TCP 445 포트 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 삼바 서비스 이용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a) 삼바 서버 접속: &lt;b&gt;smbclient&lt;/b&gt; 명령어 이용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트 공유 폴더 이름 지정 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;tex&quot;&gt;&lt;code&gt;smbclient //192.168.12.22/[공유폴더]

# 단, \\를 이용할 경우 \\ 2개씩 이용
smbclient \\\\\\\\192.168.12.22\\\\[공유폴더]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b) 삼바 사용자 목록 및 세부 내용 확인: &lt;b&gt;pdbedit&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# pdbedit -L
posein:500:
yuloje:501:

# 옵션
    - L : 등록된 삼바 사용자 목록 조회
    - v : 사용자 목록 출력 시 상세한 정보 표시
    - u : 사용자 이름 지정
    - a : 삼바 사용자 계정 추가, 패스워드 설정(반드시 리눅스 시스템에 등록된 계정이어야 함)
    - r : 삼바 사용자 계정 변경
    - x : 삼바 사용자 계정 제거
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c)&amp;nbsp; 삼바 계정 &amp;amp; 패스워드 설정: &lt;b&gt;smbpasswd&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반드시 리눅스 시스템에 등록된 계정이어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;NFS (Network FileSystem)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP를 이용하여 원격 호스트(컴퓨터)의 파일 시스템을 마치 로컬 호스트(PC)에 있는 것처럼 Mount하여 사용할 수 있는 서비스.&lt;/li&gt;
&lt;li&gt;RPC(Remote Procedure Call)을 이용하여 NFS 관련 명령어를 전달하므로 rpcbind 데몬 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;주요 패키지&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;rpcbind: rpcbind, rpcinfo 등 명령어 포함&lt;/li&gt;
&lt;li&gt;nfs-utils: nfs 관련 데몬 및 명령어 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;NFS 서버 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/exports 파일 - NFS 서비스 설정용&lt;/li&gt;
&lt;li&gt;# 주요 옵션 **시험 단골: root 사용자의 접근 권한 설정 항목 - no_root_squash: root 접근 허용 - root_squash: root 권한 접근 거부하기 위하여 클라이언트 root 요청을 기본값(nobody)로 매핑 -&amp;gt; 즉, 일반 사용자 권한 - anounuid: 특정 계정의 권한(uid)를 허용 - all_squash:NFS클라이언트에서 접근하는 모든 사용자(root포함)의 권한을 nobody로 매핑시킨다. -&amp;gt; 예외없이 모든사용자 === 일반사용자&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;NFS 서비스 이용&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mount 명령어 이용&lt;/li&gt;
&lt;li&gt;mount -t nfs [NFS 서버] : [대상(공유된) 디렉토리] [마운트 디렉토리] *ps. mount -t nfs -&amp;gt; mount.nfs 로 대체 가능 # 예시 mount -t nfs 192.168.13 : /joon /mnt&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;FTP (File Transport Protocol)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;특징&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP를 이용하여 FTP 서버 &amp;amp; 클라이언트 간 파일 전송을 위한 프로토콜.&lt;/li&gt;
&lt;li&gt;등록된 사용자만 접속 O (단, 익명의 사용자 지원 O &amp;rarr; 보안 취약 O, 권장 X)&lt;/li&gt;
&lt;li&gt;vsfpd(Very Secure FTP Daemon) : 대표 FTP 프로그램, CentOS에서 기본 제공&lt;/li&gt;
&lt;li&gt;ㄴ 보안 중요시 함, 익명 사용자 디렉터리 권한 777 &amp;rarr; 로그인 제한 O&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;FTP 패키지 설치&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vsftpd 파일 목록
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/vsftpd/ftpusers : ftp서버에 접근할 수 없는 계정 목록 파일 (PAM 연관된 설정 파일)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp;메일 서비스 관련 프로토콜 (SMTP, POP, POP3, IMAP)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;SMTP (Simple Mail Transfer Protocol) - TCP 25번 포트 이용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터넷에서 이메일을 전송하기 위해 사용하는 프로토콜&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;POP , POP3 - TCP 110번 포트 이용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메일 서버에 도착한 메일을 수신하는 프로토콜&lt;/li&gt;
&lt;li&gt;클라이언트 프로그램으로 메일을 가져온 후 서버에서 해당 메일 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;IMAP - TCP 143번 포트 이용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메일 서버에 도착한 메일을 수신하는 프로토콜&lt;/li&gt;
&lt;li&gt;서버에 일단 남겨두고 나중에 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;Tip&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;POP3 및 IMAP에서 사용하는 서버 프로그램 : dovecot&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp;메일 서비스&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;sendMail&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;****주요 설정파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/alliases: 메일의 별칭 혹은 특정 계정으로 수신한 이메일을 다른 계정으로 전달하도록 설정&lt;/li&gt;
&lt;li&gt;# 예시 - webmaster: ihduser, kalituser - admin: include:/etc/main_admin&lt;/li&gt;
&lt;li&gt;/etc/mail/local-host-names: sendmail에서 수신할 메일의 &lt;b&gt;도메인과 호스트, 즉 메일 수신자를 설정&lt;/b&gt;하며 sendmail을 다시 시작하여 적용&lt;/li&gt;
&lt;li&gt;/etc/mail/access: 메일 서버에 접속하는 &lt;b&gt;호스트의 접근을 제어하는 설정 파일&lt;/b&gt;로 &lt;b&gt;스팸 메일 방지&lt;/b&gt; 등에 사용 가능&lt;/li&gt;
&lt;li&gt;makemap hash /etc/mail/access&lt;/li&gt;
&lt;li&gt;/etc/mail/virtusertable: &lt;b&gt;가상의 메일 계정&lt;/b&gt;으로 들어오는 메일을 특정 계정으로 전달하는 정보 설정&lt;/li&gt;
&lt;li&gt;makemap hash /etc/mail/virtusertable&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;주요 명령어&lt;/li&gt;
&lt;li&gt;1) sendmail - sendmail을 관리하는 명령어 - 옵션: -bq(메일 큐 상태 표시), -b(alliases정보갱신), -oQ(특정 큐의 상태 표시) 2) mailq - 메일 큐의 내용을 표시하는 명령어 - mailq -Ac: /etc/mail/submit.cf 파일에 지정된 큐의 상태 표시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메일 서비스 관련 프로그램
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MTA (Mail Transfer Agent)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SMTP 프로토콜 이용하여 메일 전송&lt;/li&gt;
&lt;li&gt;sendmail, qmail, postfix&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MDA (Mail Delivery Agent)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일종의 대리인 역할 수행, 메일 박스에 도착한 메일을 대행해서 가져오거나 전달하는 역할 수행&lt;/li&gt;
&lt;li&gt;대표 프로그램: procmail &amp;rarr; 스팸 메일 필터링, 메일 정렬 등의 역할도 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MUA (Mail User Agent)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 메일을 수신 혹은 발신할 때 사용하는 프로그램&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메일 암호화 관련 도구: Nmap&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp;DNS (Domain Name Service)&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인 이름과 IP 주소를 상호 변환하는 서비스&lt;/li&gt;
&lt;li&gt;TCP 53, UDP 53을 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DNS 서버 종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Primary Server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Master Server&lt;/li&gt;
&lt;li&gt;필수 항목&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Secondary Server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Slave Server&lt;/li&gt;
&lt;li&gt;Primary Server의 zone 파일 백업&lt;/li&gt;
&lt;li&gt;Master DNS에 문제가 있을 경우 보조 DNS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Caching Name Server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인을 소유하지 않아도 구성 가능&lt;/li&gt;
&lt;li&gt;도메인 관리 없이 resolving 역할만 수행&lt;/li&gt;
&lt;li&gt;속도를 향상시키는 역할&amp;rarr; DNS 관련 질의가 많은 경우 해당 서버를 구성하여 인터넷 사용 속도 &amp;uarr;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DNS 서비스 이용
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;패키지 설치&lt;/li&gt;
&lt;li&gt;# DNS 서버 프로그램 : bind # 데몬: named # 설치 명령어 yum -y install bind # 설치 후 bind, bind-libs, bind-utils 패키지 설치&lt;/li&gt;
&lt;li&gt;bind 관련 파일과 디렉토리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/named.conf
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DNS 서버의 주요 환경 설정 역할 &amp;rarr; zone 파일, Reverse zone 파일 포함&lt;/li&gt;
&lt;li&gt;options
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DNS로 운영 중인 현재 시스템 외에는 네임 서버에 대한 질의를 허가하지 않으려고 할 때 옵션&lt;/li&gt;
&lt;li&gt;allow-query: {localhost}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;zone 파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포함: 도메인 이름, ip주소, 관련 리소스 간 매핑, 리소스 레코드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dns&quot;&gt;&lt;code&gt;# ZONE 파일 설정 일부
www IN A 192.168.12.22
WWW1 IN CNAME WWW
WWW2 IN CNAME WWW
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Reverse zone 파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP주소에 대한 도메인 정보 조회&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;명령어&lt;/li&gt;
&lt;li&gt;# 문법적 오류 검사 $ named-checkconf&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;/var/named
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;root 도메인 서버의 정보를 담은 &lt;a href=&quot;http://named.ca&quot;&gt;named.ca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;사용자가 설정한 zone 파일 등 저장하는 디렉토리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp;가상화 관리 서비스 (Virtualization)&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU , 메모리 , 디스크와 같은 물리적인 자원을 &amp;rarr; 여러개의 논리적인 자원으로 나눔&lt;/li&gt;
&lt;li&gt;또는, 다수의 물리적인 자원을 &amp;rarr; 하나의 논리적인 자원으로 통합하는 서비스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특징
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;논리적인 자원(Resource Pool)에 기반한 효율적인 자원 활용, 물리적인 공간 절약, 데이터 및 서비스에 대한 가용성 증가, 중앙 집중 관리에 따른 보안성 향상 등의 장점 제공&lt;/li&gt;
&lt;li&gt;대표적인 특징
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공유: 다수의 많은 가상 자원들이 하나의 동일한 물리적 자원과 연결, 가리키는 것을 의미&lt;/li&gt;
&lt;li&gt;프로비저닝: 사용자의 요구사항에 맞게 할당, 배치, 배포, 가상화 기반의 자원 할당은 물리적 단위보다 더 세밀한 조각 단위로 가능&lt;/li&gt;
&lt;li&gt;단일화&lt;/li&gt;
&lt;li&gt;애뮬레이션: 물리적 자원 자체는 원래부터 존재하지 않았지만, 가상 자원은 어떤 기능들이나 특성들을 마치 처음부터 존재했던 것처럼 가질 수 있다.&lt;/li&gt;
&lt;li&gt;절연: 하나의 가상화 서비스에 문제가 발생하여도 다른 서비스로 장애가 전이되지 않도록 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가상화 서비스 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어 레벨의 가상화 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VMM(Virtual Machine Monitor)이 물리적인 하드웨어를 가상머신의 하드웨어와 매핑, 게스트 운영체제의 자원 사용 관리&lt;/li&gt;
&lt;li&gt;종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전가상화(Full Virtualization)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU의 물리적 가상화 지원 기능을 이용하여 하드웨어를 완전히 가상화&lt;/li&gt;
&lt;li&gt;윈도우, 리눅스 등 다양한 게스트 OS를 수정없이 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;반가상화(Para Virtualization)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게스트 OS는 하이퍼바이저에 하드웨어의 제어를 요청하여 동작&lt;/li&gt;
&lt;li&gt;하이퍼바이저가 하드웨어 사용을 통제하므로 상대적으로 높은 성능&lt;/li&gt;
&lt;li&gt;게스트 OS수정 필요, 리눅스 등 오픈소스가 주로 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;호스트 기반 가상화 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트 운영체제에 VMM을 설치하고 가상 머신을 생성&lt;/li&gt;
&lt;li&gt;종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VirtualBox, VMware Player&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;운영체제 가상화 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어에 설치된 하나의 운영체제 위에 가상화 계층을 두어 가상화 서비스를 제공&lt;/li&gt;
&lt;li&gt;종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트 운영체제의 커널을 공유, 각각의 애플리케이션 별로 격리된 컨테이너 생성&lt;/li&gt;
&lt;li&gt;경량화 된 가상화 방식&lt;/li&gt;
&lt;li&gt;예시- Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하드웨어 에뮬레이션 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어를 소프트웨어 방식으로 에뮬레이션 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리눅스 대표 가상화 기술
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KVM
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인텔 CPU 지원&lt;/li&gt;
&lt;li&gt;VT-X &amp;amp; VMD-V 기반 CPU 전가상화 지원 기술 (리눅스 커널 2.6.20 이후)&lt;/li&gt;
&lt;li&gt;CPU 반가상 기술 지원 X&lt;/li&gt;
&lt;li&gt;이더넷, Disk I/O, 그래픽 등 반가상화 지원&lt;/li&gt;
&lt;li&gt;호스트 서버에서 보면 게스트 서버는 하나의 프로세스로 간주되기 때문에 오버헤더 거의 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;XEN
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1990년대 케임브리지 대학교, 오픈소스&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU 전가상화, 반가상화 모두 지원 &amp;rarr; 하이퍼바이저 기반의 가상화 기술&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;리눅수, 윈도우, Solaris 모두 지원&lt;/li&gt;
&lt;li&gt;반가상화 구성 시 &amp;rarr; 호스트와 다른 아키텍처의 게스트 실행 x&lt;/li&gt;
&lt;li&gt;전가상화 구성 시 &amp;rarr; QEMU 기반 동작&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VirtualBox
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오라클 주도&lt;/li&gt;
&lt;li&gt;x86 기반 가상화 소프트웨어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Docker
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하이퍼바이저, 게스트 운영체제 설치 필요 X&lt;/li&gt;
&lt;li&gt;서버 운영에 필요한 프로그램 &amp;amp; 라이브러리만 이미지로 &amp;rarr; 프로세스처럼 동작&lt;/li&gt;
&lt;li&gt;경량화된 가상화 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;/proc/cpuinfo
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flag값으로 CPU 가상화 지원 여부 점검 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;egrep 'svm|vmx' /proc/cpuinfo

- svm: AMD-V
- vmx: Intel VT-v
결과
flags :::블라블라
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;가상화 주요 명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;virt-top
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상화 현황 top과 유사한 형식으로 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;virsh&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;텍스트 기반의 콘솔 환경에서 가상 머신 관리 도구 (&lt;b&gt;생성, 시작, 재시작, 종료, 강제 종료&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;virt-manager
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 머신을 손쉽게 시작 및 종료 가능&lt;/li&gt;
&lt;li&gt;가상머신의 cpu 사용량, 호스트 cpu사용량 모니터링 할수 있는 GUI기반 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;libvirt
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Linux에서 가상화 지원을 위한 api, 데몬, 라이브러리, 관리 툴들 모음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;libvirtd
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;libvirt 관리시스템의 서버 데몬으로 관리도구와 통신하여 원격 도메인의 명령어 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;xm&lt;/li&gt;
&lt;li&gt;xen관리하는 명령어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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; &amp;nbsp;&lt;b&gt;슈퍼 데몬&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;inetd와 같이 다른 서비스를 실행 및 관리하는 데몬
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리눅스의 inetd방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 요구에 따라 필요한 서비스 실행&lt;/li&gt;
&lt;li&gt;요청 완료 시 서비스 종료 &amp;rarr; 시스템 자원 효율 &amp;uarr;&lt;/li&gt;
&lt;li&gt;standalone 방식에 비해 사용자 요청 처리시간 느림&lt;/li&gt;
&lt;li&gt;but, 다양한 서비스를 제한된 시스템 자원으로 운영하기에 효율 &amp;uarr;&lt;/li&gt;
&lt;li&gt;/etc/inetd.conf 에서 서비스 사용 여부 지정, 접근 제어 (TCP WRAPPER) 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CentOS7 서비스 관리 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;systemd 방식 &amp;rarr; 소켓기능(ondemand activation)을 통해 효율적으로 메모리 관리 가능&lt;/li&gt;
&lt;li&gt;기존 xinetd를 통해 제공하던 rsync, telnet등의 서비스 &amp;rarr; systemd 방식으로 통합&lt;/li&gt;
&lt;li&gt;xinetd, TCP Wrapper를 제공하는 서비스가 제한적, 접근제한이 필요할 경우 이후 iptables, fireawlld사용 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;xinetd (CentOS7 이후로 해당 방식 중요성 낮음)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP 주소 당 접속 수 제한&lt;/li&gt;
&lt;li&gt;DOS 공격에 대비한 설정 제공&lt;/li&gt;
&lt;li&gt;서비스에 대한 접속 시간 제한&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; &amp;nbsp;&lt;b&gt;프록시 서비스&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트와 서버 사이에 위치&lt;/li&gt;
&lt;li&gt;요청과 응답 과정에서 데이터를 중계하는 역할 담당&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;목적
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버의 데이터를 캐시하여 인터넷 전송 속도를 빠르게 하기 위해 사용&lt;/li&gt;
&lt;li&gt;서버의 가용성 향상을 위한 부하분산에 사용 가능&lt;/li&gt;
&lt;li&gt;사용 분야
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;응답 속도 향상&lt;/li&gt;
&lt;li&gt;서버 부하 분산 &amp;rarr; 다수의 서버를 서버팜으로 구성하여 정해진 규칙에 따라 클라이언트의 요청을 특정 서비스 요청으로 전달&lt;/li&gt;
&lt;li&gt;접근 통제 &amp;rarr; 프록시 서버에 설정한 접근 통제 정책에 따라 요청 제한&lt;/li&gt;
&lt;li&gt;악성 코드 유입 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리눅스 프록시 서버(squid)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리눅스에서 사용할 수 있는 대표적인 프록시 서버&lt;/li&gt;
&lt;li&gt;GPL 오픈소스 소프트웨어&lt;/li&gt;
&lt;li&gt;캐싱을 통해 HTTP, FTP, gopher 등 서비스의 데이터 응답 속도 향상&lt;/li&gt;
&lt;li&gt;TCP 3128 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;DHCP 서비스 (Dynamic Host Configuration Protocol)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트 호스트가 사용할 IP 주소, 게이트웨이 주소, 네임서버 주소 등을 자동으로 할당하는 속도&lt;/li&gt;
&lt;li&gt;제한된 IP주소 풀을 다수의 클라이언트에게 동적으로 할당하여 IP주소 사용의 효율을 향상 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DHCP 프로토콜을 이용하여 IP 주소 임대기간 설정 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;저장 장치가 없는 호스트에게 IP 자동 부여, 네트워크 부팅 지원하기 위해 사용 가능 &amp;rarr; BOOTP(Bootstrap Protocol) 사용&lt;/li&gt;
&lt;li&gt;UDP 프로토콜과 브로드캐스트 통신 방식 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서비스 설정 파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/dhcp/dhcpd.conf
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설정 문장 뒤에는 반드시 세미콜론 필수&lt;/li&gt;
&lt;li&gt;주요 설정 항목
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;option routers : 게이트 웨이 주소 지정&lt;/li&gt;
&lt;li&gt;# vi /etc/dhcpd.conf options routers 192.168.12.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;VNC (Virtual Network Computing) 서비스&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비트맵 이미지 기반의 RFB(Remote Frame Buffer) 프로토콜 이용&lt;/li&gt;
&lt;li&gt;GUI방식으로 원격 컴퓨터 접속 기능&lt;/li&gt;
&lt;li&gt;TCP/5900+[디스플레이번호]&lt;/li&gt;
&lt;li&gt;동시에 여러 클라이언트가 접속하여 화면 공유 가능&lt;/li&gt;
&lt;li&gt;VNC 클라이언트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 화면에 전송받아 표시, 마우스 키보드 등 컨트롤 정보를 &amp;rarr; 서버로 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;VNC 서버
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 컴퓨터의 화면을 공유하기 위해 사용&lt;/li&gt;
&lt;li&gt;VNC 클라이언트로부터 전달받은 마우스, 키보드 신호를 통해 통제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;NTP(Network Time Protocol) 서비스&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개념
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 간 시간을 동기화하는 NTP 프로토콜을 이용하여 NTP 서버와 시간 동기화&lt;/li&gt;
&lt;li&gt;UTC기준 1/1000초까지 시간 동기화 가능&lt;/li&gt;
&lt;li&gt;UDP/123 기본 포트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;계급(Startnum) 구조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클럭소스 수준의 계층적, 반계층화된 시스템을 사용하고 이 계층 구조의 각 수준을 계급이라고 함.&lt;/li&gt;
&lt;li&gt;계급 수준은 레퍼런스 시계에서 거리 정의&lt;/li&gt;
&lt;li&gt;숫자가 낮은 계급(단계)가 높은 계급(단계)보다 더 품질 우수&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;설정 파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/ntp.conf&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;주요 명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ntpdate
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원격 서버와 시간을 동기화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ntpq
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NTP 질의 명령어&lt;/li&gt;
&lt;li&gt;-p옵션으로 연결된 서버의 상태 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;기타 용어&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DOS 공격 - LAND ATTACK
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공격자가 임의로 자신의 ip 주소 및 포트를 대상 서버의 ip 주소 및 포트와 동일하게 하며 서버 공격&lt;/li&gt;
&lt;li&gt;이러한 패킷을 공격 시스템에 보내면 해당 시스템은 SYN패킷의 출발지 주소 참조&lt;/li&gt;
&lt;li&gt;패킷은 외부로 나가지 않고 자신에게 돌아옴&lt;/li&gt;
&lt;li&gt;이 공격법은 syn flooding처럼 동시 사용자 수를 증가 시키므로 CPU부하를 발생시킴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스크린 호스트 게이트웨이
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스크린 라우터와 단일 홈 게이트웨이를 조합한 형태&lt;/li&gt;
&lt;li&gt;스크린 라우터에서 패킷 필터링을 1차로 수행하고, &lt;b&gt;bastion 호스트 역할을 수행하는 단일 홈 게이트웨이&lt;/b&gt;에서 프록시와 같은 서비스를 통해 2차 방어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iptables 관련 명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 IP주소에서 60초 동안에 15번 이상 SSH 접속을 시도하면 DROP 시키는 정책을 ssh 사슬에 추가하는 명령어&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;	iptables -A SSH -p udp --dport 22 -m recent update --seconds 60 hitcount 15 -j Drop
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/sysconfig/iptables
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/rc.d/init.d/iptables 스크립트에서 iptables-save 명령어 사용해서 관련 정책 저장&lt;/li&gt;
&lt;li&gt;해당 저장 명령 수행 시, 해당 설정 파일에 관련 정책 저장&lt;/li&gt;
&lt;li&gt;시스템 재부팅 시에 자동으로 규칙 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>자격증/리눅스마스터 1급</category>
      <category>리눅스</category>
      <category>리눅스마스터1급</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/43</guid>
      <comments>https://devjooj.tistory.com/43#entry43comment</comments>
      <pubDate>Sat, 26 Aug 2023 03:42:44 +0900</pubDate>
    </item>
    <item>
      <title>[Ubuntu] OpenSSL 버전 업데이트 기록 (Ubuntu 18.04 LTS)</title>
      <link>https://devjooj.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;회사 AWS EC2 서버 내 OpenSSL은 1.1.1 버전을 사용하고 있는데, &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 버전이 2023년 9월 11일 지원 종료이므로 버전 업데이트를 진행할 필요가 생겼다.&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;현재 장기적으로 안정적인 버전은 3.0.10 (&lt;span style=&quot;background-color: #f8f8f8; color: #222222; text-align: start;&quot;&gt;2026년 9월 7일까지)이므로 해당 버전으로 업데이트 하기로 했다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-----------&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;적용 환경&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS: Ubuntu 18.X ~ 22.X&lt;/li&gt;
&lt;li&gt;Old OpenSSL: 1.1.1, 3.0.2 등&lt;/li&gt;
&lt;li&gt;New OpenSSL: 3.0.10&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL패키지, 버전 확인&lt;/h2&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# 패키지 확인
sudo apt list openssl
or
sudo apt list libssl

# 버전 확인
openssl version
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;패키지 업그레이드(사전작업)&lt;/h2&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 다운로드 (&lt;a href=&quot;https://www.openssl.org/source/&quot;&gt;OpenSSL&lt;/a&gt;)&lt;/h2&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;wget &amp;lt;https://www.openssl.org/source/openssl-3.0.10.tar.gz&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 압축해제&lt;/h2&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;tar -zxf openssl-3.0.10.tar.gz
cd openssl-3.0.10
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 설치 및 컴파일&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;# 기본실행 방법 (/usr/local/ssl로 경로가 자동 설정됨)
./config

# 경로설정 방법 (작성된 경로로 설정됨)
./config --prefix=[DIRECTORY] --openssldir=[DIRECTORY]

#######################################################
해당 글에서는 기본실행 방법으로 가이드
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;# 컴파일 및 설치
make

make install
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 라이브러리 설정&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;echo &quot;/usr/local/ssl/lib64&quot; &amp;gt;&amp;gt; /etc/ld.so.conf.d/openssl.conf

#######################################################
Permission Denied 발생시
su 관리자 권한으로 접속 후 진행
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# 라이브러리 config 적용
sudo ldconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 바이너리 백업&lt;/h2&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 경로 확인
ls -l /usr/bin/c_rehash
ls -l /usr/bin/openssl

# 백업
mv /usr/bin/c_rehash /usr/bin/c_rehash.bk
mv /usr/bin/openssl /usr/bin/openssl.bk
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 환경변수 등록&lt;/h2&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 환경변수 파일 편집기 실행
vi /etc/environment

# PATH 끝부분 (붉은글씨) 추가
#-----------------------------------------
PATH=&quot;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games**:/snap/bin:/usr/local/openssl/bin**&quot;
#-----------------------------------------
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# 환경변수 적용
source /etc/environment
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;# 환경변수 확인
echo $PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL 적용 확인&lt;/h2&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;# 버전 확인
openssl version -a
----------------------------------------------------
OpenSSL 3.0.10 .......
...

# cipher 확인
openssl ciphers -v | awk '{print $2}' | sort | uniq
----------------------------------------------------
SSLv3
TLSv1
TLSv1.2
TLSv1.3
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;http://libssl.so&quot;&gt;libssl.so&lt;/a&gt;&amp;hellip;&amp;hellip; 와 같은 에러 발생시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리가 정상 등록되지 않은 항목이 존재할 수 있으므로 이하 코드 실행&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;ldconfig /usr/local/lib64
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS. OpenSSL 적용 완료 후 반드시 HTTPS로 사이트 정상 접근 되는지 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sangchul.kr/entry/리눅스-OpenSSL-최신-버전으로-업그레이드&quot;&gt;https://sangchul.kr/entry/리눅스-OpenSSL-최신-버전으로-업그레이드&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/54124906/openssl-error-while-loading-shared-libraries-libssl-so-3&quot;&gt;https://stackoverflow.com/questions/54124906/openssl-error-while-loading-shared-libraries-libssl-so-3&lt;/a&gt;&lt;/p&gt;</description>
      <category>Server/Linux</category>
      <category>openssl</category>
      <category>ubuntu</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/42</guid>
      <comments>https://devjooj.tistory.com/42#entry42comment</comments>
      <pubDate>Sat, 19 Aug 2023 00:28:30 +0900</pubDate>
    </item>
    <item>
      <title>[Network] google.com을 검색하면 어떻게 될까?</title>
      <link>https://devjooj.tistory.com/41</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWTlWe/btsppINQl4k/3kvlTFDZRyoLoto8vh8KG0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWTlWe/btsppINQl4k/3kvlTFDZRyoLoto8vh8KG0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWTlWe/btsppINQl4k/3kvlTFDZRyoLoto8vh8KG0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bWTlWe/btsppINQl4k/3kvlTFDZRyoLoto8vh8KG0/img.gif&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;853&quot; height=&quot;480&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;div&gt;
&lt;h3 id=&quot;들어가기전&quot; data-ke-size=&quot;size23&quot;&gt; 들어가기전&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우연히 유튜브에서 해외 개발자가 이런 면접 질문을 받았을 때 당신은 대답할 수 있냐는 영상을 보게 되었다.&lt;/p&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'google.com'을 검색하면 일어나는 과정을 설명해봐라&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;google.com을 검색하면...google창이 나옵니다...&lt;br /&gt;라고 말한다면 면접 광탈하겠지..^_^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 DNS가 컴퓨터가 읽을 수 있는 IP주소로 변환해줘서 그걸 서버로 요청해서 응답받는 과정이라고만 알고있어서 이 기회에 확실히 대답할 수 있도록 공부해야겠다는 생각이 들었다.&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;먼저-우리는-googlecom이라고-검색을-해봤다&quot; data-ke-size=&quot;size23&quot;&gt;먼저, 우리는 google.com이라고 검색을 해봤다.&lt;/h3&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nIp3H/btspnj1RhYd/K2keGvskq4vwltMtbUtNKK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nIp3H/btspnj1RhYd/K2keGvskq4vwltMtbUtNKK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nIp3H/btspnj1RhYd/K2keGvskq4vwltMtbUtNKK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/nIp3H/btspnj1RhYd/K2keGvskq4vwltMtbUtNKK/img.gif&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;500&quot; height=&quot;375&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjmzst/btspnkmbfbx/D5qYSzrtUkY0f17owjnxXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjmzst/btspnkmbfbx/D5qYSzrtUkY0f17owjnxXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjmzst/btspnkmbfbx/D5qYSzrtUkY0f17owjnxXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbjmzst%2Fbtspnkmbfbx%2FD5qYSzrtUkY0f17owjnxXK%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;1280&quot; height=&quot;273&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 제일 먼저 어떤 일을 할까?&lt;/p&gt;
&lt;h2 id=&quot;1-브라우저의-url-파싱&quot; data-ke-size=&quot;size26&quot;&gt;1. 브라우저의 URL 파싱&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 먼저 웹 브라우저는 우리가 보낸 URL이 무엇인지 파악한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저에서 어떤 Protocol, domain, port, path로 요청할 것인지 입력한 정보를 바탕으로 해석 및 분석하는 과정이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7qcIv/btspjVHJK3h/fJqfQ9QuZ1QzMwEULO4rr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7qcIv/btspjVHJK3h/fJqfQ9QuZ1QzMwEULO4rr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7qcIv/btspjVHJK3h/fJqfQ9QuZ1QzMwEULO4rr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7qcIv%2FbtspjVHJK3h%2FfJqfQ9QuZ1QzMwEULO4rr0%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;1280&quot; height=&quot;148&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;보통 URI를 입력하면 위와 같은 그림이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는&lt;br /&gt;사용자가 단순 검색을 한 것인지 아니면 URL을 입력한 것인지 등등 어떤 URI를 썼는지 분석한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, port를 쓰지 않았다면 HTTP는 80, HTTPS는 443이 디폴트값으로 요청된다.&lt;/p&gt;
&lt;h2 id=&quot;2-cache-체크-후-url의-ip주소-요청&quot; data-ke-size=&quot;size26&quot;&gt;2. Cache 체크 후 URL의 IP주소 요청&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연하지만, 우리가 입력한 www.google.com은 컴퓨터가 읽을 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 서버가 이해할 수 있는 IP주소로 변환해주어야 통신이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 변환해주나? 아니!&lt;br /&gt;이미 내가&lt;span&gt;&amp;nbsp;&lt;/span&gt;google.com&lt;span&gt;&amp;nbsp;&lt;/span&gt;요청한 적이 있다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 어딘가에&lt;span&gt;&amp;nbsp;&lt;/span&gt;google.com에 대한 IP주소를 가지고 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 주소(googel.com)에 해당하는 IP주소를 찾기 위해 4가지의 캐쉬 기록을 순차적으로 체크한다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUZEjo/btspkLSPDRU/OdTgPnpEs2zvLxKw8H0Rp1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUZEjo/btspkLSPDRU/OdTgPnpEs2zvLxKw8H0Rp1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUZEjo/btspkLSPDRU/OdTgPnpEs2zvLxKw8H0Rp1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dUZEjo/btspkLSPDRU/OdTgPnpEs2zvLxKw8H0Rp1/img.gif&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;853&quot; height=&quot;480&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Brower cache : 웹브라우저를 통해 방문했던 DNS record 기록을 일정기간동안 저장하고 있는 곳 중 가장 먼저 접근, 탐색 되는 곳&lt;/li&gt;
&lt;li&gt;router cache: 라우터에 저장된 데이터가 있는지 탐색&lt;/li&gt;
&lt;li&gt;Os cache : systemcall을 통해서 운영체제가 저장하고 있는 hosts 파일에 접근하여 DNS 기록 탐색&lt;/li&gt;
&lt;li&gt;ISP(Internet Service Provider) cache: 서비스 공급자의 약자로 여기서는 각 자의 DNS 서버를 보유하고 있기 때문에 이 곳을 마지막으로 탐색한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-cache에도-없어-그럼-어쩔-수-없지-dns에-ip-주소-요청하자&quot; data-ke-size=&quot;size26&quot;&gt;3. Cache에도 없어? 그럼 어쩔 수 없지! DNS에 IP 주소 요청하자&lt;/h2&gt;
&lt;h3 id=&quot;dns-서버&quot; data-ke-size=&quot;size23&quot;&gt;DNS 서버&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 읽을 수 있는 도메인 이름(예: www.amazon.com)을 머신이 읽을 수 있는 IP 주소(예: 192.0.2.44)로 변환해주는 시스템 서버&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ISP의 DNS 서버가 DNS query로 서버의 IP주소를 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS QUERY를 통해 여러 다른 DNS 서버들을 검색해서 해당 URL의 IP주소를 찾는 것인데&lt;br /&gt;아래와 같이 Root DNS 서버에서 마지막 Third-level DNS 서버까지 IP주소를 반환받거나 또는, Error를 발생시킬 때까지 계속해서 탐색한다(recursive search)&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byHaTr/btspjXFw9lO/RgNeC5iJccHjJEL0u3TQd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byHaTr/btspjXFw9lO/RgNeC5iJccHjJEL0u3TQd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byHaTr/btspjXFw9lO/RgNeC5iJccHjJEL0u3TQd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyHaTr%2FbtspjXFw9lO%2FRgNeC5iJccHjJEL0u3TQd1%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;790&quot; height=&quot;416&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h2 id=&quot;4-드디어-ip-주소를-확인했어-그러면-이제-브라우저와-서버를-연결하자-어떻게-tcp-connection&quot; data-ke-size=&quot;size26&quot;&gt;4. 드디어 IP 주소를 확인했어, 그러면 이제 브라우저와 서버를 연결하자! 어떻게? TCP Connection!&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 IP주소를 받았으니, 해당 주소와 서버를 연결해야한다.&lt;br /&gt;TCP연결을 맺는데,&lt;br /&gt;이 과정에서 HTTP 요청일 경우, TCP(Transmisiion Control Protocol) 소켓을 열고 3-way-handshake 연결&lt;br /&gt;HTTPS 요청일 경우 TLS 과정을 통해 세션키를 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3-way-handshake가 뭐야?&lt;br /&gt;본 요청을 보내기 전에 클라이언트와 서버가 통신을 해서 서로 연결을 확인하는 절차!&lt;br /&gt;리허설 느낌이라고 생각하면 된다.&lt;/p&gt;
&lt;h2 id=&quot;5-브라우저가-서버로-request-전송&quot; data-ke-size=&quot;size26&quot;&gt;5. 브라우저가 서버로 REQUEST 전송&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말했던 리허설, 즉 3-WAY-handshake로 연결이 확인되었다면, 클라이언트에게 본 요청을 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, 필요한 경우 브라우저 식별정보(user-Agent), 수락 요청 유형 등 헤더에 다양한 정보가 포함이 되고, 일반적으로는 쿠키 정보도 함께 포함된다.&lt;/p&gt;
&lt;h2 id=&quot;6-서버가-요청-처리하고-응답reponse를-생성&quot; data-ke-size=&quot;size26&quot;&gt;6. 서버가 요청 처리하고 응답(reponse)를 생성&lt;/h2&gt;
&lt;h2 id=&quot;7-서버가-http-response를-보낸다&quot; data-ke-size=&quot;size26&quot;&gt;7. 서버가 HTTP response를 보낸다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 아는 status 코드 응답 상태와 요청에 대한 쿠키 정보, encoding type, cache control 등 다양한 정보를 함께 반환한다.&lt;/p&gt;
&lt;h2 id=&quot;8-최종-브라우저는-html-컨텐츠를-보여준다&quot; data-ke-size=&quot;size26&quot;&gt;8. 최종. 브라우저는 HTML 컨텐츠를 보여준다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹브라우저는 응답 받은 HTML을 단계별로 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차적으로, HTML 기본틀을 랜더링하고, 추가적으로 필요한 부분들을 보여준다(CSS, 이미지, javascript)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차적으로, 정적 파일들은 브라우저에서 자동 캐싱&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot; 참고자료&quot; data-ke-size=&quot;size26&quot;&gt; 참고자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://smorning.tistory.com/237&quot;&gt;https://smorning.tistory.com/237&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://websetnet.net/ko/what-is-hsts-and-how-do-you-set-it-up/&quot;&gt;https://websetnet.net/ko/what-is-hsts-and-how-do-you-set-it-up/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@jewon119/TIL100.-HTTP-%EC%9B%B9%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC&quot;&gt;https://velog.io/@jewon119/TIL100.-HTTP-%EC%9B%B9%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>개발 공부/Network</category>
      <category>Network</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/41</guid>
      <comments>https://devjooj.tistory.com/41#entry41comment</comments>
      <pubDate>Sat, 29 Jul 2023 23:33:31 +0900</pubDate>
    </item>
    <item>
      <title>[Node.js]  Node.js의 비동기적 작동이 어떻게 나오게 되었을까? (작성중)</title>
      <link>https://devjooj.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js 환경에서 약 2년 정도를 개발했지만, 이미 구성되어 있는 프레임에서만 개발을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 동작하고, 왜 Node.js가 생겨나게 된건지 이제서야 궁금해지기 시작해서 공부하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용의 기반은 Node.js 디자인 패턴 책과 기타 논문을 종합한 짬뽕 글이다.&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;- Node.js 철학, &quot;Node way&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- Reactor 패턴 - Node.js의 비동기 이벤트 주도 아키텍처의 핵심 메커니즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;-브라우저와 다르게 서버에서 동작하는 Javascript의 의미&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;Node.js 코어를 구성하는 몇가지 원칙들이 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 최소한의 기능세트를 가지고 코어의 바깥부분에 유저랜드 혹은 유저스페이스라고 불리우는 &lt;b&gt;사용자 전용 모듈 생태계&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(*유저랜드: 사용자들이 모여서 소통하고 상호작용하는 가상의 공간, 유저(사용자) + 랜드(땅, 지역) 을 합쳐서 사용자들이 모인 하나의 지역)&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Unix 철학에 근거하여 '작은 것이 아름답다', '각 프로그램은 한가지 역할만 잘하도록 만들어라' 등 두가지 수칙으로 Node.js는 새로원 차원으로 변경했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다들 아는 NPM (패키지 관리자)의 도움을 받아 각 패키지가 자신이 필요로 하는 버전의 종속성 패키지들을 갖도록 하여 종속성 지옥을 벗어나게 해준다. 이렇게 하여 재사용성이 향상되는 장점이 있다.&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;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;더 작고 집중화된 모듈을 갖는 것, 그래서 모두에게 공유와 재사용을 가능하게 하는 것 이것이 Node.js가 추구하는 원칙이다.&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;Node.js의 가장 일반적인 패턴은&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;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;단순함이야말로 궁극의 정교함이다.&lt;br /&gt;&lt;/span&gt;-레오나르도 다빈치-&lt;/blockquote&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;그렇다면, Node.js는 어떻게 작동할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 개념은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 비동기 특성의 핵심인 리액터 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 스레드 아키텍처, 논 블로킹 I/O와 같은 주요 개념을 빼놓을 수가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I/O가 컴퓨터의 기본 동작들 중에서 가장 느리다는 것을 모두 알고 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추후 To. Do&lt;/p&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>개발 공부/Javascript</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/40</guid>
      <comments>https://devjooj.tistory.com/40#entry40comment</comments>
      <pubDate>Fri, 28 Jul 2023 01:59:26 +0900</pubDate>
    </item>
    <item>
      <title>[생각정리] 지금 다니고 있는 회사에서 하는 일을 잘하기 위해서 노력하는 것이 가장 좋은 공부다.</title>
      <link>https://devjooj.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요 근래에 나의 생각 중 많은 부분을 차지하던 공부 방향에 대해 조금의 해답이 되었던 글을 공유한다.&lt;br&gt;&lt;a href=&quot;https://zdnet.co.kr/view/?no=20170616090644&quot; target=&quot;_self&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #e6f5ff;&quot;&gt;&lt;span style=&quot;color: #0070d1;&quot;&gt; 개발자의 평생공부&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;개발자의 평생공부&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;평생 공부하는 건 개발자만이 아니다. 다른 직업을 가진 사람들도 쉼 없이 공부하고, 컨퍼런스와 세미나를 참가하고, 스터디를 한다. 공부없이 할 수 있는 일이 없기 때문이다....&quot; data-og-host=&quot;zdnet.co.kr&quot; data-og-source-url=&quot;https://zdnet.co.kr/view/?no=20170616090644&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/XJrA9/hyTo7SlOqn/UkMGABqIdKJjJGd2mRnRV1/img.jpg?width=550&amp;amp;height=399&amp;amp;face=0_0_550_399,https://scrap.kakaocdn.net/dn/bm5coe/hyTpcF7kp9/KkBWUuPbORpqLCtgYJpARk/img.jpg?width=550&amp;amp;height=399&amp;amp;face=0_0_550_399&quot; data-og-url=&quot;https://zdnet.co.kr/view/?no=20170616090644&quot;&gt;&lt;a href=&quot;https://zdnet.co.kr/view/?no=20170616090644&quot; target=&quot;_blank&quot; data-source-url=&quot;https://zdnet.co.kr/view/?no=20170616090644&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/XJrA9/hyTo7SlOqn/UkMGABqIdKJjJGd2mRnRV1/img.jpg?width=550&amp;amp;height=399&amp;amp;face=0_0_550_399,https://scrap.kakaocdn.net/dn/bm5coe/hyTpcF7kp9/KkBWUuPbORpqLCtgYJpARk/img.jpg?width=550&amp;amp;height=399&amp;amp;face=0_0_550_399')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;개발자의 평생공부&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;평생 공부하는 건 개발자만이 아니다. 다른 직업을 가진 사람들도 쉼 없이 공부하고, 컨퍼런스와 세미나를 참가하고, 스터디를 한다. 공부없이 할 수 있는 일이 없기 때문이다....&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;zdnet.co.kr&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;사실 위 컬럼의 내용이 정답은 아니다.&lt;br&gt;실력을 쌓고 싶다고 말하지만 실력이란 무엇일까에 대한 깊게 고민해본 적은 없었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;실력을 쌓고 빠르게 증명 할 수 있는 방법은?&lt;br&gt;아무리 생각해도 현재 내가 담당하고 있는 업무에서 눈에 띄게 무언가 성과를 낸다는 것.. 그게 실력이 아닐까 싶다..&lt;br&gt;내가 실력을 쌓고 싶은 이유는 좋은 성과를 내고, 누군가에게 도움이 되고 싶고 이 누군가가 나에게 좋은 인맥이 되어 그 후 좋은 개발자로써 명성을 얻고 싶기 때문이다.&lt;br&gt;&amp;nbsp;&lt;br&gt;아무튼 적어도 나에게는 현업과 관련된 공부를 하여 업무의 효율을 빠르게 높이는게 실력인 것 같다.&lt;br&gt;우연히 만난 좋은 글로 인해 또 한번 생각 정리를 하게 되어 좋다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이렇게 점진적으로 나의 가치관을 정리하다보면 언젠간 확고한 가치관을 정립할 수 있겠지?ㅎㅎ&lt;br&gt;그런 의미로 나는 Node.js 개발자니까 Node.js 디자인 패턴 바이블 책을 읽고 실무에 적용해봐야겠다.&lt;br&gt;7월 마지막 주는 또 하나의 목표가 생겼다!! 디자인 패턴 바이블 독서 후 정리하기!&lt;br&gt;7월 마지막까지 화이팅!&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>생각정리</category>
      <category>개발자</category>
      <category>개발자의평생공부</category>
      <category>성장</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/39</guid>
      <comments>https://devjooj.tistory.com/39#entry39comment</comments>
      <pubDate>Mon, 24 Jul 2023 01:14:44 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] Temporary Table(임시테이블)</title>
      <link>https://devjooj.tistory.com/38</link>
      <description>&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;div&gt;
&lt;h2 id=&quot;-들어가기-전&quot; data-ke-size=&quot;size26&quot;&gt;  들어가기 전&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 임시테이블을 이용하여 데이터를 조회하는 프로시저를 생성했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 특정 테이블을 조회했는데 해당 테이블에 있는 데이터가 조회되지 않았고,&lt;br /&gt;테이블을 조회하기 직전에 호출했던 프로시저 내용이 조회되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응.....? 갑자기 왜 이러지?.. 너무나 당황했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차적으로 든 생각은&lt;br /&gt;내가 호출한 프로시저 내부에서&lt;br /&gt;임시테이블이라고 생성 또는 DROP한 테이블이 임시테이블이 아니라 그냥 테이블이었나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 임시테이블을 생성한게 맞았고,&lt;br /&gt;실제 테이블명과 같게 생성하여&lt;br /&gt;해당 세션에서는 임시테이블이 우선으로 보여지고 있는 상황이었다.&lt;br /&gt;(이런 실수를 하다니......sql 모드는 이런거 안잡아주나..?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 실수를 통해 또 한가지 배웠다.&lt;br /&gt;정말 감사하게도 개발 DB에서 배운게 다행!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 실수를 절대 반복하지 않기 위해 임시테이블에 대해 포스팅해보려고 한다!&lt;/p&gt;
&lt;h1 id=&quot;temporary-table임시테이블-이란&quot;&gt; Temporary Table(임시테이블) 이란?&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[공식 문서 정의]&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A TEMPORARY table is visible only within the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 특정 사용자가 접속한 해당 세션에서만 생성하고 조회 가능한 임시 테이블이다.&lt;/p&gt;
&lt;h2 id=&quot;-임시테이블-특징&quot; data-ke-size=&quot;size26&quot;&gt;  임시테이블 특징&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DML(SELECT, INSERT, UPDATE, DELETE)을 사용할 수 있다&lt;/li&gt;
&lt;li&gt;일반테이블처럼 영구적으로 저장되는 테이블이 아니라 임시테이블을 만들고 데이터를 잠깐 처리할 때 사용할 때 유용하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;즉, 일시적으로 처리할 데이터들을 한번에 모아놓고 처리하고싶다? 
그럴 때 임시테이블 사용하면 좋다.	
예를 들어, 문자 알림을 보내고 싶은데 특정 조건에 있는 사람한테만 보내고 싶고, 
중복된 번호들은 한번만 보내고 싶다! 

해당 조건을 select 후 임시테이블에 저장해서 한번 가공된 데이터들을 쫘락 select하면 편하다!&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;임시 테이블을 생성했던 해당 세션이 끊기면 아래 이미지와 같이 자동으로 DROP된다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vL71j/btsoyqhkrkx/qwcsvs71utA2Zu8PMEIZE1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vL71j/btsoyqhkrkx/qwcsvs71utA2Zu8PMEIZE1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vL71j/btsoyqhkrkx/qwcsvs71utA2Zu8PMEIZE1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/vL71j/btsoyqhkrkx/qwcsvs71utA2Zu8PMEIZE1/img.gif&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;853&quot; height=&quot;480&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;사용법&quot; data-ke-size=&quot;size26&quot;&gt; 사용법&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;1-임시테이블-생성-방법&quot; data-ke-size=&quot;size23&quot;&gt;1. 임시테이블 생성 방법&lt;/h3&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;CREATE TEMPORARY TABLE [IF NOT EXISTS] 테이블명
    (create_definition,...)
    [table_options]
    [partition_options]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;create_definition&lt;/b&gt;&lt;br /&gt;insert할 컬럼과 데이터 타입 정의&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IF NOT EXISTS&lt;/b&gt;&lt;br /&gt;'table already exists' 오류를 피하기 위해 사용&lt;br /&gt;사용하지 않아도 문법적 오류는 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;2-임시테이블-제거-방법&quot; data-ke-size=&quot;size23&quot;&gt;2. 임시테이블 제거 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1&lt;/b&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;현재 세션 끊기&lt;/b&gt;: 임시테이블이 생성된 현재 세션이 끊겼을 시 자동으로 삭제 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;DROP TEMPORARY TABLE&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;실행&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;DROP [TEMPORARY] TABLE [IF EXISTS] 테이블명 [, 테이블명] ...
[RESTRICT | CASCADE]&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고사항&lt;br /&gt;&lt;b&gt;RESTRICT&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:테이블 삭제 시 다른 데이터가 삭제할 데이터를 참조하고 있을 경우 변경/삭제가 취소&lt;br /&gt;&lt;b&gt;CASCADE&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:테이블 삭제 시 다른 데이터가 삭제할 데이터를 참조하고 있을 경우 함께 삭제&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임시테이블 사용법은 의외로 간단하다.&lt;br /&gt;테이블과 같이 CREATE해주고, DROP해주고 다른 DDL도 사용가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, 임시테이블은 어떨 때 사용하는 것이 좋을까?&lt;br /&gt;쿼리 성능에 크게 도움을 줄까?&lt;/p&gt;
&lt;h2 id=&quot;임시테이블-사용-시-성능에-크게-도움이-될까&quot; data-ke-size=&quot;size26&quot;&gt; 임시테이블 사용 시 성능에 크게 도움이 될까?&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일단, SELECT 시에는 Temporary Table을 사용하는 것은 성능상으로 전혀 도움이 되지 않는다.&lt;br /&gt;테이블을 생성하고, 삭제하고 데이터를 insert하여 join select하는 등 불필요한 단계로 인해 도움이 되지 않는다고 한다.&lt;/li&gt;
&lt;li&gt;하지만, 중간 결과를 저장하거나, 빈도있는 재사용을 위한 목적이라면 큰 효과가 있다.&lt;br /&gt;여러개의 JOIN이 걸려있고 조건이 있는 SELECT를 여러번하는 것 보단&lt;br /&gt;여러개의 JOIN이 걸려있고 조건이 있는 SELECT를 한번 하고 임시테이블에 저장하여 계속 재사용한다면 큰 효율이 있다.&lt;/li&gt;
&lt;li&gt;Update 시에 가장 추천한다고 한다. 동시에 업데이트 처리해야하는 경우 일반 테이블을 사용할 때 보다 한번 가공된 테이블과 조인해서 업데이트할 때 성능이 좋다고 한다.&lt;/li&gt;
&lt;li&gt;임시테이블 성능 비교 (아래 블로그 참고)&lt;br /&gt;&lt;a href=&quot;https://gywn.net/2012/06/mysql-temporary-table-effect/&quot;&gt;https://gywn.net/2012/06/mysql-temporary-table-effect/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;-사용-시-주의사항&quot; data-ke-size=&quot;size26&quot;&gt;  사용 시 주의사항&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의점&lt;/b&gt;&lt;br /&gt;임시테이블명은 실제 테이블명과 같은 이름으로 사용하지 않는다.&lt;br /&gt;임시테이블과 일반 테이블명이 같지 않도록 임시 테이블명 앞에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;TEMP_테이블명&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이렇게 해주는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 이름으로 생성이 되긴 된다.&lt;br /&gt;하지만 세션이 끊기기 전까지 실제 테이블은 조회할 수 없고 임시테이블이 조회된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜냐?&lt;/b&gt;&lt;br /&gt;기본적으로 임시테이블이 우선으로 조회되기 때문이다.&lt;/p&gt;
&lt;h2 id=&quot;️-결론&quot; data-ke-size=&quot;size26&quot;&gt;✍️ 결론&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대용량 데이터의 처리가 아닐 경우 임시테이블의 성능은 크게 도움이 되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 아래의 상황에서는 임시테이블을 사용하는게 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IF/ELSEIF/ELSE로 조건이 나누게 된다면 그때 그때 조건에 따라 조인할 것이 아니라 임시테이블로 데이터를 한 번 가공한 후 해당 테이블로 일괄적으로 JOIN할 때?&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/create-temporary-table.html&quot;&gt;https://dev.mysql.com/doc/refman/5.7/en/create-temporary-table.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/create-table.html&quot;&gt;https://dev.mysql.com/doc/refman/5.7/en/create-table.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <category>임시테이블</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/38</guid>
      <comments>https://devjooj.tistory.com/38#entry38comment</comments>
      <pubDate>Sun, 23 Jul 2023 23:34:50 +0900</pubDate>
    </item>
    <item>
      <title>[Eclipse] Properties 인코딩 깨지는 현상 해결</title>
      <link>https://devjooj.tistory.com/37</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;다른 곳에서 UTF-8 인코딩 변경했는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Properties에서만 인코딩이 깨지는 현상이 발생했다.&lt;/p&gt;
&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;u&gt;Properties 관련 인코딩 변경하러 가는 방법&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  Window &amp;gt; Preferences &amp;gt; General&amp;gt; Content-Types &amp;gt; Text 클릭 &amp;gt; Java Properties File 클릭&lt;/p&gt;
&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;b&gt;Default encoding : UTF-8&lt;/b&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;916&quot; data-origin-height=&quot;1071&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uhAyA/btsoa9G4LLi/vKEKGv5okMLPx8oftAt95K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uhAyA/btsoa9G4LLi/vKEKGv5okMLPx8oftAt95K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uhAyA/btsoa9G4LLi/vKEKGv5okMLPx8oftAt95K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuhAyA%2Fbtsoa9G4LLi%2FvKEKGv5okMLPx8oftAt95K%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;618&quot; height=&quot;723&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;1071&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;Apply 클릭하면 인코딩이 정상적으로 된 properties를 확인할 수 있다.&lt;/p&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>개발 공부/Java</category>
      <category>Eclipse</category>
      <category>Java</category>
      <category>spring</category>
      <category>UTF-8</category>
      <category>인코딩</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/37</guid>
      <comments>https://devjooj.tistory.com/37#entry37comment</comments>
      <pubDate>Wed, 19 Jul 2023 17:00:45 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] 클라이언트 device 정보 간단하게 조회하기</title>
      <link>https://devjooj.tistory.com/36</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;서론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ Spring boot 에서 클라이언트 요청 시 어떤 디바이스 환경인지 조회하는 코드 정리해보았다.&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: #333333; text-align: start;&quot;&gt;✅&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Spring AOP에 사용자 디바이스 정보를 조회하여 로그를쌓고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마침 아래 Spring 에서 제공하는 maven이 있길래 해당 라이브러리 추가하여 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별도의 어려운 방법 없이 사용 가능하기 때문에 다른 방법이 있는지는 모르겠지만! 정상 작동확인했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biQQPv/btsn8lNvE9D/TCpORlNvXsalvLqWMNoBC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biQQPv/btsn8lNvE9D/TCpORlNvXsalvLqWMNoBC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biQQPv/btsn8lNvE9D/TCpORlNvXsalvLqWMNoBC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiQQPv%2Fbtsn8lNvE9D%2FTCpORlNvXsalvLqWMNoBC0%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;840&quot; height=&quot;413&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;413&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;u&gt;&lt;b&gt;23.07.18 기준으로 안정적인 버전은 2.0.0.M3이었다.&lt;/b&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  참고: &lt;a href=&quot;https://spring.io/projects/spring-mobile#learn&quot;&gt;https://spring.io/projects/spring-mobile#learn&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;버전을 확인했으면 이제 pom.xml에 repository와 dependency를 추가해주면 끝난다.&lt;/p&gt;
&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;- repository 등록&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689686119390&quot; class=&quot;xml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;repository&amp;gt;
        &amp;lt;id&amp;gt;spring-milestones&amp;lt;/id&amp;gt;
        &amp;lt;name&amp;gt;Spring Milestones&amp;lt;/name&amp;gt;
        &amp;lt;url&amp;gt;https://repo.spring.io/libs-milestone&amp;lt;/url&amp;gt;
        &amp;lt;snapshots&amp;gt;
            &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;
        &amp;lt;/snapshots&amp;gt;
&amp;lt;/repository&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- dependency 등록&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689686178276&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.mobile&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-mobile-device&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0.0.M3&amp;lt;/version&amp;gt; //여기에 위에서 확인한 버전 작성
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- spring context 파일에 bean 등록&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;!-- 모바일 디바이스  --&amp;gt;
&amp;lt;bean id=&quot;deviceResolver&quot; class=&quot;org.springframework.mobile.device.DeviceResolverHandlerInterceptor&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  bean 등록안해주면 위 라이브러리 인식 못하고 UNKNOWN뜸&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;web.xml 작업&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689686323768&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;filter&amp;gt;
    &amp;lt;filter-name&amp;gt;deviceResolverRequestFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;filter-class&amp;gt;org.springframework.mobile.device.DeviceResolverRequestFilter&amp;lt;/filter-class&amp;gt;
&amp;lt;/filter&amp;gt;

&amp;lt;filter-mapping&amp;gt;
    &amp;lt;filter-name&amp;gt;deviceResolverRequestFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
&amp;lt;/filter-mapping&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  web.xml&amp;rarr; 이거 안해주면 &lt;span&gt;여기서 device 값 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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;최종&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 곳에서 아래와 같이 사용하면된다.&lt;/p&gt;
&lt;pre id=&quot;code_1689686403623&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();	
Device device = DeviceUtils.getRequiredCurrentDevice(request);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 로그가 정상적으로 찍히는 것을 확인!&lt;/p&gt;
&lt;pre id=&quot;code_1689685883335&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[22:10:56.000][I] - Device: [LiteDevice type=NORMAL]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/Java</category>
      <category>Java</category>
      <category>spring</category>
      <category>spring-mobile-device</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/36</guid>
      <comments>https://devjooj.tistory.com/36#entry36comment</comments>
      <pubDate>Tue, 18 Jul 2023 22:24:09 +0900</pubDate>
    </item>
    <item>
      <title>[NestJS] ExpressJS만 써본 개발자가 공부하는 NestJS - 기본 아키텍처 편</title>
      <link>https://devjooj.tistory.com/35</link>
      <description>&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;h2 data-ke-size=&quot;size26&quot;&gt;✍  들어가기 전&lt;/h2&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;해당 글은 NestJS 초보자가 study를 하기 위해 틈틈이 작성 중인 게시글입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부족한 점이 많기 때문에 NestJS 고수 분들께서 피드백 주시면 너무 감사드립니다 :)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;✅ NestJS&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NestJS를 학습하게 된 계기는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 내 담당하고 있던 프로젝트의 프레임워크인 ExpressJS를 조금 더 나은 구조로 개선할 수 있을까라는 고민에서 시작되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 약 하루 500명 정도의 방문자가 있고, 앞으로 회사 측에서 더 투자할 프로젝트이기 때문에&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;지금의 프레임워크는 node.js&amp;nbsp; 프레임워크 중 ExpressJS를 사용하고 있는데, ExpressJS도 물론 충분히 좋고 많은 곳에서 사용하고 있는 프레임워크지만, 엄격한 규칙이나 특별한 디자인 패턴이 없다는 것이 나 같은 주니어 개발자에게는 더 두려운 프레임워크 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 NestJS가 당장 도입하기 힘든 안타까운 상황이 온다면,&amp;nbsp; TypeScript라도 적용하고 싶다 ㅜㅜ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 데이터가 interface가 없고, 하물며&amp;nbsp; Response에 어떤 데이터가 넘어오는지 인터페이스조차 없는 상황이다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;b&gt;1. 아키텍처&lt;/b&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NestJS는 NodeJS 프레임워크 중 하나로, &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ExpressJS (Fastify까지 포함하여) 위에 Typescript까지 겸비한 모듈화 된 아키텍처이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이전&amp;nbsp; ExpressJS나 Fastify와 달리 프레임워크 생성 시 이미 아키텍처가 잡혀있다는 점에서 차별화된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;프레임워크 자체 내에 규칙이 정해져 있고, 디자인 패턴 또한 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;즉, 개발자는 프레임워크에서 세팅한 구조대로 개발을 진행해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 샘플을 보면 아마 이해에 도움이 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NestJs 프로젝트 구조는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2023-07-17 at 11.28.46 PM.png&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zNMkt/btsnXh6pa1N/tq4DG6ngrGdtxy1hMokfj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zNMkt/btsnXh6pa1N/tq4DG6ngrGdtxy1hMokfj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zNMkt/btsnXh6pa1N/tq4DG6ngrGdtxy1hMokfj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzNMkt%2FbtsnXh6pa1N%2Ftq4DG6ngrGdtxy1hMokfj1%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;228&quot; height=&quot;177&quot; data-filename=&quot;Screen Shot 2023-07-17 at 11.28.46 PM.png&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;main.ts&lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NestJS가 실제로 애플리케이션을 생성하는 메인 파일이라고 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1689516173191&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;app.module.ts&amp;nbsp;&lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt; Nest-Module은 애플리케이션 구조를 구성하는 데 사용되고, 개발자가 모듈의 종속성을 효율적으로 관리할 수 있게 해 준다.&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;NestJS는 3가지의 계층으로 분리할 수 있다.&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;-&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;NestJS는 이렇게 애플리케이션을 쉽게 테스트할 수 있도록 해주고, 의존성 주입이라는 디자인 패턴 또한 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(제어의 역전의 한 형태인 DI는 객체들의 조립형태로 만들어지기 때문에 느슨한 결합으로 효율적으로 개발할 수 있는 디자인패턴이다.)&lt;/p&gt;
&lt;pre id=&quot;code_1689516618102&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { MoviesController } from './movie/movie.controller';
import { MoviesService } from './movie/movie.service';


@Module({
  imports: [],
  controllers: [MoviesController],
  providers: [MoviesService],
})
export class AppModule {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 NestJS는&amp;nbsp; app.module.ts파일에 등록되어 있는 모듈들을 모아 아래와 같이 NestFactory라는 내장 함수를 통하여 애플리케이션을 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션을 생성할 때 모듈을 app.module.ts에 등록을 해줘야 NestJs는 이를 감지하여 생성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1689517143801&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;app.controller.ts&lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller는 클라이언트의 요청이 들어오는 파일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자를 통해 service를 주입하여 사용하고, 다양한 데코레이터를 통해 사용 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller에서 Service접근 시 수동으로 import 하지 않아도 해당 컨트롤러의 생성자에 서비스를 주입시켜 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;express.js에서는 수동으로 import 했다면, NestJs에 요청을 해서 import 한다고 생각하면 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;readOnly(불변성 유지): 해당 컨트롤러에서 서비스 수정하게 될 가능성이 있기 때문에 해당 클래스 내부의 변수들을 바꾸지 못하게 하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689516751164&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import {
    Controller,
    Get,
    Param,
    Post,
    Delete,
    Patch,
    Body,
    Query,
  } from '@nestjs/common';
  import { MoviesService } from './movies.service';
  import { Movie } from './entities/movie.entity';
  import { CreateMovieDto } from './dto/create-movie.dto';
  
  @Controller('movies')
  export class MoviesController {
    constructor(private readonly moviesService: MoviesService) {}
  
    @Get()
    getAll(): Movie[] {
      return this.moviesService.getAll();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;app.service.ts&lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 비즈니스 로직을 구현하는 곳이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;controller에 주입시키기 위해서는 모듈의 상단에 Injectable()이라는 데코레이터를 명시하여 의존성 주입을 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1689516807675&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Injectable, NotFoundException } from '@nestjs/common';
import { Movie } from './entities/movie.entity';
import { CreateMovieDto } from './dto/create-movie.dto';

@Injectable()
export class MoviesService {
  private movies: Movie[] = [];

  getAll(): Movie[] {
    return this.movies;
  }
}&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;일단 NestJS의 기본 구조를 알아봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 지금까지는 정말 기본 구조인 것 같고, 내가 궁금했던&amp;nbsp; &lt;u&gt;&lt;i&gt;그래서 Express보다 좋은 게 뭔데?라는&lt;/i&gt;&lt;/u&gt; 부분은 아직 해소되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Express에서는 미들웨어 내에서 필요한 부분들은 모두 일일이 세팅해줘야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 기본으로 제공해 주는 라이브러리가 없기 때문에 개발자가 손수 설치하고 개발해야 하는 부분들이 대부분이었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 부족한 부분들도 채워줄 정도로 좋은가?라는 의문이 들었고,&amp;nbsp; 내가 제일 학습하고 싶던 부분이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 NestJS의 정말 핵심 구조들을 살펴볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp; middleware, Guards, Interceptors&amp;nbsp; 등을 학습하고, 얼마나 좋은지 한번 체감하고 싶다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/NestJS</category>
      <category>Express</category>
      <category>nestjs</category>
      <category>Study</category>
      <category>아키텍처</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/35</guid>
      <comments>https://devjooj.tistory.com/35#entry35comment</comments>
      <pubDate>Sun, 16 Jul 2023 23:30:57 +0900</pubDate>
    </item>
    <item>
      <title>[개념] axios 와 fetch 어떤게 더 좋을까?</title>
      <link>https://devjooj.tistory.com/34</link>
      <description>&lt;h2 id=&quot;-들어가기-전&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  들어가기 전&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;B/E 파트에서 개발할 때는 데이터를 요청하기 보다는 데이터를 응답하는 입장이 되어 개발을 진행했다.&lt;br /&gt;그러다보니 데이터를 요청하는 부분에 대해서 깊게 생각할 기회가 없다가&lt;br /&gt;SMS 발송 파트를 개발하게 되었고, 그때 axios를 처음 접했다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 후 계속 axios만 쓰다가 최근 들어 F/E파트에서 개발하며 fetch도 보게 되었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단순히 둘다 비동기 HTTP 통신을 위해 사용하는 걸로 알고 있고, 그 둘의 차이점에 대해서는 자세히 모르고 있었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문득 axios는 라이브러리이고, fetch는 내장 함수인데 왜 굳이 axios라는 라이브러리를 설치해서 쓰는거지? 라는 의문이 들었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;둘은 뭐가 다른걸까? 뭐가 더 효율적인걸까?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번 기회에 API 요청할 때 뭐가 더 좋은지 공부해보려고 한다.&lt;/p&gt;
&lt;h1 id=&quot;axios와-fetch-개념&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt; axios와 fetch 개념&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;공통점&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;공통점&lt;/h3&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios와 fetch는 둘다 비동기 HTTP 통신을 위해 사용된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비동기 통신이란?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어,&lt;br /&gt;Velog에서 좋은 글을 만나 좋아요를 눌렀다.&lt;br /&gt;그런데 좋아요를 누르자 페이지가 새로고침 되었다.&lt;br /&gt;좋아요를 누를 때마다 페이지가 새로고침된다면..? 너무나 불편하겠지?&lt;br /&gt;이런 불편함을 방지하기 위해 사용되는 것이 비동기 통신이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 Axios와 fetch에 대해 자세히 알아보자!&lt;/p&gt;
&lt;h2 id=&quot;axios&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; Axios&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[axios 공식 문서 정의]&lt;/p&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;️특징&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✏️특징&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폭넓은 브라우저 호환성(크로스 브라우징에 신경을 많이 썼다고 한다)&lt;/li&gt;
&lt;li&gt;Promise(ES6) API를 사용&lt;/li&gt;
&lt;li&gt;response 시 json 형태로 반환&lt;/li&gt;
&lt;li&gt;XSRF 보호 가능XSRF, 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 하는 공격&lt;/li&gt;
&lt;li&gt;인터셉터 가능1) 요청할때 2) 응답 받을때 중간에 가로챈 후 공통으로 처리&lt;br /&gt;ex)&lt;br /&gt;-axios 요청할 때 매번 겹치는 url을 기본으로 설정하고 싶을 때&lt;br /&gt;-헤더를 공통으로 적용하고 싶을 떄&lt;br /&gt;-에러가 발생했을 때 공통으로 처리하고 싶을때&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;axios는 라이브러리이다. 모듈을 설치 후 사용할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;️설치방법&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✏️설치방법&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;	// npm 사용
    $ npm install axios
    
    // bower 사용
    $ bower install axios
    
    // yarn 사용
    $ yarn add axios
    
    //jsDelivr CDN 사용하기:
    &amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;

	//unpkg CDN 사용하기:
	&amp;lt;script src=&quot;https://unpkg.com/axios/dist/axios.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
   &lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;️사용법&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✏️사용법&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내가 자주 사용하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;cs&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;	
	// 1번
	const API = axios.create({
      baseURL: 'https://some-domain.com/api/',
      timeout: 1000,
      headers: {'X-Custom-Header': 'foobar'}
    });

	API.get(url, params, config)
	API.post(url, params, config)

	// 2번
    axios({
      method: 'post',
      url: '/user/12345',
      data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
      }
    });&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 그외 방법들&lt;/b&gt;&lt;br /&gt;&lt;b&gt;방법 1.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;	const axios = require('axios')
    
    axios.get('/user?ID=12345')
		.then(response =&amp;gt; console.log(response)) // 성공 핸들링
		.catch(error=&amp;gt;console.log(error)) // 에러 핸들링
		.then(something =&amp;gt; something) // 항상 실행되는 영역&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;// get 요청	
axios.get('/user', {
            params : {
                ID: 12345
            }
        })
		.then(response =&amp;gt; console.log(response)) // 성공 핸들링
		.catch(error=&amp;gt;console.log(error)) // 에러 핸들링
		.then(something =&amp;gt; something) // 항상 실행되는 영역

//post 요청
axios.post('/user',{
          firstName: 'yejin',
          lastName: 'jo'
        })
		.then(response =&amp;gt; console.log(response)) // 성공 핸들링
		.catch(error=&amp;gt;console.log(error)) // 에러 핸들링
		.then(something =&amp;gt; something) // 항상 실행되는 영역
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 3. async await 함께 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;    async function getUser() {
      try {
        const response = await axios.get('/user?ID=12345');
        console.log(response);
      } catch (error) {
        console.error(error);
      }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;axios 메소드 명령어&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;prolog&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;	axios.request(config)
    axios.get(url[, config])
    axios.delete(url[, config])
    axios.head(url[, config])
    axios.options(url[, config])
    axios.post(url[, data[, config]])
    axios.put(url[, data[, config]])
    axios.patch(url[, data[, config]])

ps. 명령어 메소드를 사용시 'url', 'method', 'data' 속성을 config에서 지정할 필요가 없습니다.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;fetch&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; Fetch&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[fetch 공식 문서 정의]&lt;/p&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 요청 전송 기능을 제공하는 WEB API&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;️특징-1&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✏️특징&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP response 객체를 래핑한 Promise 객체를 반환-&amp;gt; 데이터 다루기 편리&lt;/li&gt;
&lt;li&gt;내장 라이브러리이기 때문에 업데이트 이슈 방지 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터셉터 불가&lt;/li&gt;
&lt;li&gt;JSON 형태로 반환하지 않아 .json()으로 변환해서 사용해야함&lt;/li&gt;
&lt;li&gt;axios와 비교 시 상대적으로 기능 부족&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;️사용법-1&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✏️사용법&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;fetch(url)
	.then(response =&amp;gt; response.json())
  	.then(data=&amp;gt; console.log(data));&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;// POST 메서드 구현 예제
async function postData(url = '', data = {}) {
  // 옵션 기본 값은 *로 강조
  const response = await fetch(url, {
    method: 'POST', // *GET, POST, PUT, DELETE 등
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json',
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    redirect: 'follow', // manual, *follow, error
    referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    body: JSON.stringify(data), // body의 데이터 유형은 반드시 &quot;Content-Type&quot; 헤더와 일치해야 함
  });
  return response.json(); // JSON 응답을 네이티브 JavaScript 객체로 파싱
}

postData('https://example.com/answer', { answer: 42 }).then((data) =&amp;gt; {
  console.log(data); // JSON 데이터가 `data.json()` 호출에 의해 파싱됨
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;axios-vs-fetch-어떤걸-더-선호할까&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;❔axios vs fetch 어떤걸 더 선호할까?&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba6DNg/btsnD4mBGeu/gKn0bDyJf3fxtSn0b7c9XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba6DNg/btsnD4mBGeu/gKn0bDyJf3fxtSn0b7c9XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba6DNg/btsnD4mBGeu/gKn0bDyJf3fxtSn0b7c9XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba6DNg%2FbtsnD4mBGeu%2FgKn0bDyJf3fxtSn0b7c9XK%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;1081&quot; height=&quot;781&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;781&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;npm Trends에서 최근 1년 기준으로 다운로드 수를 axios와 react를 비교해보았다.&lt;br /&gt;(fetch는 라이브러리가 아니라 react 내장함수이기 때문에 비교 불가)&lt;br /&gt;당연히 react가 상승폭이 클 줄 알았는데 예상외로 axios가 상승폭이 컸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;969&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMhrak/btsnOfe4CSa/Zshc5YJlgjxVVMEQDKQ60K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMhrak/btsnOfe4CSa/Zshc5YJlgjxVVMEQDKQ60K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMhrak/btsnOfe4CSa/Zshc5YJlgjxVVMEQDKQ60K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMhrak%2FbtsnOfe4CSa%2FZshc5YJlgjxVVMEQDKQ60K%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;969&quot; height=&quot;490&quot; data-origin-width=&quot;969&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; 결론&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;react에서는 크로스 브라우징을 조금 더 신경 쓴 axios 모듈을 사용하는 것이 더 나아보인다.&lt;/li&gt;
&lt;li&gt;모듈을 설치하기 싫다면 내장라이브러리 fetch를 써야하지만 디테일한 작업은 못한다는 불편함을 감수해야한다! (예를 들어 인터셉터!)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부/Javascript</category>
      <category>API요청</category>
      <category>axios</category>
      <category>axios fetch 비교</category>
      <category>fectch</category>
      <category>JavaScript</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/34</guid>
      <comments>https://devjooj.tistory.com/34#entry34comment</comments>
      <pubDate>Sat, 15 Jul 2023 23:37:26 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] CloudFront 개념 뿌시기</title>
      <link>https://devjooj.tistory.com/33</link>
      <description>&lt;h1 id=&quot;cloudfront란&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt; CloudFront란?&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 id=&quot;aws-공식-문서-정의&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;[AWS 공식 문서 정의]&lt;/h4&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;Fast, highly secure and programmable content delivery network (CDN)&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Amazon CloudFront는 전 세계 고객에게 데이터, 비디오, 애플리케이션 및 API를 안전하게 제공하는 빠른 CDN(Content Delivery Network) 서비스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;cloudfront-핵심-포인트&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; CloudFront 핵심 포인트&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;1-edge-location&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. Edge Location&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CloudFront를 위한 캐시 서버(Cache Server)컬렉션&lt;/li&gt;
&lt;li&gt;사용자가 데이터 요청 시 1차적으로 엣지로케이션에 캐싱된 콘텐츠가 있는지 체크 후 있으면 즉시 전송, 없으면 오리진 서버에서 데이터 캐싱 후 사용자에게 제공&lt;/li&gt;
&lt;li&gt;캐시 서버이기 때문에 캐시 만료시간도 설정 가능&lt;/li&gt;
&lt;li&gt;2020년 기준 글로벌 205개의 엣지 로케이션 보유&lt;/li&gt;
&lt;li&gt;TMI: 우리나라는 현재 4곳의 엣지 로케이션이 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-distribution&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. Distribution&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트의 서버 웹 페이지가 요청되는 위치, 거주지 등을 근거하여 전세계의 위치한 엣지 로케이션 중 비교적 근거리에 위치한 곳으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;분산&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;즉,지연시간이 가장 낮은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Edge Location&lt;/b&gt;으로 요청&lt;br /&gt;따라서 콘텐츠의 전송 속도 빠름!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;요약--결론&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; 요약 &amp;amp; 결론&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/df0AvJ/btsnF6QBqva/wT5K63bStKdOMwJ6sOcr1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/df0AvJ/btsnF6QBqva/wT5K63bStKdOMwJ6sOcr1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/df0AvJ/btsnF6QBqva/wT5K63bStKdOMwJ6sOcr1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdf0AvJ%2FbtsnF6QBqva%2FwT5K63bStKdOMwJ6sOcr1k%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;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[참고 1. Origin 서버 요청 시 콘텐츠를 제공할 때]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEkCET/btsnGj3m6WF/OZbqgvpDPaw6eSgWdipkv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEkCET/btsnGj3m6WF/OZbqgvpDPaw6eSgWdipkv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEkCET/btsnGj3m6WF/OZbqgvpDPaw6eSgWdipkv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEkCET%2FbtsnGj3m6WF%2FOZbqgvpDPaw6eSgWdipkv1%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;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[참고 2. Edge Location에서 콘텐츠를 제공할 때]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 에서 구축한 Edge Location 중 요청한 사용자에게로부터 지리적으로 가까운 위치의 서버에 콘텐츠를 복제해주는 서비스&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 은행에서 길게 줄을 설 필요없이&lt;br /&gt;나와 가장 가까운 ATM에서 콘텐츠를 받는다고 생각하면 됨&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;장점 1. 데이터 제공 받는 속도 빠름&lt;/b&gt;&lt;br /&gt;물리적으로 멀리 떨어진 서버에서 다운로드하는 것보다, 가까운 서버에 접속하여 다운로드 받는 것이 속도가 훨씬 빠름&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장점 2. 트래픽 급증 처리 가능&lt;/b&gt;&lt;br /&gt;하나의 오리진 서버로 수많은 사용자가 몰리는 것을 방지할 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점 1. 단일 장애 지점&lt;/b&gt;&lt;br /&gt;시스템 하나가 잘못되면 전체 시스템을 사용 못 할 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점 2. 불필요한 여러개의 네트워크 연결&lt;/b&gt;&lt;br /&gt;특정 지역에서 서비스하는 즉, 타겟팅이 분명한 곳은 불필요하게 연결해야하는 네트워크 수가 많아 오히려 데이터 제공 시간이 지연될 수 있음&lt;br /&gt;(하지만 거의 미비하다고 보면 됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;보안은 괜찮은걸까?&lt;/b&gt;&lt;br /&gt;트래픽과 애플리케이션은 추가 비용 없이 Amazon Shield Standard와 같은 다양한 기본 제공 보호 기능 보유&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;개인적으로 추가 보완해야할 사항&lt;/b&gt;&lt;br /&gt;1. 배포 방법&lt;br /&gt;2. CDN에서도 데이터 전송 속도가 느린 경우 대처 사항&lt;/p&gt;</description>
      <category>Server/AWS</category>
      <category>AWS</category>
      <category>CDN</category>
      <category>CloudFront</category>
      <category>Edge Location</category>
      <category>엣지로케이션</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/33</guid>
      <comments>https://devjooj.tistory.com/33#entry33comment</comments>
      <pubDate>Fri, 14 Jul 2023 22:54:51 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] Spring-context.xml 정리</title>
      <link>https://devjooj.tistory.com/32</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Application Context&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;spring 프레임워크에서 제공하는 핵심 기능 중 하나&lt;/li&gt;
&lt;li&gt;Spring IoC 컨테이너로서 Spring 애플리케이션에서 객체의 생성, 구성 및 관리 담당&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;용어 정리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IoC (Inversion of Control) 제어의 역전
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 디자인 패턴 중 하나&lt;/li&gt;
&lt;li&gt;누구에게 주도권이 있는지가 핵심 개념&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어반전이 적용된 구조는 외부 라이브러리가 프로그래머가 작성한 코드를 돌아게하는 것 즉, 제어권이 반전됨&lt;/li&gt;
&lt;li&gt;프레임워크와 라이브러리 사용차이
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프레임워크에 등록되어있는 요소들을 가져다 씀&lt;/li&gt;
&lt;li&gt;라이브러리는 필요한 구성요소를 가져옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;미리 정해진 협약대로만 동작하게 됨&lt;/li&gt;
&lt;li&gt;모듈을 바꾸어도 다른 시스템에 부작용을 일으키지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DI (Dependency Injection)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래밍에서 구성요소간의 의존관계가 소스코드 내부가 아닌 외부의 설정파일 등을 통해 정의되게 하는 디자인 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DIP(Dependency Inversion principle)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더 중요한 모듈이 덜 중요한 모듈에 의존하면 안되게 다형성을 적극적으로 활용하며 모듈의 재사용성이 높이도록 하는 원칙&lt;/li&gt;
&lt;li&gt;다형성:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;To..do..&lt;/p&gt;</description>
      <category>개발 공부/Java</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/32</guid>
      <comments>https://devjooj.tistory.com/32#entry32comment</comments>
      <pubDate>Thu, 13 Jul 2023 23:20:31 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Spring properties 환경 변수 적용</title>
      <link>https://devjooj.tistory.com/31</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;- 변경해야 할 부분&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;환경별 properties 구분 (폴더 구조)&lt;/li&gt;
&lt;li&gt;spring-context.xml&lt;/li&gt;
&lt;li&gt;spring-datasource.xml&lt;/li&gt;
&lt;li&gt;server 탭 &amp;gt; tomcat 더블 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;폴더 구조&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같이 환경별 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;local:로컬,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;dev: 개발,prod: 운영&lt;/li&gt;
&lt;li&gt;이제 아래 폴더명으로 구성된 properties는 환경별로 세팅할 수 있도록 구성 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coM5KT/btsnpkBRKeC/pzjDSnCE85FGyesJggxr1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coM5KT/btsnpkBRKeC/pzjDSnCE85FGyesJggxr1K/img.png&quot; data-alt=&quot;환경별 폴더 &amp;amp;amp; 변수 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coM5KT/btsnpkBRKeC/pzjDSnCE85FGyesJggxr1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoM5KT%2FbtsnpkBRKeC%2FpzjDSnCE85FGyesJggxr1K%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;209&quot; height=&quot;197&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;환경별 폴더 &amp;amp; 변수 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Server (tomcat) 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- spring server 탭 &amp;gt; tomcat 더블 클릭&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;General Information &amp;gt; Open launch configureation &amp;gt; Arguments 탭 클릭&lt;/li&gt;
&lt;li&gt;VM arguments에
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;-Dspring.profiles.active=local &lt;/b&gt;추가 후 Apply&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;현재는 로컬환경이니까 local로 기본해놓고, 추후 각 server build시 catalina.out에서 해당 값 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;1318&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgkwDc/btsnn8hSuL2/iIxDMrXMvtKxXf8AKuaRok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgkwDc/btsnn8hSuL2/iIxDMrXMvtKxXf8AKuaRok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgkwDc/btsnn8hSuL2/iIxDMrXMvtKxXf8AKuaRok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgkwDc%2Fbtsnn8hSuL2%2FiIxDMrXMvtKxXf8AKuaRok%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;1318&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;1318&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;spring-context.xml&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에 server에 추가한 spiring.profiles.active를 동적 변수로 할당 (D빼고 넣는다고 생각하면 됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (3).png&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yt09j/btsnqvJEKqx/ML2Nf36hWyJqgBriYlQBN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yt09j/btsnqvJEKqx/ML2Nf36hWyJqgBriYlQBN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yt09j/btsnqvJEKqx/ML2Nf36hWyJqgBriYlQBN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyt09j%2FbtsnqvJEKqx%2FML2Nf36hWyJqgBriYlQBN1%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;940&quot; height=&quot;187&quot; data-filename=&quot;Untitled (3).png&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;spiring-datasource.xml&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마찬가지로 server에 할당한 변수를 아래에 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (4).png&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;175&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HOm17/btsnqwogKnR/ncD8lqHWUeX7iUwpfvhkYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HOm17/btsnqwogKnR/ncD8lqHWUeX7iUwpfvhkYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HOm17/btsnqwogKnR/ncD8lqHWUeX7iUwpfvhkYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHOm17%2FbtsnqwogKnR%2FncD8lqHWUeX7iUwpfvhkYK%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;837&quot; height=&quot;175&quot; data-filename=&quot;Untitled (4).png&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;175&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;각 환경별 서버 세팅&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;각 서버에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: left;&quot; href=&quot;http://catlinaout.sh&quot;&gt;catlinaout.sh&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;내부 JAVA_OPT에 아래 코드 한 줄을 추가해줘야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;톰캣 내부 &amp;gt; bin &amp;gt; vi &lt;a href=&quot;http://catalinaout.sh&quot;&gt;catalina&lt;/a&gt;.sh&lt;/li&gt;
&lt;li&gt;개발환경은 spring 위 폴더 구조의&amp;nbsp; dev로 되어있으니까 dev로 설정&lt;/li&gt;
&lt;li&gt;운영환경은 spring 위 폴더 구조의 prod로 되어있으니까 prod로 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;-Dspring.profiles.active=[환경변수]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (5).png&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9GC3G/btsnohTeaU2/EtNezAg3uUKnt3C1LYSjp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9GC3G/btsnohTeaU2/EtNezAg3uUKnt3C1LYSjp0/img.png&quot; data-alt=&quot;추가 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9GC3G/btsnohTeaU2/EtNezAg3uUKnt3C1LYSjp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9GC3G%2FbtsnohTeaU2%2FEtNezAg3uUKnt3C1LYSjp0%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;621&quot; height=&quot;33&quot; data-filename=&quot;Untitled (5).png&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;추가 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참고 &lt;a href=&quot;https://developyo.tistory.com/4&quot;&gt;https://developyo.tistory.com/4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부/Java</category>
      <category>Java</category>
      <category>spring</category>
      <category>환경변수</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/31</guid>
      <comments>https://devjooj.tistory.com/31#entry31comment</comments>
      <pubDate>Wed, 12 Jul 2023 22:45:34 +0900</pubDate>
    </item>
    <item>
      <title>[Server] Ngnix 왜 사용할까?</title>
      <link>https://devjooj.tistory.com/29</link>
      <description>&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;div&gt;
&lt;h2 id=&quot;-들어가기-전&quot; data-ke-size=&quot;size26&quot;&gt;  들어가기 전..&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅은 Nginx 사용법보다는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Nginx를 사용하는 이유&lt;/b&gt;에 대해 중점적으로 다뤄보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ngnix 서버 올리는 방법, 포트 포워딩 하는 방법, redirect하는 방법 등 과 같은 사용법에 대해서는 구글링만 하면 코드를 그대로 갖다 쓸 수 있을 정도로 잘 정리된 포스팅이 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 nginx를 굳이 왜 써야하는지, nginx를 왜 만들었는지에 대한 이해를 바탕으로 쓴다면 위에 말한 포스트들을 내가 필요한 순간에 잘 활용할 수 있을 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹서버에 대해 듣게 된다면 꼭 빠지지 않는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Ngnix&lt;/b&gt;! 왜 만들게 된 걸까?&lt;/p&gt;
&lt;h2 id=&quot;️-기존-apache의-한계&quot; data-ke-size=&quot;size26&quot;&gt;✏️ 기존 Apache의 한계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 웹의 역사와 긴밀한 관련이 있다.&lt;/p&gt;
&lt;h3 id=&quot;초기-웹-상황&quot; data-ke-size=&quot;size23&quot;&gt;초기 웹 상황&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저에 정보를 표현할 수 있게 해주는 마크업 언어 HTML이 제일 먼저 개발 되었다. 이 언어는 기존에 작성된 화면을 보여주기 때문에 초기 웹 사이트들은 모두 정적(static)인 웹사이트였다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGXv6J/btsm2HZHS43/ETHSNTByAX2RFQLSctiAb0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGXv6J/btsm2HZHS43/ETHSNTByAX2RFQLSctiAb0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGXv6J/btsm2HZHS43/ETHSNTByAX2RFQLSctiAb0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGXv6J%2Fbtsm2HZHS43%2FETHSNTByAX2RFQLSctiAb0%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;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 단순히 브라우저에 정보를 표현해주는게 전부라 서버가 데이터를 처리할 부담이 없었다.&lt;/p&gt;
&lt;h3 id=&quot;자바스크립트--spa-등장&quot; data-ke-size=&quot;size23&quot;&gt;자바스크립트 &amp;amp; SPA 등장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이후 스크립트 등장으로 동적인 데이터를 다루고,&lt;br /&gt;SPA라는 개념이 등장하면서 서버에서 처리해야할 양이 방대해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA(Single Page Application)는 기존의 웹페이지와는 달리 기본적인 정적인 정보는 한번에 다운받아 이후 페이지 갱신 시 필요한 데이터만을 전달받아 갱신하는 방식으로 개발되었다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGZ533/btsm9BKEBIi/AkPXUxCKkVuLEnO2IypypK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGZ533/btsm9BKEBIi/AkPXUxCKkVuLEnO2IypypK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGZ533/btsm9BKEBIi/AkPXUxCKkVuLEnO2IypypK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGZ533%2Fbtsm9BKEBIi%2FAkPXUxCKkVuLEnO2IypypK%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;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이때, 사용자마다 필요한 데이터들이 다를 수 밖에 없었고, 이로써 이전보다 복잡한 로직이 필요해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 정적인 페이지와 동적인 데이터 모두 한 서버에서 담당하게 되어&lt;br /&gt;서버는 부담이 커지고, 수행 속도도 느려짐에 따라 사이트가 느려지게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이에 대한 해결책으로&lt;br /&gt;정적인 페이지는 정적인 페이지대로,&lt;br /&gt;동적인 페이지는 동적인 페이지대로,&lt;br /&gt;각각 다른 서버에서 처리를 하면 어떨까? 라는 생각이 나왔고,&lt;/p&gt;
&lt;h3 id=&quot;웹-서버-등장&quot; data-ke-size=&quot;size23&quot;&gt;웹 서버 등장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리하여&lt;br /&gt;정적인 페이지는 ws(web server)&lt;br /&gt;동적인 페이지는 was(web application server)로 분리되어 처리하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, ws(web server)는 클라이언트의 요청을 처리하는 기능을 담당하고,&lt;br /&gt;was(web application server)는 db조회나 다양한 로직을 처리하는 기능을 담당하는 서버로 분리되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Unix기반으로 만들어진 최초의 웹서버 NCSA HTTd를 사용했다.&lt;br /&gt;그런데 개발자들이 사용하다보니 버그가 너무 많아 불편함을 겪었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 보완하여 개발한 웹서버 부동의 1위였던 Apache가 생겨나게 되었다.&lt;/p&gt;
&lt;h3 id=&quot;apache-구조&quot; data-ke-size=&quot;size23&quot;&gt;apache 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1995년에 apache는 기존의 웹서버의 버그, 구조 등을 보완하며 탄생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apache의 구조는 다음과 같다.&lt;br /&gt;요청이 들어오면 커넥션을 형성하기 위해 프로세스를 생성하는데,&lt;br /&gt;요청이 들어올 때마다 프로세스가 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 프로세스를 만드는 작업이 시간이 소요되는 작업이다 보니&lt;br /&gt;요청이 들어오기 전에 프로세스를 미리 만들어 놓는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;PREFORK&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방법을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 새로운 클라이언트의 요청이 들어오면 미리 만들어 놓은 프로세스를 가져다 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 만들어놓은 프로세스를 다 사용했다면, 추가로 프로세스를 할당하는 방식이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 구조의 장점은&lt;/b&gt;&lt;br /&gt;1. 개발하기 쉽다&lt;br /&gt;덕분에 다양한 모듈을 만들어 서버에 빠르게 추가할 수 있다.&lt;br /&gt;동적인 컨텐츠를 다룰 수 있게 됨&lt;br /&gt;2. 확장성이 좋다&lt;br /&gt;요청을 받고 응답하는 과정을 하나의 서버에서 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 apache는 웹 서버 1위를 차지하게 되었다.&lt;/p&gt;
&lt;h3 id=&quot;apache의-위기&quot; data-ke-size=&quot;size23&quot;&gt;apache의 위기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2000년 초반, 컴퓨터 보급이 점점 증가하던 시기였다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;421&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCImwv/btsm83OaCjJ/Yd3SuBV89LUhPhMXDAo5lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCImwv/btsm83OaCjJ/Yd3SuBV89LUhPhMXDAo5lK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCImwv/btsm83OaCjJ/Yd3SuBV89LUhPhMXDAo5lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCImwv%2Fbtsm83OaCjJ%2FYd3SuBV89LUhPhMXDAo5lK%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;762&quot; height=&quot;421&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;421&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이전보다 수많은 클라이언트들이 수많은 요청을 생성했고, 당연히 서버는 기존보다 처리해야할 양이 더 많아지게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 요청이 많아지면서 갑자기 문제가 생겼다.&lt;br /&gt;동시 커넥션이 많아졌을 경우 더이상 커넥션을 형성하지 못하는 상황이 생겼다.&lt;br /&gt;이를 C10K 문제라고 한다.&lt;/p&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C10K (connection 10,000): 10,000개의 연결 을 동시에 처리하기 위한 숫자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 클라이언트는 여러개의 커넥션을 형성할 수 있었다.&lt;br /&gt;그래서 개발자들은 이미 한 클리언트가 기존에 만든 커넥션이 있다면 그걸 재활용하자는 생각을 하고&lt;br /&gt;header정보의 keep-alive에 적힌 시간만큼 클라이언트와 서버는 한 커넥션을 길게 유지할 수 있게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 불구하고 클라이언트의 수가 현저히 많아져서 동시 커넥션 수가 10,000단위를 넘어가니&lt;br /&gt;커넥션이 형성되지 못하는 상황이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두가지 관점에서 문제를 바라보았다.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;하드웨어&lt;/li&gt;
&lt;li&gt;소프트웨어&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 하드웨어에서는 문제가 없다고 판단했다.&lt;br /&gt;왜냐하면 이미 하드웨어는 발전 속도가 어마어마했고, 현 기준 웹페이지를 다루기에 하드웨어의 성능은 충분히 좋았기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제는 그 당시, 원탑이었던 웹서버 소프트웨어 Apache의 구조였다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 id=&quot;apache-구조의-문제점&quot; data-ke-size=&quot;size23&quot;&gt;Apache 구조의 문제점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 apache의 구조는 요청이 들어올 때마다 프로세스를 할당하는 구조였다.&lt;br /&gt;즉, 이용자가 많아지면서 그만큼 프로세스도 비례하여 증가하고, 메모리 부족을 야기하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apache의 장점이었던 확장성 덕분에, 다양한 모듈을 추가할 수 있었고&lt;br /&gt;프로세스가 차지하는 리소스의 양도 증가한 상황이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 많은 요청이 들어옴에 따라 cpu 코어는 계속해서 프로세스를 바꿔가며 일을 해야했다. 이를 context-switching이라고 하는데, cpu가 감당해야하는 작업이 증가한 상황이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 수많은 클라이언트 즉, 대용량의 트래픽을 감당하기에는 Apache 서버의 구조가 적합하지 않았다.&lt;/p&gt;
&lt;h3 id=&quot;nginx의-탄생&quot; data-ke-size=&quot;size23&quot;&gt;Nginx의 탄생&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 말한 Apache 서버의 구조를 보완하기 위해 새로운 구조인 웹서버가 나오게 되는데, 현재 웹서버 1위인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Nginx&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx의 구조는 다음과 같다.&lt;br /&gt;Master process와 worker process로 이루어져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Master process&lt;/b&gt;&lt;br /&gt;설정 파일을 읽고, 설정 파일에 맞게 worker process생성하는 작업을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Worker process&lt;/b&gt;&lt;br /&gt;실제로 요청을 처리하는 작업을 한다.&lt;br /&gt;master process에서 배정받은 listen socket을 통해 클라이언트와 커넥션을 형성하고, 해당 커넥션은 keep-alive 시간만큼 유지된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;worker process는 커넥션 하나만 담당할까? 아니!&lt;br /&gt;형성된 커넥션에 아무런 요청이 없을 경우&lt;br /&gt;1. 새로운 커넥션을 형성하거나&lt;br /&gt;2. 이미 만들어진 기존의 커넥션에 요청이 들어온다면 해당 요청을 처리한다.&lt;br /&gt;이런 커넥션 형성, 제거, 새로운 요청 처리 작업들을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이벤트&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 이벤트들은 OS커널이 큐 형식으로 worker process에게 전달해준다.&lt;br /&gt;큐에 담긴 상태에서 worker process가 처리할 때까지 비동기 방식으로 대기한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;worker process는 하나의 쓰레드로 이벤트들을 꺼내서 처리해나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조의 장점은&lt;br /&gt;worker process가 쉬지 않고 작업을 할 수 있다.&lt;br /&gt;즉, apache구조와 비교 시, 요청이 없을 시 방치되던 프로세스와 컴퓨터 자원을 훨씬 효율적으로 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그렇다면, 만약 이 요청 중 하나가 시간이 오래 걸리는 작업이라면?&lt;/b&gt;&lt;br /&gt;그래서 Nginx는 시간이 오래 걸리는 요청들을 따로 수행하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;쓰레드 풀&lt;/b&gt;을 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 worker process는 특정 작업이 오래 걸릴 경우 쓰레드 풀에 그 작업을 위임하고 그 시간에 다른 요청들을 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;worker process는 보통 cpu의 코어 갯수만큼 생성되는데&lt;br /&gt;이러면 코어가 담당하는 프로세스를 바꾸는 횟수를 줄일 수 있다.&lt;br /&gt;즉, cpu가 그런 부가적인 작업을 하지 않아도 되니 cpu의 context-switching 사용을 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 구조를 이벤트 기반의 구조(event-driven model)라고 한다.&lt;/p&gt;
&lt;h3 id=&quot;nginx-단점&quot; data-ke-size=&quot;size23&quot;&gt;Nginx 단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자가 기능 추가를 시도 했을 시 돌아가고 있던 worker process를 종료하는 상황이 생길 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Nginx는 개발자가 직접 모듈을 만들기가 어렵다.&lt;/p&gt;
&lt;h3 id=&quot;nginx-장점&quot; data-ke-size=&quot;size23&quot;&gt;Nginx 장점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;가볍고 빠르다&lt;br /&gt;기존보다 동시 커넥션 수가 최소 10배가 증가했고, 생성되는 프로세스 수도 적다보니 가볍다는 장점이 있다.&lt;br /&gt;동일한 커넥션 수일 때 속도가 2배 향상된다.&lt;/li&gt;
&lt;li&gt;동적으로 설정 파일 변경 가능&lt;br /&gt;master process는 동적으로 변경된 설정파일을 읽고 해당 설정에 맞게&lt;br /&gt;worker process를 생성한다.&lt;br /&gt;기존 worker process의 커넥션 형성을 막고, 처리하던 이벤트들이 모두 완료되면 해당 worker process를 종료한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동적 파일 설정은 언제쓰는걸까?&lt;/b&gt;&lt;br /&gt;서버가 추가될 시 사용된다.&lt;br /&gt;동시 커넥션을 담당하고 있다면, 설정파일을 변경하기 위해 Nginx를 종료하는게 힘들다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 동적으로 파일 설정을 변경할 수 있다면?&lt;br /&gt;기존 요청은 요청대로 처리할 수 있고,&lt;br /&gt;뒤에서 새로운 서버를 추가할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx는 이런 설정을 초당 수십번을 변경해도 무리없이 커넥션을 관리할 수 있다.&lt;br /&gt;이러한 작업을 할 수 있는 것이 이벤트 기반의 구조라서 가능하다.&lt;/p&gt;
&lt;h3 id=&quot;nginx가-주목받게-된-계기&quot; data-ke-size=&quot;size23&quot;&gt;Nginx가 주목받게 된 계기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 Nginx 생기고 초창기 시절에는 웹서버 순위권에도 들지 못했을 정도로 관심을 받지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 2008년 이후로 Apache서버의 점유율이 낮아지고 Nginx의 점유율이 확 상승했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 그럴까?&lt;/b&gt;&lt;br /&gt;2008년 즈음에 스마트폰이 등장했다.&lt;br /&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;그래서 기존보다 폭발적으로 증가한 동시 커넥션 수를 감당하기 위해 많은 회사들이 Nginx를 도입했고, 이 중 대용량 트래픽이 발생하는 회사에서 큰 빛을 발하게 되며 점차 점유율이 상승했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이때쯤, Apache도 MPMs라는 모듈을 도입하여 성능을 개선했다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동시 커넥션 수가 많을 경우 메모리를 차지하는 비율을 비교한 사진 넣기&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;nginx-기능&quot; data-ke-size=&quot;size23&quot;&gt;Nginx 기능&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리버스 프록시&lt;/b&gt;&lt;br /&gt;Nginx와 Apache를 함께 사용할 수 있다.&lt;br /&gt;Apache 앞에 nginx를 이용하면 리버스 프록시의 장점을 활용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로드밸런싱&lt;/b&gt;&lt;br /&gt;nginx에 여러대의 서버가 연결되었을 시&lt;br /&gt;한 서버에 부하가 걸리지 않도록 균등하게 요청을 분배하는 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SSL 터미네이션&lt;/b&gt;&lt;br /&gt;Nginx가 클라이언트와 https 통신을 함&lt;br /&gt;server와는 http통신을 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 과정을 통해 서버가 복호화 과정을 담당하지 않도록 해준다.&lt;/li&gt;
&lt;li&gt;비즈니스 로직에 비중을 둘 수 있도록 부하를 줄여준다.&lt;/li&gt;
&lt;li&gt;보통 Nginx와 서버는 같은 네트워크 상에 있기 때문에 http통신을 해도 보안 이슈가 비교적 적다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐싱&lt;/b&gt;&lt;br /&gt;위와 반대로 Nginx를 클라이언트 쪽과 가깝게 배치?&lt;br /&gt;한번 서버로부터 받은 응답을 보관하고 클라이언트에게 응답한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;그럼에도-불구하고-apache를-왜-여전히-많이-사용할까&quot; data-ke-size=&quot;size23&quot;&gt;그럼에도 불구하고 Apache를 왜 여전히 많이 사용할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Apache는 안정적이다.&lt;/b&gt;&lt;br /&gt;Apache가 탄생하게 된 계기는 기존 웹서버의 버그를 보완하기 위해서였기 때문에 오랜기간 업데이트를 통해 서버자체의 호환성이 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, Nginx는 윈도우에서는 제대로 된 성능을 못 보여주는 등 호환성이 그리 높지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Apache는 확장성이 좋다&lt;/b&gt;&lt;br /&gt;Apache로 만들어진 오래된 서비스라고 해도 현재 이상이 없고,&lt;br /&gt;다양한 모듈을 자유롭게 추가할 수 있기 때문에 모듈의 종류가 훨씬 많은 Apache를 두고 굳이 다른 서버로 변경할 필요가 없다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동시 커넥션 수&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청을 처리하기 위해 한 시점에 서버가 얼마나 많은 클라이언트와 커넥션을 형성하는지 나타내는 지표&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;초당 요청 처리 수&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #000000;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초당 얼마나 빨리 클라이언트의 요청을 처리할 수 있는지를 나타내는 지표&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Server</category>
      <category>ngnix</category>
      <category>WAS</category>
      <category>ws</category>
      <category>웹서버</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/29</guid>
      <comments>https://devjooj.tistory.com/29#entry29comment</comments>
      <pubDate>Tue, 11 Jul 2023 00:27:09 +0900</pubDate>
    </item>
    <item>
      <title>[AWS Skill Builder] 유료 학습 과정 체험</title>
      <link>https://devjooj.tistory.com/27</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;1122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2HO97/btsmBwc1Va4/6hdjhcQdKeOWmK4xSSlx1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2HO97/btsmBwc1Va4/6hdjhcQdKeOWmK4xSSlx1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2HO97/btsmBwc1Va4/6hdjhcQdKeOWmK4xSSlx1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2HO97%2FbtsmBwc1Va4%2F6hdjhcQdKeOWmK4xSSlx1K%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;487&quot; height=&quot;1122&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;1122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Server/AWS</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/27</guid>
      <comments>https://devjooj.tistory.com/27#entry27comment</comments>
      <pubDate>Thu, 6 Jul 2023 14:57:54 +0900</pubDate>
    </item>
    <item>
      <title>[React] React-Hook-Form 개념편</title>
      <link>https://devjooj.tistory.com/26</link>
      <description>&lt;h3 id=&quot;-들어가기-전&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; &amp;nbsp;들어가기 전&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Form은 웹 사이트나 어플리케이션에서 개발해 본 경험이 있다면 필수로 다뤄봤을 부분이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로그인, 회원가입, 게시글을 등록하거나 등등 많은 부분에서 form을 쉽게 접할 수 있기 때문이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;react를 사용한 여러 프로젝트에서 매번 controlled component를 사용하여 Form을 개발했다.&lt;br /&gt;React에서는 state로 관리하면 실시간으로 사용자가 입력한 값을 확인할 수 있는 등의 이유로 추천하고 있기 때문이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;contolled component로 Form을 개발한다면,&lt;br /&gt;아래와 같이 input의 값을 관리하기 위해 state 변수들을 만들 것이다.&lt;br /&gt;그리고 각각 onChange 이벤트들을 추가하고, 우리는 input을 업데이트할 때마다 state가 함께 update되며 값을 controll할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt; import React, { useState } from 'react';
 
 const App = () =&amp;gt; {
   const [username, setUsername] = useState('');
   return (
     &amp;lt;form className=&quot;App&quot;&amp;gt;
       &amp;lt;input
         type=&quot;text&quot;
         placeholder=&quot;Username&quot;
         name=&quot;username&quot;
         value={username}
         onChange={e =&amp;gt; setUsername(e.target.value)}
       /&amp;gt;
       &amp;lt;input type=&quot;submit&quot; /&amp;gt;
     &amp;lt;/form&amp;gt;
   );
 };
 
 export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약에 우리가 많은 입력값들이 필요하게 된다면, 우리는 그만큼의 state를 추가하고, event함수들 또한 각각 만들어줘야한다.&lt;br /&gt;우리가 input의 값을 변경할 때마다 컴포넌트들은 그만큼 리랜더링 될 것이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Form에 점점 추가되면 코드도 그만큼 길어지고 리랜더링되는 횟수도 비례하여 증가하겠지..?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이런 점들을 보완하여 이전보다 쉽고 효율적으로 Form을 개발할 수 있도록 해주는 라이브러리가&lt;span&gt;&amp;nbsp;&lt;/span&gt;React-Hook-Form이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;공부해보니 일단 코드가 간결해지고 가독성 또한 좋아지는 것을 느꼈다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;딱 3가지 함수로 모든 걸 다 할 수 있는 느낌?!&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✍  React-hook-form 공식문서를 번역한거라 의역이 많이 되어 있습니다.&lt;br /&gt;부족한 부분은 댓글로 마구마구 피드백 부탁드립니다 :)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;react-hook-form&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;React-Hook-Form&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위에서 말한 것과 같이 Form을 보다 쉽고 효율적으로 개발할 수 있도록 도와주는 라이브러리이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;타 라이브러리 Formik, Redux Form과 비교했을 때 가장 뛰어난 성능을 보여준다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;불필요한 리랜더링을 제거하고, 작성해야하는 코드의 양을 줄여준다.&lt;/p&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;rarr; provider 방식 대신 비제어 컴포넌트(ref)방식을 사용해 불필요한 랜더링을 제거한다 
(비제어 컴포넌트 방식에 대해서는 아래에서 더 자세히 다룰 예정)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;유연하고, 확장 가능하고 또한, 유효성 검사도 쉽게 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;Fast Mounting &amp;rarr; 로딩 속도가 빠르다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;라이브러리가 가볍다.&lt;/p&gt;
&lt;h2 id=&quot;react-hook-form-사용하기&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;React Hook Form 사용하기&lt;/h2&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;// 라이브러리 설치
npm install react-hook-form&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;clean&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;// 라이브러리 import하기 
import { useForm } from 'react-hook-form';&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;react-hook-form은 3개의 props를 가지고 있다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const { register, handleSubmit, formState: { errors } } = useForm();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;input 입력값 작성하기&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; ref에 위에서 선언해준&lt;span&gt;&amp;nbsp;&lt;/span&gt;register&lt;span&gt;&amp;nbsp;&lt;/span&gt;props 적어주기&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;input
  type=&quot;text&quot;
  placeholder=&quot;Username&quot;
  name=&quot;username&quot;
  ref={register}
/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;form의 onSubmit 함수를 만들어준다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;data에는 Form 입력값들이 들어올 예정&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const onSubmit = (data) =&amp;gt; {
  console.log(data);
};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;onSubmit&lt;span&gt;&amp;nbsp;&lt;/span&gt;props로&lt;span&gt;&amp;nbsp;&lt;/span&gt;handleSubmit&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 추가하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;submit&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 콜백함수로 전달해준다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;form className=&quot;App&quot; onSubmit={handleSubmit(onSubmit)}&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️ onSubmit 할 경우&lt;/p&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;// 전체 코드
const App = () =&amp;gt; {
  return (
    &amp;lt;form className=&quot;App&quot; onSubmit={handleSubmit(onSubmit)} &amp;gt;
      &amp;lt;input {...register('userName')}/&amp;gt;
      &amp;lt;input {...register('email')}/&amp;gt;
      &amp;lt;input {...register('password')}/&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;onSubmit&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;1186&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nUMru/btsmyvr05b8/UdEmutvLIRwCqaERJyMt01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nUMru/btsmyvr05b8/UdEmutvLIRwCqaERJyMt01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nUMru/btsmyvr05b8/UdEmutvLIRwCqaERJyMt01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnUMru%2Fbtsmyvr05b8%2FUdEmutvLIRwCqaERJyMt01%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;1186&quot; height=&quot;288&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;&lt;b&gt;register 함수 : {&amp;hellip;register(name)}&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;이 함수를 통해 uncontorlled component를 hook과 연결하여 유효성 체크를 하고, 폼을 submit할 때 한꺼번에 모아서 제출이 가능하도록 해준다.&lt;/p&gt;
&lt;pre class=&quot;dust&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;input {...register('userName')}/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 즉, 해당 name의 state를 만들어서 관리한다고 볼 수 있다.&lt;br /&gt;(ex)&lt;span&gt;&amp;nbsp;&lt;/span&gt;userName이라는 input을 값을 관리한다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✏️ 해당 input에 대한 errors를 체크하고 싶으면&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const { register, handleSubmit, errors } = useForm();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위에 errors라는 함수에&lt;span&gt;&amp;nbsp;&lt;/span&gt;errors.userName처럼 확인하고 싶은 input의 name값을 key처럼 사용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;{errors.username &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Username required&amp;lt;/p&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;972&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csM2qt/btsmuqRUDME/jcUZlDvUEeKCaXamzCJNu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csM2qt/btsmuqRUDME/jcUZlDvUEeKCaXamzCJNu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csM2qt/btsmuqRUDME/jcUZlDvUEeKCaXamzCJNu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsM2qt%2FbtsmuqRUDME%2FjcUZlDvUEeKCaXamzCJNu0%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;972&quot; height=&quot;706&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✅&amp;nbsp;&lt;b&gt;Form 유효성 체크 또한 너무 간단하게 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;아래와 같이 validation을 사용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;input {...register(&quot;firstName&quot;, { required: true, maxLength: 20 })} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;지원 가능 유효성 검사&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;required &amp;rarr; 필수항목&lt;/li&gt;
&lt;li&gt;min &amp;rarr; 입력에 허용되는 최소값&lt;/li&gt;
&lt;li&gt;max &amp;rarr; 입력에 허용되는 최대값&lt;/li&gt;
&lt;li&gt;minLength &amp;rarr; 입력에 허용되는 최소 길이&lt;/li&gt;
&lt;li&gt;maxLength &amp;rarr; 입력에 허용되는 최대 길이&lt;/li&gt;
&lt;li&gt;pattern &amp;rarr; 정규식&lt;/li&gt;
&lt;li&gt;validate &amp;rarr; 콜백함수로 커스텀하게 유효성 체크 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { useForm } from &quot;react-hook-form&quot;;

export default function App() {
  const { register, handleSubmit, formState:{ errors } } = useForm();
  const onSubmit = data =&amp;gt; console.log(data);
   
  return (
    &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
      &amp;lt;input {...register(&quot;firstName&quot;, { required: true, maxLength: 20 })} /&amp;gt;
      &amp;lt;input {...register(&quot;lastName&quot;, { pattern: /^[A-Za-z]+$/i })} /&amp;gt;
      &amp;lt;input type=&quot;number&quot; {...register(&quot;age&quot;, { min: 18, max: 99 })} /&amp;gt;
      &amp;lt;input type=&quot;submit&quot; /&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;-react-hook-form-핵심-point&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  React-Hook-Form 핵심 Point&lt;/h2&gt;
&lt;h3 id=&quot;-uncontrolled-component비제어를-사용한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✍  uncontrolled component(비제어)를 사용한다.&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;제어 컴포넌트와 비제어 컴포넌트의 차이는 뭘까?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 제어 컴포넌트 controlled component&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ useState hook을 통해 state를 만들어 사용한다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;actionscript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;  const [inputText, setInputText] = useState(&quot;&quot;):&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;inputText state로 값을 관리하고 수정할 때에도 setInputText의 값을 변경해준다.&lt;/li&gt;
&lt;li&gt;사용자가 변경할때마다 onchange로 input 값을 변경할 수 있다.&lt;/li&gt;
&lt;li&gt;사용자가 타이핑할 때마다 react state는 변경되고 사용자는 계속 변경된 값을 볼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;    &amp;lt;input
      type=&quot;text&quot;
      value={inputText}
      onChange={(e) =&amp;gt; setInputText(e.target.value)}
    /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;React state에 값을 저장하여 값에 접근할 수 있다.&lt;br /&gt;✔️&amp;nbsp;사용자의 이벤트가 발생할 때마다 state로 변경되기 때문에 즉시 유효성 검사를 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;    import React, { useState } from &quot;react&quot;;
     const Controlled = () =&amp;gt; {
      const [inputText, setInputText] = useState(&quot;&quot;);
    const handleSubmit = (e) =&amp;gt; {
        e.preventDefault();
        console.log(inputText);
      };
    return (
        &amp;lt;form&amp;gt;
          &amp;lt;input
            type=&quot;text&quot;
            value={inputText}
            onChange={(e) =&amp;gt; setInputText(e.target.value)}
          /&amp;gt;
          &amp;lt;button onClick={handleSubmit}&amp;gt;Submit&amp;lt;/button&amp;gt;
        &amp;lt;/form&amp;gt;
      );
    };
    export default Controlled;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 비제어 컴포넌트 uncontrolled component&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ useRef를 통해 직접 DOM 요소에 접근하여 값을 가져온다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✔️&amp;nbsp;input과 같은 요소들의 값이 react로 관리되지 않고 내부적으로 저장되기 때문에 uncontrolled component이다.&lt;br /&gt;✔️&amp;nbsp;우리는 직접 input 요소에 접근하여 값을 가져올 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 HTML From input 요소와 비슷하다
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt; import React, { useRef } from &quot;react&quot;;
 const Uncontrolled = () =&amp;gt; {
   const inputRef = useRef(null);
 const handleSubmit = (e) =&amp;gt; {
     e.preventDefault();
     console.log(inputRef.current.value);
   };
 return (
     &amp;lt;form&amp;gt;
       &amp;lt;input type=&quot;text&quot; ref={inputRef} /&amp;gt;
       &amp;lt;button onClick={handleSubmit}&amp;gt;Submit&amp;lt;/button&amp;gt;
     &amp;lt;/form&amp;gt;
   );
 };
 export default Uncontrolled;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;input과 button으로 만들어진 form이 있다.&lt;/li&gt;
&lt;li&gt;React에서는 DOM요소에 접근하고 싶으면 useRef를 사용해야한다.&lt;/li&gt;
&lt;li&gt;useRef는 값을 가지고 있는 현재 속성에 대한 객체를 만들어준다.&lt;/li&gt;
&lt;li&gt;이 참조 값으로 값에 접근할 수 있게 된다.
&lt;pre class=&quot;verilog&quot;&gt;&lt;code&gt; // useRef hook을 통해 참조값을 만들고,
 const inputRef = useRef(null);
 // input 태그에 이 참조값을 전달한다.
 &amp;lt;input type=&quot;text&quot; ref={inputRef} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;최종적으로 Form 을 submit할 때 input 값을 불러오려면 아래와 같이 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;     inputRef.current.value&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;-참고&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  참고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.devgenius.io/the-easiest-way-to-deal-with-forms-in-react-ad6bc1250829&quot;&gt;https://blog.devgenius.io/the-easiest-way-to-deal-with-forms-in-react-ad6bc1250829&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react-hook-form.com/kr/get-started/&quot;&gt;https://react-hook-form.com/kr/get-started/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부/React</category>
      <category>React</category>
      <category>react-hook-form</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/26</guid>
      <comments>https://devjooj.tistory.com/26#entry26comment</comments>
      <pubDate>Wed, 5 Jul 2023 21:43:49 +0900</pubDate>
    </item>
    <item>
      <title>[Ubuntu] 에러 node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by node)</title>
      <link>https://devjooj.tistory.com/25</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;개발환경&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu: 18.04.6 LTS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nvm: 0.39.2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm: v8.3.1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node: v18.16.0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제상황&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;aws ec2서버에 node 설치 후 pm2 설치하려는데&amp;nbsp; 에러남&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nvm사용해서 node 18.16.0으로 버전 설치했는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node 버전이나 npm 버전을 체크하면 자꾸 아래와 같은 에러가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;에러&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688472887020&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by node)&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;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;- ubuntu &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;18.04.6&lt;span&gt; 에서는 node v18^버전을 사용하면 위 에러가 발생한다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;1. ubuntu 버전을 다운 혹은 업하거나&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;2. node버전을 다운하거나 최신 버전으로 올려야하는데,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- 나는 node 버전을 v16^으로 변경했다&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688473090780&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; $ nvm alias default 16.14.0&lt;/code&gt;&lt;/pre&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-filename=&quot;blob&quot; data-origin-width=&quot;372&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOyZSD/btsmsbZ975x/2RD2dPC7nckIU8agaaJkZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOyZSD/btsmsbZ975x/2RD2dPC7nckIU8agaaJkZ1/img.png&quot; data-alt=&quot;버전 정상 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOyZSD/btsmsbZ975x/2RD2dPC7nckIU8agaaJkZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOyZSD%2FbtsmsbZ975x%2F2RD2dPC7nckIU8agaaJkZ1%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;372&quot; height=&quot;91&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;372&quot; data-origin-height=&quot;91&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;</description>
      <category>개발 공부/에러모음</category>
      <category>ubuntu</category>
      <category>에러</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/25</guid>
      <comments>https://devjooj.tistory.com/25#entry25comment</comments>
      <pubDate>Tue, 4 Jul 2023 21:25:31 +0900</pubDate>
    </item>
    <item>
      <title>[ubuntu] ubuntu 버전 확인 명령어</title>
      <link>https://devjooj.tistory.com/24</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. ubuntu 버전 체크&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1688472199565&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cat /etc/issue&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 결과&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;170&quot; data-origin-height=&quot;20&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCWnBH/btsmmzarQnU/KXBAlI8BHlbcGZICrrCbL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCWnBH/btsmmzarQnU/KXBAlI8BHlbcGZICrrCbL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCWnBH/btsmmzarQnU/KXBAlI8BHlbcGZICrrCbL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCWnBH%2FbtsmmzarQnU%2FKXBAlI8BHlbcGZICrrCbL0%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;315&quot; height=&quot;37&quot; data-origin-width=&quot;170&quot; data-origin-height=&quot;20&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;</description>
      <category>Server</category>
      <category>ubuntu</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/24</guid>
      <comments>https://devjooj.tistory.com/24#entry24comment</comments>
      <pubDate>Tue, 4 Jul 2023 21:04:17 +0900</pubDate>
    </item>
    <item>
      <title>[NVM] nvm node 기본 버전 설정</title>
      <link>https://devjooj.tistory.com/23</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;1.특정 버전으로 기본 셋팅&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688473601134&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# nvm alias default [버전] 
$ nvm alias default 16.14.2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.그냥 최신버전으로 할때&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688473637298&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ nvm alias default node&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 최종 결과 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688473662306&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ nvm use
$ node -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Server</category>
      <category>nvm</category>
      <category>ubuntu</category>
      <category>기본버전셋팅</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/23</guid>
      <comments>https://devjooj.tistory.com/23#entry23comment</comments>
      <pubDate>Tue, 4 Jul 2023 20:53:35 +0900</pubDate>
    </item>
    <item>
      <title>[NVM] nvm node 버전 삭제하기</title>
      <link>https://devjooj.tistory.com/22</link>
      <description>&lt;pre id=&quot;code_1688470893420&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# nvm에 설치된 node 버전 리스트 조회
nvm list

#  node  8.xx 버전 삭제하기
nvm uninstall v8&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 삭제가 안된다면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 nvm&amp;nbsp; 노드 버전 조회 후&lt;/p&gt;
&lt;pre id=&quot;code_1688470930305&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nvm list&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;선택된&amp;nbsp;버전을&amp;nbsp;삭제하려고&amp;nbsp;하는건&amp;nbsp;아닌지&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;230&quot; data-origin-height=&quot;103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yard3/btsmrCdgzrR/DtAHb7MZhqK83mR2NpQ0TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yard3/btsmrCdgzrR/DtAHb7MZhqK83mR2NpQ0TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yard3/btsmrCdgzrR/DtAHb7MZhqK83mR2NpQ0TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyard3%2FbtsmrCdgzrR%2FDtAHb7MZhqK83mR2NpQ0TK%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;230&quot; height=&quot;103&quot; data-origin-width=&quot;230&quot; data-origin-height=&quot;103&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1688470995476&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nvm use [설치된 노드 버전 중 한개]&lt;/code&gt;&lt;/pre&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;181&quot; data-origin-height=&quot;26&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDOZEh/btsmtC31HuZ/5KiRtxcZ4gxgqWFMKdEtI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDOZEh/btsmtC31HuZ/5KiRtxcZ4gxgqWFMKdEtI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDOZEh/btsmtC31HuZ/5KiRtxcZ4gxgqWFMKdEtI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDOZEh%2FbtsmtC31HuZ%2F5KiRtxcZ4gxgqWFMKdEtI0%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;341&quot; height=&quot;49&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;26&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;</description>
      <category>Server</category>
      <category>node삭제</category>
      <category>nvm</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/22</guid>
      <comments>https://devjooj.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 4 Jul 2023 20:45:34 +0900</pubDate>
    </item>
    <item>
      <title>[TypeScript] setState props로 넘길 때 타입 지정하기</title>
      <link>https://devjooj.tistory.com/21</link>
      <description>&lt;pre id=&quot;code_1688388378949&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface ILibrary {
	book:string
	setBook: React.Dispatch&amp;lt;React.SetStateAction&amp;lt;string&amp;gt;&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결 방법:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- React.Dispatch&amp;lt;React.SetStateAaction&amp;lt;string&amp;gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/TypeScript</category>
      <category>React</category>
      <category>TypeScript</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/21</guid>
      <comments>https://devjooj.tistory.com/21#entry21comment</comments>
      <pubDate>Mon, 3 Jul 2023 22:10:41 +0900</pubDate>
    </item>
    <item>
      <title>[React] 에러 img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.</title>
      <link>https://devjooj.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;b&gt;  &lt;/b&gt;build 시 아래와 같이 es-lint warnig이 떴다.&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;822&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lJfrc/btsmkOi5czO/TYvGPCAKLg64GkcpSuimh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lJfrc/btsmkOi5czO/TYvGPCAKLg64GkcpSuimh1/img.png&quot; data-alt=&quot;에러 캡쳐&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lJfrc/btsmkOi5czO/TYvGPCAKLg64GkcpSuimh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlJfrc%2FbtsmkOi5czO%2FTYvGPCAKLg64GkcpSuimh1%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;822&quot; height=&quot;41&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;41&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에러 캡쳐&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&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;size16&quot;&gt;&amp;nbsp;변경 전&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1688362691343&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;/img/dog.svg&quot; /&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;아래와 같이 alt 속성을 추가해줬고, 해당 이미지가 안보일 시 보여지는 문구를 작성해주면 해결&lt;/p&gt;
&lt;pre id=&quot;code_1688362702269&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;/img/dog.svg&quot; alt=&quot;dog&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발 공부/에러모음</category>
      <category>React</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/20</guid>
      <comments>https://devjooj.tistory.com/20#entry20comment</comments>
      <pubDate>Mon, 3 Jul 2023 14:40:06 +0900</pubDate>
    </item>
    <item>
      <title>[DB] SQL과 NoSQL 개념</title>
      <link>https://devjooj.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt; 들어가기 전&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관계형 데이터베이스 vs 비관계형 데이터베이스&lt;br /&gt;SQL 기반 데이터베이스 vs. NoSQL 기반 데이터베이스&lt;br /&gt;관계형 데이터베이스 vs. NoSQL&lt;br /&gt;SQL vs. NoSQL&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;같은 듯 다른 말로 느껴지는데 각각 무슨 차이가 있는 걸까?&lt;br /&gt;SQL이 뭐고 NoSQL이 뭔지는 알지만 위 비교문들이 각각 같은 의미인지 다른 의미인지에 대해&lt;br /&gt;헷갈려서 확실하게 공부하기 위해 포스팅을 하게 되었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 관계형 데이터베이스와 비관계형 데이터베이스에 대해 중점적으로 포스팅해보려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;chapter-1-관계형-데이터베이스가-있다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Chapter 1. 관계형 데이터베이스가 있다.&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계형 데이터베이스에서는 테이블의 구조와 데이터 타입 등을 사전에 정의&lt;/li&gt;
&lt;li&gt;테이블에 정의된 내용에 알맞은 형태의 데이터만 삽입 가능&lt;/li&gt;
&lt;li&gt;테이블의 관계가 구조화된 데이터의 모음이기 때문에 구조화된 쿼리 언어를 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;여기서 구조화된 쿼리 언어가 즉 SQL이다 따라서 관계형 데이터베이스와 상호작용할 때 SQL 사용이 가능하다.&lt;/li&gt;
&lt;li&gt;특정한 형식을 지키기 때문에, 데이터를 정확히 입력했다면 데이터를 사용 수월&lt;/li&gt;
&lt;li&gt;또한, 관계형 데이터베이스에서는 테이블 간의 관계를 직관적으로 파악할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;관계형-데이터베이스-종류는-뭐가-있나&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;관계형 데이터베이스 종류는 뭐가 있나?&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Oracle&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;MariaDB&lt;/li&gt;
&lt;li&gt;PostgresSQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;관계형-데이터베이스를-sql이라고도-할-수-있나&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;관계형 데이터베이스를 SQL이라고도 할 수 있나?&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대답은 YES!&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SQL은 관계형 데이터베이스 전용 프로그래밍 언어이다.&lt;br /&gt;또한, RDBMS 프로그램에서 기본적인 SQL을 지원한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;관계형 데이터베이스 시스템을 위해 만들어진 SQL이라는 언어를 사용 하므로 (문법은 조금씩 상이) 관계형 데이터베이스를 SQL이라고 부를 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 결론은 관계형 데이터베이스를 SQL이라고도 부른다.&lt;/p&gt;
&lt;h2 id=&quot;chapter-2-비관계형-데이터베이스도-있다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Chapter 2. 비관계형 데이터베이스도 있다.&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;비관계형 데이터베이스란 관계형 데이터베이스를 뺀 나머지 유형이라고 할 수 있다.&lt;br /&gt;관계형 데이터베이스를 SQL이라고 하고 비관계형 데이터베이스는 NoSQL이라고 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;NoSql 약자에 대해&lt;br /&gt;NoSQL, Not Only SQL, Non-Relational Operational Database SQL로 엇갈리는 의견들이 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 중 어느 것이 맞을까?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Not Only SQL&lt;/b&gt;로 통용되고 있다.&lt;br /&gt;이 말의 의미는 기존의 관계형 DBMS가 갖고있는 특성 뿐만 아니라 다른 특성들을 부가적으로 지원한다는 것이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제로 Nosql을 관계형 DB처럼 쓸 수는 있긴 하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아무튼 NoSql의 약자는 No! SQL이 아니라&lt;br /&gt;Not Only SQL 의 약자로, RDBMS와 같은 관계형 DB가 아닌 다른 형태의 데이터 저장 기술이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NOSQL의 경우 sorting, join, grouping, index 매우 취약해서 로그 쌓기나 단순 작업에 적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;비관계형-데이터베이스-종류는-뭐가-있나&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;비관계형 데이터베이스 종류는 뭐가 있나?&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Key-Value 타입 Redis, Dynamo&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;속성을 Key-Value의 쌍으로 나타내는 데이터를 배열의 형태로 저장한다.&lt;br /&gt;여기서 Key는 속성 이름을 뜻하고, Value는 속성에 연결된 데이터 값을 의미한다.&lt;br /&gt;Redis, Dynamo 등이 대표적인 Key-Value 형식의 데이터베이스이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 문서형(Document) 데이터베이스 MongoDB&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터를 테이블이 아닌 문서처럼 저장하는 데이터베이스를 의미한다.&lt;br /&gt;많은 문서형 데이터베이스에서 JSON과 유사한 형식의 데이터를 문서화하여 저장한다.&lt;br /&gt;각각의 문서는 하나의 속성에 대한 데이터를 가지고 있고, 컬렉션이라고 하는 그룹으로 묶어서 관리한다.&lt;br /&gt;대표적인 문서형 데이터베이스에는 MongoDB 가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Wide-Column Store 데이터베이스 Cassandra, HBase&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스의 열(column)에 대한 데이터를 집중적으로 관리하는 데이터베이스이다.&lt;br /&gt;각 열에는 key-value 형식으로 데이터가 저장되고, 컬럼 패밀리(column families)라고 하는 열의 집합체 단위로 데이터를 처리할 수 있다.&lt;br /&gt;하나의 행에 많은 열을 포함할 수 있어서 유연성이 높다.&lt;br /&gt;데이터 처리에 필요한 열을 유연하게 선택할 수 있다는 점에서 규모가 큰 데이터 분석에 주로 사용되는 데이터베이스 형식이다.&lt;br /&gt;대표적인 wide-column 데이터베이스에는 Cassandra, HBase 가 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;그래프(Graph) 데이터베이스 Neo4J, InfiniteGraph&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자료구조의 그래프와 비슷한 형식으로 데이터 간의 관계를 구성하는 데이터베이스이다.&lt;br /&gt;노드(nodes)에 속성별(entities)로 데이터를 저장한다.&lt;br /&gt;각 노드간 관계는 선(edge)으로 표현한다.&lt;br /&gt;대표적인 그래프 데이터베이스에는 Neo4J, InfiniteGraph 가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;chapter-3-관계형-db와-비관계형-db차이&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;chapter 3. 관계형 DB와 비관계형 DB차이?&lt;/h2&gt;
&lt;h3 id=&quot;️데이터-저장storage-방식이-다르다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✍️데이터 저장(Storage) 방식이 다르다.&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;관계형 데이터베이스&lt;/b&gt;는 SQL을 이용해서 데이터를 테이블에 저장한다.&lt;br /&gt;또한 관계를 통해 각 데이터를 중복없이 한번만 저장할 수 있고, 따라서 데이터 무결성이 보장된다.&lt;br /&gt;스키마를 미리 알고 계획해야하고 join 문이 많은 매우 복잡한 쿼리가 만들어질 수 있다.&lt;br /&gt;즉, 미리 작성된 스키마를 기반으로 정해진 형식에 맞게 데이터를 저장해야 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지먄,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;NoSQL&lt;/b&gt;은 key-value, document, wide-column, graph 등의 방식으로 저장한다.&lt;br /&gt;스키마가 없기 때문에 유연성이 높고, 저장된 데이터를 언제든지 조정하고 새로운 필드를 부담없이 추가할 수 있다.&lt;br /&gt;또한, 애플리케이션에 필요한 형식으로 저장되고, 이렇게 하면 당연히 데이터를 가져오는 속도도 빨라진다.&lt;br /&gt;대신 각 데이터에 대한 중복이 될 수 있어서 어떤 데이터가 수정되어야한다면 관련 데이터를 모두 각 컬렉션에 들어가서 확인해서 수정해야 하는 불편함이 있다.&lt;/p&gt;
&lt;h3 id=&quot;️-확장성scalability&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✍️ 확장성(Scalability)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SQL 기반의 관계형 데이터베이스&lt;/b&gt;는 수직적으로 확장이 가능하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;높은 메모리, CPU를 사용하는 확장&lt;/li&gt;
&lt;li&gt;데이터베이스가 구축된 하드웨어의 성능을 많이 이용하기 때문에 비용이 많이 든다.&lt;/li&gt;
&lt;li&gt;여러 서버에 걸쳐서 데이터베이스의 관계를 정의할 수 있지만, 매우 복잡하고 시간이 많이 소모된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NoSQL&lt;/b&gt;로 구성된 데이터베이스는 수평적으로 확장한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보다 값싼 서버 증설, 또는 클라우드 서비스 이용하는 확장이라고도 한다.&lt;/li&gt;
&lt;li&gt;NoSQL 데이터베이스를 위한 서버를 추가적으로 구축하면, 많은 트래픽을 보다 편리하게 처리할 수 있다.&lt;/li&gt;
&lt;li&gt;저렴한 범용 하드웨어나 클라우드 기반의 인스턴스에 NoSQL 데이터베이스를 호스팅할 수 있어서, 수직적 확장보다 상대적으로 비용이 저렴하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;chapter-4-그럼-둘-중에-뭐가-더-좋을까&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;chapter 4. 그럼 둘 중에 뭐가 더 좋을까?&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대답은 '둘 다 상황에 따라 다르다'!&lt;br /&gt;관계형, 비관계형 데이터베이스를 모두 사용하여 서비스에 맞게 설계하는 것이 베스트이다.&lt;br /&gt;NoSQL 기반의 비관계형 데이터베이스가 확장성이나 속도면에서 더 뛰어나다.&lt;br /&gt;테이블끼리 따로 조인하지 않아도 데이터를 모두 가져올 수 있기 때문에 ?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러나 고차원으로 구조화된 SQL 기반의 데이터베이스가 더 좋은 성능을 보여주는 서비스도 있다.&lt;br /&gt;따라서 정답은 없다. 여러 사용 사례를 살펴보고 적절한 데이터베이스를 선택하는 것이 중요하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 각각의 사례에 맞는 적절한 데이터 베이스는 어떻게 선택하지?&lt;/p&gt;
&lt;h2 id=&quot;chapter-5-관계형-db는-언제써야-좋을까&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Chapter 5. 관계형 DB는 언제써야 좋을까?&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터베이스의 ACID 성질을 준수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ACID란 데이터베이스에서 실행되는 하나의 트랜잭션(Transaction)에 의한 상태의 변화를 수행하는 과정에서, 안전성을 보장하기 위해 필요한 성질이다.&lt;/li&gt;
&lt;li&gt;SQL을 사용하면 데이터베이스와 상호 작용하는 방식을 정확하게 규정할 수 있기 때문에, 데이터베이스에서 데이터를 처리할 때 발생할 수 있는 예외적인 상황을 줄이고, 데이터베이스의 무결성을 보호할 수 있다.&lt;/li&gt;
&lt;li&gt;전자 상거래를 비롯한 모든 금융 서비스를 위한 소프트웨어 개발 에서는 반드시 데이터베이스의 ACID 성질을 준수해야 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터가 구조적이고 일관적인 경우&lt;/b&gt;&lt;/p&gt;
&lt;h2 id=&quot;chapter-6-비관계형-db는-언제써야-좋을까&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Chapter 6. 비관계형 DB는 언제써야 좋을까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 개발에 정형화 되지 않은 많은 양의 데이터가 필요한 경우, NoSQL을 적용하는 것이 더 효율적일 수 있다.&lt;br /&gt;대부분의 NoSQL 데이터베이스는 저장할 수 있는 데이터의 유형에 제한이 없기 때문에 필요에 따라, 언제든지 데이터의 새 유형을 추가할 수 있다.&lt;/li&gt;
&lt;li&gt;정확한 데이터 요구사항을 알 수 없거나 관계를 맺고 있는 데이터가 자주 변경(수정)되는 경우&lt;/li&gt;
&lt;li&gt;읽기(read)처리를 자주하지만, 데이터를 자주 변경하지 않는 경우 (즉, 한번의 변경으로 수십 개의 문서를 수정 할 필요가 없는 경우)&lt;/li&gt;
&lt;li&gt;데이터베이스를 수평으로 확장해야 하는 경우 ( 즉, 막대한 양의 데이터를 다뤄야 하는 경우, 읽기/쓰기 처리량이 큰 경우)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Database/MySQL</category>
      <category>db</category>
      <category>NoSQL</category>
      <category>SQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/19</guid>
      <comments>https://devjooj.tistory.com/19#entry19comment</comments>
      <pubDate>Sun, 2 Jul 2023 23:14:37 +0900</pubDate>
    </item>
    <item>
      <title>[React] Fragments</title>
      <link>https://devjooj.tistory.com/18</link>
      <description>&lt;h3 id=&quot;들어가기-전&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; 들어가기 전&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;react로 개발할 때 아래와 같은 패턴을 많이 접했을 것이다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;return ( &amp;lt;&amp;gt;
...someting
&amp;lt;/&amp;gt;
)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;잘 알고 쓰고 있다면 베스트!&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만, 나는 그냥&lt;br /&gt;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;요렇게 감싸야 빨간 밑줄이 안쳐져서?&lt;br /&gt;또는, 단순히 여러개의 엘리먼트들을 그룹화하고 싶을 때&lt;br /&gt;사용하고 있었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러던 중 아래와 같은 코드를 보게 되었다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;  &amp;lt;Fragment&amp;gt;
    ...someting
  &amp;lt;/Fragment&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;응? 이게 뭘까?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;알고 보니&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;와 같은 의미였다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;제대로 모르고 그냥 쓰다보니&lt;br /&gt;마치 계피와 시나몬이 다른 건 줄 아는 느낌이었다..^^;;...&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이번 기회에 간단하더라도 짚고 넘어가자! 라는 의미로 포스팅하게 되었다.&lt;/p&gt;
&lt;h1 id=&quot;fragments란&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt; Fragments란?&lt;/h1&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Fragment는 React v16에 추가된 기능으로,&lt;/p&gt;
&lt;blockquote style=&quot;color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM에 별도의 노드를 추가하지 않고 여러 자식을 그룹화한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 쉽게 말해서&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 여러개의 자식 엘리먼트들을 쓸 때&lt;br /&gt;이것들을 반환해주기 위해서는 부모요소가 있어야하는데,&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt; render() {
 return (
   &amp;lt;React.Fragment&amp;gt;
     &amp;lt;ChildA /&amp;gt;
     &amp;lt;ChildB /&amp;gt;
     &amp;lt;ChildC /&amp;gt;
   &amp;lt;/React.Fragment&amp;gt;
 );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;fragments는 별도의 부모 노드없이 자식 요소들을 그룹화하여 반환해준다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위의 예시만으로는 이해가 안 될 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;✍️차이점을 비교해보면서 천천히 살펴보자!&lt;/p&gt;
&lt;h3 id=&quot;fragments를-안-썼을-경우&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; Fragments를 안 썼을 경우&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt; const Table = () =&amp;gt; {
 	  return (
     &amp;lt;table&amp;gt;
       &amp;lt;tr&amp;gt;
         &amp;lt;Columns /&amp;gt;
       &amp;lt;/tr&amp;gt;
     &amp;lt;/table&amp;gt;
   );
 }  &lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;table 요소 안에&lt;br /&gt;테이블의 행을 표현해주는&lt;span&gt;&amp;nbsp;&lt;/span&gt;tr태그와&lt;br /&gt;Columns&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 컴포넌트가 존재한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;Columns&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 자세히 살펴보자&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const Columns = () =&amp;gt; {
render() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위&lt;span&gt;&amp;nbsp;&lt;/span&gt;Columns&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는&lt;br /&gt;여러개의&lt;span&gt;&amp;nbsp;&lt;/span&gt;td&lt;span&gt;&amp;nbsp;&lt;/span&gt;엘리먼트들로 이루어져있기 때문에&lt;br /&gt;여러개의 자식들을 반환하기 위해&lt;br /&gt;div라는 상위 엘리먼트로 한번 감싸주고 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그럼 최종적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;Table&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 어떻게 보여질까?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같은 형태가 된다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
  &amp;lt;div&amp;gt;  의미없는 div!!! 
    &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;의미없는&lt;span&gt;&amp;nbsp;&lt;/span&gt;div로 한번 감싸져서 출력된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 의미없는 태그 작성을 해결해주는게 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Fragments&lt;/b&gt;다.&lt;/p&gt;
&lt;h3 id=&quot;fragments를-썼을-경우-뭐가-좋을까&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; Fragments를 썼을 경우 뭐가 좋을까?&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위에서 정의했던&lt;span&gt;&amp;nbsp;&lt;/span&gt;Columns&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Fragments&lt;/b&gt;를 사용하여 다시 정의해보자.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const columns = () =&amp;gt; {
render() {
  return (
    &amp;lt;React.Fragment&amp;gt;
      &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
    &amp;lt;/React.Fragment&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;div대신&lt;span&gt;&amp;nbsp;&lt;/span&gt;Fragments사용했다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면, 해당 컴포넌트를 사용하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;Table&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 출력해보자&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
  &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더이상 불필요한&lt;span&gt;&amp;nbsp;&lt;/span&gt;div태그가 들어가있지 않은 깔끔한 컴포넌트가 출력되었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Fragments의 장점&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;은!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 div와 같이 불필요한 DOM node의 생성을 막기때문에 메모리를 적게 사용한다.&lt;/li&gt;
&lt;li&gt;flexbox나 gridbox관계에 있는 엘리먼트 사이에
&lt;div&gt;를 추가하게 되면 레이아웃을 유지하기 어려울 때 사용하면, 레이아웃을 유지한 채로 엘리먼트들을 반환할 수 있다.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;fragment-꿀팁&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; Fragment 꿀팁!&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const columns = () =&amp;gt; {
render() {
  return (
    &amp;lt;React.Fragment&amp;gt;
      &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
    &amp;lt;/React.Fragment&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가 아니라&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;const columns = () =&amp;gt; {
 render() {
   return (
    &amp;lt;&amp;gt;
       &amp;lt;td&amp;gt;Hello&amp;lt;/td&amp;gt;
       &amp;lt;td&amp;gt;World&amp;lt;/td&amp;gt;
     &amp;lt;/&amp;gt;
   );
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;요렇게 간단하게 작성할 수 있다!&lt;br /&gt;대부분 현업에서 이렇게 쓰고 있다.&lt;br /&gt;실제로 회사 프로젝트에서도 Fragment를 직접적으로 명시해서 쓰는 경우는 거의 못봤다.&lt;/p&gt;
&lt;h3 id=&quot;-사용-시-주의사항&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  사용 시 주의사항&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Fragments는 따로 attribute가 필요하지 않지만,&lt;br /&gt;유일하게&lt;span&gt;&amp;nbsp;&lt;/span&gt;key&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성 요구한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;map을 이용하여 배열 어트리뷰트들을 나열하는 경우가 많은데, 이때&lt;span&gt;&amp;nbsp;&lt;/span&gt;Fragments를 사용한다면 아래와 같이 key값을 명시해줘야한다.&lt;br /&gt;안그러면 key props을 써달라는 경고문이 브라우저 콘솔에 도배해놓을 것이다!&lt;/p&gt;
&lt;pre class=&quot;xquery&quot; style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;code&gt;function Glossary(props) {
return (
  &amp;lt;dl&amp;gt;
    {props.items.map(item =&amp;gt; (
      &amp;lt;React.Fragment key={item.id}&amp;gt;
        &amp;lt;dt&amp;gt;{item.term}&amp;lt;/dt&amp;gt;
        &amp;lt;dd&amp;gt;{item.description}&amp;lt;/dd&amp;gt;
      &amp;lt;/React.Fragment&amp;gt;
    ))}
  &amp;lt;/dl&amp;gt;
);
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;참고자료&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/fragments.html&quot;&gt;https://ko.reactjs.org/docs/fragments.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부/React</category>
      <category>React</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/18</guid>
      <comments>https://devjooj.tistory.com/18#entry18comment</comments>
      <pubDate>Sat, 1 Jul 2023 23:19:13 +0900</pubDate>
    </item>
    <item>
      <title>[React] React 동작 방법 - Virtual DOM</title>
      <link>https://devjooj.tistory.com/17</link>
      <description>&lt;h3 id=&quot;-들어가기-전&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  들어가기 전&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트에서 React를 실제로 사용하고 있어서 React의 장점에 대해서는 어느 정도 파악하고 있다고 생각했다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 갑자기 의문이 들었다..!&lt;br /&gt;화면 깜빡임 없이 변경사항만 부드럽게 화면에 표시해주는게 사용자 경험이 향상되는데 도움을 주는 건 알겠어,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데 Virtual DOM은 왜 쓰는거지?&lt;br /&gt;실제 DOM 조작이 왜 비효율적인거지?&lt;br /&gt;어떤 부분 때문에 비효율적인거지?&lt;br /&gt;등등..&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;브라우저 작동원리에 대한 이해도가 부족함에서 오는 의문들이었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이번 기회에 React의 작동원리도 제대로 짚고 넘어갈겸&lt;br /&gt;브라우저 작동 원리 그리고 왜 DOM을 직접 조작하는게 비효율적인지에 대해서 공부해보려고 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ps. 다른 분들이 잘 정리해놓은 글을 스스로 공부하기 위해 요약한 정도의 글이라&lt;br /&gt;부족할 수 있다는 점 참고해주세요!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;브라우저-랜더링을-위한-빌드업&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; 브라우저 랜더링을 위한 빌드업&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;User Interface: 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등. 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분&lt;/li&gt;
&lt;li&gt;Browser Engine: User Interface와 Rendering Engine 사이의 동작을 제어&lt;/li&gt;
&lt;li&gt;Rendering Engine: 요청한 콘텐츠를 표시, HTML을 요청하면 HTML과 CSS를 파싱 하여 화면에 표시함&lt;/li&gt;
&lt;li&gt;Networking: HTTP 요청과 같은 네트워크 호출에 사용됨&lt;/li&gt;
&lt;li&gt;Javascript Interpreter(또는 Engine): 자바스크립트 코드를 해석하고 실행함. 크롬에서는&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://beomy.github.io/tech/javascript/javascript-runtime/#%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%97%94%EC%A7%84-v8&quot;&gt;V8 엔진&lt;/a&gt;을 사용함&lt;/li&gt;
&lt;li&gt;Display Backend: 기본적인 위젯(콤보 박스 등..)을 그림&lt;/li&gt;
&lt;li&gt;Data Persistence: Local Storage, 쿠키 등 클라이언트 사이드에서 데이터를 저장하는 영역&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;렌더링-엔진&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; 렌더링 엔진&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceOUam/btslT0q1Cvw/7kgTiOmodp0t8RHBPlC3o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceOUam/btslT0q1Cvw/7kgTiOmodp0t8RHBPlC3o0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceOUam/btslT0q1Cvw/7kgTiOmodp0t8RHBPlC3o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceOUam%2FbtslT0q1Cvw%2F7kgTiOmodp0t8RHBPlC3o0%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;624&quot; height=&quot;289&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;  chrome 브라우저 렌더링 엔진 workFlow&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;요약&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;렌더링 엔진의 역할은 요청받은 내용을 브라우저 화면에 나타내는 일&lt;/li&gt;
&lt;li&gt;HTML, CSS, JavaScript 등의 파일을 브라우저가 화면에 표시할 수 있도록 변환하여 픽셀 단위로 나타냄&lt;/li&gt;
&lt;li&gt;렌더링 엔진은 브라우저마다 다르다. 그래서 같은 소스임에도 불구하고 브라우저마다 다르게 그려지는 크로스 브라우징 이슈가 발생하는 것이다.
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;알면 좋은 지식
크로미움
  - 오픈소스 웹 브라우저
 	- v8 자바스크립트 엔진과 Blink라는 렌더링 엔진을 사용하는 브라우저
      - 크롬이 크로미움 기반으로 만들어진 브라우저?
        즉, 오픈 소스인 크로미움 브라우저 코드 위에 살을 덧붙여 개발되었다는 의미
        - Edge도 EdgeHTML 렌더링 엔진을 포기하고 크로미움 기반의 브라우저로 변경됨	&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;ㄴ 렌더링 엔진말고도 자바스크립트 엔진이 달라 발생할 수도 있긴 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;동작 과정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML 문서 파싱해서 DOM 트리를 만들고&lt;/li&gt;
&lt;li&gt;CSS 문서 파싱해서 CSSOM 트리 만들고&lt;/li&gt;
&lt;li&gt;CSSOM, DOM을 이용하여 렌더 트리를 만듬&lt;/li&gt;
&lt;li&gt;렌더 트리 생성 끝나면 &amp;rarr; Layout(Reflow)가 만들어짐
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 노드가 화면의 정확한 위치에 표시하기 위해 위치와 크기를 계산하는 과정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;paint 과정 실행됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계산된 위치와 크기 등의 스타일들이 실제 픽셀로 표시하는 과정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;렌더링-최적화-방법&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; 렌더링 최적화 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;javascript&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트는 파서 차단 리소스이다.&lt;/li&gt;
&lt;li&gt;브라우저는
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문서를 파싱하다가 자바스크립트를 만나면 진행하던&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;파싱을 중지&lt;/b&gt;하고&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자바스크립트 엔진에게 권한을 넘겨 자바스크립트를 파싱하고 실행&lt;/b&gt;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최적화 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트가 실행되는 동안 문서의 파싱은 중단되기 때문에 문서 파싱이 완료된 이후에 자바스크립트가 실행된다&lt;/li&gt;
&lt;li&gt;때문에 태그가 아닌 태그가 닫히기 바로 전에 사용되도록 하는 것이 좋다&lt;/li&gt;
&lt;li&gt;스크립트 비동기 처리가능 속성 : HTML5 스크립트 비동기로 처리하는 속성 추가됨&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;async는 스크립트 리소스 다운로드가 완료된 시점에 스크립트가 실행되지만,&amp;nbsp;defer는 HTML 파싱 하는 동안에 스크립트 다운로드하고 HTML 파싱이 완료되면 스크립트가 실행됩니다.&lt;/li&gt;
&lt;li&gt;async(default 값인&amp;nbsp;async=true일 경우)는 다운로드가 완료된 시점에 스크립트가 실행되어 스크립트 실행 순서를 보장할 수 없지만,&amp;nbsp;defer의 경우 정의된 순서대로 스크립트가 실행됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CSS&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;렌더링 차단 소스이다.&lt;/li&gt;
&lt;li&gt;안에 css를 정의해야하는 이유 - 렌더링을 할 때 반드시 필요한 리소스이기 때문에 브라우저가 빠르게 다운로드 받을 수 있도록 해줌&lt;/li&gt;
&lt;li&gt;css는 DOM트리를 변경하지 않기 때문에 문서 파싱을 기다리거나 중단할 이유가 없다.&lt;/li&gt;
&lt;li&gt;그래서 자바스크립트에서 스타일 정보를 요청하는 경우 CSS가 파싱되지 않은 경우라면 스크립트 에러 발생 가능있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 id=&quot;-virtual-dom&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; &amp;nbsp;Virtual DOM&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Virtual DOM이 필요한 이유&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM에 변화가 생기면 랜더트리를 생성하고
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때 모든 요소들의 스탈일이 다시 계산된다. 위에서 말했던 레이아웃을 만들고 페인팅을 하는 과정이 다시 반복되는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복잡한 SPA는 DOM 조작이 많이 발생된다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DOM 조작이 많이 발생되면 문제는 무엇일까?&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 조작이 레이아웃 변화, 트리 변화와 렌더링을 일으킨다.&lt;/li&gt;
&lt;li&gt;&amp;rarr; EX) 30개의 노드를 하나하나 수정하면 &amp;rarr; 30번의 (잠재적인) 레이아웃 재계산과 30번의 (잠재적인) 리렌더링을 초래한다는 말이다.&lt;/li&gt;
&lt;li&gt;반면에, Virtual DOM을 이용하면,&lt;/li&gt;
&lt;li&gt;&amp;rarr; 인터렉션 발생 시 virtual DOM에서 먼저 적용시키고 최종 변화를 딱 한번만 실제 DOM에 적용시키는 것이다.&lt;/li&gt;
&lt;li&gt;Virtual DOM이 없이도 가능하긴 하다. 하지만 불편하다.&lt;/li&gt;
&lt;li&gt;&amp;rarr; DOM fragment를 적용 후 실제 DOM에 주면 되지만 &amp;rarr; DOM fragment를 관리하는 과정을 수동으로 하나하나 다 작업해야하는데 virtual DOM은 어떤게 바뀌었는지, 어떤게 바뀌지 않았는지 자동으로 해준다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-virtual-dom-의-역할&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  Virtual DOM 의 역할&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 인터렉션이 발생되면,&lt;br /&gt;1. 실제 DOM에 적용되기 전에 가상의 DOM에 먼저 적용시킨다.&lt;br /&gt;2. 그 후 최종적인 결과를 실제 DOM에 전달한다.&lt;br /&gt;&amp;rarr; 이렇게 되면 실제 DOM은 최종 결과만 전달 받기 때문에 브라우저 내에서 발생하는 연산의 양이 줄어들고 성능이 개선된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DOM 관리를 Virtual DOM이 하도록 함으로써&lt;/b&gt;&lt;br /&gt;컴포넌트가 DOM 조작 요청을 할 때 다른 컴포넌트들과 상호작용을 하지 않아도 된다. 각 변화들의 동기화 작업을 거치치 않고 모든 작업을 하나로 묶어준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-react-장점&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;  React 장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPA로 사용자와의 인터렉션(상호작용)이 일어났을 때 화면 깜빡임 없이 변경사항만 부드럽게 화면에 표시해주는 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리이다.&lt;/li&gt;
&lt;li&gt;데이터가 변경됨에 따라 적절한 컴포넌트만 효율적으로 갱신하고 랜더링한다.&lt;img src=&quot;https://blog.kakaocdn.net/dn/AphVN/btslS3hmbTY/V0GcGklfH8EpFOcBbse4fK/img.png&quot; /&gt;&lt;/li&gt;
&lt;li&gt;위에 말했던 Virtual DOM 을 이용해서 갱신하다.&lt;br /&gt;인터렉션이 있을 때마다 DOM을 조작하면 브라우저의 연산 양이 늘어나기 때문에,&lt;br /&gt;React는 실제 DOM의 복제본으로 virtual DOM을 생성하여 인터렉션이 일어나면 Virtual DOM에서 먼저 데이터 갱신 여부를 체크하고, 변경된 사항을 반영한 후, 한번에 실제 DOM에 전달한다.&lt;/li&gt;
&lt;li id=&quot;어떻게&quot;&gt;어떻게?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;  참고&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://saiki.hashnode.dev/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom&quot;&gt;https://saiki.hashnode.dev/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.reactjs.org/&quot;&gt;https://ko.reactjs.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1688049137235&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;React &amp;ndash; 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리&quot; data-og-description=&quot;A JavaScript library for building user interfaces&quot; data-og-host=&quot;ko.legacy.reactjs.org&quot; data-og-source-url=&quot;https://ko.reactjs.org/&quot; data-og-url=&quot;https://ko.legacy.reactjs.org/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dLdqUL/hyS9Ra9NZ9/wFNXI4fucaj5xlFJQLHco1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://ko.reactjs.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.reactjs.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dLdqUL/hyS9Ra9NZ9/wFNXI4fucaj5xlFJQLHco1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;React &amp;ndash; 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A JavaScript library for building user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.legacy.reactjs.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;-&amp;gt; 아래 블로그에서 현재 블로그로 이전 중입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@devjooj/React-React-%EB%8F%99%EC%9E%91-%EB%B0%A9%EB%B2%95-Virtual-DOM&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@devjooj/React-React-%EB%8F%99%EC%9E%91-%EB%B0%A9%EB%B2%95-Virtual-DOM&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688049160370&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;[React] React 동작 방법 - Virtual DOM&quot; data-og-description=&quot;React 동작 방법, Virtual Dom의 역할!&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@devjooj/React-React-%EB%8F%99%EC%9E%91-%EB%B0%A9%EB%B2%95-Virtual-DOM&quot; data-og-url=&quot;https://velog.io/@devjooj/React-React-동작-방법-Virtual-DOM&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eFZsn/hyS9M1ZP0t/JsZHKS1q5kmkl3hW9zUfNk/img.png?width=367&amp;amp;height=137&amp;amp;face=0_0_367_137,https://scrap.kakaocdn.net/dn/Mkptd/hyS9PLasiu/j43SWOmc8JKdiqDKflsGUk/img.png?width=367&amp;amp;height=137&amp;amp;face=0_0_367_137&quot;&gt;&lt;a href=&quot;https://velog.io/@devjooj/React-React-%EB%8F%99%EC%9E%91-%EB%B0%A9%EB%B2%95-Virtual-DOM&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@devjooj/React-React-%EB%8F%99%EC%9E%91-%EB%B0%A9%EB%B2%95-Virtual-DOM&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eFZsn/hyS9M1ZP0t/JsZHKS1q5kmkl3hW9zUfNk/img.png?width=367&amp;amp;height=137&amp;amp;face=0_0_367_137,https://scrap.kakaocdn.net/dn/Mkptd/hyS9PLasiu/j43SWOmc8JKdiqDKflsGUk/img.png?width=367&amp;amp;height=137&amp;amp;face=0_0_367_137');&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;[React] React 동작 방법 - Virtual DOM&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React 동작 방법, Virtual Dom의 역할!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/React</category>
      <category>dom구조</category>
      <category>React</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/17</guid>
      <comments>https://devjooj.tistory.com/17#entry17comment</comments>
      <pubDate>Thu, 29 Jun 2023 23:33:20 +0900</pubDate>
    </item>
    <item>
      <title>[React] react-cookie vs universal-cookie vs react-cookies 비교</title>
      <link>https://devjooj.tistory.com/16</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이슈:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;F/E에서 쿠키를 설정하는 과정에서 어떤 곳에서는 react-cookie 라이브러리를 사용하고, 어디서는 react-cookies 를 사용하고 어디서는 universal-cookie를 사용하고 있었다..&lt;/li&gt;
&lt;li&gt;이 라이브러리는 어떤 차이점이 있길래 각각 쓰이고 있는건가 정리하고 싶어서 남긴다.&lt;span style=&quot;color: #000000; font-size: 1.44em; letter-spacing: -1px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-size: 1.44em; letter-spacing: -1px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;react-cookie&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Universal cookies for&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://facebook.github.io/react&quot;&gt;React&lt;/a&gt; (말그대로 react에서 사용하기 위한 쿠키 라이브러리)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1687963458767&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;React&quot; data-og-description=&quot;The library for web and native user interfaces&quot; data-og-host=&quot;react.dev&quot; data-og-source-url=&quot;https://facebook.github.io/react&quot; data-og-url=&quot;https://react.dev/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/n27Uv/hyS8s35hwh/uL0tJstjlK0HRPZhIOvVxK/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/cqknwi/hyS8vNhPIt/L0gbrC0qqtKYkCJm7s5eM0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567&quot;&gt;&lt;a href=&quot;https://facebook.github.io/react&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://facebook.github.io/react&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/n27Uv/hyS8s35hwh/uL0tJstjlK0HRPZhIOvVxK/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/cqknwi/hyS8vNhPIt/L0gbrC0qqtKYkCJm7s5eM0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567');&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;React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The library for web and native user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;react.dev&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-filename=&quot;Screen Shot 2023-06-28 at 11.42.28 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1oyVm/btslKjrJ4Wr/1CYj7qoKWiK6xnQalZph00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1oyVm/btslKjrJ4Wr/1CYj7qoKWiK6xnQalZph00/img.png&quot; data-alt=&quot;[출처: npm react-cookie]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1oyVm/btslKjrJ4Wr/1CYj7qoKWiK6xnQalZph00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1oyVm%2FbtslKjrJ4Wr%2F1CYj7qoKWiK6xnQalZph00%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;2378&quot; height=&quot;1440&quot; data-filename=&quot;Screen Shot 2023-06-28 at 11.42.28 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[출처: npm react-cookie]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;universal-cookie&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Universal cookies for &lt;b&gt;JavaScript&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;react-cookie보다 더 업그레이드된 모듈
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[react-cookie](&amp;lt;&lt;a href=&quot;https://www.npmjs.com/package/react-cookie&quot;&gt;https://www.npmjs.com/package/react-cookie&lt;/a&gt;&amp;gt;)&amp;nbsp;- Universal cookies for React&lt;/li&gt;
&lt;li&gt;[universal-cookie-express](&amp;lt;&lt;a href=&quot;https://www.npmjs.com/package/universal-cookie-express&quot;&gt;https://www.npmjs.com/package/universal-cookie-express&lt;/a&gt;&amp;gt;)&amp;nbsp;- Hook cookies get/set on Express for server-rendering&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아래와 같이 사용자가 꽤 많은 걸로 봐서는 어느정도 보장이 되는 라이브러리로 보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2023-06-28 at 11.43.30 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P2BzS/btslJedi3vW/wVvwSqm2nrlOWDrYBcuojK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P2BzS/btslJedi3vW/wVvwSqm2nrlOWDrYBcuojK/img.png&quot; data-alt=&quot;[출처] universal-cookie&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P2BzS/btslJedi3vW/wVvwSqm2nrlOWDrYBcuojK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP2BzS%2FbtslJedi3vW%2FwVvwSqm2nrlOWDrYBcuojK%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;2378&quot; height=&quot;1440&quot; data-filename=&quot;Screen Shot 2023-06-28 at 11.43.30 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[출처] universal-cookie&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;react-cookies&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제일 다운로드수가 적은 라이브러리&lt;/li&gt;
&lt;li&gt;해당 라이브러리는 웬만하면 지양한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2023-06-28 at 11.45.31 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ujsCq/btslNlVY7Z3/PX5ws5Yv34Uk4Xokf1KHYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ujsCq/btslNlVY7Z3/PX5ws5Yv34Uk4Xokf1KHYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ujsCq/btslNlVY7Z3/PX5ws5Yv34Uk4Xokf1KHYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FujsCq%2FbtslNlVY7Z3%2FPX5ws5Yv34Uk4Xokf1KHYK%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;2378&quot; height=&quot;1440&quot; data-filename=&quot;Screen Shot 2023-06-28 at 11.45.31 PM.png&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발 공부/React</category>
      <category>cookie</category>
      <category>React</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/16</guid>
      <comments>https://devjooj.tistory.com/16#entry16comment</comments>
      <pubDate>Wed, 28 Jun 2023 23:46:38 +0900</pubDate>
    </item>
    <item>
      <title>[MSSQL] 테이블 컬럼 조회하기</title>
      <link>https://devjooj.tistory.com/15</link>
      <description>&lt;pre id=&quot;code_1687788376932&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '테이블명';&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Database/MSSQL</category>
      <category>MSSQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/15</guid>
      <comments>https://devjooj.tistory.com/15#entry15comment</comments>
      <pubDate>Mon, 26 Jun 2023 23:07:23 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] UNION (distinct) vs UNION ALL 차이</title>
      <link>https://devjooj.tistory.com/13</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;공통점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 문법 모두 쿼리 결과를 합쳐준다&lt;/li&gt;
&lt;li&gt;둘다 그리 좋은 SQL은 아니고, 테이블을 통합하는게 좋음&lt;/li&gt;
&lt;li&gt;UNION ALL 보다는 UNION 중복 제거하는 쿼리가 당연히 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UNION (distinct)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복을 제거하여 합쳐준다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1687701367720&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 1 AS COL1, 100 AS MONEY UNION 
SELECT 1 AS COL1, 100 AS MONEY UNION 
SELECT 2 AS COL1, 200 AS MONEY UNION 
SELECT 2 AS COL1, 200 AS MONEY UNION 
SELECT 3 AS COL1, 300 AS MONEY UNION 
SELECT 3 AS COL1, 300 AS MONEY UNION 
SELECT 4 AS COL1, 400 AS MONEY&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2023-06-25 at 10.57.39 PM.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWzIQV/btsla0l5Xam/YcOTNND2K3jsSFwj9kDCw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWzIQV/btsla0l5Xam/YcOTNND2K3jsSFwj9kDCw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWzIQV/btsla0l5Xam/YcOTNND2K3jsSFwj9kDCw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWzIQV%2Fbtsla0l5Xam%2FYcOTNND2K3jsSFwj9kDCw1%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;440&quot; height=&quot;236&quot; data-filename=&quot;Screen Shot 2023-06-25 at 10.57.39 PM.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UNION ALL
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복을 제거하지 않고 모두 합친다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1687701413969&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 1 AS COL1, 100 AS MONEY UNION 
SELECT 1 AS COL1, 100 AS MONEY UNION 
SELECT 2 AS COL1, 200 AS MONEY UNION 
SELECT 2 AS COL1, 200 AS MONEY UNION 
SELECT 3 AS COL1, 300 AS MONEY UNION 
SELECT 3 AS COL1, 300 AS MONEY UNION 
SELECT 4 AS COL1, 400 AS MONEY&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2023-06-25 at 10.58.09 PM.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coCQU2/btslcCykUyU/ERzV2ok6NkibbfZoJoY2z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coCQU2/btslcCykUyU/ERzV2ok6NkibbfZoJoY2z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coCQU2/btslcCykUyU/ERzV2ok6NkibbfZoJoY2z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoCQU2%2FbtslcCykUyU%2FERzV2ok6NkibbfZoJoY2z0%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;440&quot; height=&quot;380&quot; data-filename=&quot;Screen Shot 2023-06-25 at 10.58.09 PM.png&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/13</guid>
      <comments>https://devjooj.tistory.com/13#entry13comment</comments>
      <pubDate>Sun, 25 Jun 2023 22:59:23 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] 트랜잭션 죽이기</title>
      <link>https://devjooj.tistory.com/11</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;이슈 :&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MYSQL 프로시저 DROP FAILED&lt;/li&gt;
&lt;li&gt;metadata lock 걸린 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행중인 트랜잭션 조회 쿼리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SELECT * FROM information_schema.innodb_trx;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;trx_state : running 인 상태 kill&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kill [trx_mysql_thread_id];&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방금 실행된 쿼리의 에러 사항 조회하는 쿼리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SHOW COUNT(*) WARNINGS;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SHOW WARNINGS;&lt;/p&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <category>트랜잭션</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/11</guid>
      <comments>https://devjooj.tistory.com/11#entry11comment</comments>
      <pubDate>Sat, 24 Jun 2023 23:46:03 +0900</pubDate>
    </item>
    <item>
      <title>[MYSQL] SQL 실행 순서</title>
      <link>https://devjooj.tistory.com/10</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;SQL 실행 순서&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&amp;nbsp;컬럼명&amp;nbsp;--------------------- (5)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FROM&amp;nbsp;테이블명&amp;nbsp;------------------- (1)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WHERE&amp;nbsp;테이블 조건&amp;nbsp;---------------&amp;nbsp;(2)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GROUP BY&amp;nbsp;컬럼명&amp;nbsp;-------------------- (3)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HAVING&amp;nbsp;그룹 조건&amp;nbsp;----------------- (4)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORDER BY&amp;nbsp;컬럼명&amp;nbsp;-------------------- (6)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;&lt;b&gt;FROM&lt;/b&gt;&amp;nbsp;: SQL은 구문이 들어오면&amp;nbsp;&lt;b&gt;테이블을 가장 먼저 확인한다.&lt;/b&gt; 테이블이 없는데 뒤에 조건부터 확인할 필요는 없으니까!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;&lt;b&gt;WHERE&lt;/b&gt; : 테이블 존재 여부 확인 후,&amp;nbsp; 테이블에 대한 조건에 맞게 데이터를 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&amp;nbsp;&lt;b&gt;GROUP BY&lt;/b&gt;&amp;nbsp;: 조건에 맞는 데이터가 추출되었으니,&amp;nbsp;&lt;b&gt;공통적인 데이터들끼리 묶어 그룹&lt;/b&gt;을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&amp;nbsp;&lt;b&gt;HAVING&lt;/b&gt; : 공통적인 데이터들이 묶여진 그룹 중에 &lt;b&gt;주어진 조건에 해당하는 데이터를 조회&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&amp;nbsp;&lt;b&gt;SELECT&lt;/b&gt; : 최종적으로 추출된 &lt;b&gt;데이터를 조회&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&amp;nbsp;&lt;b&gt;ORDER BY&lt;/b&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;** 중요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SELECT 다음으로 오는 구문은 ORDER BY 뿐이므로 SELECT 에서 만들어진 Alias 는 ORDER BY 구문에서만 사용 가능하다.&lt;/p&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>Database/MySQL</category>
      <category>MySQL</category>
      <category>SQL</category>
      <category>실행순서</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/10</guid>
      <comments>https://devjooj.tistory.com/10#entry10comment</comments>
      <pubDate>Fri, 23 Jun 2023 22:36:28 +0900</pubDate>
    </item>
    <item>
      <title>코드 리팩토링 (1) - 확장성을 고려하여 개발하기</title>
      <link>https://devjooj.tistory.com/9</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;확장성을 고려한 코드를 짜기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발할 때 항상 확장성을 고려해야 유지보수 시 어려움을 겪지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런 의미에서 업무를 진행하면서 구성했던 부분들을 간단하게 정리하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 주니어 개발자 분들에게 도움이 되었으면 좋겠다.&lt;/p&gt;
&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;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;처음엔 단순한 조건이었지만, 분명 운영 쪽에서 추가 요청이 있을 것이야...........&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;요청사항:&amp;nbsp; 계절이 SUMMER(여름) 일 경우에만 '따뜻하다'라는 문자열을 RETURN해줘&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;i&gt;변경 전&lt;/i&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;const getWeather = () =&amp;gt; {
	String season = '';		
	if (season === 'SUMMER' ) {
		 return '따뜻하다'
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 달 후...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;- 추가 요청사항1 :&amp;nbsp; 계절이 Spring(봄) 일 경우에도 '따뜻하다'라는 문자열을 RETURN해줘&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687398691635&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const getWeather = () =&amp;gt; {
	String season = '';		
	if (season === 'Summer' || season === 'Spring' ) {
		 return '따뜻하다'
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가 요청사항이 100번째가 되면 (그럴 가능성은 현저히 적지만,,)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드로 진행하면 요청이 100개, 10개가 들어오면 계속 IF 조건을 추가해야하고, 혹시나 다른 개발자가 유지보수를 진행해야할 때에도 어떤 조건이 있는지 파악이 힘들 수 도 있다.&lt;/p&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;i&gt;변경 후&lt;/i&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;변경 후 
const WEATHER_LIST = ['SUMMER'] 

const getWeather  = () =&amp;gt; {
	String season = '';
	if(WEATHER_LIST.includes(season)) {
			return &quot;따뜻하다&quot;
	}
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 좋은점은,&lt;/p&gt;
&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;- 추가 요청사항1 :&amp;nbsp; 계절이 Spring(봄) 일 경우에도 '따뜻하다'라는 문자열을 RETURN해줘&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const getWeather = () =&amp;gt; {
	String season = '';		
	if (season === 'Summer' || season === 'Spring' ) {
		 return '따뜻하다'
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 후 코드로 진행하면, 아래와 같이 배열에 데이터 추가해주면 된다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;변경 후 
const WEATHER_LIST = ['Spring', 'Summer'] 

const getWeather  = () =&amp;gt; {
	String season = '';
	if(WEATHER_LIST.includes(season)) {
			return &quot;따뜻하다&quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청사항이 10개, 100개가 들어와도 배열에 값만 추가해주면 되고, 다른 개발자가 유지보수할 때에도 조건을 추가하기 비교적 수월할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 계속 하면서 어떻게 하면 더 효율적으로, 가독성있게 할 수 있을까? 라는 지속적인 고민이 필요한 것 같다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 개발자 분들이 이해하기 쉬운 코드로 개발하는 것을 항상 소소한 목표로 개발하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로도 이런 소소한 리팩토링들을 정리하며 내 코드의 성장일기? 로 남기고 싶다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/리팩토링</category>
      <category>리팩토링</category>
      <category>자바스크립트</category>
      <category>코드 리팩토링</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/9</guid>
      <comments>https://devjooj.tistory.com/9#entry9comment</comments>
      <pubDate>Thu, 22 Jun 2023 11:02:17 +0900</pubDate>
    </item>
    <item>
      <title>[MYSQL] SUM(컬럼명) OVER(정렬)</title>
      <link>https://devjooj.tistory.com/8</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SUM(합할 컬럼명) OVER()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;합하려고 하는 컬럼의 모든 값을 합함&lt;/li&gt;
&lt;li&gt;NULL값인 데이터 제외하고 누적 계산&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SUM(합할 컬럼명) OVER(누적 계산할 순서)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OVER는 SUM의 기준이 되는 값&lt;/li&gt;
&lt;li&gt;NULL인 데이터 제외 누적 계산&lt;/li&gt;
&lt;li&gt;중복인 데이터는 제거하고 누적계산한다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT 
		RE.COL1
	,	SUM(RE.WON) OVER (ORDER BY RE.COL1)
FROM (
		SELECT 1 AS COL1, 100 AS WON UNION ALL
    SELECT 1 AS COL1, 100 AS WON UNION ALL
    SELECT 2 AS COL1, 200 AS WON UNION ALL
    SELECT 2 AS COL1, 200 AS WON UNION ALL
    SELECT 3 AS COL1, 300 AS WON UNION ALL
    SELECT 3 AS COL1, NULL AS WON UNION ALL
    SELECT 4 AS COL1, 400 AS WON 
) RE
GROUP BY RE.COL1
;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;SUM(합할 컬럼명) OVER (PARTITION BY 그룹핑할 컬럼명 ORDER BY 누적 정렬할 기준)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PARTITION BY[MYSQL] SUM(컬럼명) OVER(정렬)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <category>sum over</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/8</guid>
      <comments>https://devjooj.tistory.com/8#entry8comment</comments>
      <pubDate>Wed, 21 Jun 2023 21:26:16 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] 날짜 차이 가져오기 (DATEDIFF, TIMESTAMPDIFF 함수)</title>
      <link>https://devjooj.tistory.com/7</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DATEDIFF
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순히 일 차이를 가져올 때 사용&lt;/li&gt;
&lt;li&gt;날짜 1 - 날짜 2&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT DATEDIFF(날짜1, 날짜2);
SELECT DATEDIFF(NOW(), '2023-02-23 14:25:04')
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;TIMESTAMPDIFF
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연, 분기, 월, 주, 일, 시, 분, 초 지정하여 가져올 때 사용하는 함수&lt;/li&gt;
&lt;li&gt;날짜 1 - 날짜 2&lt;/li&gt;
&lt;li&gt;단위
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SECOND : 초&lt;/li&gt;
&lt;li&gt;MINUTE : 분&lt;/li&gt;
&lt;li&gt;HOUR : 시&lt;/li&gt;
&lt;li&gt;DAY : 일&lt;/li&gt;
&lt;li&gt;WEEK : 주&lt;/li&gt;
&lt;li&gt;MONTH : 월&lt;/li&gt;
&lt;li&gt;QUARTER : 분기&lt;/li&gt;
&lt;li&gt;YEAR : 연&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT TIMESTAMPDIFF(단위, 날짜1, 날짜2);

SELECT TIMESTAMPDIFF(MONTH, '2023-02-23 14:25:04', NOW())
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/7</guid>
      <comments>https://devjooj.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 20 Jun 2023 23:28:50 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] 모든 프로시저에서 한번에 원하는 문자열 검색하는 방법</title>
      <link>https://devjooj.tistory.com/6</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 하면 검색한 문자열을 포함한 모든 프로시저가 검색된다.&lt;/p&gt;
&lt;pre id=&quot;code_1687184077753&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT ROUTINE_SCHEMA, ROUTINE_NAME FROM information_schema.routines 
WHERE LOWER(ROUTINE_DEFINITION) LIKE '% 원하는 문자열 %';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Database/MySQL</category>
      <category>MySQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/6</guid>
      <comments>https://devjooj.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 19 Jun 2023 23:15:39 +0900</pubDate>
    </item>
    <item>
      <title>[2023년 상반기 회고] 3년차 개발자...내가 과연 치열하게 살았을까...(?)..</title>
      <link>https://devjooj.tistory.com/4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어느새 2023년 상반기가 지나고 하반기가 오는 시점이라 회고를 해보고자 한다.&lt;/p&gt;
&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;어쩌다보니 팀 내 주니어 개발자 중에 AWS 인프라를 관리할 수 있는 사람이 되었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 혼자 담당하는 프로젝트가 2개가 되고, 동시에 새로운 프로젝트에 투입하게 되면서 3개 프로젝트를 진행하며 정말 정신 없었던 기간이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 했는지 모를 정도로 열심히 했다고 생각했는데 뒤돌아보면 회사에만 집중했던 시기였던 것 같아서 살짝 아쉬운 감정이 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러개를 맡으면서 내 깊이도 그만큼 얕은 것 같고, 기술 스택에 대한 학습도 깊이 있게 하지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과연 개발을 하면서 내가 사용하고 있는 기술에 대해 고민을 했을까? 이걸 왜 사용해야하는지 의문을 가졌던 적이 있나..&lt;/p&gt;
&lt;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;1번&amp;nbsp; &amp;amp; 2번 프로젝트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;- react + next.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;- node.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;- MySQL&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번 프로젝트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;- react + next.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;- Java + Spring boot&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -&amp;nbsp; MSSQL&lt;/p&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;nbsp; AWS 인프라 구축 업무를 담당하게 해주셔서 많은 걸 배우고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ec2, subnet, 로드밸런서 관련된 부분 생성해보고, 보안그룹 설정하면서 네트워크 구조도 배우게 되었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SES 계정이 중지되면서 AWS 직접 컨택하며 당장 중지 풀어줘..하면서 장애 이슈도 해결해보고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LG DX 연동 작업을 진행하면서 KINX 측과 협업하며 전용선 &amp;amp; VIF 생성도 해봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 ec2에 접속해서 깃랩 소스 배포하여 개발 서버 구축하는 작업도 해보고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉘 스크립트 작성하여 다른 개발자 분들이 쉽게 접속 할 수 있도록 설정도 해드리고,,,,정말 온통 처음 해보는 업무들이었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때그때 진행하는 업무들을 공부하느라 너무 정신없었던 것 같기도..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하반기에는 기존에 있는 환경들에 의문을 갖고 개선할 수 있는 부분들은 개선하려고 한다.&lt;/p&gt;
&lt;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;대표적으로 당장 7월부터 1번 프로젝트 고도화 작업이 예정되어있는데, 이때 B/E 프레임워크를 새롭게 도입하고 싶어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nodejs의 유연함이..이제는 단점으로 느껴지기 시작해서&amp;nbsp; NestJS와 같은 B/E프레임워크의 아키텍처가 궁금해졌다랄까..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀장님께 B/E 프레임워크의 현재 상황에 대해 설명 드리고,&amp;nbsp; NestJS 도입하고자 연구개발을 하고자 한다고 말씀드렸더니,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히도 흔쾌히 허락해주셔서&amp;nbsp; NestJS뿐만 아니라 다른 프레임워크도 비교해보고자 한다.&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;size14&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;size14&quot;&gt;B/E API 서버의 필수 구성 요소&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 현재 Node js는 B/E API서버로서의 역할을 하고 있는지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 디자인 패턴, 방법론으로 바라보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;현재 B/E API 아키텍처 구조 &amp;amp; 문제점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 현재 구조 현황 (Node js + pm2 사용하여 B/E 서버로 구성됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 해당 구조의 장점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 해당 구조의 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Node js 장점 &amp;amp; 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; 왜 Node.js를 B/E 로 쓸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;ㄴ 단일쓰레드라 무거운 작업이 필요할 때 버거울 수 있음 ex) 동영상 스트리밍, 용량이 큰 파일 업로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;ㄴ Nodes.js + nest.js를 사용하면 무거운 작업을 어떻게 커버할지? (로드밸런싱으로는 힘들 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;NestJS 장점 &amp;amp; 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; Nest js &amp;rarr; API 서버의 요구사항을 충족시키기 위해 탄생&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; Nest.js를 만든 사람이 누구고, 왜 이걸 만들었는지 동기 파악&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; Node의 기준이 되는 프레임워크 / ex) java + spring&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;JAVA + Spring 장점 &amp;amp; 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; NestJS 보다 나은점이 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;-&amp;gt; NesJS가 더 좋은 점은? (MSA구조도 염두하여 생각해보자)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;타 기업에서 Nest js를 사용하는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;우리가 그럼에도 불구하고 Nest.js를 사용해야하는 이유&lt;/p&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;여러가지 사항들을 고려하여야하는데, 당당하게 말씀은 드렸지만 사실 잘 할 수 있을지 모르겠다...(?)..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또, SQL 기본기 보충하고, AWS 업무도 맡겨주셨으니까 제대로 해보고자 자격증도 따보고 클라우드 엔지니어로 갈 수 있도록 네트워크 지식도 본격적으로 쌓아볼 예정이다.&lt;/p&gt;
&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;리팩토링과 같은 책도 읽고 인문학 소양도 기르고,,,, 2024년에는 4년차 개발자가 된다고 생각하니까 정말 하루하루 알차게 살아야겠다는 생각밖에 안든다...ㅎㅎㅎ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 개발 리드를 하게 된다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실력은 말할 필요도 없이 좋고, 좋은 인성을 겸비한,, 누구든 편하게 도움을 요청할 수 있는 그런 개발 리더가 되고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러기 위해선 일단 실력부터 기르자..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;2023년 하반기 회고에는 부디 회사의 업무도, 내 커리어에서도 치열하게 사는 기간이라고 쓸 수 있었으면 좋겠다..!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;2023년 상반기도 수고했다 나 자신..!!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>생각정리</category>
      <category>회고</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/4</guid>
      <comments>https://devjooj.tistory.com/4#entry4comment</comments>
      <pubDate>Sat, 17 Jun 2023 22:32:40 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] COUNT(*), COUNT(1),COUNT(COLUMN), COUNT(DISTINCT COLUMN) 차이</title>
      <link>https://devjooj.tistory.com/3</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;COUNT(*) &amp;amp; COUNT(1)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SELECT 문에 의해 검색된 모든행을 조회&lt;/li&gt;
&lt;li&gt;NULL 및 중복 값 포함 (말그대로 모든 행을 조회)&lt;/li&gt;
&lt;li&gt;COUNT(*) 와 COUNT(1)은 동일한 방식으로 작동, 성능 차의 거의 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;#COUNT(*)
SELECT COUNT(*) FROM 테이블

#COUNT(1)
SELECT COUNT(1) FROM 테이블
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;b&gt;COUNT(COLUMN)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬럼이 NULL 이 아닌 값을 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT COUNT(컬럼명) FROM 테이블
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;COUNT(DISTINCT COLUMN)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬럼이 NULL, 중복 제거 후 갯수 조회&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Database/MySQL</category>
      <category>#MYSQL</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/3</guid>
      <comments>https://devjooj.tistory.com/3#entry3comment</comments>
      <pubDate>Tue, 13 Jun 2023 23:47:38 +0900</pubDate>
    </item>
    <item>
      <title>[NEXT] router.isReady (router.query가 빈 값일 경우)</title>
      <link>https://devjooj.tistory.com/2</link>
      <description>&lt;h1&gt;[NEXT] router.isReady (router.query가 빈 값일 경우)&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Next.js 에서 router.query에 값을 넘기는데도 빈 값일때 해결방법!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이슈&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;localhost:3005?param=&amp;rdquo;qsdfsdfsdfsdf&amp;rsquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보내는데, 자꾸 router.query객체를 확인해보니 빈객체였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈객체면 로그인을 못하는데, 자꾸 빈객체가 뜨니 로그인으로 넘어가는 이슈가 생김&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;automatic static optimization에 의해 정적으로 최적화된 페이지는 루트 매개변수가 제공되지 않아서 query가 빈객체가 된다고 한다.&lt;/li&gt;
&lt;li&gt;컴포넌트 밖에 있는 wrapper에서 호출하는 거니까 정적으로 최적화된 페이지인가..?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;NextJS @10.0.5이후 - isReady 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라우터 필드가 클라이언트 측에서 업데이트되고 사용할 준비가 되었는지 여부.&lt;/li&gt;
&lt;li&gt;useEffect 메소드 내에서만 사용해야하며 서버에서 조건부로 렌더링 하는데에 사용해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1686581088571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
		
		if (mount) {
			resetSignUp()
			if (validateUserInfo()) {
				storeUserInfo()
			} else {
					alert(&quot;잘못된 접근입니다.&quot;)
					resetUserInfo()
					// ❗❗ [TO DO] 에러페이지로 이동할지 또는 창을 닫을지 정해야함
					router.replace('/error')
			}
		}
     
	}, [router.isReady])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 공부/에러모음</category>
      <category>Next</category>
      <category>Router</category>
      <category>에러모음</category>
      <author>데브쥬쥬</author>
      <guid isPermaLink="true">https://devjooj.tistory.com/2</guid>
      <comments>https://devjooj.tistory.com/2#entry2comment</comments>
      <pubDate>Mon, 12 Jun 2023 23:47:56 +0900</pubDate>
    </item>
  </channel>
</rss>