<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>꿈꾸는 개발자</title>
    <link>https://dreamcode.tistory.com/</link>
    <description>안녕하세요 해당 블로그는 저의 개발 성장 과정을 담기 위해 개설했습니다!</description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 14:09:46 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>rickysin</managingEditor>
    <image>
      <title>꿈꾸는 개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/4927212/attach/4f1082265caf45e0822f4812346ac5c0</url>
      <link>https://dreamcode.tistory.com</link>
    </image>
    <item>
      <title>Dokcer Error 해결하기</title>
      <link>https://dreamcode.tistory.com/510</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgMMko/btsI42AJYNy/ARhjFTRSyo9KQ4enPKE0r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgMMko/btsI42AJYNy/ARhjFTRSyo9KQ4enPKE0r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgMMko/btsI42AJYNy/ARhjFTRSyo9KQ4enPKE0r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgMMko%2FbtsI42AJYNy%2FARhjFTRSyo9KQ4enPKE0r1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;230&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;230&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;Docker로 Nuxt3을 실행하게 되면 위와 같은 Error가 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;해결 방법&lt;/h4&gt;
&lt;pre id=&quot;code_1723767804431&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker-compose up --force-recreate&lt;/code&gt;&lt;/pre&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;b&gt;docker-compose up&lt;/b&gt;: 이 명령어는 docker-compose.yml 파일에 정의된 서비스를 기반으로 컨테이너를 생성하고 시작합니다. 필요한 경우 이미지도 빌드하고, 네트워크, 볼륨 등을 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;--force-recreate&lt;/b&gt;: 이 플래그는 기존의 컨테이너가 이미 존재하는 경우에도, 기존 컨테이너를 중지하고 새로 생성하여 시작하게 합니다. 즉, 모든 컨테이너를 강제로 다시 생성(recreate)합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 기존에 이미 생성된 Docker Container가 있어서 충돌이 발생하는 것으로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/510</guid>
      <comments>https://dreamcode.tistory.com/510#entry510comment</comments>
      <pubDate>Fri, 16 Aug 2024 09:25:15 +0900</pubDate>
    </item>
    <item>
      <title>Three.js 수학 (행렬)</title>
      <link>https://dreamcode.tistory.com/507</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;행렬의 곱의 의미 ( Right에서부터 순차적으로 적용된다)&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &amp;nbsp;A x B : 행렬&amp;nbsp;&amp;nbsp;A 의 변환이 먼저 적용되고, 그 다음에 행렬&amp;nbsp;&amp;nbsp;B 의 변환이 적용됩니다.&lt;br /&gt;&amp;bull; &amp;nbsp;B x A : 행렬&amp;nbsp;&amp;nbsp;B 의 변환이 먼저 적용되고, 그 다음에 행렬&amp;nbsp;&amp;nbsp;A 의 변환이 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시:&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; &amp;nbsp;A&amp;nbsp;:&amp;nbsp;객체를&amp;nbsp;&amp;nbsp;5&amp;nbsp;&amp;nbsp;단위만큼&amp;nbsp;x&amp;nbsp;축으로&amp;nbsp;이동하는&amp;nbsp;행렬&lt;br /&gt;&amp;bull; &amp;nbsp;B&amp;nbsp;:&amp;nbsp;객체를&amp;nbsp;&amp;nbsp;90&amp;nbsp;도&amp;nbsp;만큼&amp;nbsp;z&amp;nbsp;축을&amp;nbsp;중심으로&amp;nbsp;회전시키는&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;bull;&amp;nbsp; A x B: 객체를 먼저&amp;nbsp;&amp;nbsp;90 도 만큼 z 축을 중심으로 회전시키고, 그 다음에 x 축을 따라&amp;nbsp;&amp;nbsp;5&amp;nbsp;&amp;nbsp;단위만큼 이동시킵니다.&lt;br /&gt;&amp;bull;&amp;nbsp; B x A : 객체를 먼저 x 축을 따라&amp;nbsp;&amp;nbsp;5&amp;nbsp;&amp;nbsp;단위만큼 이동시키고, 그 다음에&amp;nbsp;&amp;nbsp;90 도 만큼 z 축을 중심으로 회전시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행렬의 곱셈의 경우 A와 B의 각 요소를 곱하고 더한 결과라고 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;변환의 반전:&amp;nbsp;&lt;/b&gt;&lt;/u&gt;행렬의 역행렬은 원래 변환의&lt;b&gt; 반대 방향&lt;/b&gt;으로 변환을 적용합니다. 예를 들어, 어떤 객체를 이동시키는 행렬이 있다면, 그 행렬의 역행렬을 적용하면 객체를 원래 위치로 되돌릴 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;카메라 변환:&lt;/b&gt;&lt;/u&gt;&lt;b&gt; &lt;/b&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;일반: (카메라 =&amp;gt; 월드좌표)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;역행렬: (월드좌표 =&amp;gt; 카메라 좌표)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;카메라 변환:&lt;/b&gt;&lt;/u&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;world =&amp;gt; local&amp;nbsp;&lt;/li&gt;
&lt;li&gt;local =&amp;gt; world&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3D상에서 각 행렬이 가지는 의미 (4x4)&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1721822863754&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const matrix = new THREE.Matrix4();

// 예제: 행렬의 각 요소를 설정
matrix.set(
  1, 0, 0, 10, // 첫 번째 열 (X축 방향 벡터 및 X 위치) 객체의 x축 회전과 크기 변환을 포함
  0, 1, 0, 20, // 두 번째 열 (Y축 방향 벡터 및 Y 위치) y축의
  0, 0, 1, 30, // 세 번째 열 (Z축 방향 벡터 및 Z 위치) z축의
  0, 0, 0, 1   // 네 번째 열 (균등한 스케일링)
);

