<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>임서인 학습해라</title>
    <link>https://tin814.tistory.com/</link>
    <description>쓰다보면 늘어나는 코드지식</description>
    <language>ko</language>
    <pubDate>Sat, 9 May 2026 00:32:14 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Lim임</managingEditor>
    <item>
      <title>프로그래밍 면접질문대비 스터디 3주차</title>
      <link>https://tin814.tistory.com/167</link>
      <description>&lt;h1&gt;면접 준비 3주차&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CS&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. OSI 7계층과 그 존재 이유, TCP/IP 4계층에 대해 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OSI 7계층이란?&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;OSI(Open Systems Interconnection) 모델은 네트워크 통신을 7개의 계층으로 나눈 표준 모델입니다.&lt;br /&gt;각 계층은 &lt;b&gt;독립적인 역할&lt;/b&gt;을 가지며, 바로 &lt;b&gt;위아래 계층&lt;/b&gt;과만 통신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OSI 7계층이 존재하는 이유&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;: 서로 다른 회사, 운영체제, 장비 간 통신이 가능하도록&lt;b&gt; 공통 규약을 정의&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모듈화&lt;/b&gt;: 특정 계층에 문제가 생기면 &lt;b&gt;그 계층만 수정&amp;middot;교체&lt;/b&gt;할 수 있어 유지보수가 용이합니다.&lt;/li&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;&amp;nbsp;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;계층&lt;/th&gt;
&lt;th&gt;이름&lt;/th&gt;
&lt;th&gt;역할&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;응용(Application)&lt;/td&gt;
&lt;td&gt;사용자와 직접 상호작용&lt;/td&gt;
&lt;td&gt;HTTP, FTP, DNS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;표현(Presentation)&lt;/td&gt;
&lt;td&gt;데이터 인코딩/압축/암호화&lt;/td&gt;
&lt;td&gt;SSL, JPEG, ASCII&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;세션(Session)&lt;/td&gt;
&lt;td&gt;통신 세션 관리 (연결 유지/종료)&lt;/td&gt;
&lt;td&gt;NetBIOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;전송(Transport)&lt;/td&gt;
&lt;td&gt;데이터 신뢰성, 흐름 제어, 포트 관리&lt;/td&gt;
&lt;td&gt;TCP, UDP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;네트워크(Network)&lt;/td&gt;
&lt;td&gt;IP 주소 기반 라우팅&lt;/td&gt;
&lt;td&gt;IP, ICMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;데이터링크(Data Link)&lt;/td&gt;
&lt;td&gt;MAC 주소 기반 노드 간 통신, 오류 검출&lt;/td&gt;
&lt;td&gt;Ethernet, Wi-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;물리(Physical)&lt;/td&gt;
&lt;td&gt;비트를 전기/광신호로 변환&lt;/td&gt;
&lt;td&gt;케이블, 허브&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TCP/IP 4계층&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 인터넷에서 사용하는 모델로, OSI 7계층을 실용적으로 단순화한 모델입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TCP/IP 계층&lt;/th&gt;
&lt;th&gt;대응하는 OSI 계층&lt;/th&gt;
&lt;th&gt;역할&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;응용(Application)&lt;/td&gt;
&lt;td&gt;5, 6, 7&lt;/td&gt;
&lt;td&gt;HTTP, DNS, FTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;전송(Transport)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;TCP, UDP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인터넷(Internet)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;IP, ICMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크 접근(Network Access)&lt;/td&gt;
&lt;td&gt;1, 2&lt;/td&gt;
&lt;td&gt;Ethernet, Wi-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OSI는 이론적 표준, TCP/IP는 실제 인터넷에서 사용하는 구현 모델입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: TCP와 UDP의 차이점은 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP는 연결 지향 프로토콜로, 3-way handshake를 통해 연결을 맺고 데이터의 순서 보장, 재전송, 흐름 제어를 지원합니다. 신뢰성이 높지만 속도가 상대적으로 느립니다. 파일 전송, HTTP 통신 등에 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP는 비연결형 프로토콜로, 연결 과정 없이 데이터를 바로 전송합니다. 신뢰성은 낮지만 속도가 빠릅니다. 실시간 스트리밍, 게임, DNS 조회 등에 사용됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: 3-way handshake가 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 연결을 수립하는 과정입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SYN&lt;/b&gt;: 클라이언트가 서버에 연결 요청&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SYN-ACK&lt;/b&gt;: 서버가 요청을 수락하고 응답&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ACK&lt;/b&gt;: 클라이언트가 확인 응답 &amp;rarr; 연결 수립&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결 종료 시에는 4-way handshake(FIN &amp;rarr; ACK &amp;rarr; FIN &amp;rarr; ACK)를 사용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 인증과 인가에 대해 설명해주세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인증 (Authentication)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;당신이 누구인지&quot;를 확인하는 과정입니다.&lt;br /&gt;&lt;b&gt;사용자가 주장하는&lt;/b&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;예시: 로그인 시 아이디/비밀번호 입력, 지문 인식, OTP 인증&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인가 (Authorization)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;당신이 무엇을 할 수 있는지&quot;를 결정하는 과정입니다.&lt;br /&gt;&lt;b&gt;인증된 사용자가&lt;/b&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;/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;&lt;b&gt;인증 &amp;rarr; 인가&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;- 실제 웹에서의 흐름 (JWT 기준)&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 로그인 &amp;rarr; 서버가 신원을 &lt;b&gt;인증&lt;/b&gt;하고 &lt;b&gt;JWT 토큰 발급&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;이후 요청마다 토큰을 헤더에 포함&lt;/li&gt;
&lt;li&gt;서버가 토큰을 검증해 해당 유저의 권한을 확인 &amp;rarr; &lt;b&gt;인가&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: 세션 기반 인증과 토큰 기반 인증(JWT)의 차이는 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 기반 인증은 서버가 세션 정보를 직접 저장(상태 유지, stateful)하고, 클라이언트는 세션 ID만 쿠키로 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 메모리를 사용하고, 분산 서버 환경에서 세션 공유 문제가 생길 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT 기반 인증은 서버가 상태를 저장하지 않고(stateless), 토큰 자체에 유저 정보와 서명이 담겨 있습니다. 서버 부하는 낮지만 토큰이 탈취되면 만료 전까지 막기 어렵습니다. 그래서 Access Token의 만료 시간을 짧게 하고 Refresh Token을 함께 사용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: JWT의 구조를 설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT는 점(&lt;code&gt;.&lt;/code&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;Header&lt;/b&gt;: 토큰 타입(JWT)과 알고리즘(HS256 등) 정보, Base64로 인코딩&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Payload&lt;/b&gt;: 사용자 ID, 권한, 만료 시간 등 클레임(claim) 데이터, Base64로 인코딩&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Signature&lt;/b&gt;: Header + Payload를 비밀키로 서명한 값 &amp;rarr; 위변조 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Payload는 Base64 인코딩이라 누구나 디코딩할 수 있으므로, 비밀번호 같은 민감한 정보는 담으면 안 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 컴파일러와 인터프리터의 차이점과 각 예시를 설명하세요.&lt;/h3&gt;
&lt;div id=&quot;SE-568e7ca1-bd9e-4dd5-942c-d27bbbe2f1f8&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M1fSI/dJMcaiwfDfS/CRbiX3TKVQa1WwkyuvvzYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M1fSI/dJMcaiwfDfS/CRbiX3TKVQa1WwkyuvvzYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M1fSI/dJMcaiwfDfS/CRbiX3TKVQa1WwkyuvvzYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM1fSI%2FdJMcaiwfDfS%2FCRbiX3TKVQa1WwkyuvvzYk%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;1274&quot; height=&quot;352&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-4725e1b6-6e85-4146-973b-5dadd4256e76&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;사진출처:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;a href=&quot;https://blog.naver.com/tipsware/221041215416&quot;&gt;https://blog.naver.com/tipsware/221041215416&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-2f978f53-3cbe-448a-b1b2-9079b6ac4cc8&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;p id=&quot;SE-de7b7c79-a4c3-4c1a-b796-329a830883aa&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;인간이 이해할 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;고수준 언어&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(C++,Java,JavaScript 등)를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;CPU가&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이해할 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;저수준 언어&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(기계어)로 번역(변환)하는 방식은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;두 가지로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;*인터프리터&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방식과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;*컴파일러&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;방식이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&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;컴파일러 (Compiler)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드 전체를 한꺼번에 분석하고 기계어(또는 중간 코드)로 변환한 후 실행 파일을 생성합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 전에 모든 번역이 완료되므로 &lt;b&gt;실행 속도가 빠릅니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;문법 오류가 있으면 컴파일 자체가 실패합니다.&lt;/li&gt;
&lt;li&gt;예시: C, C++, Go, Rust, Java (&amp;rarr; 바이트코드로 컴파일)&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&quot;SE-2f978f53-3cbe-448a-b1b2-9079b6ac4cc8&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-9a9fb0bf-7fe9-4458-b9ed-2964c1ef398e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;**오브젝트 코드(목적코드):&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-237042a5-da0f-42c0-adb8-f17468ed6f82&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ez5oLC/dJMcaiwfDfI/dytsdrO298QZ299Xw38OW0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ez5oLC/dJMcaiwfDfI/dytsdrO298QZ299Xw38OW0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ez5oLC/dJMcaiwfDfI/dytsdrO298QZ299Xw38OW0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fez5oLC%2FdJMcaiwfDfI%2FdytsdrO298QZ299Xw38OW0%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;1000&quot; height=&quot;200&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-8064edd0-4285-4322-a5e0-891249da35e6&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;[ .c &amp;gt; .obj ]&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소스코드를 컴파일한 결과물, 즉&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;컴파일된 파일&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-7cad01d2-d202-4f68-a40a-67f7143a2ab1&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-5a44e160-83ca-4405-8db4-f9a20da6b8f4&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;C언어의 경우)&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-85a6793f-458c-43e2-9947-f3c989284046&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. [파일명&lt;/span&gt;&lt;span&gt;&lt;b&gt;.c&lt;/b&gt;&lt;/span&gt;&lt;span&gt;]인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;소스파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 프로그램을 작성하여 저장함 &amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-0a1bdbae-4317-4717-ab26-2d49cd98e991&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;컴파일러&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 의해 어셈블리 코드로 변함(일반적인 컴파일러들은 어셈블러의 역할도 수행) &amp;gt; 바이너리 코드로 변경됨 &amp;gt; 변경된 바이너리 코드는 [파일명.&lt;/span&gt;&lt;span&gt;&lt;b&gt;obj&lt;/b&gt;&lt;/span&gt;&lt;span&gt;]인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;오브젝트 파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 불리고 링커의 대상이 됨 &amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2375c5b9-faf4-4243-be62-3b54cfb11bd5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3. 링커로 인해 [파일명.&lt;/span&gt;&lt;span&gt;&lt;b&gt;exe&lt;/b&gt;&lt;/span&gt;&lt;span&gt;]인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;*실행파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 만듦.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-46cd32d2-a6ad-4e3f-afcc-22dd6195abd6&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3e6ddc2f-6a39-4bef-b002-bd6062eb27c7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;*실행파일: CPU에 일을 시키는 프로그램&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ec4fab4c-66d8-4cc9-89bf-0cbb2a4b04b5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;b&gt;컴파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(Compiler/번역,변환하는 프로그램) [&lt;/span&gt;&lt;span&gt;&lt;b&gt;C&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;b&gt;C++,C#&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;b&gt;JAVA&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,Ada,파스칼 등]&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d92f55c1-9c61-45e7-bc5d-87143234c381&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-18084869-e7a9-44e3-81c1-17de95a3f09e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;프로그램 소스코드&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;전체를 한꺼번에 스캔하여 번역&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는 과정을 거친다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-650cc6d9-782a-4d90-8e90-25fae3e5da12&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;초기실행 시간이 오래 걸리&lt;/span&gt;&lt;span&gt;지만, 작업을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;u&gt;&lt;i&gt;**&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;단순화&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;​&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;시켜&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;전체적인 실행시간&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;은 더 빠를 수 있다&lt;/span&gt;&lt;span&gt;는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;span&gt;변환하는 과정에서 **&lt;/span&gt;&lt;span&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;오브젝트 코드&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span&gt;Object Code)라는 파일을 만들어야 하기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;많은 메모리가 필요함&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;span&gt;전체 코드를 검사한 후 오류메세지를 생성하기에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;프로그램 실행 전에 오류를 발견&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;할 수 있다&lt;/span&gt;&lt;span&gt;는 장점이 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;SE-0ae15688-4858-4177-8364-b1d131cb0140&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-33c5f05f-ef3c-4afd-b50b-cdbd4359a42d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;**&lt;/span&gt;&lt;span&gt;&lt;b&gt;단순화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9805cfb5-5db5-4b8e-ad72-7cada4c06878&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;​&lt;/b&gt;&lt;/span&gt;&lt;span&gt;컴파일 과정에서 특정 함수를 많이 반복해야 할 경우, 함수를 반복하는 것이 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;함수의 결과물을 반복하도록 컴파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한다. 이처럼 불필요한 동작을 제거하는 방식을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;최적화&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(Optimization)라 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-----&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터프리터 (Interpreter)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드를 한 줄씩 읽고 즉시 실행합니다. 별도의 실행 파일을 생성하지 않습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉시 실행 가능하고 디버깅이 편하지만 &lt;b&gt;실행 속도가 상대적으로 느립니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;오류가 있는 줄에 도달해야 오류가 발생합니다.&lt;/li&gt;
&lt;li&gt;예시: Python, JavaScript(전통적), Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript는 컴파일러? 인터프리터?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 원래 인터프리터 언어였지만, 현대 엔진(V8 등)은 &lt;b&gt;JIT(Just-In-Time) 컴파일&lt;/b&gt; 방식을 사용합니다. 실행 시점에 자주 사용되는 코드를 기계어로 컴파일해 성능을 높입니다. 즉, 두 방식의 장점을 혼합한 형태입니다.&lt;span style=&quot;background-color: #ffffff; color: #444444; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;SE-2f978f53-3cbe-448a-b1b2-9079b6ac4cc8&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;p id=&quot;SE-a1470cf8-2775-4f25-8af4-1898d11d5216&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;장점 &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ba0000;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-25b7a2d9-fd1c-439a-8ed7-708dfdfc5962&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;​&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5e527821-a0b6-4817-b284-bb557f2851f0&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;b&gt;인터프리터&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(Interpreter/해석기) &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&lt;b&gt;JavaScript&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;b&gt;Python&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,Ruby,스크래치 등]&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b1dbb061-c1eb-4394-a884-845e03e6b0ff&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-863729cf-3d97-4027-964c-0df8772e3f11&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자바스크립트 파일을 받으면, 코드를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;한 줄 한 줄&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 해석하면서 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-971aa15d-83b6-4242-8ed1-bc2420f1d966&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;바로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;기계어&lt;/b&gt;&lt;/span&gt;&lt;span&gt;(Machine Code)&lt;/span&gt;&lt;span&gt;&lt;b&gt;로 번역하여 실행&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는&lt;/span&gt;&lt;span&gt; 방식. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2a199875-6214-4d64-8843-600eadc1b031&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드실행 전 *&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;u&gt;&lt;i&gt;컴파일&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt; 단계가 없기&lt;/span&gt;&lt;span&gt; 때문에 &lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;실행속도가 빠르다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b6c4770a-269e-4120-bf0b-093c653c100a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;span&gt;별도의 실행파일이 없어서,&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt; 매 실행마다 인터프리트 과정이 반복 수행&lt;/span&gt;&lt;span&gt;되어 &lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;메모리 사용 효율&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;은 좋으나 &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;&lt;b&gt;실행시간이 더 소요&lt;/b&gt;&lt;/span&gt;&lt;span&gt;됨&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;span&gt;한 번에 한 문장씩 번역 및 실행하기 때문에 &lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;&lt;b&gt;오류&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #00a84b;&quot;&gt;를 만나면 그 즉시 프로그램을 중지한다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;span style=&quot;color: #ff0010;&quot;&gt;소스코드가 쉽게 공개&lt;/span&gt;&lt;span&gt;된다는 단점이 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;SE-44c984ca-f18b-403a-b421-7e0e7015cefd&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-7cad01d2-d202-4f68-a40a-67f7143a2ab1&quot; style=&quot;background-color: #ffffff; color: #444444; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-00b5f053-b619-48b2-ade9-818fd36f7c1e&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[출처]&lt;/b&gt; &lt;a style=&quot;color: #000000;&quot; href=&quot;https://blog.naver.com/tin814/223788134399&quot;&gt;개초보 리액트 설명문[리액트뭐임/인터프리터뭐임]&lt;/a&gt;&lt;span&gt;|&lt;/span&gt;&lt;b&gt;작성자&lt;/b&gt; &lt;a style=&quot;color: #000000;&quot; href=&quot;https://blog.naver.com/tin814&quot;&gt;뫠&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: JIT 컴파일이란 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JIT(Just-In-Time) 컴파일은 프로그램 실행 중에 필요한 코드를 실시간으로 기계어로 컴파일하는 방식입니다. 인터프리터처럼 바로 실행할 수 있는 유연성을 가지면서, 자주 실행되는 코드(hot code)는 컴파일해 캐싱하여 실행 속도를 높입니다. V8 엔진(Chrome, Node.js)이 대표적으로 JIT를 사용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: Java는 컴파일 언어인가요, 인터프리터 언어인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java는 두 가지 모두에 해당합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소스 코드(&lt;code&gt;.java&lt;/code&gt;)를 &lt;b&gt;컴파일러&lt;/b&gt;가 바이트코드(&lt;code&gt;.class&lt;/code&gt;)로 변환합니다.&lt;/li&gt;
&lt;li&gt;JVM(Java Virtual Machine)이 바이트코드를 &lt;b&gt;인터프리팅&lt;/b&gt;하거나 JIT 컴파일로 실행합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;한 번 작성하면 어디서나 실행(Write Once, Run Anywhere)&quot;이 가능한 이유가 바로 JVM 덕분입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 가상 메모리에 대해 설명해보세요.&lt;/h3&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;실제 물리적 RAM의 크기에 관계없이, 각 프로세스가 자신만의 독립적인 연속된 메모리 공간을 갖는 것처럼 보이게 하는 메모리 관리 기법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제가 물리 메모리(RAM)와 하드디스크의 일부(스왑 공간)를 조합해 프로세스에게 가상의 주소 공간을 제공합니다.&lt;/p&gt;
&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;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;b&gt;보안과 안정성&lt;/b&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;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;li&gt;&lt;b&gt;페이지 테이블&lt;/b&gt;이 가상 주소 &amp;rarr; 물리 주소를 매핑합니다.&lt;/li&gt;
&lt;li&gt;필요한 페이지만 물리 메모리에 올려두고, 나머지는 디스크에 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이지 폴트 (Page Fault)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 접근하려는 페이지가 물리 메모리에 없을 때 발생합니다. OS가 해당 페이지를 디스크에서 RAM으로 불러오는데, 이 과정에서 성능 저하가 발생합니다. 페이지 폴트가 너무 자주 발생하면 &lt;b&gt;스래싱(Thrashing)&lt;/b&gt; 이 생겨 성능이 급격히 저하됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: 스래싱(Thrashing)이란 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 실제 작업보다 페이지를 교체하는 데 더 많은 시간을 소비하는 현상입니다.&lt;br /&gt;메모리에 너무 많은 프로세스가 올라가 있을 때, 각 프로세스에 할당된 페이지 수가 부족해져 페이지 폴트가 연속적으로 발생합니다. 해결책으로는 프로세스 수를 줄이거나, 물리 메모리를 증설하거나, 워킹 셋(Working Set) 기법으로 필요한 페이지를 예측해 메모리에 유지하는 방법이 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: 페이지 교체 알고리즘에는 어떤 것이 있나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물리 메모리가 가득 찼을 때 어떤 페이지를 내보낼지 결정하는 알고리즘입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;FIFO&lt;/b&gt;: 가장 먼저 올라온 페이지를 먼저 제거. 구현 간단하지만 성능이 좋지 않을 수 있음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LRU (Least Recently Used)&lt;/b&gt;: 가장 오랫동안 사용되지 않은 페이지 제거. 실제로 많이 사용되는 방식.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OPT (Optimal)&lt;/b&gt;: 앞으로 가장 오랫동안 사용되지 않을 페이지 제거. 이론상 최적이지만 미래를 알 수 없어 실제 구현은 불가.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프론트엔드&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 호이스팅에 대해서 설명해주세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;호이스팅(Hoisting)이란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 엔진이 코드를 실행하기 전 &lt;b&gt;변수 선언과 함수 선언을 해당 스코프의 최상단으로 끌어올리는 동작&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 코드가 이동하는 것이 아니라, 자바스크립트 엔진이 코드를 파싱하는 단계에서 선언을 먼저 메모리에 등록하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언 정보만 등록되며 변수종류와 뭐에따라 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&lt;b&gt;var 호이스팅&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;var&lt;/code&gt;는 선언과 동시에 &lt;code&gt;undefined&lt;/code&gt;로 초기화됩니다. 선언 전에 접근해도 에러가 나지 않고 &lt;code&gt;undefined&lt;/code&gt;를 반환합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;console.log(a); // undefined
var a = 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;let, const 호이스팅&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES5에 나온 개념으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;let&lt;/code&gt;과 &lt;code&gt;const&lt;/code&gt;도 호이스팅이 되지만 초기화가 되지 않아, 선언 전에 접근하면 &lt;b&gt;ReferenceError&lt;/b&gt;가 발생합니다.&lt;br /&gt;이 선언 시점 전까지의 구간을 &lt;b&gt;TDZ(Temporal Dead Zone, 일시적 사각지대)&lt;/b&gt; 라고 합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 선언식 vs 함수 표현식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 선언식(&lt;code&gt;function foo() {}&lt;/code&gt;)은 함수 전체가 호이스팅되어 선언 전에 호출할 수 있습니다.&lt;br /&gt;함수 표현식(&lt;code&gt;const foo = function() {}&lt;/code&gt;)은 변수 선언만 호이스팅되므로 선언 전에 호출하면 에러가 납니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;hello(); // &quot;Hello!&quot; (함수 선언식은 가능)
function hello() { console.log(&quot;Hello!&quot;); }

greet(); // TypeError: greet is not a function
var greet = function() { console.log(&quot;Hi!&quot;); }&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: TDZ(Temporal Dead Zone)가 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;let&lt;/code&gt;과 &lt;code&gt;const&lt;/code&gt;로 선언된 변수가 호이스팅은 되었지만 아직 초기화되지 않은 상태의 구간입니다. 스코프의 시작부터 실제 선언문에 도달하기 전까지가 TDZ입니다. 이 구간에서 해당 변수에 접근하면 ReferenceError가 발생합니다. TDZ는 예측하기 어려운 &lt;code&gt;var&lt;/code&gt;의 동작을 개선하기 위해 도입된 개념입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var에는 TDZ가 없다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: var 대신 let/const를 써야 하는 이유는 무엇인가요?&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;: &lt;code&gt;var&lt;/code&gt;는 함수 스코프, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;는 블록 스코프입니다. &lt;code&gt;var&lt;/code&gt;는 if문이나 for문 블록 밖에서도 접근이 가능해 예상치 못한 버그를 유발합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;재선언&lt;/b&gt;: &lt;code&gt;var&lt;/code&gt;는 같은 스코프에서 같은 이름으로 재선언이 가능하지만, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;는 불가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;호이스팅 안전성&lt;/b&gt;: &lt;code&gt;var&lt;/code&gt;는 &lt;code&gt;undefined&lt;/code&gt;로 초기화되어 조용히 버그를 만들 수 있지만, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;는 TDZ로 명확한 에러를 냅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;const&lt;/b&gt;: 재할당이 불가능하므로 의도하지 않은 값 변경을 방지합니다. 기본적으로 &lt;code&gt;const&lt;/code&gt;를 사용하고, 재할당이 필요한 경우만 &lt;code&gt;let&lt;/code&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;let과 const의 차이점이뭔가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const 재할당 불가 let은 재할당 가능&lt;/p&gt;
&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;const는 값을 바꿀 수 없나요?&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776751890929&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = { name: &quot;seoin&quot; };
obj.name = &quot;kim&quot;;   // ✅ 가능 (참조값은 그대로, 내부 프로퍼티만 변경)
obj = {};           // ❌ 불가 (참조 자체를 바꾸는 재할당)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const는&amp;nbsp;참조(주소)가&amp;nbsp;고정되는&amp;nbsp;것이지,&amp;nbsp;참조한&amp;nbsp;데이터의&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. CSR vs SSR vs SSG 차이를 설명하세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CSR (Client-Side Rendering)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 빈 HTML을 받고, JavaScript 번들을 다운로드한 후 클라이언트 측에서 직접 화면을 렌더링하는 방식입니다.&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;: 초기 로딩 이후 페이지 전환이 빠르고 부드럽습니다 (SPA 경험). 서버 부하가 낮습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt;: 초기 로딩이 느립니다. JavaScript가 실행되기 전까지 빈 화면이 보입니다. 크롤러가 JS를 실행하지 못하는 경우 SEO에 불리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;: React (기본), Vue, Angular&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 빈 HTML을 렌더링 하고 JS로&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증에 적합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SSR (Server-Side Rendering)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 요청할 때마다 서버에서 HTML을 완성해 클라이언트에 전달하는 방식입니다.&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;: 초기 로딩이 빠르고 완성된 HTML을 내려주므로 SEO에 유리합니다. 실시간 데이터 반영에 적합합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt;: 요청마다 서버에서 렌더링하므로 서버 부하가 높습니다. 페이지 이동 시 전체 새로고침이 발생할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;: Next.js (&lt;code&gt;getServerSideProps&lt;/code&gt;), Nuxt.js&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 HTML을 미리 완성해두고 요청시에 보내줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SEO에는 유리할 수 있으나 서버부하가 높아지는 단점이 있습니다.&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;SSG (Static Site Generation)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드 시점에 미리 모든 HTML을 생성해두고, 요청 시 정적 파일을 그대로 서빙하는 방식입니다.&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;: 응답 속도가 가장 빠릅니다 (CDN 캐싱 가능). SEO에 매우 유리합니다. 서버가 없어도 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt;: 내용이 변경될 때마다 재빌드가 필요합니다. 실시간 데이터에 적합하지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;: Next.js (&lt;code&gt;getStaticProps&lt;/code&gt;), Gatsby, Jekyll&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;속도와 SEO에는 최적 자주바뀌는 데이터는 부적합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그나 문서에 적합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비교 요약&lt;/b&gt;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;CSR&lt;/th&gt;
&lt;th&gt;SSR&lt;/th&gt;
&lt;th&gt;SSG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;렌더링 위치&lt;/td&gt;
&lt;td&gt;클라이언트&lt;/td&gt;
&lt;td&gt;서버 (요청마다)&lt;/td&gt;
&lt;td&gt;빌드 타임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;초기 로딩&lt;/td&gt;
&lt;td&gt;느림&lt;/td&gt;
&lt;td&gt;빠름&lt;/td&gt;
&lt;td&gt;가장 빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;불리&lt;/td&gt;
&lt;td&gt;유리&lt;/td&gt;
&lt;td&gt;매우 유리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실시간 데이터&lt;/td&gt;
&lt;td&gt;적합&lt;/td&gt;
&lt;td&gt;적합&lt;/td&gt;
&lt;td&gt;부적합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버 부하&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;적합한 서비스&lt;/td&gt;
&lt;td&gt;대시보드, 관리자 페이지&lt;/td&gt;
&lt;td&gt;뉴스, 커머스&lt;/td&gt;
&lt;td&gt;블로그, 문서&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ①: Next.js의 ISR(Incremental Static Regeneration)이란 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ISR은 SSG의 단점을 보완한 방식으로, 특정 주기(예: 60초마다)마다 정적 페이지를 백그라운드에서 재생성합니다. 정적 파일의 빠른 응답 속도를 유지하면서도 일정 주기로 최신 데이터를 반영할 수 있습니다. Next.js에서 &lt;code&gt;getStaticProps&lt;/code&gt;에 &lt;code&gt;revalidate&lt;/code&gt; 옵션을 설정하면 사용할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예상 꼬리 질문 ②: SEO 관점에서 CSR의 단점을 어떻게 보완할 수 있나요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR은 크롤러가 JS 실행 전 빈 HTML만 보는 경우 SEO에 불리합니다. 보완 방법으로는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SSR 도입&lt;/b&gt;: Next.js처럼 서버에서 완성된 HTML을 내려줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Pre-rendering&lt;/b&gt;: React Helmet, React Snap 등으로 주요 페이지를 미리 정적 HTML로 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dynamic Rendering&lt;/b&gt;: Googlebot 같은 크롤러에게는 SSR 결과를, 일반 사용자에게는 CSR 결과를 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메타 태그 관리&lt;/b&gt;: 크롤러가 읽는 &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, Open Graph 태그를 적절히 설정합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? 크롤러가 왜 빈 HTML만 보게될까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롤러는 HTML파일만 읽고 JS를 실행하지 않는데, CSR은 초기 HTML의 텅빈페이지를 보게되는구나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR은 완성된 HTML(JS)포함된&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? Hydration&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하이드레이션은 서버에서 렌더링된 정적 html에 자바스크립트 이벤트리스너나 동적 연결하는 것을 의미합니다.&lt;/p&gt;</description>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/167</guid>
      <comments>https://tin814.tistory.com/167#entry167comment</comments>
      <pubDate>Tue, 21 Apr 2026 13:23:03 +0900</pubDate>
    </item>
    <item>
      <title>프로그래밍 면접질문대비 스터디 2주차</title>
      <link>https://tin814.tistory.com/166</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  2주차 CS 기초&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q1. async/await에 대해 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;async/await&lt;/code&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;는 &lt;/span&gt;&lt;b&gt;Promise를 더 읽기 쉽게 작성하기 위한 문법&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;내부적으로는 Promise를 기반으로 동작하며, 비동기 코드를 마치 &lt;/span&gt;&lt;b&gt;동기 코드처럼 작성&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;할 수 있게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt; 키워드를 함수 앞에 붙이면, 그 함수는 항상 &lt;b&gt;Promise를 반환&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 내부에서 &lt;code&gt;await&lt;/code&gt; 키워드를 사용하면, 해당 Promise가 &lt;b&gt;resolve될 때까지 실행을 일시 중지&lt;/b&gt;하고 결과값을 반환받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러 처리는 &lt;code&gt;try/catch&lt;/code&gt;로 할 수 있어 &lt;code&gt;.catch()&lt;/code&gt;를 연결하는 것보다 가독성이 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// Promise 방식
fetch('/api/user')
  .then((res) =&amp;gt; res.json())
  .then((data) =&amp;gt; console.log(data))
  .catch((err) =&amp;gt; console.error(err));

// async/await 방식 (더 읽기 쉬움)
async function getUser() {
  try {
    const res = await fetch('/api/user');
    const data = await res.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 주의: await는 async 함수 내부에서만 사용 가능합니다.&lt;br /&gt;await는 해당 줄에서 기다리지만, 메인 스레드를 블로킹하지 않습니다 &amp;mdash; 이벤트 루프가 다른 작업을 처리할 수 있습니다.&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Promise의 문법적 설탕&lt;/code&gt;, &lt;code&gt;async 함수는 항상 Promise 반환&lt;/code&gt;, &lt;code&gt;await = Promise resolve 대기&lt;/code&gt;, &lt;code&gt;try/catch 에러 처리&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q2. &lt;a href=&quot;http://www.google.com%EC%9D%84&quot;&gt;www.google.com을&lt;/a&gt; 주소창에 입력하면 어떻게 될까요?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계 - URL 파싱 &amp;amp; DNS 조회:&lt;/b&gt;&lt;br /&gt;브라우저는 입력된 URL을 파싱하고, &lt;code&gt;www.google.com&lt;/code&gt;의 IP 주소를 찾기 위해 &lt;b&gt;DNS(Domain Name System)&lt;/b&gt; 조회를 합니다. 브라우저 캐시 &amp;rarr; OS 캐시 &amp;rarr; 로컬 DNS 서버 &amp;rarr; Root DNS &amp;rarr; TLD(&lt;code&gt;.com&lt;/code&gt;) DNS &amp;rarr; &lt;code&gt;google.com&lt;/code&gt; 권한 DNS 순으로 조회합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계 - TCP 연결 (3-way handshake):&lt;/b&gt;&lt;br /&gt;IP 주소를 찾으면 서버와 &lt;b&gt;TCP 3-way handshake&lt;/b&gt;로 연결을 맺습니다. HTTPS라면 여기에 &lt;b&gt;TLS Handshake&lt;/b&gt;도 추가됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3단계 - HTTP 요청:&lt;/b&gt;&lt;br /&gt;브라우저가 서버에 &lt;code&gt;GET /&lt;/code&gt; HTTP 요청을 보냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4단계 - 서버 응답:&lt;/b&gt;&lt;br /&gt;서버가 HTML, CSS, JS 등의 리소스를 응답으로 전송합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5단계 - 브라우저 렌더링:&lt;/b&gt;&lt;br /&gt;HTML &amp;rarr; DOM 트리, CSS &amp;rarr; CSSOM 트리 생성 후 렌더 트리 구성 &amp;rarr; 레이아웃 &amp;rarr; 페인트 &amp;rarr; 화면 출력.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;주소 입력
  &amp;rarr; DNS 조회 (IP 주소 획득)
  &amp;rarr; TCP 3-way handshake (+ TLS handshake if HTTPS)
  &amp;rarr; HTTP GET 요청
  &amp;rarr; 서버 응답 (HTML/CSS/JS)
  &amp;rarr; 브라우저 렌더링
  &amp;rarr; 화면 출력  ️&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;DNS&lt;/code&gt;, &lt;code&gt;TCP 3-way handshake&lt;/code&gt;, &lt;code&gt;TLS handshake&lt;/code&gt;, &lt;code&gt;HTTP 요청&lt;/code&gt;, &lt;code&gt;브라우저 렌더링&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q3. 쿠키와 세션의 차이에 대해서 설명해주세요.&lt;/h3&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;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키와 세션은 모두 HTTP의 무상태성(Stateless)을 보완하기 위한 방법으로, 사용자 상태를 유지하는 데 사용됩니다. &lt;br /&gt;가장 큰 차이는 &lt;b&gt;데이터를 어디에 저장&lt;/b&gt;하느냐입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿠키(Cookie)&lt;/b&gt; 는 데이터를 &lt;b&gt;클라이언트(브라우저)&lt;/b&gt; 에 저장합니다. &lt;br /&gt;서버가 &lt;code&gt;Set-Cookie&lt;/code&gt; 헤더를 통해 브라우저에 전달하고, 이후 요청마다 자동으로 서버에 전송됩니다. 만료 시간을 설정할 수 있어 브라우저를 닫아도 유지됩니다. 다만 클라이언트에 저장되기 때문에 &lt;b&gt;조작&amp;middot;탈취 위험&lt;/b&gt;이 있어 민감한 정보 저장에는 적합하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션(Session)&lt;/b&gt; 은 데이터를 &lt;b&gt;서버&lt;/b&gt;에 저장합니다. &lt;br /&gt;클라이언트에는 세션을 식별하는 &lt;b&gt;세션 ID&lt;/b&gt;만 쿠키로 저장됩니다. 브라우저를 닫으면 세션이 만료되고, 실제 데이터는 서버에 있어 &lt;b&gt;보안이 더 강합니다&lt;/b&gt;. 단, 사용자가 많아지면 서버 메모리 부담이 증가합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;쿠키&lt;/th&gt;
&lt;th&gt;세션&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;저장 위치&lt;/td&gt;
&lt;td&gt;클라이언트(브라우저)&lt;/td&gt;
&lt;td&gt;서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;만료&lt;/td&gt;
&lt;td&gt;설정된 만료 시간까지&lt;/td&gt;
&lt;td&gt;브라우저 종료 시 / 서버 설정 시간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;보안&lt;/td&gt;
&lt;td&gt;상대적으로 취약&lt;/td&gt;
&lt;td&gt;상대적으로 안전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버 부하&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;td&gt;있음 (세션 데이터 관리)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;용량 제한&lt;/td&gt;
&lt;td&gt;약 4KB&lt;/td&gt;
&lt;td&gt;서버 설정에 따라 다름&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;저장 위치&lt;/code&gt;, &lt;code&gt;무상태성 보완&lt;/code&gt;, &lt;code&gt;세션 ID&lt;/code&gt;, &lt;code&gt;보안&lt;/code&gt;, &lt;code&gt;서버 부하&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q4. TCP 3-way, 4-way handshake에 대해서 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3way는 연결설정 4way는 연결 끊는 과정&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;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 3-way handshake는 클라이언트와 서버가 신뢰성 있는 연결을 맺기 위한 과정입니다. 3단계로 진행됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SYN&lt;/b&gt;: 클라이언트가 서버에 연결 요청 (&lt;code&gt;SYN&lt;/code&gt; 패킷 전송)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SYN + ACK&lt;/b&gt;: 서버가 요청을 수락하고, 자신도 연결 요청 (&lt;code&gt;SYN+ACK&lt;/code&gt; 전송)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ACK&lt;/b&gt;: 클라이언트가 확인 응답 (&lt;code&gt;ACK&lt;/code&gt; 전송) &amp;rarr; 연결 완료&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;클라이언트          서버
    │──── SYN ────▶│
    │◀── SYN+ACK ──│
    │──── ACK ────▶│
    │   연결 완료   │&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 4-way handshake는 연결을 종료할 때 사용하며, 4단계가 필요합니다. &lt;br /&gt;양쪽이 각각 독립적으로 종료 신호를 보내야 하기 때문입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;FIN&lt;/b&gt;: 클라이언트가 종료 요청&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ACK&lt;/b&gt;: 서버가 확인 응답 (서버는 아직 데이터 전송 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FIN&lt;/b&gt;: 서버가 종료 준비 완료 신호&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ACK&lt;/b&gt;: 클라이언트가 확인 &amp;rarr; 연결 종료&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;클라이언트          서버
    │──── FIN ────▶│
    │◀──── ACK ────│  (서버: 아직 보낼 데이터 있을 수 있음)
    │◀──── FIN ────│  (서버: 이제 다 보냄)
    │──── ACK ────▶│
    │   연결 종료   │&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트는 마지막 ACK 후 바로 종료하지 않고 &lt;b&gt;TIME_WAIT&lt;/b&gt; 상태를 유지합니다. &lt;br /&gt;혹시 ACK가 유실됐을 때 서버가 FIN을 재전송하면 다시 응답하기 위함입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;SYN&lt;/code&gt;, &lt;code&gt;ACK&lt;/code&gt;, &lt;code&gt;FIN&lt;/code&gt;, &lt;code&gt;3-way(연결)&lt;/code&gt;, &lt;code&gt;4-way(종료)&lt;/code&gt;, &lt;code&gt;TIME_WAIT&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  2주차 프론트엔드&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q1. 클로저에 대해서 설명해주세요.&lt;/h3&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;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로저(Closure) 란, 함수가 선언될 당시의 &lt;b&gt;렉시컬 환경(Lexical Environment)(어디서만들어졌는지)&lt;/b&gt;을 기억하는 것입니다. &lt;br /&gt;즉, 내부 함수가 외부 함수의 실행이 끝난 후에도 외부 함수의 변수에 접근할 수 있는 특성입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function counter() {
  let count = 0; // 외부 함수의 변수

  return function () {
    count++; // 외부 함수 종료 후에도 count에 접근 가능!
    return count;
  };
}

const increment = counter();
console.log(increment()); // 1
console.log(increment()); // 2
console.log(increment()); // 3&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시에서 counter()가 실행을 마쳤지만, 반환된 함수는 여전히 count를 기억하고 있습니다. 이것이 클로저입니다.&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;데이터 은닉&lt;/b&gt;: 외부에서 &lt;code&gt;count&lt;/code&gt;에 직접 접근 불가 &amp;rarr; 캡슐화 효과&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 유지&lt;/b&gt;: 함수 호출 간 상태를 유지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;팩토리 함수&lt;/b&gt;: 설정값을 고정한 함수 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;렉시컬 환경&lt;/code&gt;, &lt;code&gt;외부 변수 접근&lt;/code&gt;, &lt;code&gt;데이터 은닉&lt;/code&gt;, &lt;code&gt;상태 유지&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q2. 코드 스플리팅(Code Splitting)이란?&lt;/h3&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;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 스플리팅이란, 하나의 큰 JavaScript 번들 파일을 여러 개의 작은 청크(chunk)로 분리하는 기술입니다. 사용자가 실제로 필요한 코드만 그때그때 로드하게 해서 초기 로딩 속도를 개선합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번들링 없이 모든 JS를 한 파일에 담으면, 사용자가 처음 페이지에 접속할 때 불필요한 코드까지 전부 다운로드해야 합니다. 코드 스플리팅을 적용하면 &lt;b&gt;당장 필요한 코드만 먼저 로드&lt;/b&gt;하고, 나머지는 필요할 때 동적으로 가져옵니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// ❌ 코드 스플리팅 없이 (모든 컴포넌트를 처음부터 다 로드)
import HeavyComponent from './HeavyComponent';

// ✅ 코드 스플리팅 적용 (필요할 때 로드)
const HeavyComponent = React.lazy(() =&amp;gt; import('./HeavyComponent'));

function App() {
  return (
    &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;로딩 중...&amp;lt;/div&amp;gt;}&amp;gt;
      &amp;lt;HeavyComponent /&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리할&amp;nbsp;가치가&amp;nbsp;있는&amp;nbsp;경우:&lt;br /&gt;&amp;nbsp;&amp;nbsp;✅&amp;nbsp;파일&amp;nbsp;크기가&amp;nbsp;큰&amp;nbsp;것&amp;nbsp;(보통&amp;nbsp;50KB&amp;nbsp;이상&amp;nbsp;기준)&lt;br /&gt;&amp;nbsp;&amp;nbsp;✅&amp;nbsp;자주&amp;nbsp;방문&amp;nbsp;안&amp;nbsp;하는&amp;nbsp;페이지&lt;br /&gt;&amp;nbsp;&amp;nbsp;✅&amp;nbsp;특정&amp;nbsp;사용자만&amp;nbsp;보는&amp;nbsp;기능&amp;nbsp;(관리자,&amp;nbsp;프리미엄&amp;nbsp;등)&lt;br /&gt;분리&amp;nbsp;안&amp;nbsp;하는&amp;nbsp;게&amp;nbsp;나은&amp;nbsp;경우:&lt;br /&gt;&amp;nbsp;&amp;nbsp;❌&amp;nbsp;모든&amp;nbsp;페이지에서&amp;nbsp;쓰는&amp;nbsp;공통&amp;nbsp;컴포넌트&amp;nbsp;(Header,&amp;nbsp;Button&amp;nbsp;등)&lt;br /&gt;&amp;nbsp;&amp;nbsp;❌&amp;nbsp;크기가&amp;nbsp;작은&amp;nbsp;것&lt;br /&gt;&amp;nbsp;&amp;nbsp;❌&amp;nbsp;첫&amp;nbsp;화면에&amp;nbsp;바로&amp;nbsp;보여야&amp;nbsp;하는&amp;nbsp;것&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 방법:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Route 기반 스플리팅&lt;/b&gt;: 페이지 단위로 분리 (가장 일반적)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컴포넌트 기반 스플리팅&lt;/b&gt;: 무거운 컴포넌트만 분리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;dynamic &lt;code&gt;import()&lt;/code&gt;&lt;/b&gt;: webpack/Vite가 자동으로 청크로 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;번들 분리&lt;/code&gt;, &lt;code&gt;초기 로딩 속도&lt;/code&gt;, &lt;code&gt;React.lazy&lt;/code&gt;, &lt;code&gt;dynamic import&lt;/code&gt;, &lt;code&gt;Route 기반 스플리팅&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL&amp;nbsp;파싱&amp;nbsp;&amp;nbsp;-&amp;gt;&amp;nbsp;프로토콜&amp;nbsp;도메인&amp;nbsp;경로&amp;nbsp;분리&lt;br /&gt;&lt;br /&gt;브라우저&amp;nbsp;캐시&amp;nbsp;os&amp;nbsp;캐시&amp;nbsp;라우터&amp;nbsp;캐시&amp;nbsp;dns&amp;nbsp;캐시&amp;nbsp;확인&lt;br /&gt;캐시의&amp;nbsp;ip주소가있으면&amp;nbsp;DNS생략&amp;nbsp;없으면&amp;nbsp;DNS&amp;nbsp;resolver가&amp;nbsp;ip주소&amp;nbsp;반환&lt;br /&gt;&lt;br /&gt;주소&amp;nbsp;얻으면&amp;nbsp;TCP&amp;nbsp;3way&amp;nbsp;handshake&amp;nbsp;양방향&amp;nbsp;연결&amp;nbsp;수립&lt;br /&gt;HTTPS인&amp;nbsp;경우에는&amp;nbsp;TCP&amp;nbsp;연결&amp;nbsp;후&amp;nbsp;TLS&amp;nbsp;handshake&amp;nbsp;진행&amp;nbsp;-&amp;gt;&amp;nbsp;암호화된&amp;nbsp;통신&amp;nbsp;채널&amp;nbsp;생성&lt;br /&gt;&lt;br /&gt;HTTP&amp;nbsp;요청&amp;nbsp;전송&amp;nbsp;&amp;nbsp;GET&amp;nbsp;&lt;br /&gt;서버&amp;nbsp;응답&amp;nbsp;HTML&amp;nbsp;CSS&amp;nbsp;JS&amp;nbsp;이미지&amp;nbsp;등등&lt;br /&gt;&lt;br /&gt;브라우저&amp;nbsp;렌더링&lt;br /&gt;HTML&amp;nbsp;-&amp;gt;&amp;nbsp;DOM&amp;nbsp;트리&lt;br /&gt;CSS&amp;nbsp;-&amp;gt;&amp;nbsp;CSSOM&amp;nbsp;트리&lt;br /&gt;DOM&amp;nbsp;+&amp;nbsp;CSSOM&amp;nbsp;-&amp;gt;&amp;nbsp;렌더&amp;nbsp;트리&lt;br /&gt;레이아웃&lt;br /&gt;페인트&lt;br /&gt;화면&amp;nbsp;출력&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;TCP&amp;nbsp;핸드쉐이크&amp;nbsp;TLS&amp;nbsp;핸드쉐이크&amp;nbsp;머가다르냐&lt;br /&gt;&lt;br /&gt;TCP가&amp;nbsp;수립되고&amp;nbsp;TLS&amp;nbsp;다음에&amp;nbsp;한다&lt;br /&gt;TLS&amp;nbsp;가&amp;nbsp;뭐냐&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;스코프는&amp;nbsp;함수ㄱ나&amp;nbsp;변수가&amp;nbsp;접근할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;&lt;br /&gt;전역스코프&amp;nbsp;-&amp;gt;&amp;nbsp;함수레벨&amp;nbsp;스코프&amp;nbsp;-&amp;gt;&amp;nbsp;블록레벨&amp;nbsp;스코프&lt;br /&gt;&lt;br /&gt;자바스크립트&amp;nbsp;특징중에하나가&lt;br /&gt;함수가&amp;nbsp;선언된&amp;nbsp;시점의&amp;nbsp;스코프를&amp;nbsp;기억하는것이&amp;nbsp;클로저&amp;nbsp;&lt;br /&gt;외부함수의&amp;nbsp;변수를&amp;nbsp;기억하고&amp;nbsp;참조할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;함수&lt;br /&gt;&lt;br /&gt;자바스크릡트의&amp;nbsp;스코프&amp;nbsp;구조를&amp;nbsp;통해&amp;nbsp;&lt;br /&gt;함수가&amp;nbsp;선언된&amp;nbsp;시점이&amp;nbsp;어디인지&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있고&lt;br /&gt;그&amp;nbsp;함수가&amp;nbsp;실행될때&amp;nbsp;외부함수의&amp;nbsp;변수를&amp;nbsp;참조할&amp;nbsp;수&amp;nbsp;있는것이&amp;nbsp;클로저&lt;br /&gt;&lt;br /&gt;자바스크립트가&amp;nbsp;렉시컬&amp;nbsp;스코프를&amp;nbsp;따른다&lt;br /&gt;함수가&amp;nbsp;호출되었을때&amp;nbsp;선언되었을&amp;nbsp;떄&amp;nbsp;기준으로&amp;nbsp;스코프가&amp;nbsp;결정되는데&lt;br /&gt;정적환경&lt;br /&gt;렉시컬&amp;nbsp;스코프&lt;br /&gt;캡쳐했던&amp;nbsp;그&amp;nbsp;변수를&amp;nbsp;쓸&amp;nbsp;수&amp;nbsp;있디.&lt;br /&gt;함수&amp;nbsp;선언시에&amp;nbsp;변수를&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;자바스크립트는&amp;nbsp;랙시컬&amp;nbsp;스코프&amp;nbsp;환경을&amp;nbsp;따르고&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;클로저를&amp;nbsp;사용하게&amp;nbsp;되면&amp;nbsp;주의할&amp;nbsp;점&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;외부함수의&amp;nbsp;변수를&amp;nbsp;계속&amp;nbsp;참조하고있기때문에&lt;br /&gt;외부함수가&amp;nbsp;실행이끝나도&amp;nbsp;변수는&amp;nbsp;외부함수를&amp;nbsp;참조하고있어서&lt;br /&gt;메모리에서&amp;nbsp;해제가&amp;nbsp;되지&amp;nbsp;않아서&amp;nbsp;(가비지&amp;nbsp;컬렉터가&amp;nbsp;수거하지&amp;nbsp;못해서)&lt;br /&gt;메모리&amp;nbsp;누수가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;&lt;br /&gt;메모리가&amp;nbsp;사라지지&amp;nbsp;않아서&lt;br /&gt;&lt;br /&gt;클로저&amp;nbsp;자체를&amp;nbsp;없애거나&amp;nbsp;범위를&amp;nbsp;줄이기&lt;br /&gt;&lt;br /&gt;불필요하게&amp;nbsp;클로저를&amp;nbsp;만들고&amp;nbsp;있으면&amp;nbsp;구조를&amp;nbsp;바꿔야&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;create()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;const&amp;nbsp;huge&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Array(1000000);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.log(&quot;hi&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;이건&amp;nbsp;huge를&amp;nbsp;쓸&amp;nbsp;필요&amp;nbsp;없는데&amp;nbsp;계속&amp;nbsp;붙잡고&amp;nbsp;있음&lt;br /&gt;&lt;br /&gt;&amp;rarr;&amp;nbsp;해결:&amp;nbsp;아예&amp;nbsp;밖으로&amp;nbsp;빼거나&amp;nbsp;제거&lt;br /&gt;&lt;br /&gt;const&amp;nbsp;huge&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Array(1000000);&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;create()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.log(&quot;hi&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;참조를&amp;nbsp;명시적으로&amp;nbsp;끊기&lt;br /&gt;&lt;br /&gt;클로저&amp;nbsp;안에서&amp;nbsp;큰&amp;nbsp;데이터를&amp;nbsp;쓰다가&amp;nbsp;더&amp;nbsp;이상&amp;nbsp;필요&amp;nbsp;없으면&amp;nbsp;끊어준다.&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;create()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;let&amp;nbsp;huge&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Array(1000000);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;function&amp;nbsp;()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.log(&quot;hi&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;huge&amp;nbsp;=&amp;nbsp;null;&amp;nbsp;//&amp;nbsp;참조&amp;nbsp;끊기&lt;br /&gt;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;rarr;&amp;nbsp;이렇게&amp;nbsp;하면&amp;nbsp;이후&amp;nbsp;GC가&amp;nbsp;수거&amp;nbsp;가능&lt;br /&gt;&lt;br /&gt;이벤트&amp;nbsp;/&amp;nbsp;타이머&amp;nbsp;정리&amp;nbsp;(실무에서&amp;nbsp;제일&amp;nbsp;중요)&lt;br /&gt;&lt;br /&gt;이게&amp;nbsp;진짜&amp;nbsp;많이&amp;nbsp;터지는&amp;nbsp;케이스다.&lt;br /&gt;&lt;br /&gt;useEffect(()&amp;nbsp;=&amp;gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;const&amp;nbsp;handler&amp;nbsp;=&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;console.log(data);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;window.addEventListener(&quot;click&quot;,&amp;nbsp;handler);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.removeEventListener(&quot;click&quot;,&amp;nbsp;handler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;},&amp;nbsp;[]);&lt;br /&gt;&lt;br /&gt;이걸&amp;nbsp;안&amp;nbsp;하면&lt;br /&gt;&lt;br /&gt;&amp;rarr;&amp;nbsp;handler가&amp;nbsp;클로저로&amp;nbsp;data&amp;nbsp;계속&amp;nbsp;잡고&amp;nbsp;있음&lt;br /&gt;&amp;rarr;&amp;nbsp;컴포넌트&amp;nbsp;사라져도&amp;nbsp;메모리&amp;nbsp;안&amp;nbsp;날아감&lt;br /&gt;&lt;br /&gt;useEffect&amp;nbsp;cleanup&amp;nbsp;필수&lt;br /&gt;&lt;br /&gt;useEffect(()&amp;nbsp;=&amp;gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;const&amp;nbsp;id&amp;nbsp;=&amp;nbsp;setInterval(()&amp;nbsp;=&amp;gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.log(&quot;running&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;},&amp;nbsp;1000);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;clearInterval(id);&lt;br /&gt;},&amp;nbsp;[]);&lt;br /&gt;&lt;br /&gt;이거&amp;nbsp;안&amp;nbsp;하면&amp;nbsp;interval이&amp;nbsp;계속&amp;nbsp;살아있어서&lt;br /&gt;&amp;rarr;&amp;nbsp;클로저&amp;nbsp;+&amp;nbsp;메모리&amp;nbsp;계속&amp;nbsp;유지됨&lt;br /&gt;&lt;br /&gt;필요한&amp;nbsp;값만&amp;nbsp;참조하기&lt;br /&gt;&lt;br /&gt;클로저&amp;nbsp;안에서&amp;nbsp;전체&amp;nbsp;객체를&amp;nbsp;들고&amp;nbsp;있지&amp;nbsp;말고&lt;br /&gt;진짜&amp;nbsp;필요한&amp;nbsp;값만&amp;nbsp;뽑아서&amp;nbsp;쓰는&amp;nbsp;게&amp;nbsp;좋다&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;❌&amp;nbsp;안좋은&amp;nbsp;예&lt;br /&gt;const&amp;nbsp;user&amp;nbsp;=&amp;nbsp;{&amp;nbsp;name:&amp;nbsp;&quot;a&quot;,&amp;nbsp;data:&amp;nbsp;huge&amp;nbsp;};&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;fn()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;console.log(user.name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;rarr;&amp;nbsp;user&amp;nbsp;전체가&amp;nbsp;잡힘&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;✅&amp;nbsp;좋은&amp;nbsp;예&lt;br /&gt;const&amp;nbsp;name&amp;nbsp;=&amp;nbsp;user.name;&lt;br /&gt;&lt;br /&gt;function&amp;nbsp;fn()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;console.log(name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;리액트&amp;nbsp;useState&amp;nbsp;클로저&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;트랜잭션은&amp;nbsp;하나의작업단위를&amp;nbsp;성공&amp;nbsp;혹은&amp;nbsp;실패할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;성질&lt;br /&gt;ACID&amp;nbsp;&lt;br /&gt;원자성&amp;nbsp;-&amp;gt;&amp;nbsp;all&amp;nbsp;or&amp;nbsp;nothing&amp;nbsp;&lt;br /&gt;일관성&amp;nbsp;-&amp;gt;&amp;nbsp;트랜잭션&amp;nbsp;전후&amp;nbsp;데이터는&amp;nbsp;일관성을&amp;nbsp;유지해야한다.&lt;br /&gt;독립성&amp;nbsp;-&amp;gt;&amp;nbsp;트랜잭션은&amp;nbsp;독립적으로&amp;nbsp;실행되어야한다.&amp;nbsp;다른&amp;nbsp;트랜잭션이&amp;nbsp;끼어들&amp;nbsp;수&amp;nbsp;없음&lt;br /&gt;지속성&amp;nbsp;-&amp;gt;&amp;nbsp;트랜잭션이&amp;nbsp;완료되면&amp;nbsp;데이터는&amp;nbsp;영구적으로&amp;nbsp;저장되어야한다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;쿠키&amp;nbsp;세션&lt;br /&gt;사용자의&amp;nbsp;상태를&amp;nbsp;저장하기&amp;nbsp;위한&amp;nbsp;기술&lt;br /&gt;쿠키는&amp;nbsp;클라이언트&amp;nbsp;서버&amp;nbsp;둘다&amp;nbsp;저장&lt;br /&gt;세션은&amp;nbsp;서버에&amp;nbsp;저장&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/166</guid>
      <comments>https://tin814.tistory.com/166#entry166comment</comments>
      <pubDate>Wed, 15 Apr 2026 14:04:29 +0900</pubDate>
    </item>
    <item>
      <title>프로그래밍 면접질문대비 스터디 1주차</title>
      <link>https://tin814.tistory.com/165</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  CS 기초&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q1. GET과 POST의 차이점에 대해서 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET과 POST는 &lt;b&gt;HTTP 메서드로&lt;/b&gt;, 가장 큰 차이는 데이터를 어디에 담느냐와 &lt;b&gt;목적&lt;/b&gt;에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GET&lt;/b&gt;은 데이터를 &lt;b&gt;URL의 쿼리스트링&lt;/b&gt;에 담아서 서버에 요청합니다. 주로 데이터를 조회할 때 사용하며, URL에 데이터가 노출되기 때문에 민감한 정보 전송에는 적합하지 않습니다. 또한 브라우저에 캐싱될 수 있고, URL 길이 제한이 있어 대용량 데이터 전송이 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;POST&lt;/b&gt;는 &lt;b&gt;데이터를 HTTP Body에 담아서&lt;/b&gt; 전송합니다. 주로 &lt;b&gt;데이터를 생성하거나 변경&lt;/b&gt;하는 작업에 사용하며, Body에 담기 때문에 URL에 노출되지 않아 상대적으로 안전합니다. 또한 데이터 크기 제한도 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면, GET은 &lt;b&gt;멱등성&lt;/b&gt;이 있어 같은 요청을 여러 번 해도 결과가 동일하지만, POST는 요청마다 서버 데이터가 달라질 수 있습니다.&lt;/p&gt;
&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;code&gt;쿼리스트링 vs Body&lt;/code&gt;, &lt;code&gt;조회 vs 생성&lt;/code&gt;, &lt;code&gt;캐싱&lt;/code&gt;, &lt;code&gt;멱등성&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;get은 주로 데이터를 조회할 때 사용하며 데이터를 url의 쿼리스트링에 담아서 서버에 요청합니다&lt;br /&gt;&amp;nbsp;url은 노출되는 부분이기때문에 민감한 정보 전송에는 적합하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;post&amp;nbsp;는&amp;nbsp;주로&amp;nbsp;데이터를&amp;nbsp;생성하거나&amp;nbsp;변경하는&amp;nbsp;작업에&amp;nbsp;사용하며&amp;nbsp;데이터를&amp;nbsp;HTTP&amp;nbsp;BODY에&amp;nbsp;담아서&amp;nbsp;전송합니다.&amp;nbsp;http&amp;nbsp;body는&amp;nbsp;url에&amp;nbsp;노출되지&amp;nbsp;않아&amp;nbsp;상대적으로는&amp;nbsp;안전합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q2. 객체 지향 프로그래밍이란 무엇인가요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍, 즉 &lt;b&gt;OOP(Object-Oriented Programming)&lt;/b&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OOP의 핵심 특징은 4가지입니다.&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;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;의 속성과 메서드를 자식 클래스가 물려받아 &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;하는 것입니다.&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;p data-ke-size=&quot;size16&quot;&gt;이러한 특성 덕분에 코드의 &lt;b&gt;재사용성&lt;/b&gt;, &lt;b&gt;유지보수성&lt;/b&gt;, &lt;b&gt;확장성&lt;/b&gt;이 높아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;캡슐화&lt;/code&gt;, &lt;code&gt;상속&lt;/code&gt;, &lt;code&gt;다형성&lt;/code&gt;, &lt;code&gt;추상화&lt;/code&gt;, &lt;code&gt;재사용성&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q3. HTTP와 HTTPS의 차이점에 대해서 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP&lt;/b&gt;는 HyperText Transfer Protocol의 약자로, 클라이언트와 서버 간 데이터를 주고받기 위한 통신 규약입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 HTTP는 데이터를 &lt;b&gt;평문(Plain Text)&lt;/b&gt; 으로 전송하기 때문에, 중간에 제3자가 데이터를 가로채면 내용이 그대로 노출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTPS&lt;/b&gt;는 HTTP에 &lt;b&gt;SSL/TLS&lt;/b&gt; 프로토콜을 추가한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 암호화하여 전송하기 때문에 중간에 가로채더라도 내용을 알 수 없습니다. 동작 과정에서는 서버가 &lt;b&gt;CA(인증 기관)&lt;/b&gt; 으로부터 발급받은 인증서를 클라이언트에 제공하고, 클라이언트는 이를 검증한 후 대칭키를 생성해 암호화 통신을 시작합니다. 이 과정을 &lt;b&gt;TLS Handshake&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 HTTPS는 데이터 암호화 외에도 &lt;b&gt;데이터 무결성&lt;/b&gt;(전송 중 변조 방지)과 &lt;b&gt;서버 인증&lt;/b&gt;(진짜 서버인지 확인)도 보장합니다. 때문에 로그인, 결제 등 민감한 정보를 다루는 서비스에서는 반드시 HTTPS를 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;SSL/TLS&lt;/code&gt;, &lt;code&gt;암호화&lt;/code&gt;, &lt;code&gt;TLS Handshake&lt;/code&gt;, &lt;code&gt;CA 인증서&lt;/code&gt;, &lt;code&gt;무결성&lt;/code&gt;&lt;/p&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는 암호화되지않은 https가 도입된 secure가 붙은 약자로서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http의 데이터를 암호화된 통신 프로토콜이 포함되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 제3자에게 정보가 노출되지 않을 숭 ㅣㅆ기땜누에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안에 신경쓴 통신규약&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? HTTPS 포트번호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 80 HTTPS 443&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? 암호화 계층에 대해 간단하게 설명해주세요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLS Handshake 과정에서 SSL인증서를 서버 공개키로 설정을 하면 클라ㅣ언트가 바아서 검증하고 검증이 끝나면 공개킬호 암호화한 세션키로 전송한 다음에 암호화된 통신을 그떄부터 시작을 해서 핸드쉐이크 해서 연결이 맺어져서 통신이 가능해지는 것&lt;/p&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를 사용하는 경우는 뭔가요? HTTPS가 무조건 좋은 거 아닌가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서빕스 관점에서는 https가 보안에 상대적으로 좋기 때문에 https를 사용하는 것이 맞다고 보고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스가 아닌 내부적으로 런칭이 되지않은 http를 사용하는게&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는&amp;nbsp;주요&amp;nbsp;이유가&amp;nbsp;아마도&amp;nbsp;인증서&amp;nbsp;비용과&amp;nbsp;웹&amp;nbsp;서버의&amp;nbsp;부하&amp;nbsp;때문이었을&amp;nbsp;것입니다.&amp;nbsp;하지만&amp;nbsp;오늘날에는&amp;nbsp;무료로&amp;nbsp;인증서를&amp;nbsp;얻을&amp;nbsp;수&amp;nbsp;있고,&amp;nbsp;클라우드&amp;nbsp;호스팅도&amp;nbsp;비교적&amp;nbsp;저렴합니다.&amp;nbsp;요즘&amp;nbsp;방문하는&amp;nbsp;대부분의&amp;nbsp;웹사이트는&amp;nbsp;https를&amp;nbsp;사용합니다.&amp;nbsp;더&amp;nbsp;이상&amp;nbsp;http만&amp;nbsp;사용할&amp;nbsp;이유는&amp;nbsp;없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;목적에 따라 다르지.&lt;br /&gt;집에서&amp;nbsp;뭐&amp;nbsp;테스트하는&amp;nbsp;거,&amp;nbsp;별로&amp;nbsp;안&amp;nbsp;중요한&amp;nbsp;거:&amp;nbsp;HTTP&lt;br /&gt;공격자한테&amp;nbsp;노출될&amp;nbsp;위험&amp;nbsp;0인&amp;nbsp;두&amp;nbsp;개체&amp;nbsp;간의&amp;nbsp;데이터&amp;nbsp;전송&amp;nbsp;(예:&amp;nbsp;별도&amp;nbsp;네트워크의&amp;nbsp;두&amp;nbsp;장치/컨테이너):&amp;nbsp;HTTP&lt;br /&gt;그&amp;nbsp;외:&amp;nbsp;HTTPS&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q4. 자바스크립트는 싱글 스레드인데 어떻게 비동기 처리가 가능한지 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 싱글 스레드로 동작하지만, 비동기 처리가 가능한 이유는 &lt;b&gt;이벤트 루프(Event Loop)&lt;/b&gt; 와 &lt;b&gt;Web API&lt;/b&gt; 덕분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적으로 설명하면, 자바스크립트 엔진에는 &lt;b&gt;콜 스택(Call Stack)&lt;/b&gt; 이 하나 있어서 코드를 순서대로 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 &lt;code&gt;setTimeout&lt;/code&gt;이나 &lt;code&gt;fetch&lt;/code&gt; 같은 비동기 작업이 들어오면, 이 작업들을 &lt;b&gt;브라우저의 Web API&lt;/b&gt;에게 넘깁니다. Web API는 별도의 스레드로 해당 작업을 처리하고, 완료되면 콜백 함수를 &lt;b&gt;태스크 큐(Task Queue)&lt;/b&gt; 에 넣습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이벤트 루프&lt;/b&gt;는 콜 스택이 비어 있는지 계속 확인하다가, 비어 있으면 태스크 큐에서 콜백을 꺼내 콜 스택에 올려 실행시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 자바스크립트 자체는 싱글 스레드지만, 무거운 비동기 작업은 &lt;b&gt;브라우저(또는 Node.js)의 환경&lt;/b&gt;에 위임하고, 그 결과만 이벤트 루프를 통해 받아처리하는 구조 덕분에 논블로킹 비동기 처리가 가능한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;이벤트 루프&lt;/code&gt;, &lt;code&gt;콜 스택&lt;/code&gt;, &lt;code&gt;Web API&lt;/code&gt;, &lt;code&gt;태스크 큐&lt;/code&gt;, &lt;code&gt;논블로킹&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하연: 자바스크립트 엔진 단독으로 동작하는게 아니라 브라우저나 nodejs같은 런타임 환경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 자체는 싱글스레드이지만 비동기 잡업은 브라우저나 런타임 환경으로 위임됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 상세히 말씀드ㄹ면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;settimeout이나 네트워크요청같은 비동기작더을 만나면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백그라운드로 넘기고 콜스택에서 제거한 이후&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업완료되면 콜백함수를 큐로 보내 대기시킵니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택이 비워지면 큐에있던 콜백을 스택으로 올려보내 실행하게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐에도 우선순위가 있다는것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이크로테스트 큐에들어가고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋타임아웃은 테스크 큐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 루프는 마이크로테스크 큐를 비우고 테스크 큐를 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한게 중요한 이유는 브라우저환겨에서 js실행과 ui렌더링이 같은 메인 스레드를 공유하기때문인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무거운 동기작업을 하면 화면을 멈추는 콜백 프로미스 어싱크어웨잇 적절한 비동기처리를 해주어야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? 비동기 처리가 뭔가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;가스불 하나씩 - 동기처리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;가스불 네개 다쓸 수있는데 하나 요리안끝나도 쓸 수있음 - 비동기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기는 안기다린다!! 멀티스레드처럼 가스불이 여러개있는거랑은 분리해서 생각해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기다리지 않&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? 자바스크립트에서 비동기 처리를 구현하는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setTime out으로 구현할 수 있다고 알고있ㅇ므&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;settimeout은 비동기를 볼 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백개념이 가장 기본적인 프로미스랑 어싱크어웨잇이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  백엔드&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q5. REST란 무엇인가요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST는 &lt;b&gt;Representational State Transfer&lt;/b&gt;의 약자로, 웹의 장점을 최대한 활용하기 위한 &lt;b&gt;소프트웨어 아키텍처 스타일&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP를 기반으로 클라이언트와 서버 간의 통신 규칙을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST의 핵심 원칙은 크게 6가지가 있는데, 실무에서 중요한 것들을 말씀드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, &lt;b&gt;자원(Resource) 기반 URI&lt;/b&gt;입니다. 모든 자원은 고유한 URI로 식별되며, 행위가 아닌 명사로 표현합니다. 예를 들어 &lt;code&gt;/users&lt;/code&gt;, &lt;code&gt;/users/1&lt;/code&gt; 이런 식으로요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;HTTP 메서드로 행위를 표현&lt;/b&gt;합니다. 조회는 GET, 생성은 POST, 수정은 PUT/PATCH, 삭제는 DELETE를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째, &lt;b&gt;무상태성(Stateless)&lt;/b&gt; 입니다. 서버는 클라이언트의 상태를 저장하지 않으며, 매 요청은 독립적으로 처리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 원칙을 잘 따른 API를 &lt;b&gt;RESTful API&lt;/b&gt;라고 하는데, 이를 통해 클라이언트와 서버가 &lt;b&gt;독립적으로 개발&lt;/b&gt;되고 &lt;b&gt;확장성&lt;/b&gt;이 높은 시스템을 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;자원 기반 URI&lt;/code&gt;, &lt;code&gt;HTTP 메서드&lt;/code&gt;, &lt;code&gt;무상태성&lt;/code&gt;, &lt;code&gt;RESTful&lt;/code&gt;&lt;/p&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;br /&gt;REST란 웹 기반 API를 설계하는 아키텍처이고 자원에 이름을 붙여서 상태를 주고받는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP URI를 통해 자원을 명시하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET post put delete등을 통해서 crud를 적용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? RESTful하지않은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자원 명시 규칙에 어긋나는 http 메서드 랑 중복되는의미가 들어가ㅓ는 update user find 같은 uri의 일므을 붙이면 restful하지못하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;? PUT PATCH중에 무엇을 쓰는ㄱ ㅓㅅ이 좋을까요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PATCH와 PUT은 자원의 전첼르 바꾸는가 일부를 바꾸는가에 대한 관점 차이인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 차이없다 PATCH 쓰지말라 혼용해서 쓰지말라 통일해서 써라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PUT으로 통일하는 팀도 있고, PATCH를 구분해서 쓰는 팀도 있습니다.&lt;br /&gt;저는&amp;nbsp;팀&amp;nbsp;컨벤션에&amp;nbsp;따르는&amp;nbsp;게&amp;nbsp;중요하다고&amp;nbsp;생각하며,&amp;nbsp;개인적으로는&amp;nbsp;단순함을&amp;nbsp;위해&amp;nbsp;PUT으로&amp;nbsp;통일하는&amp;nbsp;방식도&amp;nbsp;충분히&amp;nbsp;합리적이라고&amp;nbsp;생각합니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q6. 정규화에 대해 설명해주세요.&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;목적은 삽입, 수정, 삭제 시 발생하는 &lt;b&gt;이상 현상(Anomaly)&lt;/b&gt; 을 방지하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정규화는 단계별로 이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1NF(제1정규형)&lt;/b&gt;: 하나의 컬럼에는 원자적인 값(더 이상 나눌 수 없는 값)만 존재해야 합니다. 예를 들어, 전화번호 컬럼에 여러 번호가 들어가면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2NF(제2정규형)&lt;/b&gt;: 1NF를 만족하면서, 부분적 함수 종속을 제거합니다. 즉 복합 기본키에서 일부 키에만 종속된 컬럼을 분리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3NF(제3정규형)&lt;/b&gt;: 2NF를 만족하면서, 이행적 함수 종속을 제거합니다. 기본키가 아닌 컬럼이 다른 비기본키 컬럼에 종속되지 않아야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 정규화를 과도하게 적용하면 &lt;b&gt;조인이 많아져 성능이 저하&lt;/b&gt;될 수 있어서, 실무에서는 성능을 위해 의도적으로 중복을 허용하는 &lt;b&gt;역정규화(Denormalization)&lt;/b&gt; 를 적용하기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;데이터 중복 제거&lt;/code&gt;, &lt;code&gt;이상 현상&lt;/code&gt;, &lt;code&gt;1NF/2NF/3NF&lt;/code&gt;, &lt;code&gt;함수 종속성&lt;/code&gt;, &lt;code&gt;역정규화&lt;/code&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  프론트엔드&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q7. 브라우저에서 렌더링 원리에 대해서 설명해보세요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저의 렌더링 과정은 크게 5단계로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계 - 파싱:&lt;/b&gt; 브라우저는 서버로부터 받은 HTML을 파싱하여 &lt;b&gt;DOM(Document Object Model) 트리&lt;/b&gt;를 생성하고, CSS를 파싱하여 &lt;b&gt;CSSOM(CSS Object Model) 트리&lt;/b&gt;를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계 - 렌더 트리 생성:&lt;/b&gt; DOM과 CSSOM을 결합하여 실제 화면에 표시될 요소들만 포함한 &lt;b&gt;렌더 트리(Render Tree)&lt;/b&gt; 를 만듭니다. &lt;code&gt;display: none&lt;/code&gt;인 요소는 렌더 트리에 포함되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3단계 - 레이아웃(Layout / Reflow):&lt;/b&gt; 렌더 트리를 기반으로 각 요소의 &lt;b&gt;위치와 크기&lt;/b&gt;를 계산합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4단계 - 페인트(Paint):&lt;/b&gt; 계산된 스타일을 기반으로 요소를 실제 픽셀로 &lt;b&gt;화면에 그립니다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5단계 - 합성(Composite):&lt;/b&gt; 여러 레이어를 합쳐 최종 화면을 완성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, JavaScript가 DOM을 변경하면 &lt;b&gt;리플로우(Reflow)&lt;/b&gt; 나 &lt;b&gt;리페인트(Repaint)&lt;/b&gt; 가 발생할 수 있어 성능에 영향을 줍니다. 때문에 React 같은 프레임워크는 &lt;b&gt;Virtual DOM&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;1단계 문서파싱&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-1: HTML 파싱&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 HTML 문서를 파싱하여 DOM트리(Document Odject Model Tree)를 구성합니다 (DOM트리가뭔가요?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-2: CSS 파싱&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS 파일과 스타일 요소를 파싱하여 CSSOM트리 (CSS Object Model Tree)를 구성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2단계 렌더 트리 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구성한 DOM과 CSSOM을 결합하여 렌더트리를 형성합니다.&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;display:none인 요소는 포함하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;visibility:invisible은 공간은 차지하고 보이지 않게만 하기 때문에 렌더 트리에 포함됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3단계 레이아웃 계산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 노드의 정확한 위치와 크기를 각 속성과 스타일에 따라 어느 위치에 어느 크기로 출력될지 계산합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;계산된 레이아웃에 따라 노드를 실제화면에 그립니다. 이때 텍스트, 색, 이미지, 그림자 효과등이 모두 처리됩니다.&lt;/p&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단계 페인팅 이후&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떠한 액션이나 이벤트에 따라 수정되면 렌더 트리와 각 요소들의 크기와 위치를 다시 계산하고(Reflow) 다시 출력합니다(Repaint)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 현상을 줄이기 위해서는 visibility:invisible보다 display:none을 사용하고(공간차지안함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;transform 과&amp;nbsp; opacity는 Reflow Repaint가 일어나지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 left, right, width, height보다 &lt;b&gt;transform&lt;/b&gt;을, visibility보다 &lt;b&gt;display, opacity&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;완전 최종단계에서 transform 과 opacity를 사용하기 때문에 (2단계에서 일어남) 애니메이션은 transform과 opacity를 사용하는게 성능 면에서 유리하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접 답변:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;브라우저 렌더링은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199; color: #000000; text-align: start;&quot;&gt;HTML, CSS, JavaScript 등의 웹 페이지 자원을 브라우저가 화면에 그리는 과정&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;을 말합니다. 브라우저 렌더링 과정은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;HTML문서 파싱하여 DOM트리를 형성&lt;/span&gt;하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;CSS문서를 파싱해서 CSSOM트리를 형성&lt;/span&gt;하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;DOM트리와 CSSOM트리를 결합하여 렌더트리를 형성&lt;/span&gt;합니다. 브라우저는 렌더 트리를 이용해서 각 요소의 크기 위치를 계산하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;레이아웃&lt;/span&gt;을 거쳐 화면에 요소를 그리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;페인팅&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;과정을 거치게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;? HTML 파싱 중에 스크립트 태그를 만나게 되면 파싱을 멈추고 js가 먼저 실행되는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이떄 블로킹되지 않도록 처리하려면 어떻게 해야하는지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;파싱 블로킹이 되지 않기 위해서는 스크립트 태그를 바디 맨 아래에 두거나&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;스크립트 태그 안에 defer 라는 속성을 &lt;a href=&quot;https://weirdsector.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://weirdsector.tistory.com/55&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심 키워드:&lt;/b&gt; &lt;code&gt;DOM&lt;/code&gt;, &lt;code&gt;CSSOM&lt;/code&gt;, &lt;code&gt;렌더 트리&lt;/code&gt;, &lt;code&gt;Reflow&lt;/code&gt;, &lt;code&gt;Repaint&lt;/code&gt;, &lt;code&gt;Virtual DOM&lt;/code&gt;&lt;/p&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;DOM트리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML의 각 태그를 노드 객체로 변환하여 계층구조(트리)로 만듭니다.&lt;/p&gt;
&lt;pre id=&quot;code_1775537352759&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 원본 HTML --&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;안녕하세요&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;반갑습니다&amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1775537362202&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DOM 트리로 변환:

Document
└── html
    └── body
        ├── h1  &amp;rarr;  &quot;안녕하세요&quot;
        └── p   &amp;rarr;  &quot;반갑습니다&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* JavaScript에서 document.querySelector('h1') 같은 걸 쓸 수 있는 이유가 바로 이 DOM 트리가 만들어졌기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSSOM 트리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS파일의 요소에 어떤 스타일이 적용되는지 트리로 표현한 것&lt;/p&gt;
&lt;pre id=&quot;code_1775537441618&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;body { font-size: 16px; }
h1   { color: blue; }
p    { color: gray; }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1775537448577&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CSSOM 트리:

body (font-size: 16px)
├── h1 (color: blue, font-size: 16px 상속)
└── p  (color: gray, font-size: 16px 상속)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* CSS는 상속(Cascading) 이 있기 때문에, 부모에 적용된 스타일이 자식으로 내려가는 것도 CSSOM이 계산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 두 개를 따로 만드나요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML과 CSS는 역할이 다르기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 트리를 합쳐서 렌더 트리(Render Tree)를 만들어 그걸 기반으로 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더트리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM&amp;nbsp;트리&amp;nbsp;+&amp;nbsp;CSSOM&amp;nbsp;트리&amp;nbsp;=&amp;nbsp;렌더&amp;nbsp;트리&lt;br /&gt;&quot;실제로&amp;nbsp;화면에&amp;nbsp;보여줄&amp;nbsp;것들만&quot;&amp;nbsp;골라서&amp;nbsp;스타일까지&amp;nbsp;붙인&amp;nbsp;트리&lt;/p&gt;
&lt;pre id=&quot;code_1775537573750&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DOM 트리              CSSOM 트리
─────────             ──────────
html                  body
└── body              ├── h1  { color: blue, font-size: 24px }
    ├── h1            ├── p   { display: none }
    ├── p             └── span{ color: gray }
    └── span

           &amp;darr; 결합 (display:none 제외!)

         렌더 트리
         ─────────
         body
         ├── h1   { color: blue, font-size: 24px }
         └── span { color: gray }
         
         &amp;larr; p는 display:none 이라 렌더 트리에서 제외! ❌&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q8. SPA에서 라우팅이 어떻게 동작하나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적인 MPA(Multi Page Application)에서는 페이지를 이동할 때마다 서버에 새로운 HTML을 요청했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;SPA(Single Page Application)&lt;/b&gt; 에서는 최초에 HTML을 한 번만 받고, 이후 페이지 이동은 &lt;b&gt;JavaScript가 직접 화면을 교체&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;SPA 라우팅 방식에는 크게 두 가지가 있습니다.&lt;/p&gt;
&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;Hash 방식&lt;/b&gt;: URL에서 &lt;code&gt;#&lt;/code&gt; 뒤의 값이 바뀌어도 브라우저는 서버에 요청을 보내지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜&amp;nbsp;서버&amp;nbsp;요청이&amp;nbsp;없냐?&lt;br /&gt;#&amp;nbsp;뒤의&amp;nbsp;값(해시)은&amp;nbsp;원래부터&amp;nbsp;브라우저&amp;nbsp;내부에서만&amp;nbsp;사용하는&amp;nbsp;값이에요.&lt;br /&gt;서버엔&amp;nbsp;절대&amp;nbsp;전송하지&amp;nbsp;않는&amp;nbsp;게&amp;nbsp;브라우저의&amp;nbsp;규칙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 이용해 JavaScript가 &lt;code&gt;#&lt;/code&gt; 이후 값을 읽어 화면을 전환합니다. 예) &lt;code&gt;example.com/#/home&lt;/code&gt;&lt;/p&gt;
&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;(React Router의 방식)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;History API 방식&lt;/b&gt;: HTML5의 &lt;code&gt;history.pushState()&lt;/code&gt; API를 사용하여 URL을 변경하되 서버 요청 없이 화면만 바꿉니다.&lt;br /&gt;이&amp;nbsp;함수는&amp;nbsp;&quot;URL은&amp;nbsp;바꾸되&amp;nbsp;서버에&amp;nbsp;요청은&amp;nbsp;보내지&amp;nbsp;마&quot;&amp;nbsp;라는&amp;nbsp;특별한&amp;nbsp;명령입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React Router가 이 방식을 사용합니다. 예) &lt;code&gt;example.com/home&lt;/code&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1775537870123&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 버튼 클릭 시
document.getElementById('menuBtn').addEventListener('click', () =&amp;gt; {
  
  // URL을 /menu 로 바꾸지만 서버 요청 ❌
  history.pushState(null, '', '/menu');
  
  // JavaScript가 직접 화면을 교체
  document.getElementById('app').innerHTML = '&amp;lt;h1&amp;gt;메뉴 페이지&amp;lt;/h1&amp;gt;';
});&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1775537911788&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;처음 접속: myapp.com
       &amp;darr;
서버가 index.html 딱 한 번 전송
(+ React/Vue 앱 전체 JS 코드 포함)
       &amp;darr;
이후부터는 JS가 모든 걸 관리

유저: /menu 클릭
       &amp;darr;
┌──────────────────────────────────┐
│  React Router가 중간에서 가로챔   │
│  &quot;서버야 잠깐, 내가 처리할게&quot;     │
└──────────────────────────────────┘
       &amp;darr;
history.pushState('/menu') &amp;rarr; URL만 변경
       &amp;darr;
React가 &amp;lt;MenuPage /&amp;gt; 컴포넌트 렌더링
       &amp;darr;
서버 요청 없이 화면 전환 완료! ✅&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로고침&amp;nbsp;문제&amp;nbsp;(중요!)&lt;br /&gt;History&amp;nbsp;API&amp;nbsp;방식의&amp;nbsp;함정이&amp;nbsp;있어요.&lt;/p&gt;
&lt;pre id=&quot;code_1775537983027&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;유저가 myapp.com/menu 에서 새로고침 누름
       &amp;darr;
브라우저: &quot;서버야, /menu 페이지 줘!&quot;
       &amp;darr;
서버: &quot;??? /menu 파일이 없는데...&quot; &amp;rarr; 404 에러  &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;History API 방식은 URL이 깔끔하지만, 새로고침 시 서버에 해당 경로로 요청이 가기 때문에 &lt;b&gt;서버에서 모든 경로에 대해 동일한 &lt;code&gt;index.html&lt;/code&gt;을 반환&lt;/b&gt;하도록 설정해야 합니다. 이를 &lt;b&gt;Fallback 설정&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1775537993381&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;서버 설정: &quot;어떤 URL로 요청이 와도 index.html 줘&quot;
       &amp;darr;
index.html 받음
       &amp;darr;
JS 앱이 로드되면서 URL을 보고 /menu 화면 렌더링 ✅&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;code&gt;History API&lt;/code&gt;, &lt;code&gt;pushState&lt;/code&gt;, &lt;code&gt;Hash 라우팅&lt;/code&gt;, &lt;code&gt;index.html Fallback&lt;/code&gt;, &lt;code&gt;React Router&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;SPA는&amp;nbsp;최초&amp;nbsp;접속&amp;nbsp;시&amp;nbsp;index.html&amp;nbsp;하나만&amp;nbsp;받고,&amp;nbsp;이후&amp;nbsp;페이지&amp;nbsp;이동은&amp;nbsp;history.pushState()&amp;nbsp;API로&amp;nbsp;URL만&amp;nbsp;바꾸고&amp;nbsp;JavaScript가&amp;nbsp;화면을&amp;nbsp;교체합니다.&amp;nbsp;서버&amp;nbsp;요청&amp;nbsp;없이&amp;nbsp;동작하기&amp;nbsp;때문에&amp;nbsp;빠르고&amp;nbsp;부드럽지만,&amp;nbsp;새로고침&amp;nbsp;시&amp;nbsp;서버에서&amp;nbsp;404가&amp;nbsp;나지&amp;nbsp;않도록&amp;nbsp;모든&amp;nbsp;경로에&amp;nbsp;index.html을&amp;nbsp;반환하는&amp;nbsp;Fallback&amp;nbsp;설정이&amp;nbsp;필요합니다.&quot;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에서 적용한 사례를 1~2문장 연결하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아는 부분은 자신있게 모르는 부분은 솔직하게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피드백 추가질문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동기 비동기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async await&amp;nbsp;&lt;/p&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/165</guid>
      <comments>https://tin814.tistory.com/165#entry165comment</comments>
      <pubDate>Tue, 7 Apr 2026 13:35:02 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 5.3 비선형 자료 구조</title>
      <link>https://tin814.tistory.com/164</link>
      <description>&lt;h1&gt;비선형 자료 구조&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비선형 자료 구조란 일렬로 나열하지 않고 &lt;b&gt;자료 순서나 관계가 복잡한 구조&lt;/b&gt;를 말합니다.&lt;br /&gt;일반적으로 &lt;b&gt;트리&lt;/b&gt;나 &lt;b&gt;그래프&lt;/b&gt;를 말합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.1 그래프&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 &lt;b&gt;정점(vertex)&lt;/b&gt; 과 &lt;b&gt;간선(edge)&lt;/b&gt; 으로 이루어진 자료 구조입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정점과 간선&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;어떠한 곳에서 어떠한 곳으로 무언가를 통해 간다&quot;&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; &amp;rarr; 정점(vertex)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무언가(길)&lt;/b&gt; &amp;rarr; 간선(edge)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;개념&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;단방향 간선&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;한쪽 방향으로만 갈 수 있음 (예: 짝사랑)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;양방향 간선&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;양쪽 방향 모두 갈 수 있음 (예: 서로 좋아함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;outdegree&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;해당 정점에서 &lt;b&gt;나가는&lt;/b&gt; 간선의 수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;indegree&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;해당 정점으로 &lt;b&gt;들어오는&lt;/b&gt; 간선의 수&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 &quot;U에서부터 V로 간다.&quot;라고 표현합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가중치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간선과 정점 사이에 드는 &lt;b&gt;비용&lt;/b&gt;을 뜻합니다.&lt;br /&gt;예) 성남 &amp;rarr; 네이버까지 택시비가 13,000원이라면, 해당 간선의 가중치는 &lt;b&gt;13,000원&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.2 트리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 그래프의 일종으로, &lt;b&gt;정점과 간선&lt;/b&gt;으로 이루어진 &lt;b&gt;계층적 데이터의 집합&lt;/b&gt;입니다.&lt;br /&gt;루트 노드, 내부 노드, 리프 노드 등으로 구성됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  트리로 이루어진 집합을 &lt;b&gt;숲(forest)&lt;/b&gt; 이라고 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트리의 특징&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;부모-자식 계층 구조&lt;/b&gt;를 가집니다.&lt;br /&gt;같은 경로상에서 위에 있으면 부모, 아래에 있으면 자식 노드&lt;/li&gt;
&lt;li&gt;&lt;b&gt;V - 1 = E&lt;/b&gt; : 간선 수 = 노드 수 - 1&lt;/li&gt;
&lt;li&gt;임의의 두 노드 사이의 경로는 &lt;b&gt;유일하게 존재&lt;/b&gt;합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트리의 구성&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;노드 종류&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;루트 노드&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가장 위에 있는 노드. 트리 탐색의 시작점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;내부 노드&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;루트 노드와 리프 노드 사이에 있는 노드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;리프 노드&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자식 노드가 없는 노드 (끝 노드)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트리의 높이와 레벨&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;용어&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;깊이&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;루트 노드부터 특정 노드까지의 최단 거리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;높이&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;루트 노드부터 리프 노드까지 거리 중 가장 긴 거리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;레벨&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;보통 깊이와 같은 의미 (문제마다 기준이 다를 수 있음)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;서브트리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;트리 내의 하위 집합 (부분집합)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이진 트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 노드 수가 &lt;b&gt;두 개 이하&lt;/b&gt;인 트리&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;정이진 트리&lt;/b&gt; (full binary tree)&lt;/td&gt;
&lt;td&gt;자식 노드가 0개 또는 2개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;완전 이진 트리&lt;/b&gt; (complete binary tree)&lt;/td&gt;
&lt;td&gt;왼쪽부터 채워져 있으며, 마지막 레벨만 비어있을 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;변질 이진 트리&lt;/b&gt; (degenerate binary tree)&lt;/td&gt;
&lt;td&gt;자식 노드가 하나밖에 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;포화 이진 트리&lt;/b&gt; (perfect binary tree)&lt;/td&gt;
&lt;td&gt;모든 노드가 꽉 차 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;균형 이진 트리&lt;/b&gt; (balanced binary tree)&lt;/td&gt;
&lt;td&gt;왼쪽/오른쪽 높이 차이가 최대 1 (예: 레드 블랙 트리)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이진 탐색 트리 (BST)&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;오른쪽&lt;/b&gt; 하위 트리: 노드 값보다 &lt;b&gt;큰&lt;/b&gt; 값&lt;/li&gt;
&lt;li&gt;&lt;b&gt;왼쪽&lt;/b&gt; 하위 트리: 노드 값보다 &lt;b&gt;작은&lt;/b&gt; 값&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;평균&lt;/th&gt;
&lt;th&gt;최악&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;탐색 / 삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 삽입 순서에 따라 &lt;b&gt;선형(편향) 트리&lt;/b&gt;가 될 수 있어 최악 O(n)이 발생할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AVL 트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AVL 트리(Adelson-Velsky and Landis tree)는 BST의 최악 케이스를 방지하기 위해 &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;항상 최대 1&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;삽입/삭제 시 균형이 깨지면 &lt;b&gt;트리를 회전&lt;/b&gt;시켜 균형을 복원&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;탐색 / 삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레드 블랙 트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;균형 이진 탐색 트리로, C++ STL의 &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;multiset&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;multimap&lt;/code&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; 또는 &lt;b&gt;검은색&lt;/b&gt; 비트를 추가로 저장&lt;/li&gt;
&lt;li&gt;&quot;모든 리프 노드와 루트 노드는 블랙, 레드 노드의 자식은 반드시 블랙&quot; 등의 규칙으로 균형 유지&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;탐색 / 삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.3 힙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙은 &lt;b&gt;완전 이진 트리&lt;/b&gt; 기반의 자료 구조입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;최대힙&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;루트 노드가 항상 &lt;b&gt;최댓값&lt;/b&gt; (부모 &amp;ge; 자식, 재귀적으로 적용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;최소힙&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;루트 노드가 항상 &lt;b&gt;최솟값&lt;/b&gt; (부모 &amp;le; 자식, 재귀적으로 적용)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최대힙의 삽입&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새 노드를 &lt;b&gt;마지막 노드&lt;/b&gt;에 삽입&lt;/li&gt;
&lt;li&gt;부모 노드와 비교하며 &lt;b&gt;위로 올라가며 스왑&lt;/b&gt; &amp;rarr; 힙 조건 만족&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최대힙의 삭제&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;루트 노드(최댓값)&lt;/b&gt; 삭제&lt;/li&gt;
&lt;li&gt;마지막 노드를 루트로 올린 후 &lt;b&gt;아래로 내려가며 스왑&lt;/b&gt; &amp;rarr; 재구성&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.4 우선순위 큐&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위 큐는 &lt;b&gt;우선순위가 높은 요소가 먼저 나오는&lt;/b&gt; 자료 구조입니다.&lt;br /&gt;힙을 기반으로 구현됩니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

priority_queue&amp;lt;int, vector&amp;lt;int&amp;gt;, greater&amp;lt;int&amp;gt;&amp;gt; pq; // 오름차순 (최소힙)
// priority_queue&amp;lt;int, vector&amp;lt;int&amp;gt;, less&amp;lt;int&amp;gt;&amp;gt; pq; // 내림차순 (최대힙)

int main() {
    pq.push(5);
    pq.push(4);
    pq.push(3);
    pq.push(2);
    pq.push(1);
    cout &amp;lt;&amp;lt; pq.top() &amp;lt;&amp;lt; &quot;\n&quot;;
    return 0;
}
/*
1
*/&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;greater&lt;/code&gt; &amp;rarr; 오름차순(최소 우선), &lt;code&gt;less&lt;/code&gt; &amp;rarr; 내림차순(최대 우선)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.5 맵&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맵(map)은 &lt;b&gt;키(key)와 값(value)의 쌍&lt;/b&gt;으로 이루어진 자료 구조입니다.&lt;br /&gt;레드 블랙 트리 기반으로 구현되며, &lt;b&gt;삽입 시 자동 정렬&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;정렬 보장&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;map&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ 정렬 보장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unordered_map&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ 정렬 없음 (해시 기반, 더 빠름)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 함수: &lt;code&gt;insert()&lt;/code&gt;, &lt;code&gt;emplace()&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;find()&lt;/code&gt;, &lt;code&gt;erase()&lt;/code&gt;, &lt;code&gt;size()&lt;/code&gt;, &lt;code&gt;clear()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int main() {
    unordered_map&amp;lt;string, int&amp;gt; umap;

    umap.insert({&quot;test1&quot;, 1});   // insert로 추가
    umap.emplace(&quot;test5&quot;, 5);    // emplace로 추가
    umap[&quot;test1&quot;] = 4;           // 값 변경 (권장 방식)

    for (auto element : umap) {
        cout &amp;lt;&amp;lt; element.first &amp;lt;&amp;lt; &quot; :: &quot; &amp;lt;&amp;lt; element.second &amp;lt;&amp;lt; '\n';
    }

    auto search = umap.find(&quot;test4&quot;);
    if (search != umap.end()) {
        cout &amp;lt;&amp;lt; &quot;found: &quot; &amp;lt;&amp;lt; search-&amp;gt;first &amp;lt;&amp;lt; &quot; &quot; &amp;lt;&amp;lt; (*search).second &amp;lt;&amp;lt; '\n';
    } else {
        cout &amp;lt;&amp;lt; &quot;not found..&quot; &amp;lt;&amp;lt; '\n';
    }

    umap[&quot;test1&quot;]++;
    cout &amp;lt;&amp;lt; umap[&quot;test1&quot;] &amp;lt;&amp;lt; &quot;\n&quot;;
    cout &amp;lt;&amp;lt; umap.size() &amp;lt;&amp;lt; &quot;\n&quot;;

    umap.erase(&quot;test1&quot;);
    cout &amp;lt;&amp;lt; umap.size() &amp;lt;&amp;lt; &quot;\n&quot;;
    return 0;
}
/*
test5 :: 5
test1 :: 4
not found..
5
2
1
*/&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순회 시 &lt;code&gt;element.first&lt;/code&gt; &amp;rarr; 키, &lt;code&gt;element.second&lt;/code&gt; &amp;rarr; 값&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.6 셋&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋(set)은 &lt;b&gt;고유한(unique) 값만 저장&lt;/b&gt;하는 컨테이너입니다.&lt;br /&gt;중복 요소가 없으며, 특정 순서에 따라 요소를 저장합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;pair&lt;/code&gt;는 두 가지 형을 담을 수 있는 구조이며 &lt;code&gt;first&lt;/code&gt;, &lt;code&gt;second&lt;/code&gt;로 접근합니다.&lt;br /&gt;나머지 사용법은 &lt;code&gt;map&lt;/code&gt;과 유사합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3.7 해시 테이블&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블은 &lt;b&gt;무한에 가까운 데이터를 유한한 해시 값으로 매핑&lt;/b&gt;한 테이블입니다.&lt;br /&gt;C++에서는 &lt;code&gt;unordered_map&lt;/code&gt;으로 구현합니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;평균 시간 복잡도&lt;/th&gt;
&lt;th&gt;최악 시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;삽입 / 삭제 / 탐색&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 해시 충돌이 많이 발생하면 최악 O(n)까지 떨어질 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/164</guid>
      <comments>https://tin814.tistory.com/164#entry164comment</comments>
      <pubDate>Wed, 25 Mar 2026 14:39:51 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 5.2 선형 자료 구조</title>
      <link>https://tin814.tistory.com/163</link>
      <description>&lt;h1&gt;선형 자료 구조&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선형 자료 구조란 요소가 &lt;b&gt;일렬로 나열&lt;/b&gt;되어 있는 자료 구조를 말합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2.1 연결 리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결 리스트는 데이터를 감싼 &lt;b&gt;노드를 포인터로 연결&lt;/b&gt;해서 공간적인 효율성을 극대화시킨 자료 구조입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;탐색&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;prev&lt;/code&gt; 포인터와 &lt;code&gt;next&lt;/code&gt; 포인터로 앞과 뒤의 노드를 연결한 구조이며, 맨 앞에 있는 노드를 &lt;b&gt;헤드(head)&lt;/b&gt; 라고 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;종류&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;싱글 연결 리스트&lt;/td&gt;
&lt;td&gt;&lt;code&gt;next&lt;/code&gt; 포인터만 가짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이중 연결 리스트&lt;/td&gt;
&lt;td&gt;&lt;code&gt;next&lt;/code&gt; + &lt;code&gt;prev&lt;/code&gt; 포인터 둘 다 가짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;원형 이중 연결 리스트&lt;/td&gt;
&lt;td&gt;이중 연결 리스트와 같지만, 마지막 노드의 &lt;code&gt;next&lt;/code&gt;가 헤드 노드를 가리킴&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 책에서는 &lt;b&gt;이중 연결 리스트&lt;/b&gt; 를 기반으로 설명합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 함수: &lt;code&gt;push_front()&lt;/code&gt;, &lt;code&gt;push_back()&lt;/code&gt;, &lt;code&gt;insert()&lt;/code&gt;, &lt;code&gt;pop_front()&lt;/code&gt;, &lt;code&gt;pop_back()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int main() {
    list&amp;lt;int&amp;gt; a;
    for (int i = 0; i &amp;lt; 10; i++) a.push_back(i);
    for (int i = 0; i &amp;lt; 10; i++) a.push_front(i);

    auto it = a.begin(); it++;
    a.insert(it, 1000);

    for (auto it : a) cout &amp;lt;&amp;lt; it &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; '\n';

    a.pop_front();
    a.pop_back();

    for (auto it : a) cout &amp;lt;&amp;lt; it &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; '\n';

    return 0;
}
/*
9 1000 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9
1000 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8
*/&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2.2 배열&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열(array)은 &lt;b&gt;같은 타입의 변수들&lt;/b&gt;로 이루어져 있고, &lt;b&gt;크기가 정해져 있으며&lt;/b&gt;, &lt;b&gt;인접한 메모리 위치&lt;/b&gt;에 있는 데이터를 모아놓은 집합입니다. 중복을 허용하고 순서가 있습니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;접근(참조)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어떤 걸 써야 할까?&lt;/b&gt;&lt;/p&gt;
&lt;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; 가 많다 &amp;rarr; &lt;b&gt;연결 리스트&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;데이터 &lt;b&gt;접근/참조&lt;/b&gt; 가 많다 &amp;rarr; &lt;b&gt;배열&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;랜덤 접근 vs 순차적 접근&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;랜덤 접근&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;임의의 인덱스에 동일한 시간에 바로 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;순차적 접근&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;저장된 순서대로 처음부터 하나씩 검색&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 vs 연결 리스트 비교&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;배열&lt;/th&gt;
&lt;th&gt;연결 리스트&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;n번째 요소 접근&lt;/td&gt;
&lt;td&gt;O(1) ⚡ 빠름&lt;/td&gt;
&lt;td&gt;O(n)   느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데이터 추가/삭제&lt;/td&gt;
&lt;td&gt;O(n)   느림&lt;/td&gt;
&lt;td&gt;O(1) ⚡ 빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비유&lt;/td&gt;
&lt;td&gt;번호 붙은 상자 &amp;rarr; 번호만 알면 바로 꺼냄&lt;/td&gt;
&lt;td&gt;선으로 연결된 상자 &amp;rarr; 하나씩 열어봐야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int a[10];

int main() {
    for (int i = 0; i &amp;lt; 10; i++) a[i] = i;
    for (auto it : a) cout &amp;lt;&amp;lt; it &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; '\n';
    return 0;
}
/*
0 1 2 3 4 5 6 7 8 9
*/&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2.3 벡터&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터(vector)는 &lt;b&gt;동적으로 요소를 할당&lt;/b&gt;할 수 있는 &lt;b&gt;동적 배열&lt;/b&gt;입니다.&lt;br /&gt;컴파일 시점에 개수를 모른다면 벡터를 써야 합니다. 중복을 허용하고 순서가 있으며 랜덤 접근이 가능합니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;탐색&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;맨 뒤 삽입/삭제 (&lt;code&gt;push_back&lt;/code&gt;, &lt;code&gt;pop_back&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;중간 삽입/삭제&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;push_back()이 O(1)인 이유 &amp;mdash; amortized 복잡도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 배열 크기를 늘리는 게 아니라, &lt;b&gt;2의 제곱승 + 1마다 크기를 2배&lt;/b&gt; 로 늘립니다.&lt;br /&gt;n번 &lt;code&gt;push_back()&lt;/code&gt;을 했을 때 평균 비용은 약 &lt;b&gt;3&lt;/b&gt; 으로, 상수에 수렴하기 때문에 &lt;b&gt;amortized O(1)&lt;/b&gt; 이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 함수: &lt;code&gt;push_back()&lt;/code&gt;, &lt;code&gt;pop_back()&lt;/code&gt;, &lt;code&gt;erase()&lt;/code&gt;, &lt;code&gt;find()&lt;/code&gt;, &lt;code&gt;fill()&lt;/code&gt;, &lt;code&gt;clear()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

vector&amp;lt;int&amp;gt; v;

int main() {
    for (int i = 1; i &amp;lt;= 10; i++) v.push_back(i);
    for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; &quot;\n&quot;;

    v.pop_back();
    for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; &quot;\n&quot;;

    v.erase(v.begin(), v.begin() + 1);
    for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; &quot;\n&quot;;

    auto a = find(v.begin(), v.end(), 100);
    if (a == v.end()) cout &amp;lt;&amp;lt; &quot;not found&quot; &amp;lt;&amp;lt; &quot;\n&quot;;

    fill(v.begin(), v.end(), 10);
    for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; &quot;\n&quot;;

    v.clear();
    for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &quot; &quot;;
    cout &amp;lt;&amp;lt; &quot;\n&quot;;

    return 0;
}
/*
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
not found
10 10 10 10 10 10 10 10

*/&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;벡터 순회 방법 (두 가지는 동일)&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;for (int a : v) cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; '\n';
for (int i = 0; i &amp;lt; v.size(); i++) cout &amp;lt;&amp;lt; v[i] &amp;lt;&amp;lt; '\n';&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터에 &lt;code&gt;pair&lt;/code&gt; 값이 들어간다면 &amp;rarr; &lt;code&gt;for (pair&amp;lt;int,int&amp;gt; a : v)&lt;/code&gt; 방식으로 순회&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2.4 스택&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택(stack)은 &lt;b&gt;가장 마지막으로 들어간 데이터가 가장 먼저 나오는&lt;/b&gt; 성질을 가진 자료 구조입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LIFO&lt;/b&gt; (Last In First Out)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;탐색&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;활용 예시&lt;/b&gt;: 재귀 함수/알고리즘, 웹 브라우저 방문 기록, 실행 취소(Undo)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2.5 큐&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐(queue)는 &lt;b&gt;먼저 집어넣은 데이터가 먼저 나오는&lt;/b&gt; 성질을 지닌 자료 구조입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FIFO&lt;/b&gt; (First In First Out) &amp;mdash; 스택과 반대 개념&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산&lt;/th&gt;
&lt;th&gt;시간 복잡도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;삽입 / 삭제&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;탐색&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;활용 예시&lt;/b&gt;: CPU 프로세스/스레드 대기열, 네트워크 접속 대기열, 너비 우선 탐색(BFS), 캐시&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;SECTION 5.3 비선형 자료 구조&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비선형 자료 구조란 일렬로 나열하지 않고 &lt;b&gt;자료 순서나 관계가 복잡한 구조&lt;/b&gt;를 말합니다.&lt;br /&gt;일반적으로 &lt;b&gt;트리&lt;/b&gt;나 &lt;b&gt;그래프&lt;/b&gt;를 말합니다.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/163</guid>
      <comments>https://tin814.tistory.com/163#entry163comment</comments>
      <pubDate>Wed, 25 Mar 2026 14:39:46 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 5.1 복잡도</title>
      <link>https://tin814.tistory.com/162</link>
      <description>&lt;h1&gt;자료 구조(Data Structure) 기초 — 복잡도 완벽 정리&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;자료 구조(data structure)란 효율적으로 데이터를 관리하고 수정, 삭제, 탐색, 저장할 수 있는 데이터 집합을 말합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;  사전 지식 — STL이란?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;STL(Standard Template Library)&lt;/strong&gt; 은 C++의 표준 템플릿 라이브러리로, 스택·배열 등 다양한 자료 구조와 알고리즘 함수를 제공하는 라이브러리 묶음입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  C++는 어려운 언어처럼 느껴지지만, 자료 구조를 공부하는 수준에서는 매우 쉬운 난이도만 알아도 충분합니다.&lt;br&gt;별도 설치 없이 아래 링크에서 바로 실행해볼 수 있어요.&lt;br&gt;  &lt;a href=&quot;https://www.onlinegdb.com/online_c++_compiler&quot;&gt;C++ 온라인 컴파일러&lt;/a&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;5.1 복잡도&lt;/h2&gt;
&lt;p&gt;복잡도는 크게 두 가지로 나뉩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;시간 복잡도&lt;/strong&gt; — 알고리즘 실행에 걸리는 시간&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;공간 복잡도&lt;/strong&gt; — 알고리즘 실행에 필요한 메모리 공간&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;5.1.1 시간 복잡도&lt;/h2&gt;
&lt;h3&gt;C++ 기본 문법 훑기&lt;/h3&gt;
&lt;p&gt;시간 복잡도에 앞서, C++의 기본 구조를 간단히 살펴보겠습니다.&lt;br&gt;아래는 입력받은 문자열을 출력하는 가장 간단한 예제입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;bits/stdc++.h&amp;gt;  // (1) STL 전체 포함 헤더
using namespace std;      // (2) std 네임스페이스 기본 설정
string a;                 // (3) 문자열 변수 선언

int main()
{
    cin &amp;gt;&amp;gt; a;             // (4) 입력
    cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;    // (5) 출력
    return 0;             // (6) 프로세스 정상 종료
}&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;번호&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;(1)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bits/stdc++.h&lt;/code&gt; — 모든 표준 라이브러리가 포함된 헤더&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(2)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::cin&lt;/code&gt; → &lt;code&gt;cin&lt;/code&gt; 처럼 네임스페이스 없이 사용 가능하게 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(3)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;타입&amp;gt; &amp;lt;변수명&amp;gt;&lt;/code&gt; 형태로 선언. &lt;code&gt;a&lt;/code&gt;는 lvalue, &lt;code&gt;&amp;quot;큰돌&amp;quot;&lt;/code&gt;은 rvalue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4)&lt;/td&gt;
&lt;td&gt;입력: &lt;code&gt;cin&lt;/code&gt;, &lt;code&gt;scanf&lt;/code&gt; 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(5)&lt;/td&gt;
&lt;td&gt;출력: &lt;code&gt;cout&lt;/code&gt;, &lt;code&gt;printf&lt;/code&gt; 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(6)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;return 0&lt;/code&gt; — 정상 종료 신호&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;빅오(Big-O) 표기법&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;시간 복잡도 = &lt;strong&gt;입력 크기 n에 대해 알고리즘이 실행되는 데 걸리는 시간&lt;/strong&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;주요 로직의 &lt;strong&gt;반복 횟수&lt;/strong&gt;를 기준으로 측정하며, &lt;strong&gt;빅오 표기법&lt;/strong&gt;으로 나타냅니다.&lt;/p&gt;
&lt;p&gt;예를 들어 아래 코드의 시간 복잡도를 계산해봅시다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;for (int i = 0; i &amp;lt; 10; i++) {
    for (int j = 0; j &amp;lt; n; j++) {
        for (int k = 0; k &amp;lt; n; k++) {
            if (true) cout &amp;lt;&amp;lt; k &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;  // 10 * n * n 번 실행
        }
    }
}
for (int i = 0; i &amp;lt; n; i++) {
    if (true) cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &amp;#39;\n&amp;#39;;          // n번 실행
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;총 연산량 = &lt;code&gt;10n² + n&lt;/code&gt;&lt;br&gt;→ 빅오 표기법으로는 &lt;strong&gt;O(n²)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;핵심 원칙&lt;/strong&gt;: 가장 영향이 큰 항만 남기고, 상수 계수와 하위 항은 제거합니다.&lt;br&gt;n이 커질수록 &lt;code&gt;n²&lt;/code&gt;이 압도적으로 커지기 때문에 나머지는 무시해도 됩니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h3&gt;시간 복잡도가 왜 필요한가?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;효율적인 코드로 개선하는 척도&lt;/strong&gt;가 되기 때문입니다.&lt;/p&gt;
&lt;p&gt;예를 들어 어떤 버튼을 누를 때 &lt;code&gt;O(n²)&lt;/code&gt; 알고리즘으로 9초가 걸린다면,&lt;br&gt;이를 &lt;code&gt;O(n)&lt;/code&gt; 알고리즘으로 개선하면 &lt;strong&gt;3초&lt;/strong&gt;로 줄일 수 있습니다.&lt;/p&gt;
&lt;h3&gt;속도 비교&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;O(1) &amp;lt; O(log n) &amp;lt; O(n) &amp;lt; O(n log n) &amp;lt; O(n²) &amp;lt; O(2ⁿ)&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;O(n²)&lt;/strong&gt; 보다는 &lt;strong&gt;O(n)&lt;/strong&gt;, &lt;strong&gt;O(n)&lt;/strong&gt; 보다는 &lt;strong&gt;O(1)&lt;/strong&gt; 을 항상 지향하세요.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;5.1.2 공간 복잡도&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;공간 복잡도 = &lt;strong&gt;프로그램 실행 시 필요한 자원(메모리) 공간의 양&lt;/strong&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;정적 변수뿐만 아니라, &lt;strong&gt;재귀 함수로 인해 동적으로 쌓이는 공간&lt;/strong&gt;도 포함합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;int a[1004];  // 1004 × 4바이트 = 약 4KB 사용&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;5.1.3 자료 구조별 시간 복잡도&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;자료 구조를 선택할 때는 &lt;strong&gt;평균&lt;/strong&gt;과 &lt;strong&gt;최악&lt;/strong&gt;의 시간 복잡도를 함께 고려해야 합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;평균 시간 복잡도&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;자료 구조&lt;/th&gt;
&lt;th&gt;접근&lt;/th&gt;
&lt;th&gt;탐색&lt;/th&gt;
&lt;th&gt;삽입&lt;/th&gt;
&lt;th&gt;삭제&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;배열(Array)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스택(Stack)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;큐(Queue)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이중 연결 리스트&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;해시 테이블&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이진 탐색 트리(BST)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVL 트리&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;레드 블랙 트리&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;최악 시간 복잡도&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;자료 구조&lt;/th&gt;
&lt;th&gt;접근&lt;/th&gt;
&lt;th&gt;탐색&lt;/th&gt;
&lt;th&gt;삽입&lt;/th&gt;
&lt;th&gt;삭제&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;배열(Array)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스택(Stack)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;큐(Queue)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이중 연결 리스트&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;해시 테이블&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이진 탐색 트리(BST)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVL 트리&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;레드 블랙 트리&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;⚠️ &lt;strong&gt;BST vs AVL/레드 블랙 트리&lt;/strong&gt;&lt;br&gt;BST는 편향 트리가 되면 최악 O(n)까지 떨어질 수 있지만,&lt;br&gt;AVL이나 레드 블랙 트리는 자동으로 균형을 맞춰 항상 O(log n)을 보장합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/162</guid>
      <comments>https://tin814.tistory.com/162#entry162comment</comments>
      <pubDate>Wed, 25 Mar 2026 14:39:40 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 4.6 조인의 종류 4.7 조인의 원리</title>
      <link>https://tin814.tistory.com/160</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;SECTION 4.6 조인의 종류&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 개 이상의 테이블을 묶어서 하나의 결과물을 만드는 것&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL: &lt;code&gt;JOIN&lt;/code&gt; 쿼리&lt;/li&gt;
&lt;li&gt;MongoDB: &lt;code&gt;lookup&lt;/code&gt; 쿼리 (단, 성능이 RDBMS보다 낮아 되도록 사용 지양)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조인 종류&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXsFoE/dJMcac3rhaB/TcU4Fgnhnj96wUzJVHfi7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXsFoE/dJMcac3rhaB/TcU4Fgnhnj96wUzJVHfi7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXsFoE/dJMcac3rhaB/TcU4Fgnhnj96wUzJVHfi7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXsFoE%2FdJMcac3rhaB%2FTcU4Fgnhnj96wUzJVHfi7k%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;571&quot; height=&quot;163&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;내부 조인 (INNER JOIN)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;두 테이블에서 &lt;b&gt;모두 일치하는 행&lt;/b&gt;만 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;왼쪽 조인 (LEFT OUTER JOIN)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;왼쪽 테이블 전체&lt;/b&gt; + 오른쪽 일치 행 (없으면 NULL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;오른쪽 조인 (RIGHT OUTER JOIN)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;오른쪽 테이블 전체&lt;/b&gt; + 왼쪽 일치 행 (없으면 NULL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;합집합 조인 (FULL OUTER JOIN)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;양쪽 테이블 전체&lt;/b&gt; (일치 안 해도 포함, 없으면 NULL)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SECTION 4.7 조인의 원리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.7.1 중첩 루프 조인 (NLJ, Nested Loop Join)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중첩 for문과 같은 원리로 조인하는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;for each row in t1 {
    for each row in t2 {
        if 조건 일치 &amp;rarr; 결과 반환
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜덤 접근 비용이 높아 &lt;b&gt;대용량 테이블에는 부적합&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;발전형: &lt;b&gt;블록 중첩 루프 조인(BNL)&lt;/b&gt; &amp;mdash; 테이블을 작은 블록으로 나눠 블록 단위로 조인&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.7.2 정렬 병합 조인 (Sort Merge Join)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테이블을 조인 필드 기준으로 정렬 후 조인하는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용 조건:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적절한 인덱스가 없을 때&lt;/li&gt;
&lt;li&gt;대용량 테이블 조인 시&lt;/li&gt;
&lt;li&gt;조인 조건이 &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt; 등 &lt;b&gt;범위 비교 연산자&lt;/b&gt;일 때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.7.3 해시 조인 (Hash Join)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블을 기반으로 조인하는 방식 (MySQL 8.0.18부터 지원)&lt;/p&gt;
&lt;/blockquote&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;li&gt;&lt;b&gt;동등(=) 조인에서만&lt;/b&gt; 사용 가능&lt;/li&gt;
&lt;li&gt;메모리 초과 시 디스크 사용 &amp;rarr; 비용 증가&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;해시 조인 단계&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;단계&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;빌드 단계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;두 테이블 중 &lt;b&gt;더 작은 테이블&lt;/b&gt;을 메모리에 해시 테이블로 빌드. 조인 필드가 해시 키로 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;프로브 단계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;나머지 테이블을 읽으며 해시 테이블에서 일치하는 레코드를 찾아 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uufup/dJMcaiby2Tf/QcSbh90j0Ukrn3R5IC6KPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uufup/dJMcaiby2Tf/QcSbh90j0Ukrn3R5IC6KPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uufup/dJMcaiby2Tf/QcSbh90j0Ukrn3R5IC6KPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUufup%2FdJMcaiby2Tf%2FQcSbh90j0Ukrn3R5IC6KPk%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;601&quot; height=&quot;356&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lIOMU/dJMcagEO07W/gJKmJIqg3cRP2FxAeKKxpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lIOMU/dJMcagEO07W/gJKmJIqg3cRP2FxAeKKxpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lIOMU/dJMcagEO07W/gJKmJIqg3cRP2FxAeKKxpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlIOMU%2FdJMcagEO07W%2FgJKmJIqg3cRP2FxAeKKxpK%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;500&quot; height=&quot;277&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;277&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;한 번씩만 읽으므로&lt;/b&gt; 중첩 루프 조인보다 성능 우수&lt;/li&gt;
&lt;li&gt;메모리 사용량은 시스템 변수 &lt;code&gt;join_buffer_size&lt;/code&gt;로 제어&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/160</guid>
      <comments>https://tin814.tistory.com/160#entry160comment</comments>
      <pubDate>Wed, 18 Mar 2026 13:58:31 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 4.5 인덱스</title>
      <link>https://tin814.tistory.com/159</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;SECTION 4.5 인덱스&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.5.1 인덱스의 필요성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 빠르게 찾을 수 있는 장치 (책의 찾아보기와 동일한 개념)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;261&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EboJ1/dJMcaivOkzb/oLpg469nTwMnS3i9f85N3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EboJ1/dJMcaivOkzb/oLpg469nTwMnS3i9f85N3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EboJ1/dJMcaivOkzb/oLpg469nTwMnS3i9f85N3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEboJ1%2FdJMcaivOkzb%2FoLpg469nTwMnS3i9f85N3K%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;375&quot; height=&quot;261&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;261&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;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.5.2 B-트리&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;B-트리(Balanced Tree)&lt;/b&gt; 자료 구조로 구성&lt;/li&gt;
&lt;li&gt;구성: &lt;b&gt;루트 노드&lt;/b&gt; &amp;rarr; &lt;b&gt;브랜치 노드&lt;/b&gt; &amp;rarr; &lt;b&gt;리프 노드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;탐색 시 루트부터 시작해 리프 노드까지 내려가며 값을 비교&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mJWkl/dJMcaaYR1O9/Yo46wqLjAChADKV9ZfYYeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mJWkl/dJMcaaYR1O9/Yo46wqLjAChADKV9ZfYYeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mJWkl/dJMcaaYR1O9/Yo46wqLjAChADKV9ZfYYeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmJWkl%2FdJMcaaYR1O9%2FYo46wqLjAChADKV9ZfYYeK%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;435&quot; height=&quot;293&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcrPRa/dJMcaf0aAh6/krDAp9e0gb5hLojrgituo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcrPRa/dJMcaf0aAh6/krDAp9e0gb5hLojrgituo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcrPRa/dJMcaf0aAh6/krDAp9e0gb5hLojrgituo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcrPRa%2FdJMcaf0aAh6%2FkrDAp9e0gb5hLojrgituo0%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;644&quot; height=&quot;433&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;대수확장성&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 특성&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;깊이가 1 증가할 때마다 최대 인덱스 항목 수는 &lt;b&gt;4배 증가&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;트리 깊이&lt;/th&gt;
&lt;th&gt;인덱스 항목 수&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1,024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;16,384&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1,048,576&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 깊이 10짜리 트리로 &lt;b&gt;100만 개&lt;/b&gt; 레코드 검색 가능&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.5.3 인덱스 만드는 방법&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MySQL&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;생성 방법&lt;/th&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;클러스터형 인덱스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PRIMARY KEY&lt;/code&gt; 또는 &lt;code&gt;UNIQUE NOT NULL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;테이블당 1개, 성능 더 좋음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;세컨더리 인덱스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CREATE INDEX ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;여러 개 가능, 다양한 필드 쿼리에 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MongoDB&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도큐먼트 생성 시 &lt;b&gt;ObjectID가 기본키&lt;/b&gt;로 자동 설정&lt;/li&gt;
&lt;li&gt;세컨더리키를 추가해 &lt;b&gt;복합 인덱스&lt;/b&gt; 설정 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.5.4 인덱스 최적화 기법(MongoDB 기반)&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 인덱스는 비용이다&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 탐색 시 &lt;b&gt;인덱스 리스트 &amp;rarr; 컬렉션&lt;/b&gt; 순으로 &lt;b&gt;두 번 탐색&lt;/b&gt; (읽기 비용 증가)&lt;/li&gt;
&lt;li&gt;컬렉션 수정 시 인덱스도 수정 필요 &amp;rarr; B-트리 균형 조절 비용 발생&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무작정 모든 필드에 인덱스 설정은 비효율적&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;가져와야 하는 데이터 양이 많을수록 인덱스가 오히려 비효율&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 항상 테스팅하라&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스 특징(서비스에서 사용하는 객체 깊이, 데이터 양)에 따라 최적화 기법이 달라짐&lt;/li&gt;
&lt;li&gt;&lt;code&gt;explain()&lt;/code&gt; 함수로 쿼리 실행 후 소요 시간 측정&amp;middot;최소화&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 복합 인덱스 생성 순서:&amp;nbsp; 같음 &amp;rarr; 정렬 &amp;rarr; 다중 값 &amp;rarr; 카디널리티&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;같음(==)&lt;/b&gt;: equal 비교 쿼리 필드를 &lt;b&gt;가장 먼저&lt;/b&gt; 인덱스로 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정렬&lt;/b&gt;: 정렬에 쓰는 필드를 &lt;b&gt;그다음&lt;/b&gt; 인덱스로 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 값&lt;/b&gt;: &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt; 등 범위 쿼리 필드는 &lt;b&gt;나중에&lt;/b&gt; 설정&lt;/li&gt;
&lt;li&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;예: &lt;code&gt;age&lt;/code&gt; vs &lt;code&gt;email&lt;/code&gt; &amp;rarr; email의 카디널리티가 더 높으므로 email 먼저&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/159</guid>
      <comments>https://tin814.tistory.com/159#entry159comment</comments>
      <pubDate>Wed, 18 Mar 2026 13:52:49 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 4.4 데이터베이스의 종류</title>
      <link>https://tin814.tistory.com/158</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.4.1 관계형 데이터베이스 (RDBMS)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행과 열을 가지는 표 형식 데이터를 저장하며 SQL로 조작하는 데이터베이스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대표 제품: MySQL, PostgreSQL, Oracle, SQL Server, MSSQL&lt;/li&gt;
&lt;li&gt;각 제품마다 표준 SQL 외에 &lt;b&gt;자체 SQL&lt;/b&gt;을 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Oracle &amp;rarr; PL/SQL&lt;/li&gt;
&lt;li&gt;SQL Server &amp;rarr; T-SQL&lt;/li&gt;
&lt;li&gt;MySQL &amp;rarr; SQL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MySQL&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 &lt;b&gt;가장 많이 사용&lt;/b&gt;하는 데이터베이스 (스택오버플로우 2021 기준 1위)&lt;/li&gt;
&lt;li&gt;메타, 트위터 등 대형 기업에서 사용&lt;/li&gt;
&lt;li&gt;C, C++로 개발&lt;/li&gt;
&lt;li&gt;주요 기능: MyISAM 인덱스 압축, B-트리 기반 인덱스, 스레드 기반 메모리 할당, 최대 64개 인덱스&lt;/li&gt;
&lt;li&gt;롤백, 커밋, 이중 암호 지원 보안 제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;쿼리 캐시&lt;/b&gt; 지원: 동일한 쿼리 재요청 시 구문 분석&amp;middot;최적화&amp;middot;실행을 건너뛰고 캐시 결과 반환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모듈식 스토리지 엔진 아키텍처&lt;/b&gt;: 데이터 웨어하우징, 트랜잭션, 고가용성 처리에 강점&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PostgreSQL&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL 다음으로 개발자들이 선호하는 데이터베이스&lt;/li&gt;
&lt;li&gt;특징: &lt;b&gt;VACUUM&lt;/b&gt; (디스크 조각 영역 회수 장치)&lt;/li&gt;
&lt;li&gt;최대 테이블 크기: &lt;b&gt;32TB&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;SQL 외에도 &lt;b&gt;JSON&lt;/b&gt;으로 데이터 접근 가능&lt;/li&gt;
&lt;li&gt;지정 시간 복구, 로깅, 접근 제어, 중첩 트랜잭션, 백업 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.4.2 NoSQL 데이터베이스&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;Not only SQL&quot; &amp;mdash; SQL을 사용하지 않는 데이터베이스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MongoDB&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSON으로 데이터 접근, &lt;b&gt;BSON(Binary JSON)&lt;/b&gt; 형태로 저장&lt;/li&gt;
&lt;li&gt;기본 스토리지 엔진: &lt;b&gt;와이어드타이거(WiredTiger) -&amp;gt; &lt;/b&gt;키-값 모델에서 확장된 &lt;b&gt;도큐먼트 기반&lt;/b&gt; 데이터베이스&lt;/li&gt;
&lt;li&gt;빅데이터 저장 성능 우수, 고가용성&amp;middot;샤딩&amp;middot;레플리카셋 지원&lt;/li&gt;
&lt;li&gt;스키마 없이 데이터 삽입 가능 &amp;rarr; 로깅, 다양한 도메인 분석에 강점&lt;/li&gt;
&lt;li&gt;도큐먼트 생성 시 &lt;b&gt;ObjectID&lt;/b&gt; 자동 생성 (기본키 역할)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv5QRT/dJMcagdJ3vN/DtVzUFty4V84y6QsTzFYI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv5QRT/dJMcagdJ3vN/DtVzUFty4V84y6QsTzFYI1/img.png&quot; data-alt=&quot;유닉스 타임스탬프(4바이트) + 랜덤 값(5바이트) + 카운터(3바이트)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv5QRT/dJMcagdJ3vN/DtVzUFty4V84y6QsTzFYI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv5QRT%2FdJMcagdJ3vN%2FDtVzUFty4V84y6QsTzFYI1%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;400&quot; height=&quot;126&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;102&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;유닉스 타임스탬프(4바이트) + 랜덤 값(5바이트) + 카운터(3바이트)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;redis&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;인메모리&lt;/b&gt; 데이터베이스 + 키-값 모델 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;119&quot; data-end=&quot;152&quot; data-ke-size=&quot;size16&quot;&gt;일반 DB는 보통&lt;br /&gt;  하드디스크(SSD/HDD)에 저장&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;154&quot; data-end=&quot;190&quot; data-ke-size=&quot;size16&quot;&gt;근데 인메모리 DB는&lt;br /&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;메모리에 바로 올려놓고 사용 -&amp;gt; 속도가 진짜 빠름!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 데이터 타입: 문자열(string), 최대 512MB&lt;/li&gt;
&lt;li&gt;이외에도 셋(set), 해시(hash) 등 지원&lt;/li&gt;
&lt;li&gt;주요 사용 사례:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pub/sub 기반 &lt;b&gt;채팅 시스템&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;다른 DB 앞단의 &lt;b&gt;캐싱 계층&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세션 정보 관리&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;sorted set을 이용한 &lt;b&gt;실시간 순위표&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;152&quot; data-start=&quot;119&quot; data-ke-size=&quot;size16&quot;&gt;일반 DB는 보통&lt;br /&gt;  하드디스크(SSD/HDD)에 저장&lt;/p&gt;
&lt;p data-end=&quot;190&quot; data-start=&quot;154&quot; data-ke-size=&quot;size16&quot;&gt;근데 인메모리 DB는&lt;br /&gt;  &lt;b&gt;메모리에 바로 올려놓고 사용&lt;/b&gt;&lt;/p&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/158</guid>
      <comments>https://tin814.tistory.com/158#entry158comment</comments>
      <pubDate>Wed, 18 Mar 2026 13:44:25 +0900</pubDate>
    </item>
    <item>
      <title>SECTION 4.3 트랜잭션과 무결성</title>
      <link>https://tin814.tistory.com/157</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;SECTION 4.3 트랜잭션과 무결성&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.3.1 트랜잭션 (Transaction)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 논리적 기능을 수행하기 위한 *여러 쿼리들을 하나로 묶은 작업 단위&lt;br /&gt;*이에 대한 특징은 원자성, 일관성, 독립성, 지속성이 있으며 이를 ACID특징이라고 함.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;커밋 &amp;amp; 롤백&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;커밋(commit)&lt;/b&gt;: 여러 쿼리가 성공적으로 처리되어 DB에 &lt;b&gt;영구 저장&lt;/b&gt; 확정&lt;/li&gt;
&lt;li&gt;커밋이 수행되었다 = 하나의 트랜잭션이 성공적으로 수행되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXCOPv/dJMcaiicMsZ/aY5x0RMJT8GnjlgYmUhbj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXCOPv/dJMcaiicMsZ/aY5x0RMJT8GnjlgYmUhbj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXCOPv/dJMcaiicMsZ/aY5x0RMJT8GnjlgYmUhbj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXCOPv%2FdJMcaiicMsZ%2FaY5x0RMJT8GnjlgYmUhbj0%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;525&quot; height=&quot;324&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;324&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;롤백(rollback)&lt;/b&gt;: 문제 발생 시 트랜잭션 이전 상태로 &lt;b&gt;취소/복원&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;커밋&amp;middot;롤백 덕분에 &lt;b&gt;데이터 무결성&lt;/b&gt; 보장&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAIcaO/dJMcabwBR64/FXD3LKCn5M4lAnApKcuK01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAIcaO/dJMcabwBR64/FXD3LKCn5M4lAnApKcuK01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAIcaO/dJMcabwBR64/FXD3LKCn5M4lAnApKcuK01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAIcaO%2FdJMcabwBR64%2FFXD3LKCn5M4lAnApKcuK01%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;446&quot; height=&quot;275&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;트랜잭션 전파&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;트랜잭션을 수행할 때 커넥션 단위로 수행하기 때문에 커넥션 객체를 넘겨야 함 -&amp;gt; 매번 하기 어렵고 귀찮음&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커넥션 객체를 매번 넘기지 않고, 여러 메서드를 &lt;b&gt;하나의 트랜잭션으로 묶는&lt;/b&gt; 것&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ACID 특징&lt;/h4&gt;
&lt;h5&gt;A &amp;mdash; 원자성 (Atomicity) : &quot;All or Nothing&quot;&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 내의 모든 작업은 &lt;b&gt;전부 성공하거나 전부 실패&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;[이체 예시]
1. 홍철 잔고 조회 (1000만원)
2. 홍철 잔고에서 500만원 차감
3. 규영 잔고에 500만원 추가

&amp;rarr; 2번에서 오류 발생 시? 1, 2번 모두 롤백 &amp;rarr; 처음 상태로 완전 복구
&amp;rarr; 홍철 500만원 / 규영 0원 같은 &quot;중간 상태&quot;는 절대 허용 안 됨&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;커밋&lt;/b&gt;: 모두 성공 &amp;rarr; 영구 저장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;롤백&lt;/b&gt;: 하나라도 실패 &amp;rarr; 전체 취소&lt;/li&gt;
&lt;li&gt;트랜잭션 내에 외부 API 호출이 있다면, 롤백 시 처리 방법을 반드시 고려해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;C &amp;mdash; 일관성 (Consistency) : &quot;규칙을 항상 준수&quot;&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 완료된 후에도 데이터베이스는 &lt;b&gt;미리 정의된 규칙&amp;middot;제약 조건을 항상 만족&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[예시]
범석 잔고: 0원
범석이 500만원 이체 시도 &amp;rarr; ❌ 불가

0원에서 500만원이 나오는 것은 &quot;잔고 &amp;gt;= 0&quot; 규칙 위반
&amp;rarr; DB가 이 트랜잭션을 거부하여 일관성 유지&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션 실행 전후 모두 &lt;b&gt;유효한 상태&lt;/b&gt;를 유지해야 함&lt;/li&gt;
&lt;li&gt;제약 조건(기본키, 외래키, 도메인 규칙 등)을 위반하는 데이터 변경은 허용되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;I &amp;mdash; 격리성 (Isolation) : &quot;트랜잭션끼리 서로 간섭 금지&quot;&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 트랜잭션이 동시에 실행될 때, &lt;b&gt;각 트랜잭션은 다른 트랜잭션의 중간 상태를 볼 수 없어야&lt;/b&gt; 합니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;[예시]
사용자 A: 잔고 조회 중 (트랜잭션 진행 중)
사용자 B: 동시에 같은 잔고를 수정 중

&amp;rarr; A는 B가 수정 중인 &quot;확정되지 않은&quot; 값을 보면 안 됨
&amp;rarr; 마치 순차적으로 실행된 것처럼 동작해야 함&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;격리 수준(SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED)으로 강도 조절 가능&lt;/li&gt;
&lt;li&gt;격리성이 강할수록 동시성(성능)은 낮아짐&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;D &amp;mdash; 지속성 (Durability) : &quot;한 번 커밋되면 영구 보존&quot;&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공적으로 커밋된 트랜잭션은 &lt;b&gt;시스템 장애(정전, 오류)가 발생해도 반드시 유지&lt;/b&gt;되어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[예시]
이체 완료 후 커밋 &amp;rarr; 서버 갑자기 다운
&amp;rarr; 재시작 후에도 이체된 내용은 그대로 유지되어야 함&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;체크섬&lt;/b&gt;: 데이터 무결성 오류 검출&lt;/li&gt;
&lt;li&gt;&lt;b&gt;저널링&lt;/b&gt;: 변경 전 로그를 먼저 기록해 복구 가능하게 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;롤백&lt;/b&gt;: 장애 시 마지막 커밋 상태로 복구&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  격리성 &amp;mdash; 격리 수준&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlAUjb/dJMcafFNumR/gbj8xHCGstPCPMSvyCY7N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlAUjb/dJMcafFNumR/gbj8xHCGstPCPMSvyCY7N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlAUjb/dJMcafFNumR/gbj8xHCGstPCPMSvyCY7N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlAUjb%2FdJMcafFNumR%2Fgbj8xHCGstPCPMSvyCY7N1%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;418&quot; height=&quot;282&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위로 갈수록 &lt;b&gt;동시성 &amp;uarr;, 격리성 &amp;darr;&lt;/b&gt; / 아래로 갈수록 &lt;b&gt;동시성 &amp;darr;, 격리성 &amp;uarr;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;낮은 격리 (빠름)  READ_UNCOMMITTED
                  READ_COMMITTED
                  REPEATABLE_READ
높은 격리 (느림)  SERIALIZABLE&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;1. READ_UNCOMMITTED (가장 낮은 격리)&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋되지 않은 데이터도 읽을 수 있는 수준.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;발생 현상&lt;/b&gt;: 더티 리드, 반복 불가 조회, 팬텀 리드 모두 발생 가능&lt;/li&gt;
&lt;li&gt;데이터 무결성에 위험하므로 &lt;b&gt;되도록 사용하지 않는 것이 좋음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;단, 거대한 데이터를 &quot;어림잡아&quot; 집계할 때는 유용할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;[더티 리드 예시]
사용자 A: 보석 개수 100 &amp;rarr; 1로 수정 (아직 커밋 안 함)
사용자 B: 조회 &amp;rarr; 1로 읽음 &amp;larr; 커밋 안 된 값을 읽어버림
사용자 A: 롤백 &amp;rarr; 실제 값은 100이지만 B는 이미 1을 읽은 상태&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;2. READ_COMMITTED&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋이 완료된 데이터만 읽을 수 있는 수준.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;발생 현상&lt;/b&gt;: 반복 불가 조회, 팬텀 리드 발생 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가장 많이 사용&lt;/b&gt;되는 격리 수준&lt;/li&gt;
&lt;li&gt;기본값: PostgreSQL, SQL Server, Oracle&lt;/li&gt;
&lt;li&gt;커밋되지 않은 정보는 읽을 수 없지만, 다른 트랜잭션이 접근한 행을 수정할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;[반복 불가 조회 예시]
사용자 A: 보석 100 조회
사용자 B: 보석 100 &amp;rarr; 1로 수정 후 커밋
사용자 A: 다시 조회 &amp;rarr; 1로 읽힘 (같은 트랜잭션인데 값이 달라짐)&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;3. REPEATABLE_READ&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 트랜잭션 내에서 같은 행을 읽으면 항상 같은 값을 보장하는 수준.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;발생 현상&lt;/b&gt;: 팬텀 리드 발생 가능&lt;/li&gt;
&lt;li&gt;기본값: &lt;b&gt;MySQL InnoDB&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;수정(UPDATE)은 막지만, 삽입(INSERT)/삭제(DELETE)는 막지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;[팬텀 리드 예시]
사용자 A: age &amp;gt;= 12인 회원 조회 &amp;rarr; 3건
사용자 B: age = 15인 회원 삽입 후 커밋
사용자 A: 다시 조회 &amp;rarr; 4건 (행이 추가되어 결과가 달라짐)&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h5&gt;4. SERIALIZABLE (가장 높은 격리)&lt;/h5&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션을 순차적으로 처리하는 수준.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;발생 현상&lt;/b&gt;: 없음 (가장 안전)&lt;/li&gt;
&lt;li&gt;여러 트랜잭션이 동시에 같은 행에 접근 불가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;교착 상태 발생 가능성이 높고 성능이 가장 낮음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;트랜잭션 A가 행 X를 처리 중
  &amp;rarr; 트랜잭션 B가 행 X 접근 시도
    &amp;rarr; B는 A가 끝날 때까지 대기&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;발생 현상 상세&lt;/h4&gt;
&lt;h5&gt;더티 리드 (Dirty Read)&lt;/h5&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;li&gt;롤백 시 실제로 존재하지 않는 값을 읽은 것이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;반복 불가 조회 (Non-repeatable Read)&lt;/h5&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;b&gt;값이 달라&lt;/b&gt;지는 현상&lt;/li&gt;
&lt;li&gt;다른 트랜잭션이 그 행을 &lt;b&gt;수정(UPDATE)&lt;/b&gt; 하고 커밋했기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;팬텀 리드 (Phantom Read)&lt;/h5&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;b&gt;행 수가 달라&lt;/b&gt;지는 현상&lt;/li&gt;
&lt;li&gt;다른 트랜잭션이 행을 &lt;b&gt;삽입(INSERT) 또는 삭제(DELETE)&lt;/b&gt; 했기 때문&lt;/li&gt;
&lt;li&gt;반복 불가 조회와의 차이: &lt;b&gt;행의 값&lt;/b&gt;이 바뀌는 게 아니라 &lt;b&gt;행 자체&lt;/b&gt;가 추가/삭제됨&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;현상&lt;/th&gt;
&lt;th&gt;원인&lt;/th&gt;
&lt;th&gt;영향 범위&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;더티 리드&lt;/td&gt;
&lt;td&gt;미커밋 데이터 읽기&lt;/td&gt;
&lt;td&gt;행의 미확정 값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;반복 불가 조회&lt;/td&gt;
&lt;td&gt;타 트랜잭션 UPDATE&lt;/td&gt;
&lt;td&gt;행의 값 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;팬텀 리드&lt;/td&gt;
&lt;td&gt;타 트랜잭션 INSERT/DELETE&lt;/td&gt;
&lt;td&gt;결과 행 수 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.3.2 무결성 (Integrity)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 &lt;b&gt;정확성&amp;middot;일관성&amp;middot;유효성&lt;/b&gt;을 유지하는 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;개체 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기본키는 빈 값(NULL) 허용 안 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;참조 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;참조 관계의 두 테이블 데이터는 항상 일관성 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;고유 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;특정 속성은 고유한 값만 가져야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;NULL 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;NULL 불가 조건이 있는 속성은 NULL이 될 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>STUDY</category>
      <author>Lim임</author>
      <guid isPermaLink="true">https://tin814.tistory.com/157</guid>
      <comments>https://tin814.tistory.com/157#entry157comment</comments>
      <pubDate>Tue, 10 Mar 2026 13:34:33 +0900</pubDate>
    </item>
  </channel>
</rss>