console.log(matrix);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Transpose and Inverse and identity Matrix&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Transpose (전치)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;transpose는 행과열을 뒤바꾸는 것을 의미한다.행렬 &lt;span&gt;&lt;span&gt;A&lt;/span&gt;&lt;/span&gt;의 전치 행렬은 &lt;span&gt;&lt;span&gt;A^T &lt;/span&gt;&lt;/span&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;478&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xBOjL/btsIMk3efM5/8tGKbOoL6FFqW90q11Si91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xBOjL/btsIMk3efM5/8tGKbOoL6FFqW90q11Si91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xBOjL/btsIMk3efM5/8tGKbOoL6FFqW90q11Si91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxBOjL%2FbtsIMk3efM5%2F8tGKbOoL6FFqW90q11Si91%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;462&quot; height=&quot;231&quot; data-origin-width=&quot;478&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;용도:&lt;/u&gt;&amp;nbsp; 데이터 변환, 행과 열의 교환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Inverse (역행렬)&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;u&gt;&lt;b&gt;단위 행렬&lt;/b&gt;&lt;/u&gt;을 생성하는 행렬을 의미한다.행렬 &lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 역행렬은 &lt;span&gt;&lt;span&gt;A^-1&lt;/span&gt;&lt;/span&gt;로 표시한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;조건&lt;/u&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;행렬 A의 행과 열의 수가 같아야 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;용도:&lt;/u&gt; 선형 방정식 풀기, 시스템 해석&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Identity Matrix (단위 행렬)&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단위 행렬은 대각선 요소가 모두 1이고 나머지 요소가 모두 0인 정사각 행렬이다. 단위 행렬은 보통 &lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&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;538&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qFZNo/btsIN6bldPY/HxqGbllQra2WFX0E125fy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qFZNo/btsIN6bldPY/HxqGbllQra2WFX0E125fy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qFZNo/btsIN6bldPY/HxqGbllQra2WFX0E125fy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqFZNo%2FbtsIN6bldPY%2FHxqGbllQra2WFX0E125fy1%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;456&quot; height=&quot;206&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;* 참고사항:&lt;/b&gt;&lt;/u&gt; 3D 상에서 Rotation [R/t]에서 R의 경우 회전 Matrix의 역행렬은 곧 기존 Matrix의 전치에 해당한다. (S,T의 경우는 다르다)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>3D</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/507</guid>
      <comments>https://dreamcode.tistory.com/507#entry507comment</comments>
      <pubDate>Wed, 24 Jul 2024 21:09:11 +0900</pubDate>
    </item>
    <item>
      <title>axios interceptor로 rate limit에 대응하기</title>
      <link>https://dreamcode.tistory.com/502</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Rate Limiting&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rate Litming이란 일정한 시간 동안 호출할 수 있는 API 수를 의미한다. 사용자가 혹은 개발자의 실수로 일정 시간 동안 제한된 수 이상의 요청을 보내게 되면 요청이 실패하게 된다. (보통은 429 too many request error가 반환된다) 보통 서버에서 rate limit을 적용하면, 서버의 안정성을 높일 수 있다.&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;하지만 본 글은 rate limit에 관해 다루는 글이 아니기 떄문에, 자세한 사항들은 추가적으로 학습하길 권장한다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프론트에서 Api call 제한하는 방법&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 rate limit에 대응의 필요성을 인지한 후 여러 방법을 시도해봤다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫 번째, tanstack Query을 활용한 요청 제한&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 tanstack query에서 위와 같은 기능을 제공하지 않을까? 라는 기대와 함께 조사를 진행했지만,&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;894&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbwThU/btsG6byw3iy/BHSfSRSptPbr7u4KVIkEx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbwThU/btsG6byw3iy/BHSfSRSptPbr7u4KVIkEx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbwThU/btsG6byw3iy/BHSfSRSptPbr7u4KVIkEx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbwThU%2FbtsG6byw3iy%2FBHSfSRSptPbr7u4KVIkEx1%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;894&quot; height=&quot;585&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/TanStack/query/discussions/4609&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/TanStack/query/discussions/4609&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714542301784&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Add a rate limiting option &amp;middot; TanStack query &amp;middot; Discussion #4609&quot; data-og-description=&quot;This could be a entire new library, but I think the idea really fits TanStack Query. I noticed the problem while developing a SPA using Vue Query. Constantly hot reloading and refreshing the page u...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/TanStack/query/discussions/4609&quot; data-og-url=&quot;https://github.com/TanStack/query/discussions/4609&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bv5H5k/hyVVytx5R8/8TVPcdQrTHqsu16EvkuapK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/TanStack/query/discussions/4609&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/TanStack/query/discussions/4609&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bv5H5k/hyVVytx5R8/8TVPcdQrTHqsu16EvkuapK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Add a rate limiting option &amp;middot; TanStack query &amp;middot; Discussion #4609&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This could be a entire new library, but I think the idea really fits TanStack Query. I noticed the problem while developing a SPA using Vue Query. Constantly hot reloading and refreshing the page u...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 TkDodo에 따르면 관련 기능은 추가되지 않을 것으로 보인다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그렇게 생각한 것이 두 번째 방법이다. 바로 interceptors을 사용하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios request interceptors를 사용해봤다면, 알 것으로 생각되지만, interceptors는 말 그대로 모든 요청 전에 거치는 middleware 역할을 수행한다. 그렇다면, 여기에 rate limit을 가하면 어떨까 생각을 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714542756198&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function rateLimitRequest(axiosInstance: AxiosInstance, delay: number) {
  let lastInvocationTime: number | undefined = undefined;

  const delayCalls = (config: InternalAxiosRequestConfig) =&amp;gt; {
    const now = Date.now();
    if (lastInvocationTime) {
      lastInvocationTime += delay;
      const waitPeriodForThisRequest = lastInvocationTime - now;
      if (waitPeriodForThisRequest &amp;gt; 0) {
        return new Promise&amp;lt;InternalAxiosRequestConfig&amp;gt;((resolve) =&amp;gt; {
          setTimeout(() =&amp;gt; resolve(config), waitPeriodForThisRequest);
        });
      }
    }

    lastInvocationTime = now;
    return config;
  };

  axiosInstance.interceptors.request.use(scheduler);
}&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;위 코드를 적용하면, 한 페이지에 요청이 5개가 동시에 호출된다고 했을 때 delay 매개변수에 할당되는 number 만큼의 지연이 순차적으로 보장된다. delay가 150ms라고 했을 때 (A =&amp;gt; 150초후 B =&amp;gt; 150초 후 C와 같이 순차적으로 진행된다. 따라서, 매 요청 사이의 필수적으로 간격을 줘야 한다면 위 방법을 시도해보는 것도 나쁘지 않을 것 같다.&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;</description>
      <category>기타</category>
      <category>axios</category>
      <category>interceptors</category>
      <category>rate limit</category>
      <category>RateLimit</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/502</guid>
      <comments>https://dreamcode.tistory.com/502#entry502comment</comments>
      <pubDate>Wed, 1 May 2024 14:55:50 +0900</pubDate>
    </item>
    <item>
      <title>useMemo를 사용하는 기준 - (언제 사용하나? 지양하는 게 더 좋다!?!)</title>
      <link>https://dreamcode.tistory.com/492</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원티드 프론트엔드 최적화 강의를 들었을 때 현업에서는 useMemo, useCallback을 자주 사용하지 않는다는 말을 들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70#5aca&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70#5aca&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1694931858790&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;Stop Using useMemo Now!&quot; data-og-description=&quot;Most of the Time It Slows Down Your Application&quot; data-og-host=&quot;javascript.plainenglish.io&quot; data-og-source-url=&quot;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70#5aca&quot; data-og-url=&quot;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bPTvbv/hyTVRaqzeH/P9Pdr1zYAKr7RliKdAPve1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380,https://scrap.kakaocdn.net/dn/x32sK/hyTY8hh4Le/5KQvkb5fDrdDfAByqcVyD0/img.png?width=1358&amp;amp;height=928&amp;amp;face=0_0_1358_928,https://scrap.kakaocdn.net/dn/VePfz/hyTY82Fx97/y9vt7TsITkjSnCAxT4KWIK/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380&quot;&gt;&lt;a href=&quot;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70#5aca&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70#5aca&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bPTvbv/hyTVRaqzeH/P9Pdr1zYAKr7RliKdAPve1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380,https://scrap.kakaocdn.net/dn/x32sK/hyTY8hh4Le/5KQvkb5fDrdDfAByqcVyD0/img.png?width=1358&amp;amp;height=928&amp;amp;face=0_0_1358_928,https://scrap.kakaocdn.net/dn/VePfz/hyTY82Fx97/y9vt7TsITkjSnCAxT4KWIK/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380');&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;Stop Using useMemo Now!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Most of the Time It Slows Down Your Application&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;javascript.plainenglish.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 링크는 useMemo를 난발하면 안 좋은 점과 최적화가 아닌, 오히려 App의 성능을 저하할 수도 있다고 말한다.&amp;nbsp; 컴퓨터공학은 항상 trade-off를 고려해야 한다. 이 말은 즉슨 최적화에 따른 댓가가 분명 있다는 것!&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;일차적으로 useMemo, 그 자체보단 React.memo, useCallback debouncing concurrent rendering 등과 합쳐져야 한다. 저자에 따르면, useMemo 등의 최적화 과정은 분명히 도움이 되는 곳이 있지만, 모든 value에 useMemo를 사용 후 적절한 최적화가 되기를 바라는 것은 적합하지 않다고 말한다. 이는 오히려 메모리 사용량을 증가시킬 뿐이다!&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;useMemo는 re-render phase에서 value를 가져온다. 따라서, 초기화 및 메모제이션 과정에서 app 자체의 속도를 저하시킨다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;보통 useMemo를 사용하는 경우는&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;복잡한 계산이 들어가는 경우&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Memoized component을 전달하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1694932534290&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const NavTabs = ({ tabs, className, withExpander }) =&amp;gt; {
  const currentMainPath = useMemo(() =&amp;gt; {
    return pathname.split(&quot;/&quot;)[1];
  }, [pathname]);
  const isCurrentMainPath = useMemo(() =&amp;gt; {
    return currentMainPath === pathname.substr(1);
  }, [pathname, currentMainPath]);

  return (
    &amp;lt;StyledWrapper&amp;gt;
      &amp;lt;Span fontSize={18}&amp;gt;
        {isCurrentMainPath ? (
          t(currentMainPath)
        ) : (
          &amp;lt;StyledLink to={`/${currentMainPath}`}&amp;gt;
            {t(currentMainPath)}
          &amp;lt;/StyledLink&amp;gt;
        )}
      &amp;lt;/Span&amp;gt;
    &amp;lt;/StyledWrapper&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 저자의 코드에선 어떠한 부분에도 두 가지가 경우가 포함되지 않기 때문에 useMemo를 제거해도 무방하다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1694932810214&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const Client = ({ clientId, ...otherProps }) =&amp;gt; {
  const tabs = useMemo(
    () =&amp;gt; [
      {
        label: t(&quot;client withdrawals&quot;),
        path: `/clients/${clientId}/withdrawals`
      },
      ...
    ],
    [t, clientId]
  );
  
  ...
  
  return (
    &amp;lt;&amp;gt;
      ...
      &amp;lt;NavTabs tabs={tabs} /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}

export const NavTabs = ({ tabs, className, withExpander }) =&amp;gt; {
  return (
    &amp;lt;Wrapper className={className} withExpander={withExpander}&amp;gt;
      {tabs.map((tab) =&amp;gt; (
        &amp;lt;Item
          key={tab.path}
          to={tab.path}
          withExpander={withExpander}
        &amp;gt;
          &amp;lt;StyledLabel&amp;gt;{tab.label}&amp;lt;/StyledLabel&amp;gt;
        &amp;lt;/Item&amp;gt;
      ))}
    &amp;lt;/Wrapper&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위 코드의 경우 useMemo보단, React.memo를 사용해서 부모 컴포넌트가 re-rendering되더라도, props의 변화가 없는 한 재랜더링되지 않도록 코드를 작성해야 적절한 optimization이 된다. (React.memo의 경우 shallow compraison을 시행하지만, 두 번째 arg로 사용자가 원하는 검사 조건을 추가할 수 있다)&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; 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;thousands의 items의 계산, 팩토리얼 계산이 아닌 이상 대체적으로 복잡한 계산에 속하지 않는다! Profiler을 활용해 optimization이 필요한 컴포넌트를 찾을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://react.dev/learn/you-might-not-need-an-effect&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://react.dev/learn/you-might-not-need-an-effect&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1694933292000&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;You Might Not Need an Effect &amp;ndash; 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://react.dev/learn/you-might-not-need-an-effect&quot; data-og-url=&quot;https://react.dev/learn/you-might-not-need-an-effect&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dC45qU/hyTVPwTMMR/0xpM6UOKaKrjfNcuhgdeFk/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/i2pFV/hyTV2QzPUU/jUeF1kZ6X7I9mskKm5S4jK/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567&quot;&gt;&lt;a href=&quot;https://react.dev/learn/you-might-not-need-an-effect&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://react.dev/learn/you-might-not-need-an-effect&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dC45qU/hyTVPwTMMR/0xpM6UOKaKrjfNcuhgdeFk/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/i2pFV/hyTV2QzPUU/jUeF1kZ6X7I9mskKm5S4jK/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;You Might Not Need an Effect &amp;ndash; 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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 위 React 공식문서에 따르면,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1694933317199&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.time('filter array');
const visibleTodos = getFilteredTodos(todos, filter);
console.timeEnd('filter array');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 처럼 시간을 측정하는 함수를 통해 함수 실행 시간을 측정했을 때 1ms 이상일 경우에만 useMemo의 사용을 고려해도 좋다고 말한다. useMemo를 사용한 후 동일하게 실행 시간이 유의미하게 감소했는지 확인 해보는 것도 좋다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기억해야 할 것은: useMemo는 첫 번째 render를 빠르게 해주는 게 아니라, memoization을 re-render을 빠르게 해주는 것이기 때문에 잘 판단하고 사용하는 게 중요하다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이러한 경우에는 useMemeo를 사용하지 마라!&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;가벼운 계산일 경우&amp;nbsp;&lt;/li&gt;
&lt;li&gt;memoization이 필요한지 애매한 경우: 처음에는 제외하고 나중에 문제가 생기면 추가하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;memoizing하고 있는 값이 component에 전달되지 않는 경우&lt;/li&gt;
&lt;li&gt;dependency array가 너무 자주 변동되는 경우:&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; 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;React component는 props나 state가 change될 때마다&amp;nbsp; re-rendering이 발생한다. 따라서, rendering 단계에서 최적화를 하기 위해서는 문제에 대한 근본적인 판단이 우선이 되어야 한다. 나아가, React.memo, debouncing, code-splitting, lazy-loading 등을 항상 고려하는 것도 중요하다.&amp;nbsp;&lt;/p&gt;</description>
      <category>React.js</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/492</guid>
      <comments>https://dreamcode.tistory.com/492#entry492comment</comments>
      <pubDate>Sun, 17 Sep 2023 16:01:12 +0900</pubDate>
    </item>
    <item>
      <title>GraphQL찍먹하기</title>
      <link>https://dreamcode.tistory.com/482</link>
      <description>&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;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDUd97/btso5tDaduT/BZELKR88OmwAtjsSxpv7gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDUd97/btso5tDaduT/BZELKR88OmwAtjsSxpv7gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDUd97/btso5tDaduT/BZELKR88OmwAtjsSxpv7gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDUd97%2Fbtso5tDaduT%2FBZELKR88OmwAtjsSxpv7gk%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;675&quot; height=&quot;383&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL은 페이스북에서 만든 쿼리 언어이다. graphQL은 Graph+Query Language의 줄임말이다. Server API를 통해 정보를 주고 받기 위해 사용하는 Query Language를 의미한다. 결론: API를 위한 쿼리 언어이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL에선 모든 데이터가 그래프 형태로 연결되어 있다고 전제한다. 일대일로 연결된 관계도 여러 계층으로 이루어진 관계도 모두 그래프이다. GraphQL은 클라이언트 요청에 따라 유연하게 &lt;b&gt;트리 구조의 JSON 데이터를&lt;/b&gt; 응답으로 전송할 수 있다. (엄청난 장점)&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;&lt;b&gt;GraphQL로 그래프 순회&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;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;957&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l87Br/btsoZbKD7r5/mpoQKYj27nHTTzaxhVEIZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l87Br/btsoZbKD7r5/mpoQKYj27nHTTzaxhVEIZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l87Br/btsoZbKD7r5/mpoQKYj27nHTTzaxhVEIZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl87Br%2FbtsoZbKD7r5%2FmpoQKYj27nHTTzaxhVEIZK%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;679&quot; height=&quot;344&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;485&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;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;엔티티는&lt;/b&gt; 사물의 구조나 상태, 동작 등을 모델로 표현하는 경우, 그 모델의 구성요소를 말합니다&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 그래프를 그릴 수 있게 된다면, GraphQL을 사용해 트리를 추출할 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot; 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;&lt;b&gt;그래프에서 트리 추출하는 방법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL 쿼리와 위의 그래프에서 트리를 추출해보면 다음과 같을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690345895744&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
	책(ISBN이 &quot;9780674430006&quot;) {
		책 이름
		저자 {
			이름
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 권의 책만 검색하기 위해 &lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;ISBN이 &quot;9780674430006인 조건을 걸었다. 서버가 해당 요청에 따른 반환된 쿼리는 아래와 같을 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;clojure&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
	책 : {
		책 이름 : &quot;GraphQL은 어렵지 않다&quot;,
		저자 : [
			{ 이름 : &quot;김코딩&quot;},
			{ 이름 : &quot;박해커&quot;},
		]
	}
}&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;965&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbN7z1/btsoY7ooxIE/ekBF5qKCbIKgjeJFROakqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbN7z1/btsoY7ooxIE/ekBF5qKCbIKgjeJFROakqK/img.png&quot; data-alt=&quot;[그림] GraphQL로 쿼리한 것을 그래프의 관점으로 도식화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbN7z1/btsoY7ooxIE/ekBF5qKCbIKgjeJFROakqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbN7z1%2FbtsoY7ooxIE%2FekBF5qKCbIKgjeJFROakqK%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;671&quot; height=&quot;353&quot; data-origin-width=&quot;965&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[그림] GraphQL로 쿼리한 것을 그래프의 관점으로 도식화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;ISBN 번호를 사용하여 선택한 &amp;ldquo;책&quot; 노드에서 시작한다. 그 다음 graphQl은 중첩된 각 필드로 표시된 간선을 따라 그래프를 탐색하기 시작한다. 쿼리 내 중첩된 &quot;책 이름&quot; 필드를 통해 책의 제목이 있는 노드로 이동을 한다. &quot;저자&quot;로 레이블이 지정된 &quot;책&quot;의 간선을 따라 &quot;&lt;b&gt;저자&lt;/b&gt;&quot; 노드를 가져오고, 각 저자의 &lt;b&gt;이름을&lt;/b&gt; 얻어오는 것이다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ed2QLb/btso0O2GvUZ/cIKkUVaWPuENroKlo14Kp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ed2QLb/btso0O2GvUZ/cIKkUVaWPuENroKlo14Kp1/img.png&quot; data-alt=&quot;GraphQL로 퀴리한 것을 트리 구조로 도식화한 것&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ed2QLb/btso0O2GvUZ/cIKkUVaWPuENroKlo14Kp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fed2QLb%2Fbtso0O2GvUZ%2FcIKkUVaWPuENroKlo14Kp1%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;640&quot; height=&quot;344&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GraphQL로 퀴리한 것을 트리 구조로 도식화한 것&lt;/figcaption&gt;
&lt;/figure&gt;
&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;&lt;b&gt;GraphQL의 특징&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbi88m/btso5Xj6Cps/UPk7iKdKFnbXMuC6ptoZP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbi88m/btso5Xj6Cps/UPk7iKdKFnbXMuC6ptoZP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbi88m/btso5Xj6Cps/UPk7iKdKFnbXMuC6ptoZP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcbi88m%2Fbtso5Xj6Cps%2FUPk7iKdKFnbXMuC6ptoZP0%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;462&quot; height=&quot;230&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;280&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;GraphQL에서는 Resource에 대한 형태 정의와 데이터 요청이 완전히 분리되어 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;GraphQL에서는 Resource에 대한 정보만 정의하고, 필요한 크기와 형태는 클라이언트 단에서 요청 시 결정한다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;GraphQL에서는 GraphQL Schema가 Resource를 나타내고 Query, Mutation 타입이 작업의 유형을 나타낸다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;GraphQL에서는 한 번의 요청에서 여러 Resource에 접근할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;GraphQL에서는 요청받은 각 필드에 대한 resolver를 호출하여 작업을 처리한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;GraphQL의 장단점&lt;/b&gt;&lt;/h4&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;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tx1NW/btsoYOWYk16/tgI1xtKWp0CHBTpxCRaSiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tx1NW/btsoYOWYk16/tgI1xtKWp0CHBTpxCRaSiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tx1NW/btsoYOWYk16/tgI1xtKWp0CHBTpxCRaSiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftx1NW%2FbtsoYOWYk16%2FtgI1xtKWp0CHBTpxCRaSiK%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;612&quot; height=&quot;347&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;726&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;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oGXWJ/btso4yroSqV/U9SzAkIN4undqXbbeO8SYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oGXWJ/btso4yroSqV/U9SzAkIN4undqXbbeO8SYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oGXWJ/btso4yroSqV/U9SzAkIN4undqXbbeO8SYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoGXWJ%2Fbtso4yroSqV%2FU9SzAkIN4undqXbbeO8SYk%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;688&quot; height=&quot;390&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;726&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;하나의 &lt;b&gt;endpoint&lt;/b&gt; 요청
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;graphql&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;이라는 하나의 &lt;/span&gt;&lt;b&gt;endpoint&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;로 요청을 받고 그 요청에 따라 query , mutation을 &lt;/span&gt;&lt;b&gt;resolver&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt; 함수로 전달해서 요청에 응답한다. (모든 클라이언트 요청은 &lt;b&gt;POST&lt;/b&gt; 메서드를 사용한다)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;&lt;b&gt;No! under &amp;amp; overfetching&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 endpoint 요청을 할 필요 없이 하나의 endpoint에서 쿼리를 이용해 원하는 데이터를 정확하게 API에 요청하고 응답으로 받을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;강력한 playground&amp;nbsp; (GUI를이용resolver와schema를 한 눈에&amp;nbsp; 보고&amp;nbsp; 테스트해&amp;nbsp; 볼 수 있다)&lt;br /&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;b&gt;&lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1690346458664&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;GraphQL Playground&quot; data-og-description=&quot;Visually explore Apollo Server&quot; data-og-host=&quot;www.apollographql.com&quot; data-og-source-url=&quot;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&quot; data-og-url=&quot;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/D6nbt/hyTrK2uVYx/B78iToN1adV0fa5o2bBSwK/img.jpg?width=1280&amp;amp;height=669&amp;amp;face=0_0_1280_669,https://scrap.kakaocdn.net/dn/iNVpH/hyTrPbFg0F/N9qnbNgoNiBNxescnzZYJk/img.png?width=3104&amp;amp;height=1968&amp;amp;face=0_0_3104_1968&quot;&gt;&lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/D6nbt/hyTrK2uVYx/B78iToN1adV0fa5o2bBSwK/img.jpg?width=1280&amp;amp;height=669&amp;amp;face=0_0_1280_669,https://scrap.kakaocdn.net/dn/iNVpH/hyTrPbFg0F/N9qnbNgoNiBNxescnzZYJk/img.png?width=3104&amp;amp;height=1968&amp;amp;face=0_0_3104_1968');&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;GraphQL Playground&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Visually explore Apollo Server&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.apollographql.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;br /&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;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;GraphQL의 구조&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GraphQL Keywords&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버로부터 데이터를 조회하는 경우, REST API에서는 GET 요청을 보내지만, GraphQL에선 &lt;b&gt;Query&lt;/b&gt;를 이용해 원하는 데이터를 요청할 수 있다. Create/Delete와 같이 저장된 데이터를 수정하는 경우는 &lt;b&gt;Mutation&lt;/b&gt;을 이용해 수행 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구독(subscription)이라는 개념을 &lt;/b&gt;통해 실시간 업데이트를 구현할 수 있다&lt;b&gt;.&amp;nbsp;&lt;/b&gt;이는 전통적인 Client(요청)- Server(응답) 모델을 따르는 Query 또는 Mutation과 달리&amp;nbsp;&lt;b&gt;발행/구독 모델을 따른다.&amp;nbsp;&lt;/b&gt;클라이언트가 이벤트를 구독하면 클라이언트는 서버와 Websocket을 기반으로 지속적인 연결을 형성하고 유지한다. 특정 이벤트가 발생하면 서버는 대응하는&amp;nbsp; 데이터를 클라이언트에 푸시한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Query&lt;/b&gt;: 저장된 데이터 가져오기 (REST의 GET과 비슷)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Mutation&lt;/b&gt;: 저장된 데이터 수정하기&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Create&lt;/b&gt;: 새로운 데이터 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Update&lt;/b&gt;: 기존의 데이터 수정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Delete&lt;/b&gt;: 기존의 데이터 삭제&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Subscription&lt;/b&gt;: 특정 이벤트가 발생 시 서버가 대응하는 데이터를 실기간으로 클라이언트에 전송한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Query(쿼리 데이터 조회)&amp;nbsp;&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;b&gt;필드(field):&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;매우 간단한 query(데이터 조회)를 실행했을 때 얻는 결과&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;hero의 name을 쿼리&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;clojure&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  hero {
    name
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;쿼리를 실행했을 때의 결과&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1690346972032&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;data&quot;: {
    &quot;hero&quot;: {
      &quot;name&quot;: &quot;R2-D2&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드 name은 string의 타입을 반환한다. 위 경우 hero의 name이 &quot;R2-D2&quot;임을 알 수 있다. 쿼리와 결과가 정확하게 같은 모양임을 알 수 있다. GraphQL에서 필수적인 부분이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  hero {
    name
    # 이런 식으로 GraphQL 내에서 주석도 작성할 수 있습니다.
    friends {
      name
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  &quot;data&quot;: {
    &quot;hero&quot;: {
      &quot;name&quot;: &quot;R2-D2&quot;,
      &quot;friends&quot;: [
        {
          &quot;name&quot;: &quot;Luke Skywalker&quot;
        },
        {
          &quot;name&quot;: &quot;Han Solo&quot;
        },
        {
          &quot;name&quot;: &quot;Leia Organa&quot;
        }
      ]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 원하는 필드를 중첩하며 쿼리하는 것도 가능하다. friends 필드는 배열을 반환한다. GraphQL 쿼리는 관련 객체 및 필드를 순회할 수 있기 때문에 고전적인 REST API처럼 다양한 endpoint를 만들어 각기 요청을보내는 &lt;b&gt;대신&amp;nbsp;&lt;/b&gt;client가 하나의 요청을 보내 관련 데이터를 가져올 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전달인자(Arguments)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드에 인수를 전달하는 부분을 추가하게 되면 쿼리의 필드 및 중첩된 객체들에 전달하여 원하는 데이터만 받을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;clojure&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  human(id: &quot;1000&quot;) {
    name
    height
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  &quot;data&quot;: {
    &quot;human&quot;: {
      &quot;name&quot;: &quot;Luke Skywalker&quot;,
      &quot;height&quot;: 1.72
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id가 1000인 human의 이름과 키를 쿼리해 올 수 있다. REST API의 ?id=1000과 비슷한 개념&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;별명(Aliases) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드를 중복해서 사용할 수 없기 때문에 중복해야 할 때는 별명을 붙여서 쿼리는 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;clojure&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  hero(episode: EMPIRE) {
    name
  }
  hero(episode: JEDI) {
    name
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 중복해서 쿼리할 수 없음&lt;/p&gt;
&lt;pre class=&quot;clojure&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처러 별명을 붙여야 함&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  &quot;data&quot;: {
    &quot;empireHero&quot;: {
      &quot;name&quot;: &quot;Luke Skywalker&quot;
    },
    &quot;jediHero&quot;: {
      &quot;name&quot;: &quot;R2-D2&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀴러 결과&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오퍼레이션 네임 (Operation name)&amp;nbsp;&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;pre class=&quot;nginx&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 query keyword와 query name을 작성한다.&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;{
  &quot;data&quot;: {
    &quot;hero&quot;: {
      &quot;name&quot;: &quot;R2-D2&quot;,
      &quot;friends&quot;: [
        {
          &quot;name&quot;: &quot;Luke Skywalker&quot;
        },
        {
          &quot;name&quot;: &quot;Han Solo&quot;
        },
        {
          &quot;name&quot;: &quot;Leia Organa&quot;
        }
      ]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀴러 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 쿼리는 오퍼레이션 타입이다. 오퍼레이션 타입에는 query 뿐만 아니라, mutation , subscription, describes 등이 있다. 쿼리를 약식으로 작성하지 않는 한 이런 오퍼레이션 타입은 반드시 필요하다. 오퍼레이션 네음을 작성할 때는 타입에 맞는 이름을 작성하는 것이 가독성에 좋다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;변수(Variables)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고정된 인수 대신 동적 인수를 받아 쿼리하는 경우가 대다수이다. 변수는 그런 인수들을 동적으로 받고 싶을 때 사용한다.&lt;/p&gt;
&lt;pre class=&quot;less&quot; style=&quot;background-color: #f5f2f0; color: #000000; text-align: left;&quot;&gt;&lt;code&gt;query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}&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;오퍼레이션 네임 옆에 변수를 $변수 이름: 타입 형태로 정의한다. 위의 예시처럼 $episode: Episode일 때, 뒤에 !가 붙는다면 episode는 반드시 Episode여야 한다는 뜻입니다. !는 옵셔널한 사항입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;뮤테이션(mutation, 데이터 수정)&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;GraphQL은 대개 데이터를 가져오는 데에 중점을 두고 있지만, 서버 측 데이터를 수정하기도 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;REST API에서 &lt;/span&gt;GET&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt; 요청을 사용하여 데이터를 수정하지 않고, &lt;/span&gt;POST&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt; 혹은 &lt;/span&gt;PUT&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt; 요청을 사용하는 것처럼 GraphQL도 유사하다. &lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;GraphQL은 &lt;/span&gt;&lt;b&gt;mutation&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;이라는 키워드를 사용하여 서버 측 데이터를 수정한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690347703592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스키마/타입(schema/Type)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQL 스키마의 가장 기본적인 구성 요소는 서비스에서 가져올 수 있는 객체의 종류, 그리고 포함하는 필드를 나타내는 객체 유형이다.&lt;/p&gt;
&lt;pre id=&quot;code_1690347768520&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Character {
  name: String!
  appearsIn: [Episode!]!
}&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;character는 GraphQL 객체 타입이다, 필드가 있는 타입임을 의미한다. 스키마에 있는 대부분의 타입은 객체 타입이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;name과 appearIn은 character 타입의 필드이다. name과 appearIn은 GraphQl 쿼리의 Chareacter 타입 어디서든 사용할 수 있는 필드이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;string은 내장된 스칼라 타입 중 하나이다. 단일 스칼라 객체로 확인되는 유형이며 쿼리에서 하위 선택을 가질 수 없다. (ID, Int도 있음)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;!가 붙는다면 필드는 nullable하지 않고 반드시 값이 들어와야 한다. 이것을 붙여 쿼리하면 반드시 값을 받을 수 있을 것이라고 예상할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;[]&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;는 배열을 의미합니다. 배열에도 &lt;/span&gt;!&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;가 붙을 수 있다. ! 뒤에 붙어 있어 null 값을 허용하지 않음으로 항상 0개 이상의 요소를 포함한 배열을 기대할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e; text-align: left;&quot;&gt;리졸버(Resolver)&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청에 대한 응답을 결정해주는 함수이다. GraphQL의 여러 가지 타입 중&amp;nbsp; Query, Mutation, subscription과 같은 타입의 실제 일하는 로직을 작성한다. 다시 말해 위와 같이 스키마를 정의하면 스 스키마 필드에 사용되는 함수의 실제 해동을 Resolver에서 정의한다. 이러한 함수들이 모이면 Resolvers라 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690348115016&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const db = require(&quot;./../db&quot;)
const resolvers = {
  Query: { // **Query :** 저장된 데이터 가져오기 (REST 에 GET 과 비슷합니다.)
		getUser: async (_, { email, pw }) =&amp;gt; {
			db.findOne({
				where: { email, pw }
			}) ... // 실제 디비에서 데이터를 가져오는 로직을 작성합니다. 
			...
		}
  },
  Mutation: { // **Mutation :** 저장된 데이터 수정하기 ( Create , Update , Delete )
		createUser: async (_, { email, pw, name }) =&amp;gt; {
			...
		}
  }
  Subscription: { // **Subscription :** 실시간 업데이트
    newUser: async () =&amp;gt; {
      ...
		}
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;GraphQL에서는 데이터를 가져오는 구체적인 과정을 직접 구현해야 하는데 이와 같은 작업(e.g. 데이터베이스 쿼리, 원격 API 요청)을 Resolver가 담당하게 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보다 자세한 기능에 대한 &lt;a href=&quot;https://graphql.org/learn/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/482</guid>
      <comments>https://dreamcode.tistory.com/482#entry482comment</comments>
      <pubDate>Wed, 26 Jul 2023 12:34:23 +0900</pubDate>
    </item>
    <item>
      <title>면접을 위한 CS 전공 지식 노트-[4.1 데이터베이스의 기본]</title>
      <link>https://dreamcode.tistory.com/479</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;DB는 일정한 규칙/규약을 통해 구조화되어 저장되는 데이터의 모음이다. 데이터를 관리하는 통합 시스템을 DBMS라고 한다. DB에 있는 데이터들은 특정 DBMS마다 정의된 쿼리 언어(query language)를 통해, 삽입, 삭제, 수정, 조회 등을 수행할 수 있다. DB는 실시간 동시 공유도 가능하다.&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;1066&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ki8OE/btsozjBffgo/sA1uRBtFHA4A8zQOKMXm3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ki8OE/btsozjBffgo/sA1uRBtFHA4A8zQOKMXm3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ki8OE/btsozjBffgo/sA1uRBtFHA4A8zQOKMXm3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKi8OE%2FbtsozjBffgo%2FsA1uRBtFHA4A8zQOKMXm3k%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;501&quot; height=&quot;332&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 구조를 기반으로 데이터를 주고 받는다. ex) MySQL이라는 DBMS가 있고, 그 위에 응용 프로그램에 속하는 Node.js나 php에서 해당 데이터 안에 있는 데이터를 끄집어내는 관련 로직을 구축할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.1&amp;nbsp; &amp;nbsp;엔터티&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Entity:&amp;nbsp;&lt;/b&gt;사람, 장소, 물건 등 여러 개의 속성을 지닌 명사를 의미한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xAzFW/btsoyqHrj6a/we3rnIQCA4oubUlBez84nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xAzFW/btsoyqHrj6a/we3rnIQCA4oubUlBez84nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xAzFW/btsoyqHrj6a/we3rnIQCA4oubUlBez84nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxAzFW%2FbtsoyqHrj6a%2Fwe3rnIQCA4oubUlBez84nk%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;695&quot; height=&quot;326&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림처럼 학생이라는 entity가 있으면 학생은 학번, 이름, 학점 등의 속성을 가지게 된다. 더 다양한 속성이 존재하겠지만 서비스의 요구 사항에 따라 맞춰진다.(보통 서비스 요구사항과 무관한 속성을 사라진다)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약한 엔터티와 강한 언터디&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약한 엔터티:&amp;nbsp;&lt;/b&gt;A가 B에게 종속돼 있으면, A는 약한 언터티이고 B는 강한 언터티이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.4.2&amp;nbsp; &amp;nbsp;릴레이션 (relation)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;DB에서 정보를 구분하여 저장하는 기본 단위이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔터티에 관한 데이터를 DB는 릴레이션 하나에 담아서 관리한다. relation은 관계형 DB에선 &quot;&lt;b&gt;Table&lt;/b&gt;&quot; 이라 불린다. NoSQL DB에선 &lt;b&gt;collection&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;ex) 회원이란 relation이 있다면, 이름, 아이디 등 엔터티들이 묶여서 DB에 담겨서 관리된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Table &amp;amp; Collection&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB의 종류는 크게 관계형 DB와 NoSQL로 나눌 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적인 관계형 DB: MySQL =&amp;gt; 구조: record-table-DB&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적인 NoSQL: MongoDB&amp;nbsp; =&amp;gt; 구조: document-collection-DB&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;1182&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yP0aR/btsoINIUH9X/opQffHaMSpYWIPX4xwHRr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yP0aR/btsoINIUH9X/opQffHaMSpYWIPX4xwHRr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yP0aR/btsoINIUH9X/opQffHaMSpYWIPX4xwHRr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyP0aR%2FbtsoINIUH9X%2FopQffHaMSpYWIPX4xwHRr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;321&quot; data-origin-width=&quot;1182&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림처럼 record들이 쌓여서 테이블이 되고 그게 쌓여서 DB가 된다.&amp;nbsp;&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.3&amp;nbsp; 속성 (attribute)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;relation에서 관리하는 구체적이며 고유한 이름을 갖는 정보이다. 예를 들어 차라는 엔터티의 속성을 보면, 차 넘버, 바퀴 수 등이 있을 것이다. 서비스 요구 사항을 기반으로 관리 해야 하는 속성들만 엔터티의 속성을 본다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.4&amp;nbsp; 도메인 (Domain)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;relation에 포함된 각각의 속성들이 가질 수 있는 값의 집합을 말한다. ex) 성별이란 속성이 있다면 이 속성을 가질 수 있는 값은 (남,여)라는 집합이 된다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oq50G/btsoKYDAgZR/JAhHrvr31pKKAsQ6pQ5gvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oq50G/btsoKYDAgZR/JAhHrvr31pKKAsQ6pQ5gvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oq50G/btsoKYDAgZR/JAhHrvr31pKKAsQ6pQ5gvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOq50G%2FbtsoKYDAgZR%2FJAhHrvr31pKKAsQ6pQ5gvK%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;576&quot; height=&quot;364&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서 볼 수 있는 것처럼&amp;nbsp;&lt;b&gt;학생&lt;/b&gt;이라는 relation에 학번, 이름, 학년, 신장, 학과란&amp;nbsp;&lt;b&gt;속성&lt;/b&gt;이 있고 학년은 (1,2,3,4) 라는 도메인을 가지는 것을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.5&amp;nbsp; 필드와 레코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 설명된 것을 기반으로 DB에서 필드와 레코드로 구성된 테이블을 만들 수 있다.&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;800&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q6F4x/btsoCi3WGfL/TO2Nlvy46DgOiuVpCOYJDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q6F4x/btsoCi3WGfL/TO2Nlvy46DgOiuVpCOYJDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q6F4x/btsoCi3WGfL/TO2Nlvy46DgOiuVpCOYJDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq6F4x%2FbtsoCi3WGfL%2FTO2Nlvy46DgOiuVpCOYJDk%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;584&quot; height=&quot;267&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객이란 엔터티는 속성으로 이름, 전번, 주소, 고객 등급 등의 &lt;b&gt;필드를&lt;/b&gt; 가진다. row(행) 단위의 테이터를 &lt;b&gt;record&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;ex) 책이란 엔터티를 정의하고 이를 기반으로 테이블을 만들어보자!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;속성: &lt;/b&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;MySQL를 기준으로 타입을 정의해보면 (MongoDB의 경우는 다르다)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책의 아이디: INT&lt;/li&gt;
&lt;li&gt;책의 제목: VARCHAR(255)&lt;/li&gt;
&lt;li&gt;책의 저자 아이디: INT&lt;/li&gt;
&lt;li&gt;책의 출판년도: VARCHAR(255)&lt;/li&gt;
&lt;li&gt;책의 장르: VARCHAR(255)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;생성 일시: DATEIME&lt;/li&gt;
&lt;li&gt;업데이트 일시: DATEIME&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 정의한 속성의 타입에 따라 테이블을 만들면&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 30.5814%; height: 263px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;Book&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;id INT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;title VARCHAR(255)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;author_id INT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;publishing_year VARCHAR(255)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;genre VARCHAR(255)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;created_at &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DATEIME&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;updated_at &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DATEIME&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kOTbu/btsox9NJA5I/tWjMjOEUHrZh5HpB5lRU50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kOTbu/btsox9NJA5I/tWjMjOEUHrZh5HpB5lRU50/img.png&quot; data-alt=&quot;보통 이런 형태를 띤다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kOTbu/btsox9NJA5I/tWjMjOEUHrZh5HpB5lRU50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkOTbu%2Fbtsox9NJA5I%2FtWjMjOEUHrZh5HpB5lRU50%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;492&quot; height=&quot;205&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;300&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; title, author_id 등으로 영어 이름에 매핑해서 쓰고 앞서 설명한 속성과 타입들이 들어가게 된다.&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;위 테이블을 MySQL로 만드려면 아래와 같이 작성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1690115446304&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE book{
 id INT NOT NULL AUTO _INCREMENT,
 title VARCHAR(255)
 author_id INT
 publishing_year VARCHAR(255)
 genre VARCHAR(255)
 created_at  DATEIME
 updated_at  DATEIME
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필드 타입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드는 타입을 갖는다. 예를 들어 이름은 문자열이고 전화번호는 숫자일 것이다. 이런 타입들은 DBMS마다 다르며, 여기에서는 MySQL를 기준으로 설명하겠다. 여러 가지 타입이 있고 대표적인 타입인 숫자, 날짜, 문자 타입에 대해 알아보면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;숫자 타입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자 타입으로는 TINYINT, SMALLINT, MEDIUMINT,INT DIGINT 등이 있다.&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;760&quot; data-origin-height=&quot;505&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNkmBk/btsoyqhhBYS/ikVArTykzlJcgohPIIyYL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNkmBk/btsoyqhhBYS/ikVArTykzlJcgohPIIyYL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNkmBk/btsoyqhhBYS/ikVArTykzlJcgohPIIyYL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNkmBk%2FbtsoyqhhBYS%2FikVArTykzlJcgohPIIyYL1%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;597&quot; height=&quot;397&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;505&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;날짜 타입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;날짜 타입으로는 DATE, DATETIEM, TIMESTAMP 등이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DATE&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;날짜 부분은 있지만 시간 부분은 없는 값에 사용된다. 지원되는 범위는 1000-01-01~9999-12-31이다. 3바이트 용량을 가진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DATETIME&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;날짜 및 시간 부분을 모두 포함하는 값에 사용된다.&amp;nbsp; 지원되는 범위는 1000-01-01 00:00:00에서&amp;nbsp; 9999-12-31 23:59:59이다. 8 바이트 용량을 가진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TIMESTAMP&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;날짜 및 시간 부분을 모두 포함하는 값에 사용된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문자 타입&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자 타입으로는 CHAR, VARCHAR,TEXT, BLOB, ENUM, SET 이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CHAR와 VARCHAR&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CHAR 또는 VARCHAR 모두 그 안에 수를 입력해서 몇자까지 입력할지 정한다. 예를 들어 CHAR(30)이라며 최대 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;CHAR는 테이블을 생성할 때 선언한 길이로 고정되며 길이는 0 ~255 사이의 값을 가진다. 레코드를 저장할 때 무조건 선언한 길이 값으로 고정해서 저장한다.&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;VARCHAR는 가변 길이 문자열이다. 길이는 0~65,535 사이의 값으로 지정할 수 있으며, 입력된 데이터에 따라 용량을 가변시켜 저장한다. ex) 10글자의 이메일을 저장할 경우 10글자에 해당하는 바이트 + 길이기록용 1바이트로 저장하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TEXT와 BLOB&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;두 타입 모두 큰 데이터를 저장할 때 쓰는 타입이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TEXT&lt;/b&gt;는 큰 문자열 저장에쓰인다. (주로 게시판의 본문을 저장)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;BLOB&lt;/b&gt;은 이미지, 동영상 등 데이터 저장에 쓰인다. 그러나 보통은 아마존의 이미지 호스팅 서비스인 S3를 이용하는 등 서버에 파일을 올리고 파일에 관한 경로를 VARCHAR로 저장한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ENUM과 SET&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ENUM과 SET 모두 문자열을 열거하&amp;nbsp; 타입이다.&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;ENUM: (x-small, small, medium, large,) 형태로 쓰인다. 단일 선택만이 가능하고, 없는 값을 삽입하면 빈 문자열이 대신 삽입된다. ENUM을 이용하면 x-small 등이 0,1 등으로 매핑되어 메모리를 적게 사용하는 이점을 얻을 수 있다.&amp;nbsp; ENUM은 최대 65,535개의 요소들을 넣을 수 있다.&lt;/p&gt;
&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;SET:&lt;/b&gt; ENUM과 비슷하지만 여러 개의 데이터 선택이 가능하다. 비트 단위의 연산을 할 수 있다. 최대 64개의 요소를 집어넣을 수 있다는 점이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 다 공간적인 절약을 할 수 있다는 장점이 있지만, ENUM이나 SET에서 정의한 목록을 수정해야 한다는 단점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.6&amp;nbsp; 관계&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB에 테이블은 여러 개가 있으며, 상호 관계가 정의돼 있다. 관계화살표를 통해 나타낸다.&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;639&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yIhyG/btsoSlZ4PtU/dtZaZqQWCkW5sFbaQumwU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yIhyG/btsoSlZ4PtU/dtZaZqQWCkW5sFbaQumwU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yIhyG/btsoSlZ4PtU/dtZaZqQWCkW5sFbaQumwU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyIhyG%2FbtsoSlZ4PtU%2FdtZaZqQWCkW5sFbaQumwU1%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;477&quot; height=&quot;639&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;639&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;1:1 관계&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) user 당 user의 이메일은 한 개씩 존재하기 때문에 1:1 관계가 성립된다.&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;401&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjoxjI/btsoRCnvHdE/uR4g86nNVblpZRifaXJHPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjoxjI/btsoRCnvHdE/uR4g86nNVblpZRifaXJHPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjoxjI/btsoRCnvHdE/uR4g86nNVblpZRifaXJHPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjoxjI%2FbtsoRCnvHdE%2FuR4g86nNVblpZRifaXJHPK%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;349&quot; height=&quot;279&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1:1 관계는 테이블을 두 개의 테이블로 나눠 테이블의 구조를 더 이해하기 쉽게 만들어 준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1:N 관계 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 쇼핑몰을 운영한다고 할 때 한 user 당 여러 장바구니에 넣을 수 있을 것이다. 이 경우 1:N 관계가 된다. 물론 0도 포함되어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;N:M 관계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학생과 강의의 관계를 정의하면, 학생이 여러 강의를 선택할 수 있고, 강의도 여러 학생을 포함할 수 있으니 N:M관계를 형성하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wwvQW/btsoULYi8DQ/0MAtHTBzwK9dYbqQ0hOMPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wwvQW/btsoULYi8DQ/0MAtHTBzwK9dYbqQ0hOMPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wwvQW/btsoULYi8DQ/0MAtHTBzwK9dYbqQ0hOMPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwwvQW%2FbtsoULYi8DQ%2F0MAtHTBzwK9dYbqQ0hOMPk%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;763&quot; height=&quot;272&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진을 보면 중간에 학생-수업 테이블이 하나 껴져 있는 상태이다. N:M테이블은 직접 연결이 아닌, 1:N, 1:M이라는 관계를 갖는 테이블 두 개로 나눠서 설정한다.&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4.1.7&amp;nbsp; 키&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 간의 관계를 조금 더 명확하게 하고 테이블 자체의 인덱스를 위해 설정된 장치로 기본키, 외래키, 후보키, 슈퍼키, 대체키가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;460&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MgPwu/btsoYVnsBp5/lkuNO8TZCpegRTKC1r5B9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MgPwu/btsoYVnsBp5/lkuNO8TZCpegRTKC1r5B9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MgPwu/btsoYVnsBp5/lkuNO8TZCpegRTKC1r5B9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMgPwu%2FbtsoYVnsBp5%2FlkuNO8TZCpegRTKC1r5B9K%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;412&quot; height=&quot;274&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키들은 위의 그림과 같은 관계를 가진다. 후보키 중에 기본키로 선택되지 못한 키는 대체키가 된다. 유일성은 중복되는 값은 없으며, 최소성은 필드를 조합하지 않고 최소 필드만 써서 키를 형성할 수 있는 것을 말한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기본키 (Primary Key) - 유일성 + 최소성 만족&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블의 데이터 중 고유하게 존재하는 속성이다. 기본키에 해당하는 데이터는 =&amp;nbsp; ID처럼 중복되어서는 안 된다. 만약 중복이 된다면 해당 필드는 기본키가 되면 안 된다.&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;307&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egg830/btsoTnd8v8I/8GVdzuhSYKtKnr24VSFpJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egg830/btsoTnd8v8I/8GVdzuhSYKtKnr24VSFpJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egg830/btsoTnd8v8I/8GVdzuhSYKtKnr24VSFpJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fegg830%2FbtsoTnd8v8I%2F8GVdzuhSYKtKnr24VSFpJ1%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;479&quot; height=&quot;256&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학번은 기본키로 설정할 수 있을 것이다. 물론 복합키를(학번 + 주민번호) 설정할 수 있겠지만, 그렇게 되면 최소성을 만족하지 못하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본키 는 자연키 또는 인조키 중 골라 설정하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자연키&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저 테이블을 만든다고 가정했을 때&amp;nbsp; 주민번호, 이름, 성별 등의 속성이 있다. 이 중 이름,성별 등은 중복된 값이 들어올 수 있기 때문에 부적절 =&amp;gt; 남는 것은 주민번호이다. 이 방법처럼 중복된 값을 제외하고 중복되지 않은 것을 뽑다보면 나오는 키를 자연키라고 한다. (자연키는 언젠가 변하는 속성을 가진다)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인조키&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시와 동일한 상황을 가정했을 때 인위적으로&amp;nbsp; 유저 아이디를 부여하는 것이다. (고유 식별자가 생긴다).&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 오라클: sequence&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- MySQL: auto increment&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인위적으로 생성한 키를 인조키라고 부른다. 자연키와는 대조적으로 변하지 않는다. (&lt;b&gt;보통 기본키는 인조키로 설정한다&lt;/b&gt;)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;외래키(Foreign Key)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FK라고 하며, 다른 테이블의 기본키를 그대로 참조하는 값으로 개체와의 관계를 식별하는 데 사용한다.&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;1280&quot; data-origin-height=&quot;958&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UoHak/btso0PzWMyc/sCkAwKOEjqsD4fBDNoD5SK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UoHak/btso0PzWMyc/sCkAwKOEjqsD4fBDNoD5SK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UoHak/btso0PzWMyc/sCkAwKOEjqsD4fBDNoD5SK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUoHak%2Fbtso0PzWMyc%2FsCkAwKOEjqsD4fBDNoD5SK%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;550&quot; height=&quot;412&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;958&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외래키는 중복돼도 무방하다. 위 그림을 보면 외래키가 어떻게 사용되는지 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;후보키(candidate key)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본키가 될 수 있는 후보들이며 유일성과 최소성을 동시에 만족한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대체키(alternate key)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후보키가 두 개 이상일 경우 어느 하나를 기본키로 지정하고 남은 후보키들을 말한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;슈퍼키 (super key)&amp;nbsp;&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;</description>
      <category>면접 준비</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/479</guid>
      <comments>https://dreamcode.tistory.com/479#entry479comment</comments>
      <pubDate>Fri, 21 Jul 2023 22:05:57 +0900</pubDate>
    </item>
    <item>
      <title>면접을 위한 CS 전공 지식 노트-[3.4 CPU 스케줄링 알고리즘]</title>
      <link>https://dreamcode.tistory.com/477</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAmarO/btsn9UojKtI/afysQFUtk0Xn3Bxm6MjezK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAmarO/btsn9UojKtI/afysQFUtk0Xn3Bxm6MjezK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAmarO/btsn9UojKtI/afysQFUtk0Xn3Bxm6MjezK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAmarO%2Fbtsn9UojKtI%2FafysQFUtk0Xn3Bxm6MjezK%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;944&quot; height=&quot;222&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;222&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;CPU 스케줄링 알고리즘이 어떤 프로그램에 CPU 소유권을 줄 것인지 결정을 한다. 이 알고리즘은 CPU 이용률은 높게, 주어진 시간에 많은 일을 하게, 준비 큐에 있는 프로세스는 적게, 응답 시간은 짧게 설정하는 것을 목표로 한다.&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;3.4.1 비선점형 방식(non-preemptive)&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비선점형 방식은 프로세스가 스스로 CPU 소유권을 포기하는 방식이다. 강제로 프로세스를 종료하지 않기 때문에 context switching에 따른 부하 적다.&lt;/p&gt;
&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;FCFS(First Come, First Served)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 온 것을 가정 먼저 처리하는 알고리즘이다. 길게 수행되는 프로세스 때문에 준비 큐에서 오래 기다리는 현상(convoy effect)이 발생하는 단점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SJF (Shortest&amp;nbsp; Job First)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 시간이 가장 짧은 프로세스를 먼저 실행하는 알고리즘이다. 긴 시간을 가진 프로세스가 실행되지 않는 현상(starvation)이 일어나며 평균 대기 시간이 가장 짧다. 하지만 &lt;b&gt;실제로 실행 시간을 알 수 없기 때문에 과거의 실행했더 시간을 토대로 추측해서 사용한다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선순위&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜된 작업일 수록 우선순위를 높이는 방법을 통해 SJF의 프로세스가 길면 실행되지 않는 단점을 보완한 것이다.&amp;nbsp;&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;&lt;b&gt;3.4.2&amp;nbsp; 선점형 방식(preemptive)&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선점형 방식(preemptive)은 지금 사용하고 있는 프로세스를 알고리즘에 의해 중단시켜 버리고 강제로 다른 프로세스에 CPU 소유권을 할당하는 방식이다. (현대 운영체제에서 사용하고 있는 방식)&lt;/p&gt;
&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;라운드 로빈 (RR, Round Robin)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 컴퓨터가 쓰는 스케줄링인 우선순위 스케줄링(priority scheduling)의 일종이다. 각 프로세스는 동일한 할당 시간을 주고 그 시간에 끝나지 않으면 다시 준비 큐(ready queue)의 뒤로 가는 알고리즘이다.&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;ex) x 만큼의 할당 시간이 부여되고, N 개의 프로세스가 운영된다고 하면 (N -1) * x 시간이 지나면 차례가 오게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;할당 시간이 너무 크면 FCFS가 되고 짧으면 컨텍스트 스위칭이 잦아져서 비용이 커진다. 전체 작업 시간은 길지만 응답 시간은 짧다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로드벨런서에서 트래피 분산 알고리즘으로도 쓰인다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SRF&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SJF와 달리 중간에 더 짧은 프로세스가 들어오면 실행을 중단하고 해당 프로세스를 수행하는 알고리즘이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다단계 큐&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위에 따른 준비 큐를 여러 개 사용하고, 큐마다 라운드 로빈이나 FCFS 드 다른 스케줄링 알고리즘을 적용한 것을 말한다. 큐 간 프로세스 이동은 X, 스케줄링 부담이 적음, 그래서 유연성이 떨어진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접 준비</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/477</guid>
      <comments>https://dreamcode.tistory.com/477#entry477comment</comments>
      <pubDate>Tue, 18 Jul 2023 22:31:07 +0900</pubDate>
    </item>
    <item>
      <title>면접을 위한 CS 전공 지식 노트-[3.2 메모리]</title>
      <link>https://dreamcode.tistory.com/473</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3.2.1 메모리 계층&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 계층은 register, cache, Main memory, Storage&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bT6eau/btsmZfvAfzq/Kl07E2A2j25wKsxG9epOrk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bT6eau/btsmZfvAfzq/Kl07E2A2j25wKsxG9epOrk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bT6eau/btsmZfvAfzq/Kl07E2A2j25wKsxG9epOrk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbT6eau%2FbtsmZfvAfzq%2FKl07E2A2j25wKsxG9epOrk%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;523&quot; height=&quot;234&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;150&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;register: CPU 안에 있는 작은 메모리, 휘발성, 속도 가장 빠름,&amp;nbsp; 기억 용량이 가장 적다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Cache: L1,L2 ,캐시를 지칭한다. 휘발성, 속도 빠름,&amp;nbsp; 기억 용량이 적다. L3 캐시도 존재&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Main Memory: RAM을 지칭, 휘발성, 속도 보통,&amp;nbsp; 기억 용량이 보통&amp;nbsp;&lt;/li&gt;
&lt;li&gt;보조기억장치: HDD, SSD를 말한다. 비휘발성, 속도 낮음, 기억 용량이 많다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정량의 데이터를 하드디스크로부터 복사 =&amp;gt; CPU에게 전달하는 역할을 담당한다.&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;- 로딩 중은 RAM이 전송 중이란 의미이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시 (Cache):&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;미리 저장해놓는 임시 저장소이다. 빠른 장치와 느린 장치에서 속도 차이에 따른 병목 현상을 줄이기 위한 메모리이다.&lt;br /&gt;- 데이터 접근 시간 절약&amp;nbsp;&lt;br /&gt;- 계산 횟수 감소&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐싱 계층&lt;/b&gt;: 계층과 계층 사이의 있는 계층을 의미하며, 메모리와 CPU 사이의 극심한 속도차를 register를 두어 해결하는 것을 말한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지역성의 원리&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;자주 사용하는 데이터 위주로 접근을 하는 것&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;b&gt;시간 지역성:&lt;/b&gt; 최근에 사용한 데이터에 다시 접근하려는 특성을 말한다.ex) for문에선 &quot;i&quot;에 반복해서 접근을 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공간 지역성:&lt;/b&gt; 최근에 접근한 데이터를 이루고 있는 공간이나 그 가까운 공간에 접근하는 특성을 말한다. ex) 배열에 연속적으로 접근하는 것을 의미한다.&amp;nbsp;&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;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;: 캐시에서 원하는 데이터를 찾았을 때 제어장치를 거쳐서 가져오게 되고, CPU 내부 버스 기반으로 작동하기 때문에 빠르다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시미스&lt;/b&gt;: 찾는 데이터가 캐시 없을 때 주 메모리에 다시 찾아오는 것 시스템 버스 가빈이기 때문에 느리다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시매핑&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;캐시가 히트되기 위해 매핑하는 방법을 말한다. CPU의 register와 RAM 간 데이터 교환에 기반해서 설명한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- RAM은 register에 비해 크기 때문에 register가 캐시 계층으로&amp;nbsp; 역할을 잘 수행하기 위해 매핑법이 중요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;b&gt;이름&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;직접 매핑(directed mapping)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;메모리 1~100/캐시 1~10이면 1:1~10,2:1~20식의 매핑을 의미한다. 처리는 빠르지만 충돌이 잦다.&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;연관 매핑(associative mapping)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;순서를 일치시키지 않고 관련 있는 캐시와 메모리를 매핑한다.&amp;nbsp; 충돌은 적음, but 전체 블록 탐색을 하기에 slow&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;집합 연관 매핑(set associative mapping)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;직접 매핑 + 연관 매핑 =&amp;gt; 순서 일치 + 집합을 뒤서 블록으화되어 저장&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;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;쿠키&amp;nbsp;&lt;/li&gt;
&lt;li&gt;로컬 스토리지&amp;nbsp;&lt;/li&gt;
&lt;li&gt;세션 스토리지&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 컴스텀 정보나 인증 모듈 관련 사항들을 웹 브라우저에 저장해서 추후 서버에 요청할 때 아이덴티티나 중복 요청 방지를 위해 쓰인다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿠기&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;만료기한이 있는 키-값 저장소이다. same site 옵션을 strict로 설정하지 않으면 다른 도메인 요청시 자동 전송된다. 4KB까지 데이터 저장이 가능하며, 만료기한 설정도 가능하다. 쿠키 설정시 document.cookie로 쿠키를 볼 수 없게 httponly 옵션을 거는 게 중요하다. 보통 서버에서 만료 기한을 정한다.&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;&lt;b&gt;로컬 스토리지&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;로컬 스토리지는 만료기한이 없는 키-값 저장소이다. 10MB까지 저장할 수 있으며, 웹 브라우저를 닫아도 유지되며, 도메인 단위로 저장/생성이 된다. HTML5에서만 가능하며, 클라이언트만 수정 가능하다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션 스토리지&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;세션 스토로지는 만료기한이 없는 키-값 저장소이다. 탭 단위로 생성/닫으면 데이터가 삭제된다. 5MB까지 저장이 가능하며, HTML5에서만 가능하다. 클라이언트에서만 수정이 가능하다.\&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;&lt;b&gt;데이터베이스 캐시&amp;nbsp; 계층&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 시스템을 구할 때 메인 데이터베이스 위에 redis 데이터베이스 계층을 &quot;캐싱 계층&quot;으로 둬서 성능을 향상하기도 한다.&amp;nbsp;&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;&lt;b&gt;3.2.2 메모리 관리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS의 대표적인 업무가 메모리 관리이다. 컴퓨터의 한정된 메모리를 극한으로 사용해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가상 메모리(virtual memory)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메모리 관리 기업 중 하나로 컴퓨터가 실제로 이용 가능한 메모리 자원을 추상화하여 이를 사용하는 사용자들에게 매우 큰 메모리로 보이게 만드는 것을 말한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 가상 주소(logical address): 가상적으로 주어진 주소를 뜻한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실제 주소(physical address):실제 메모리 상에 있는 주소를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 주소는 가상 메모리 관리 장치 (MMU)에 의해 실제 주소로 변환되기 때문에 신경쓰지 않고 프로그램 구축이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;용어&lt;br /&gt;- TLB:&amp;nbsp;&lt;/b&gt;메모리 CPU 사이에 있는 주소 변환을 위한 캐시이다. 페이지 테이블에 있는 리스트를 보관, CPU가 페이지 테이블까지 가지 않도록 해 속도를 향상시킬 수 있는 캐시 계층이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스와핑&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메모리에 당장 사용하지 않는 영역을 하드디스크로 옮기고 하드디스크의 일부분을 마치 메모리처럼 불러와 쓰는 것&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리에는 존재하지만 실제 메모리인 RAM에는 현재 없는 데이터나 코드에&amp;nbsp; 접근할 경우 &lt;b&gt;페이지 폴트가&lt;/b&gt; 발생하며, 이를 해결하기 위해 스와핑을 적용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이지 폴트(page fault)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로세스의 주소 공간에는 존재하지만 지금 이 컴퓨터의 RAM에는 없는 데이터에 접근햇을 경우 발생한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;과정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. CPU는 물리 메모리를 확인하여 해당 페이지가 없으면 트랩을 발생해서 OS에 알린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. OS는 CPU의 동작을 잠시 stop!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. OS는 페이지 테이블을 확인하여 가상 메모리에 페이지가 존재하는지 확인 =&amp;gt; 없으면 프로세스 중단 및 비어있는 물리 메모리 프레임을 찾음 =&amp;gt; 그래도 없으면 스와핑 발동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 비어 있는 프레임에 해당 페이지를 로드하고, 페이지 테이블 최신화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 중단됐던 CPU 다시 가동&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;용어&lt;br /&gt;&lt;/b&gt;- 페이지(page): 가상 메모리를 사용하는 최소 크기 단위&amp;nbsp;&lt;br /&gt;- 프레임(frame): 실제 메모리를 사용하는 최소 크기 단위&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스레싱(thrashing)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메모리 페이지 풀트율이 높은 것을 의미하며, 컴퓨터의 심각한 성능 저하를 초래한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c212VN/btsngMySKtr/l1ArXzkEHh3EG4HkqcZFN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c212VN/btsngMySKtr/l1ArXzkEHh3EG4HkqcZFN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c212VN/btsngMySKtr/l1ArXzkEHh3EG4HkqcZFN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc212VN%2FbtsngMySKtr%2Fl1ArXzkEHh3EG4HkqcZFN0%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;402&quot; height=&quot;168&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레싱은 메모리에 너무 많은 프로세스가 동시에 올라가게 되면 스와핑이 많이 일어나서 발생하는 것이다.&amp;nbsp; 페이지 폴트가 발생하면 CPU 이용율이 낮아진다 =&amp;gt; OS는 CPU 가용성을 높이기 위해 더 많은 프로세스를 메모리에 올리게 된다. 이 악순화이 반복되면 스레싱이 일어난다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결법&amp;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;/li&gt;
&lt;li&gt;HDD =&amp;gt; SDD로 변경&lt;/li&gt;
&lt;li&gt;OS
&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;PFF&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작업 세트(working set)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로세스 과거 사용 이력인 지역성을 통해 결정된 페이지 집합을 만들어서 미리 메모리에 로드하는 것. 미리 올림에 따라 탐색 비용/스와핑 감소&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PFF (Page Fault Frequency)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;페이지 폴트 빈도를 조절하는 방법으로 상하선과 하한선을 만드는 방법이다. 상한선에 도달하면 프레임을 늘리고, 하한선에 도달한다면 프레임을 줄이는 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메모리 할당&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에 프로그램을 할당할 때는 &lt;b&gt;시작 메모리 위치,&lt;/b&gt; &lt;b&gt;메모리의 할당 크기를&lt;/b&gt; 기반으로 할당한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;연속 할당&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;연속 할당은 메모리에 '연속적으로' 할당하는 것을 의미한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 A,B,C가 있을 때 순차적으로 공간에 할당하는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;b&gt;고정 분할 방식(fixed partition allocation):&lt;/b&gt;메모리를 미리 나누어 관리하는 방식이다. 미리 나누기 때문에 가변적이지 않고, 내부 단편화가 발생한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가변 분할 방식(variable partition allocation):&amp;nbsp;&lt;/b&gt;매 시점 프로그램의 크기에 맞게 동적으로 메모리를 나눠서 사용한다. 내부 단편화는 발생하지 않고, 외부 단편화는 발생할 수 있다. 최초적합(first fit), 최적적합(best fit), 최악적합(worst fit)이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50.1163%;&quot;&gt;&lt;b&gt;이름&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.8837%;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50.1163%;&quot;&gt;최초적합&lt;/td&gt;
&lt;td style=&quot;width: 49.8837%;&quot;&gt;위쪽이나 아래쪽부터 시작해서 홀을 찾으면 바로 할당한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50.1163%;&quot;&gt;최적적합&lt;/td&gt;
&lt;td style=&quot;width: 49.8837%;&quot;&gt;프로세스의 크기 이상인 공간 중 가장 작은 홀부터 할당한다.&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50.1163%;&quot;&gt;최악적합&lt;/td&gt;
&lt;td style=&quot;width: 49.8837%;&quot;&gt;프로세스의 크기와 가장 많이 차이가 나는 홀에 할당한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;용어 정리&amp;nbsp;&lt;br /&gt;- 내부 단편화(internal fragmentation):&lt;/b&gt; 메모리를 나눈 크기보다 프로그램 작아서 들어가지 못하는 공간이 많이 발생하는 현상&lt;br /&gt;&lt;b&gt;- 외부 단편화(external fragmentation):&amp;nbsp;&lt;/b&gt;메모리를 나눈 크기보다 프로그램이 커서 들어가지 못하는 공간이 많이 발생하는 현상, 예를 들어 100MB를, 50MB로 나눴지만 프로그램의 크기를 70MB일 때 들가지 못한다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;- 홀 (hole):&lt;/b&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;&lt;b&gt;불연속 할당&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;현대 OS가 쓰는 방법으로 불연속 할당인 페이지 기법이 있다.&lt;/blockquote&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;메모리를 동일한 크기의 페이지(보통 4KB)로 나눠서 프로그램마다 페이지 테이블을 두어 이를 기반으로 메모리에 할당하는 것을 의미! (그 외에 세크멘테이션, 페이지드 세그멘테이션 등 기법들이 있다)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이징(paging)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;동일한 크기의 페이지 단위로 나누어 &lt;b&gt;메로리의 서로 다른 위치에 프로세스를 할당한다&lt;/b&gt;.&amp;nbsp;&amp;nbsp;&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;&lt;b&gt;세그멘테이션(segmentation)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 단위가 아닌 의미 단위인 세그먼트(segment)로 나누는 방식을 의미한다. &lt;b&gt;프로세스는 코드, 데이터, 스택, 힙&lt;/b&gt; 등으로 로 이루어진다. 코드와 데이터 등을 기반으로 나눌 수 있고, 함수 단위로 나눌 수도 있다. 보안에는 좋지만 홀의 크기가 균일하지 않게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이지 세그멘테이션(page segmentation)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공유나 보안을 의미 단위의 세크먼트로 나누고, 물리적 메모리는 페이지로 나누는 것을 말한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이지 교체 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리는 한정되어 있기 때문에 스와핑이 많이 일어난다. 스와핑은 말이 일어나지 않도록 설계하는 것이 중요하며, 스와핑을 페이지 교체 알고리즘을 기반으로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오프라인 알고리즘 (offline algorithm)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼 미래에 참조되는 페이지와 현재 할당하는 페이지를 바꾸는 알고리즘이다. 비록, 미래 사용할 페이지를 알 수 없어 사용이 어렵지만, 다른 알고리즘과의 성능 비교의 기준점을 제시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FIFO&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 온 페이지를 교체 영역에 가장 먼저 놓는 방법을 의미한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LRU (Least Rcently Used)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조가 가장 오래된 페이지를 바꾼다. 오랜된 페이지를 파악하기 위해&amp;nbsp; 각 페이지마다 계수기, 스택을 두어야 하는 문제점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LRU를 구현할 때 보통 두 개의 자료구조를 사용한다. 해시 테이블 + 이중 연결 리스트 이다. 해시 테이블은 이중 연결 리스트에서 검색의 속도를 높이고, 이중 연결 ㅅ리시트는 한정된 메로리를 나타낸다.&lt;/p&gt;
&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;NUR(Not used Recently)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LRU에서 발전한 형태이다. clock 알고리즘이라고도 하며, 먼저 0과 1을 가진 비트를 둔다. 1은 최근에 참조되었고 0은 참조 되지 않았음을 의미한다. 시계 방향으로 돌면서 0을 찾고 0을 찾은 순간 해당 프로세스를 교체하면 1로 변경한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LFU(Least Frequently USed)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 참조 횟수가 적은 페이지를 교체한다. 즉, 많이 사용되지 않은 것을 교체하는 것!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접 준비</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/473</guid>
      <comments>https://dreamcode.tistory.com/473#entry473comment</comments>
      <pubDate>Sun, 9 Jul 2023 16:08:46 +0900</pubDate>
    </item>
    <item>
      <title>면접을 위한 CS 전공 지식 노트-[3.1 운영체제와 컴퓨터]</title>
      <link>https://dreamcode.tistory.com/472</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;3.1.1 운영체제의 역할과 구조&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;운영체제의 역할&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제의 역할은 크게 네 가지가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;cpu 스케줄링과 프로세스 관리:&lt;/b&gt; cpu 소유권 할당, 프로세스의 생성/삭제, 자원 할당 및 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;&lt;b&gt;메모리 관리:&amp;nbsp;&lt;/b&gt;한정된 메모리를 어떤 프로세스에 얼마큼 할당해야 하는지 관리합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&amp;nbsp;&lt;b&gt;디스크 파일 관리:&amp;nbsp;&lt;/b&gt;디스크 파일을 어떠한 방법으로 보과할지 관리한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;b&gt;I/O 디바이스 관리:&amp;nbsp;&lt;/b&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;&lt;b&gt;운영체제의 구조 (참고: GUI가 없고, CUI만 있는 리눅스 서버도 존재한다)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FDKf9/btsmOz17vN8/4Hc96sgzKjyK1HvKhJ67J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FDKf9/btsmOz17vN8/4Hc96sgzKjyK1HvKhJ67J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FDKf9/btsmOz17vN8/4Hc96sgzKjyK1HvKhJ67J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFDKf9%2FbtsmOz17vN8%2F4Hc96sgzKjyK1HvKhJ67J1%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;305&quot; height=&quot;323&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;363&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;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;용어&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;- GUI:&lt;/b&gt; 사용자가 전자장치와 상호 작용할 수 있도록 하는 사용자 인터페이스의 한 형태이다. 단순 명령어창이 아닌, 아이콘으로 마우스 클릭하는 단순한 동작으로 컴퓨터와 상호작용이 가능하다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;- 드라이버:&lt;/b&gt; 하드웨어를 제어하기 위한 소프트웨어&lt;br /&gt;&lt;b&gt;- CUI:&lt;/b&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;&lt;b&gt;시스템콜&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;운영체제가&amp;nbsp;&lt;b&gt;커널&lt;/b&gt;에 접근하기 위한 인터페이스, 유저 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출할 때 사용한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약: 유저 프로그램 =&amp;gt; 시스템 콜(거쳐서) =&amp;gt; 커널로 가는 중간 다리 역할(인터페이스) &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bi8Mb/btsmRqhNZgb/dDOTEPKLru18QBX5del0m0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bi8Mb/btsmRqhNZgb/dDOTEPKLru18QBX5del0m0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bi8Mb/btsmRqhNZgb/dDOTEPKLru18QBX5del0m0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBi8Mb%2FbtsmRqhNZgb%2FdDOTEPKLru18QBX5del0m0%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;362&quot; height=&quot;254&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;351&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;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;용어&lt;/span&gt;&lt;br /&gt;- I/O 요청: 입출력 함수, 데이터베이스, 네트워크, 파일 접근 등에 관한 일&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjSDNP/btsmR8gUkz0/koUkIlsP7YCFJBRSLIvtz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjSDNP/btsmR8gUkz0/koUkIlsP7YCFJBRSLIvtz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjSDNP/btsmR8gUkz0/koUkIlsP7YCFJBRSLIvtz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjSDNP%2FbtsmR8gUkz0%2FkoUkIlsP7YCFJBRSLIvtz1%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;462&quot; height=&quot;304&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림처럼 프로세스나 스레드에서 운영체제로 어떠한 요청을 할 때 &lt;b&gt;시스템콜이라는 인터페이스와 커널을&lt;/b&gt; 거쳐서 가게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템콜은 하나의 추상화 계층이다. 따라서, 네트워크 통신 + 데이터베이스와 같은 낮은 단계의 영역 처리에 대해 많이 신경쓰지 않고 프로그램을 구현할 수 있는 장점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;modebit&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템콜이 작동될 때 modebit을 참고해서 유저 모드와 커널 모드를 구분한다. modebit은 1 또는 0의 값을 가지는 플래그 변수이다. 카메라, 키도드 등 I/O 디바이스는 운영체제를 통해서만 작동해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 카메라를 키는 프로그램이 있다고 했을 때 유저 모드를 기반으로 카메라가 켜진다면, 공격자가 사용자의 의도와 관계없이 카메라를 킬 수 있다. (커널 모드를 거쳐 OS에 오면 비교적 더 안전하게 보호할 수 있다) 이 기능을 도와주는 장치가 바로 modebit이다. modebit의 0 === 커널모드, 1 === 유저 모드&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buQ0MA/btsmRNxdJDk/lTtfcVBaAH2shNKxkKtMz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buQ0MA/btsmRNxdJDk/lTtfcVBaAH2shNKxkKtMz0/img.png&quot; data-alt=&quot;modebit의 역할&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buQ0MA/btsmRNxdJDk/lTtfcVBaAH2shNKxkKtMz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuQ0MA%2FbtsmRNxdJDk%2FlTtfcVBaAH2shNKxkKtMz0%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;684&quot; height=&quot;357&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;modebit의 역할&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;용어&lt;br /&gt;&lt;/b&gt;-&amp;nbsp;&lt;b&gt;유저 모드:&amp;nbsp;&lt;/b&gt;유저가 접근할 수 있는 영역을 제한적으로 두 컴퓨넡 자원에 함부로 침범할 수 없는 모드&lt;br /&gt;-&lt;b&gt; 커널 모드:&amp;nbsp;&lt;/b&gt;모든 컴퓨터 자원에 접근할 수 있는 모드&amp;nbsp;&lt;br /&gt;-&amp;nbsp;&lt;b&gt;커널:&amp;nbsp;&lt;/b&gt;운영체제의 핵심 부분이자 시스템콜 인터페이스를 제공하며 보안, 메모리, 프로세스, 파일 시스템, I/O 디바이스, I/O 디바이스, I/O 요청 관리 등 운영체제의 중추적인 역할을 한다.&amp;nbsp;&lt;/blockquote&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;3.1.2 컴퓨터의 요소&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는&amp;nbsp;&lt;b&gt;CPU, DMA 컨트롤러, 메모리, 타이머, 디바이스 컨트롤러 등&lt;/b&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be8dFa/btsmQPwu0TQ/b9CHzQDrFRKsdpYOZkhzN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be8dFa/btsmQPwu0TQ/b9CHzQDrFRKsdpYOZkhzN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be8dFa/btsmQPwu0TQ/b9CHzQDrFRKsdpYOZkhzN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe8dFa%2FbtsmQPwu0TQ%2Fb9CHzQDrFRKsdpYOZkhzN0%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;413&quot; height=&quot;243&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU (Central Processing Unit)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;산술논리연산장치(ALU), 제어장치(CU), 레지스터(register)로 구성된 컴퓨터 장치를 말한다. interrupt에 의해 단순히 메모리에 존재하는 명령어를 해석해서 실행하는 일꾼이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU는 일꾼이며 kernel은 관리자!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 역할을 하는 운영체제의 커널이 프로그램을 메모리에 올려 프로세스로 만들면 일꾼인 CPU가 이를 처리한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제정장치(CU)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로세스 조작을 지시하는 CPU의 부품이다. (입출력 장치 간 통신 제, 명령어들 해석, 순서 지정)&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레지스터 (Register)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;CPU 안에 있는 매우 빠른 임시기억장치이다. CPU와 직접 연결돼 있기 때문에 메모리보다 수십~백배 빠르다. CPU는 자체적으로 데이터를 저장할 방법 X 레지스터를 거쳐 데이터를 전달한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;산술논리연산장치(ALU)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;덧셈, 뺼셈, 두 자리 수의 연산과 배타적 논리합 (XOR), 논리곱 등 논리 연산을 계산하는 &lt;b&gt;디지털 회로이다&lt;/b&gt;.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU의 연산 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n7ZV2/btsmUwCFzR8/aRD1KfIxOLf3iDR9h8RMKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n7ZV2/btsmUwCFzR8/aRD1KfIxOLf3iDR9h8RMKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n7ZV2/btsmUwCFzR8/aRD1KfIxOLf3iDR9h8RMKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn7ZV2%2FbtsmUwCFzR8%2FaRD1KfIxOLf3iDR9h8RMKK%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;591&quot; height=&quot;357&quot; data-origin-width=&quot;1132&quot; data-origin-height=&quot;684&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;CU가 메모리 + 레지스터에 계산할 값을 로드한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;CU가 register에 있는 값을 계산하라고 ALU에 명령한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;CU가 계산된 ㄱ밧을 다시 register 메모리로 계산한 값을 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Interrupt&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;어떤 신호가 들어왔을 때 CPU를 잠깐 정지시키는 것을 말한다.&amp;nbsp;&amp;nbsp;&lt;/blockquote&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;Interrupt가 발생하면 interrupt handler 함수가 모여 있는 interrupt vector로 가서 interrupt handler function이 실행된다. Interrupt 간에는 우선순의가 있고, 그것에 따라 실행된다.&lt;/p&gt;
&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;Interrupt 종류&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;Software Interrupt:&amp;nbsp;&lt;/b&gt;Trap이라고 하며, 프로세스 오류 등 프로스세가 시스템 콜을 호출할 때 발동한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hardware Interrupt:&amp;nbsp;&lt;/b&gt;IO 디바이스에서 발생하는 interrupt를 의미한다. interrupt 라인이 설계 된 후 순차적인 interrupt 실행을 중지하고, 운영체제에 있는 시스템콜을 요청해 원하는 디바이스로 향한다. 디바이스에 있는 작은 로컬 버퍼에 직접 접근해서 일을 수행한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;용어 정리 &lt;/span&gt;&lt;br /&gt;- Interrupt Handler Function: Interrupt가 발생했을 때 헨들링하는 함수. (커널 내부의 IRQ를 통해 호출되며, request_irq()를 통해 interrrupt handler function 함수 등록 가능&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DMA 컨트롤러&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DMA 컨트롤러는 IO 디바이스가 메모리에 직접 접근할 수 있도록 하는 하드웨어 장치를 뜻한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기능:&amp;nbsp;&lt;/b&gt;CPU에만 interrupt 요청이 들어오기 때문에 CPU 부하를 막아주며 CPU의 일을 부담하는 보조 일꾼으로 보면 된다. (CPU + DMA가 하나의 작업을 담당하는 것도 방지한다)&lt;/p&gt;
&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;Memory&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전자회로에서 데이터나 상태, 명령어 등을 기록하는 장치이다. 보통 RAM (Random Access Memory)을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU는 계산을&lt;/b&gt; 담당하고, &lt;b&gt;메모리는 기억을&lt;/b&gt; 담당한다.&amp;nbsp;&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;CPU: 일꾼&lt;/li&gt;
&lt;li&gt;Memory: 작업장 (작업장 크기 = == Memory 크기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RAM (Random Access Memory):&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAM은 주기억장치에 해당한다. RAM은 컴퓨터가 켜진 동안만 사용이 가능하며, 전원이 차단되면 모든 데이터가 손실된다. 따라서, RAM은 휘발성 메모리로 분류되며, delete/Write가 가능하다. RAM은 주로 실행 중인 프로그램, 작업 파일, 프로세스의 정보 및 시스템 운영체제에 의해 사용된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;타이머 (Timer)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;nbsp;몇 초 안에 작업이 끝나야 한다는 것을 정하고 특정 프로그램에 시간 제한을 다는 역할을 한다.&amp;nbsp;&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;&lt;b&gt;디바이스 컨트롤러 (Device Controller)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴퓨터와 연결되어 있는 IO 디바이스들의 작은 CPU를 말한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접 준비</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/472</guid>
      <comments>https://dreamcode.tistory.com/472#entry472comment</comments>
      <pubDate>Fri, 7 Jul 2023 21:19:18 +0900</pubDate>
    </item>
    <item>
      <title>면접을 위한 CS 전공 지식 노트-[2.5 HTTP]</title>
      <link>https://dreamcode.tistory.com/469</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 애플리케이션 계층에 속하며, 웹 서비스 통신에 사용된다. HTTP/1.0부터 발전해 HTTP/까지 이어져 왔다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.5.1 HTTP/1.0&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/1.0은 한 연결 당 하나의 요청만 처리 가능하다. (RTT 증가 초래)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;용어정리&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;RTT(Round Trip Time):&amp;nbsp;&lt;/b&gt;패킷망(인터넷)에서 패킷을 보내고자 할 때 패킷이 목적지에 도달한 후 패킷에 대한 응답이 다시 출발지로 돌아오기까지의 시간이다. (&lt;b&gt;패킷 &lt;/b&gt;&lt;b&gt;왕복 시간)&lt;/b&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;인코딩: &lt;/b&gt;정보의 형태나 형식을 표준화, 보안, 처리 속도 향상, 저장 공간 절약 등을 위해&amp;nbsp; 다른 형태나 형식으로 변환하는 처리 방식&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLBpOA/btslZ2KLGQK/YWm2ra7zKOIXkkX0KWapPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLBpOA/btslZ2KLGQK/YWm2ra7zKOIXkkX0KWapPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLBpOA/btslZ2KLGQK/YWm2ra7zKOIXkkX0KWapPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLBpOA%2FbtslZ2KLGQK%2FYWm2ra7zKOIXkkX0KWapPk%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;424&quot; height=&quot;411&quot; data-origin-width=&quot;228&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버로부터 파일을 가져올 때마다 TCP의 3 way-handshake를 해야 하기 때문에 RTT가 증가한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RTT의 증가를 해결하기 위한 방법&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;이미지 스플링팅&amp;nbsp;&lt;/li&gt;
&lt;li&gt;코드 압축&amp;nbsp;&lt;/li&gt;
&lt;li&gt;이미지 Base64 인코딩 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이미지 스플링팅&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 이미지를 다운 받으면 과부하가 걸리기 때문에 합쳐 있는 하나의 이미지로 다운을 받는다. 이를 기반으로 background-image의 position을 이용해 이미지를 표기하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 압축&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 압축해 개행 문자, 빈칸을 업애서 코드의 크기를 최소화하는 방법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이미지 Base64 인코딩&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;이미지 파일을 64진번으로 이루어진 문자열로 인코딩하는 방법이다. 서버와의 연결을 열고 이미지에 대해 서버에 &lt;b&gt;HTTP 요청을 할 필요가 없다는&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;하지만 Base64 문자열로 변환할 경우 37% 정도 크기가 더 커지는 단점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.5.2 HTTP/1.1&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/1.0의 발전된 형태가 곧 HTTP/1.1이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개선된 점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 TCP 연결을 하는 것이 아닌, 한 번 TCP 초기화 한 후 keep-alive라는 옵션으로 여러 개의 파일을 송수신할 수 있게 바뀐 것이다. HTTP/1.0에도 keep-alive가 있었지만 표준화X&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;783&quot; data-origin-height=&quot;461&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXin4k/btslZ0THDHB/YYKfUkYmKjBO1PoVeA0om1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXin4k/btslZ0THDHB/YYKfUkYmKjBO1PoVeA0om1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXin4k/btslZ0THDHB/YYKfUkYmKjBO1PoVeA0om1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXin4k%2FbtslZ0THDHB%2FYYKfUkYmKjBO1PoVeA0om1%2Fimg.webp&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;642&quot; height=&quot;378&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;461&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서 확인할 수 있듯이 HTTP/1.1의 경우 TCP 3-웨이 핸드셰이크가 발생하면 그 다음부터는 발생하지 않는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서 안에 포함된 다수의 리소스(이미지, src 등)를 처리하면 요청할 리소스 개수에 비례해서 대기 시간이 길어진다는 문제점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HOL Blocking (Head of Line Blocking)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;네트워크에서 같은 큐에 있는 패킷이 그 첫 번째 패킷에 의해 지연될 때 발생하는 성능 저하 현상을 말한다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCIs2p/btsmiHkpdP7/KN9Qm7PxrwVLpRMxUUWDxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCIs2p/btsmiHkpdP7/KN9Qm7PxrwVLpRMxUUWDxK/img.png&quot; data-alt=&quot;ㅟ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCIs2p/btsmiHkpdP7/KN9Qm7PxrwVLpRMxUUWDxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCIs2p%2FbtsmiHkpdP7%2FKN9Qm7PxrwVLpRMxUUWDxK%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;470&quot; height=&quot;163&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;132&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;위 사진에서 볼 수 있는 것처럼 image.jpg를 다운 받는 속도가 느려진다면 그 뒤에 있는 것들도 자연스럽게 느려지게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무거운 헤더 구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/1.1 헤더에는 쿠키 등 많은 메타데이터가 들어 있고, 또 압축되지 않아 무겁다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.5.3 HTTP/2&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;HTTP/2는 SPDY 프로토콜에서 파생된 HTTP/1.x보다 지연 시간을 줄이고, 응답 시간을 더 빠르게 할 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/li&gt;
&lt;li&gt;헤더 압축&lt;/li&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;&lt;b&gt;멀티플렉싱&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;여러 개의 스트림을 사용하여 송수신한다는 것. 따라서, 특정 스트림의 패킷이 손실되더라도 다른 스트림에 영향X&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;용어 정리&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;스트림(stream): 시간이 자님에 따라 사용할 수 있게 되는 일련의 데이터 요소를 가리키는 데이터의 흐름&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N0LlW/btsl6VYvlGA/PAMKLDv5aknobVd4wuxzA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N0LlW/btsl6VYvlGA/PAMKLDv5aknobVd4wuxzA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N0LlW/btsl6VYvlGA/PAMKLDv5aknobVd4wuxzA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN0LlW%2Fbtsl6VYvlGA%2FPAMKLDv5aknobVd4wuxzA1%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;448&quot; height=&quot;112&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 연결 내 여러 스트림을 캡쳐한 모습이다. 병렬적인 스트림들을 통해 데이터를 서빙하고 있다. 애플리케이션에서&amp;nbsp; 받아온 메시지를 독립된 프레임으로 조각내어 서로 송수신 한 후 다시 조립하며 데이터를 주고 받는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;264&quot; data-origin-height=&quot;191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bruJvQ/btsl4maVda4/9dhxnQUnKm7zLtdFKdIyp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bruJvQ/btsl4maVda4/9dhxnQUnKm7zLtdFKdIyp1/img.png&quot; data-alt=&quot;데이터를 쪼갠 후 다시 조립&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bruJvQ/btsl4maVda4/9dhxnQUnKm7zLtdFKdIyp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbruJvQ%2Fbtsl4maVda4%2F9dhxnQUnKm7zLtdFKdIyp1%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;264&quot; height=&quot;191&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;191&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;단일 연결을 사용해 병렬로 여러 요청/응답을 할 수 있다. HTTP/1.X에 있던 HTL Blocking&amp;nbsp; 문제를 해결할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;헤더 압축&lt;/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;HTTP/1.x 헤더 크기가 크다는 문제가 있었다.&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;HTTP/2에선 허프만 코딩 압축 알고리즘을 사용하는 HPACK 압축 형식을 가진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;허프만 코딩 (huffman coding)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;문자열 단위로 쪼개 빈도수를 세어 빈도가 높은 정보는 적은 비트 수를 사용하여 표현하고, 빈도가 낮은 정보는 비트 수를 많이 사용하여 표현한다. (결국, &lt;b&gt;전체적인 표현 양은 감소&lt;/b&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;&lt;b&gt;서버 푸시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/2에서는 클라이언트 요청 없이 서버가 바로 리소스를 푸시할 수 있다.&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;292&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bouds4/btsl2RPLmH1/tpRVNToDzxIqbVmZ2mADt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bouds4/btsl2RPLmH1/tpRVNToDzxIqbVmZ2mADt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bouds4/btsl2RPLmH1/tpRVNToDzxIqbVmZ2mADt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbouds4%2Fbtsl2RPLmH1%2FtpRVNToDzxIqbVmZ2mADt1%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;393&quot; height=&quot;233&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;html에는 CSS나 JS 파일이 포함되기 때문에 html을 읽으면서 그 안에 있던 CSS 파일을 서버에서 푸시하여 클라이언트에 먼저 줄 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.5.4 HTTPS&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;HTTP/2는 HTTPS 위에서 동작한다. 애플리케이션 계층과 전송 계층 사이에 있는 신뢰 계층인 SSL/TLS 계층을 넣은 신뢰할 수 있는 HTTP 요청을 말한다. (통신 암호화를 한다)&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;&lt;b&gt;SSL/TLS (Secure Socket Layer)/Transport Layer Security Protocol)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS 1.3 버전을 기준으로 설명한다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;SSL/TLS는 전송 계층에서 보안을 제공하는 프로토콜이다. client &amp;lt;=&amp;gt; server 통신에서 SSL/TLS를 통해 제3가자 메시지를 도청, 변조하지 못하도록 한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5ZcTi/btsmkM6H02M/2GivZYtf8Rwr34YmOltmjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5ZcTi/btsmkM6H02M/2GivZYtf8Rwr34YmOltmjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5ZcTi/btsmkM6H02M/2GivZYtf8Rwr34YmOltmjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5ZcTi%2FbtsmkM6H02M%2F2GivZYtf8Rwr34YmOltmjk%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;432&quot; height=&quot;243&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;168&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;SSL/TLS는 보안 세션을 기반으로 데이터를 암호화하며, 보안 세션이 만들어질 때 인증 매커니즘, 키 교환 암호화 알고리즘, 해싱 알고리즘 등이 사용된다. .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;용어 정리&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세선:&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 운영체제가 어떠한 사용자로부터 자신의 자산 이용을 허락하는 일정한 기간을 뜻한다. 사용자는 일정 기간 동안 응용 프로그램, 자원 등을 사용할 수 있다.&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TLS Handshake&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp9w27/btsl6NM6XtZ/PFgvwGdobRcjKkwPnVPNJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp9w27/btsl6NM6XtZ/PFgvwGdobRcjKkwPnVPNJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp9w27/btsl6NM6XtZ/PFgvwGdobRcjKkwPnVPNJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp9w27%2Fbtsl6NM6XtZ%2FPFgvwGdobRcjKkwPnVPNJK%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;366&quot; height=&quot;256&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;256&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;클라이언트와 서버와 키를 공유하고 이를 기반으로 인증, 인증 확인 등의 작업이 일어나는 단 한 번의 1-RTT가 생긴 후 데이터 송수신한다.&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;클라이언트에서 사이퍼 슈트(cypher suites)를 서버에 전달한 후 서버는 제공 받은 사이퍼 슈트의 암호화 알고리즘 리스트를 제공할 수 있는지 확인한다.&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사이퍼 슈트&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사이퍼 슈트는 프로토콜, AEAD 사이퍼 모드, 해싱 알고리즘이 나열된 규약을 말한다. &lt;b&gt;5개 존재!&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- TLS_AES_128_GCM_SHA256&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- TLS_AES_256_GCM_SHA384&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- TLS_CHACHA20_POLY1305_SHA256&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- TLS_AES_128_CCM_SHA256&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- TLS_AES_128_CCM_8_SHA256&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ex) TLS_AES_128_GCM에는 세 가지 규약이 존재한다.&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;TLS: 프로토콜&amp;nbsp;&lt;/li&gt;
&lt;li&gt;AES_128_GCM:AEAD 사이퍼 모드&lt;/li&gt;
&lt;li&gt;SHA256: 해싱 알고리즘&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AEAD(Authenticated Encryption with Associated Data) 사이퍼 모드&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;데이터 암호화 알고리즘 AES_128_GCM 등이 있다.&amp;nbsp;&lt;br /&gt;ex) 위 예로 들자면, 128비트의 키를 사용하는 표준 블록 암호화 기술과 병렬 계산에 용이한 암호화 알고리즘 GCM이 결합된 알고리즘을 의미한다.&lt;/blockquote&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;인증 매커니즘은 CA(Certificate Authorities)에서 발급한 인증서를 기반으로 이루어진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CA 인증서는 안전한 연결을 위한 &quot;공개키&quot;를 클라이언트에 제공&lt;/li&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;&lt;b&gt;CA 발급 과정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CA 인증서를 발급 받기 위해서는 사이트 정보 + 공개키를 CA에 제출해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CA는 공개키를 해시한 값인 지문을 사용하는 CA의 비밀키 등을 기반으로 CA 인증서를 발급한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;용어 정리&lt;/span&gt;&lt;br /&gt;&lt;b&gt;개인 키: &lt;/b&gt;비밀키 , 개인 소유하고 있는 키, 반드시 자신만이 소유해야 하는 키&amp;nbsp;&lt;br /&gt;&lt;b&gt;공개 키: &lt;/b&gt;공개되어 있는 키&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;암호화 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;키 교환 알고리즘으로는 대수곡선 기반의 ECDHE (Elloptic Curve Diffie-Hellman Ephermeral) 또는 모듈식 기반의 DHE(Diffie-Hellman Ephermeral)를 사용한다. 둘 다 디피 헬만(Diffie-Hellman) 방식 근간이다.&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;&lt;b&gt;디피-헬만 키 교환 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디피-헬만 키 교환 암호화 알고리즘은 암호키를 교환하는 하나의 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해싱 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;데이터를 추정하기 힘든 더 작고, 섞여 있는 조각으로 만다는 알고리즘이다. (SHA-246,SHA-384 등 사용)&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;&lt;b&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;SHA-246&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;해시 함수의 결과값이 256비트인 알고리즘이다. 해싱을 해야 할 메시지에 1을 추가하는 등 전처리를 하고 전처리된 메시지를 기반으로 해시를 반환한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접 준비</category>
      <author>rickysin</author>
      <guid isPermaLink="true">https://dreamcode.tistory.com/469</guid>
      <comments>https://dreamcode.tistory.com/469#entry469comment</comments>
      <pubDate>Sat, 1 Jul 2023 14:59:01 +0900</pubDate>
    </item>
  </channel>
</rss>