<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>w_dw_r.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 20 Feb 2026 07:42:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>w_dw_r.log</title>
            <url>https://velog.velcdn.com/images/w_dw_r/profile/7c670bca-bb87-45c6-8b22-0514a83aeb9a/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. w_dw_r.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/w_dw_r" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-6 응용 계층 - HTTP의 응용 (쿠키, 캐시, 콘텐츠 협상, SSL/TLS와 HTTPS)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-6-%EC%9D%91%EC%9A%A9-%EA%B3%84%EC%B8%B5-HTTP%EC%9D%98-%EC%9D%91%EC%9A%A9-%EC%BF%A0%ED%82%A4-%EC%BA%90%EC%8B%9C-%EC%BD%98%ED%85%90%EC%B8%A0-%ED%98%91%EC%83%81-SSLTLS%EC%99%80-HTTPS</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-6-%EC%9D%91%EC%9A%A9-%EA%B3%84%EC%B8%B5-HTTP%EC%9D%98-%EC%9D%91%EC%9A%A9-%EC%BF%A0%ED%82%A4-%EC%BA%90%EC%8B%9C-%EC%BD%98%ED%85%90%EC%B8%A0-%ED%98%91%EC%83%81-SSLTLS%EC%99%80-HTTPS</guid>
            <pubDate>Fri, 20 Feb 2026 07:42:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
<p>① <strong>쿠키 &amp; 웹 스토리지</strong>: 상태가 없는(Stateless) HTTP에서 사용자 정보를 기억하는 방법
② <strong>HTTP 캐시</strong>: 서버를 거치지 않고 저장된 사본을 재사용하여 성능을 높이는 기술
③ <strong>캐시 재검사</strong>: 유효 기간이 지난 캐시가 아직 쓸만한지 확인하고 재사용(<code>304</code>)하는 과정
④ <strong>콘텐츠 협상</strong>: 클라이언트 환경에 맞는 최적의 자원(언어, 타입 등)을 골라 응답하는 방식
⑤ <strong>HTTPS &amp; TLS</strong>: 인증서와 암호화 키 교환을 통해 안전한 보안 연결을 맺는 원리
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-응용-계층---http의-응용">1. 응용 계층 - HTTP의 응용</h2>
<h3 id="1-1-쿠키-cookie">1-1. 쿠키 (Cookie)</h3>
<p>HTTP는 기본적으로 모든 요청이 독립적인 메시지로 간주되는 <strong>스테이트리스(Stateless) 프로토콜</strong>이다.</p>
<p>하지만 실무에서는 &#39;로그인 상태 유지&#39;나 &#39;3일간 보지 않기&#39; 같은 기능이 필요하므로, 이를 위해 <code>서버가 클라이언트에 저장하는 데이터</code>가 바로 <strong>쿠키</strong>이다.</p>
<p><em>➡️ 즉, 쿠키는 HTTP의 스테이트리스한 특성을 보완하기 위해 서버에서 생성되어 클라이언트 측에 저장되는 <strong>&lt;이름, 값&gt; 쌍 형태의 데이터</strong>이다.</em></p>
<blockquote>
<h4 id="쿠키의-저장-위치">쿠키의 저장 위치</h4>
<p>클라이언트는 서버로부터 받은 쿠키를 주로 웹 브라우저에 저장한다.
<image src ="https://velog.velcdn.com/images/w_dw_r/post/948a5e94-8f07-431b-aa35-c9a3354ad0d3/image.png"
width=500/>크롬 브라우저의 경우 <code>[개발자 도구] - [Application] - [Storage] - [Cookies]</code> 항목에서 이름(Name), 값(Value), 도메인(Domain) 등 상세 정보를 확인할 수 있다.</p>
</blockquote>
<h4 id="①-쿠키-전달-방식-set-cookie와-cookie-헤더">① 쿠키 전달 방식: Set-Cookie와 Cookie 헤더</h4>
<p>쿠키는 서버와 클라이언트 사이에서 <code>Set-Cookie</code>,<code>Cookie</code>와 같은 헤더를 통해 주고받는다.</p>
<p>여기서 핵심은 <strong>&quot;한 번 받은 쿠키는 이후 요청 시 자동으로 포함된다&quot;</strong>는 점이다.</p>
<ul>
<li><p><strong>서버 → 클라이언트 (응답):</strong> <code>Set-Cookie</code> 헤더를 통해 쿠키를 생성하여 전달한다.</p>
<blockquote>
<p><strong>응답 메시지 예시</strong></p>
<pre><code>Set - Cookie: 이름 = 값
Set - Cookie: 이름 = 값; 속성 1
Set - Cookie: 이름 = 값; 속성 1; 속성 2</code></pre><pre><code>Set-Cookie: name=minchul
Set-Cookie: phone=100-100
</code></pre></blockquote>
</li>
<li><p><strong>클라이언트 → 서버 (요청):</strong> 전달받은 쿠키를 브라우저에 저장해 두었다가, 이후 동일한 서버에 요청을 보낼 때 자동으로 <code>Cookie</code> 헤더에 포함하여 보낸다.</p>
<blockquote>
<p><strong>요청 메시지 예시</strong></p>
<pre><code>Cookie: 이름 = 값; 이름 = 값;</code></pre><pre><code class="language-http">GET /next_page HTTP/1.1
Cookie: name=minchul; phone=100-100
</code></pre>
</blockquote>
</li>
</ul>
<p><code>*개발자가 직접 코드로 넣지 않아도 브라우저가 알아서 챙겨 보내는 것이 특징이다.</code>
<code>*여러 개의 쿠키를 보낼 때는 하나의 Cookie 헤더 안에 세미콜론(;)으로 각 &lt;이름, 값&gt; 쌍을 구분하여 나열한다.</code></p>
<h4 id="②-쿠키의-주요-속성-제약-조건">② 쿠키의 주요 속성 (제약 조건)</h4>
<p>쿠키는 단순한 값 외에도 안전한 관리를 위한 다양한 속성을 가진다.</p>
<table>
<thead>
<tr>
<th>속성</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Domain/Path</strong></td>
<td>쿠키를 전송할 도메인과 경로를 제한한다.</td>
<td><code>domain=minchul.net</code>, <code>path=/lectures</code></td>
</tr>
<tr>
<td><strong>Expires</strong></td>
<td>쿠키가 삭제될 특정 날짜와 시간을 지정한다.</td>
<td><code>Expires=Fri, 23 Aug 2024 09:00:00 GMT</code></td>
</tr>
<tr>
<td><strong>Max-Age</strong></td>
<td>초 단위로 유효 기간을 설정한다.</td>
<td><code>Max-Age=2592000</code> (30일)</td>
</tr>
<tr>
<td><strong>Secure</strong></td>
<td><strong>HTTPS</strong> 연결일 때만 쿠키를 전송하도록 설정한다.</td>
<td><code>Set-Cookie: ID=abc; Secure</code></td>
</tr>
<tr>
<td><strong>HttpOnly</strong></td>
<td>자바스크립트를 통한 접근을 금지하여 XSS 공격을 방어합한다.</td>
<td><code>Set-Cookie: ID=abc; HttpOnly</code></td>
</tr>
</tbody></table>
<blockquote>
<p><strong>💡 웹 스토리지(Web Storage)</strong>
: 브라우저 내 저장 공간으로, 이는 <code>로컬 스토리지</code>와 <code>세션 스토리지</code>로 나뉜다.</p>
</blockquote>
<p>쿠키보다 <code>큰 데이터</code>를 보관할 수 있고, 쿠키는 서버로 자동 전송되지만 웹 스토리지의 정보는 서버로 <code>자동 전송되지 않아</code> 네트워크 부하가 적다.</p>
<blockquote>
<ul>
<li><strong>로컬 스토리지 (localStorage)</strong>: 사용자가 직접 삭제하지 않는 한 데이터가 <code>영구적으로 유지</code>된다.</li>
<li><strong>세션 스토리지 (sessionStorage)</strong>: 브라우저 창이나 <code>탭이 열려 있는 동안</code>에만 정보가 유지된다.
<code>*개발자 도구(F12) → [Application] → [Storage] 메뉴에서 저장된 정보를 확인할 수 있다.</code>
<img src="https://velog.velcdn.com/images/w_dw_r/post/0235758e-0d39-4863-aec3-4765fb493f77/image.png" alt=""></li>
</ul>
</blockquote>
<h3 id="1-2-http-캐시-cache">1-2. HTTP 캐시 (Cache)</h3>
<p>캐시는 서버로부터 받은 자원의 사본을 <code>임시 저장</code>하여,
<strong>동일한 요청 시 서버를 거치지 않고 빠르게 재사용</strong>하는 기술이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/0bf7a219-5bd9-402b-b658-72c1ecfddb67/image.png" alt=""></p>
<p>캐시는 클라이언트(주로 웹 브라우저)에 저장되기도 하고, 클라이언트와 서버 사이에 위치한 중간 서버에 저장되기도 한다.</p>
<p><code>*Private Cache: 웹 브라우저 등 개인 기기에 저장되는 캐시</code>
<code>*Public Cache: 프록시 서버나 CDN 등 중간 서버에 저장되는 캐시</code></p>
<h4 id="①-캐시의-유효-기간과-신선도">① 캐시의 유효 기간과 신선도</h4>
<p>캐시 데이터는 원본과 일치해야 하기 때문에 <strong>신선도</strong>가 중요하다.
이를 위해 <strong>유효 기간</strong>을 명시한다.</p>
<blockquote>
<p><strong>응답 메시지</strong></p>
<pre><code>HTTP/1.1 200 OK
Date: Mon, 05 Feb 2024 12:00:00 GMT
Expires: Tue, 06 Feb 2024 12:00:00 GMT  // 절대적인 날짜로 만료 시점 명시
Cache-Control: max-age=1200             // 1200초 동안 유효함 (상대적 시간)</code></pre></blockquote>
<ul>
<li><strong>Expires:</strong> 절대적인 만료 기한 지정</li>
<li><strong>Cache-Control: max-age:</strong> 상대적인 초 단위 유효 기간 (예: <code>max-age=1200</code>)</li>
</ul>
<blockquote>
<h4 id="📍-캐시에-유효-기간이-부여되는-근본적인-이유">📍 캐시에 유효 기간이 부여되는 근본적인 이유</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/490b1e1b-60d9-4059-af3c-418c54b8e7da/image.png" alt=""></p>
</blockquote>
<p>클라이언트가 캐시를 참조하는 사이 서버의 원본 데이터가 변경되어 원본 데이터와 캐시된 사본 데이터 간의 일관성이 깨질 수 있기 때문이다‼️</p>
<h4 id="②-캐시-재검사validation-아직-쓸만한가">② 캐시 재검사(Validation): &quot;아직 쓸만한가?&quot;</h4>
<p>캐시 유효 기간이 만료되어도 서버의 데이터가 변하지 않았다면 자원을 새로 받을 필요가 없다.</p>
<p>이때, 클라이언트는 <strong>조건부 요청</strong>을 보내 서버의 데이터 변경 여부를 확인하고 캐시를 <strong>재사용</strong>한다.</p>
<blockquote>
<h4 id="요청-메시지">요청 메시지</h4>
<pre><code>GET /index.html HTTP/1.1
Host: www.example.com
If-Modified-Since: Fri, 23 Aug 2024 09:00:00 GMT</code></pre></blockquote>
<pre><code>&gt;

1. **If-Modified-Since (날짜 기반):**
&gt; ```http
&gt; **클라이언트의 조건부 요청 (날짜 기반)**
&gt; GET /index.html HTTP/1.1
&gt; If-Modified-Since: Mon, 05 Feb 2024 12:00:00 GMT
&gt; 
&gt; ```
* 클라이언트: &quot;이 날짜 이후로 데이터가 변경되었나요?&quot;
* 서버 (변경X): `304 Not Modified` 응답 (본문 없이 헤더만 보내 전송 효율 극대화)
* 서버 (변경O): `200 OK` + `새로운 자원`
`*이때, Last-Modified 헤더로 마지막 변경 시점을 함께 알릴 수 있다.`

2. **If-None-Match (ETag 기반):**
&gt; ```http
&gt; **클라이언트의 조건부 요청 (ETag 기반)**
&gt; GET /index.html HTTP/1.1
&gt; If-None-Match: &quot;abc-123&quot;
&gt; 
&gt; ```
* 클라이언트: &quot;내가 가진 버전(ETag)인 **&#39;abc&#39;**와 지금 서버 버전이 다른가요?&quot;
* 서버 (변경X, ETag 일치): `304 Not Modified` 응답 (기존 캐시 사용)
* 서버 (변경O, ETag 불일치): `200 OK` + `새로운 자원` (새 ETag 포함) 반환
* 서버 (자원 삭제): `404 Not Found` (자원이 존재하지 않음)

`*ETag(Entity Tag)는 자원의 버전을 식별하기 위한 고유 정보를 말한다. 자원이 변경되면 ETag 값도 변하기 때문에 이를 비교하여 변경 여부를 파악한다.`

&gt; #### 📍 304 Not Modified
&gt; : 자원이 변경되지 않았으니 기존에 가지고 있던 캐시를 그대로 사용해라.
&gt; ```
&gt; HTTP/1.1 304 Not Modified
&gt; Last-Modified: Mon, 05 Feb 2024 12:00:00 GMT
&gt; ETag: &quot;abc-123&quot;
&gt; 
&gt; ```
&gt; `*메시지 본문(Body)을 생략하고 헤더만 보내기 때문에 네트워크 대역폭을 매우 효율적으로 사용하는 특징이 있다.`
&gt; 

### 1-3. 콘텐츠 협상 (Content Negotiation)

똑같은 자원(URI)이라도 사용자의 환경에 따라 가장 적절한 **표현(Representation)**으로 응답하는 과정을 뜻한다.

#### 주요 협상 헤더
* `Accept`: 선호하는 미디어 타입 (html, json 등)
* `Accept-Language`: 선호하는 언어 (ko, en 등)
* `Accept-Encoding`: 지원하는 압축 방식 (gzip 등)

### 1-4. 보안: SSL/TLS와 HTTPS

오늘날 대부분의 웹 서비스는 HTTP에 보안을 더한 **HTTPS(HTTP over TLS, HTTP Secure)**로 동작한다.

&gt; #### HTTPS 사용 유무 확인하는 법
&gt; 브라우저 주소창에 있는 자물쇠 아이콘은 해당 사이트가 `HTTPS`를 사용하며, `브라우저와 서버 간에 암호화 통신`이 이루어지고 있음을 의미한다. 😎
&gt;
![](https://velog.velcdn.com/images/w_dw_r/post/729b5754-9552-45b3-a8c0-740f13c8fef0/image.png)

#### ① SSL/TLS의 개념

: **HTTPS**는 `HTTP`에 SSL 혹은 TLS라는 `보안 프로토콜이 추가된 형태`이다.

초기 SSL 2.0, 3.0을 거쳐 현재는 이를 계승한 **TLS(Transport Layer Security)**가 사용되고 있으며, 최신 버전인 **TLS 1.2와 1.3**이 주로 쓰인다.

#### ② TLS 1.3 핸드셰이크 과정

TLS 1.3 기반 HTTPS 메시지는 크게 `TCP 쓰리 웨이 핸드셰이크`, `TLS 핸드셰이크`, `메시지 송수신 단계`를 거쳐 송수신 된다.

`TCP 쓰리 웨이 핸드셰이크`는 지난 시간에 설명했으니, **`TLS 핸드셰이크`** 위주로 살펴보면

&lt;image src=&quot;https://velog.velcdn.com/images/w_dw_r/post/0bd26b6a-0ed1-49dc-8836-e40a87f6ccf2/image.png&quot;
width=400/&gt;

1. **TCP 쓰리 웨이 핸드셰이크**: 먼저 기반이 되는 TCP 연결을 수립한다.
2. **ClientHello**: 클라이언트가 서버에 암호화 통신을 위한 정보를 보낸다.
`*지원하는 TLS 버전, 클라이언트 난수, 암호 스위트(Cipher Suite) 등을 포함한다.`
3. **ServerHello**: 서버가 응답하며 암호화 방식을 결정한다.
`*선택된 TLS 버전, 암호 스위트, 서버 난수 등을 보낸다.`
4. **Certificate &amp; CertificateVerify**: 서버는 자신의 **인증서**를 보내고, 해당 인증서의 내용이 올바른지 검증하기 위한 메시지를 보낸다.
5. **Finished**: 양측이 암호화에 사용할 키 획득을 완료하고, 서로가 틀림없음을 확인하면 핸드셰이크가 종료된다.
`*이후부터는 생성된 키를 기반으로 암호화된 애플리케이션 데이터(Application Data)를 주고받는다.`

#### ③ 암호 스위트 (Cipher Suite)

암호화 통신에 사용될 알고리즘들의 묶음을 말한다.

* **구성 예시**: `TLS_AES_128_GCM_SHA256`
* `TLS`: 프로토콜 종류
* `AES_128_GCM`: 암호화 알고리즘
* `SHA256`: 해시 함수

&gt; #### 암호화와 복호화, 키(Key)
암호화 통신을 이해하려면 먼저 키의 역할을 알아야 한다.
&gt;
* 암호화: 누구나 읽을 수 있는 **데이터(평문)**를 **알아볼 수 없는 형태(암호문)**로 만드는 것
* 복호화: **암호문**을 다시 원래의 **평문**으로 되돌리는 것
* 키(Key): 암호화와 복호화를 수행할 때 필요한 **비밀번호**와 같은 정보
`*이 키를 가진 호스트만이 데이터를 제대로 읽을 수 있다.`
![](https://velog.velcdn.com/images/w_dw_r/post/f54fc27c-469c-4c73-bb61-22674345833f/image.png)

#### ④ 공개 키 인증서 (Public Key Certificate)

**인증서**는 통신하는 상대방이 내가 의도한 대상(예: `www.hanbit.co.kr`)이 맞는지 보장하는 정보이다.

* **인증 기관(CA, Certification Authority)**: 인증서를 발급하고 검증하는 신뢰할 수 있는 제3의 기관이다.
* **검증 과정**: 브라우저는 서버가 보낸 인증서가 신뢰할 수 있는 CA에서 발급되었는지 확인하고 보안 경고 여부를 결정한다.

---

&gt; #### 📍 총정리
&gt; 
&gt; 1. **쿠키**: Stateless한 HTTP에서 클라이언트의 상태를 관리하기 위한 `&lt;이름, 값&gt;` 형태의 데이터다.
&gt; 2. **캐시**: 자원의 사본을 저장하여 대역폭 낭비를 막고 응답 속도를 높이며, `304 Not Modified`를 통해 효율적으로 재검사한다.
&gt; 3. **HTTPS (SSL/TLS)**: 핸드셰이크를 통해 암호화 키를 교환하고 인증서로 상대를 검증해서 안전한 통신을 보장힌다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-5 응용 계층 - HTTP의 기초 (DNS와 URI/URL, HTTP의 특징과 메시지 구조 )]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-5-%EC%9D%91%EC%9A%A9-%EA%B3%84%EC%B8%B5-HTTP%EC%9D%98-%EA%B8%B0%EC%B4%88-DNS%EC%99%80-URIURL-HTTP%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EB%A9%94%EC%8B%9C%EC%A7%80-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-5-%EC%9D%91%EC%9A%A9-%EA%B3%84%EC%B8%B5-HTTP%EC%9D%98-%EA%B8%B0%EC%B4%88-DNS%EC%99%80-URIURL-HTTP%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EB%A9%94%EC%8B%9C%EC%A7%80-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Mon, 09 Feb 2026 12:49:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
</blockquote>
<p>① DNS와 서버 연결: 도메인과 IP를 잇는 원리와 DNS 레코드 등록 과정
② DNS 리졸빙: 계층적 질의를 통해 정답 IP를 찾아가는 과정
③ URL 구조: 웹 자원을 식별하고 위치를 나타내는 상세 구성 요소
④ HTTP 특징: 확장성을 위한 Stateless 방식과 효율적인 지속 연결
⑤ HTTP 메시지 및 버전: 패킷의 규격화된 구조와 버전별(1.1~3.0) 특징
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
<hr>
<h2 id="1-응용-계층---http의-기초">1. 응용 계층 - HTTP의 기초</h2>
<p>응용 계층은 네트워크 참조 모델의 최상단 계층으로, 개발자가 가장 자주 접하게 되는 핵심 계층이다. HTTP를 이해하기 위해서는 <strong>DNS</strong>와 <strong>URI</strong>에 대한 배경지식이 필요하므로 아래에서 살펴보자❗️</p>
<h3 id="1-1-도메인-네임과-dns">1-1. 도메인 네임과 DNS</h3>
<p>네트워크상의 호스트를 식별하기 위해 <code>IP 주소</code>를 사용한다.</p>
<p><em>➡️ 하지만, <strong>숫자로 된 IP는 기억하기 어렵고 호스트의 특징을 나타내지 못하며 언제든 바뀔 수 있다는 단점이 있다.</strong></em></p>
<p>그래서 사용하는 것이 <code>도메인 네임</code>이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/be6a3b60-3c28-4bfe-97cc-1e76f0e20d24/image.png" alt=""></p>
<ul>
<li><strong>도메인 네임(Domain Name):</strong> <code>www.example.com</code>과 같이 문자열 형태로 표현된 호스트 특정 정보이다.</li>
<li><strong>네임 서버(DNS 서버):</strong> 도메인 네임과 그에 대응하는 IP 주소를 관리하는 특별한 서버이다.</li>
<li><strong>DNS(Domain Name System):</strong> 호스트가 네임 서버에 특정 도메인의 IP를 질의하고 응답받는 시스템을 의미하며, 이를 통해 IP 주소를 알아내는 과정을 <strong>&#39;도메인 네임을 풀이(resolve)한다&#39;</strong>고 한다.</li>
</ul>
<h3 id="1-2-도메인-네임의-계층적-구조">1-2. 도메인 네임의 계층적 구조</h3>
<p>도메인 네임은 점(<code>.</code>)을 기준으로 계층적인 트리 구조를 이룬다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/7492eaf7-8aee-4856-a6f5-681bef687f81/image.png" alt=""></p>
<ul>
<li><strong>루트 도메인:</strong> 최상단에 위치하며 점(<code>.</code>)으로 표현된다. 보통 표기 시 생략한다.</li>
<li><strong>최상위 도메인(TLD):</strong> <code>com</code>, <code>net</code>, <code>org</code>, <code>kr</code> 등 국가나 조직의 성격을 나타낸다.</li>
<li><strong>2단계 도메인:</strong> TLD 하위의 도메인으로, 보통 서비스의 이름을 나타낸다.</li>
<li><strong>FQDN(Fully Qualified Domain Name):</strong> 루트 도메인까지 모두 포함하는 전체 도메인 네임이다.</li>
</ul>
<blockquote>
<p><strong>참고: 서브 도메인(Subdomain)</strong>
<code>mail.example.com</code>, <code>www.example.com</code>은 모두 <code>example.com</code>의 서브 도메인이다.</p>
</blockquote>
<h3 id="1-3-dns-동작-원리와-레코드">1-3. DNS 동작 원리와 레코드</h3>
<p>DNS는 전 세계에 분산된 네임 서버들이 계층적으로 협력하여 동작한다.
<code>*DNS(Domain Name System): 호스트가 네임 서버에 특정 도메인의 IP를 질의하고 응답받는 시스템을 의미한다.</code></p>
<h4 id="①-리졸빙resolving-과정---누가-이-주소-알아">① 리졸빙(Resolving) 과정 - &quot;누가 이 주소 알아?&quot;</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/58283abd-2bee-4981-b2eb-33a9fa7a4ce1/image.png" alt=""></p>
<ol>
<li><strong>로컬 네임 서버:</strong> 클라이언트가 가장 먼저 찾는 서버로, 주로 ISP가 제공한다. (공개 DNS: 8.8.8.8 등)</li>
<li><strong>계층적 질의:</strong> 로컬 서버가 주소를 모를 경우 <code>루트 네임 서버</code> → <code>TLD 네임 서버</code> → <code>책임 네임 서버</code> 순으로 질의를 반복하여 최종 IP를 알아낸다.</li>
</ol>
<blockquote>
<h4 id="📍-dns는-주소를-찾아가는-여정과-같다">📍 DNS는 주소를 찾아가는 여정과 같다.</h4>
<p>사용자가 브라우저에 <code>www.example.com</code>을 입력했을 때, 컴퓨터 내부에서 일어나는 과정이다.</p>
</blockquote>
<p><strong>1. 로컬 네임 서버</strong></p>
<blockquote>
</blockquote>
<p>가장 먼저 컴퓨터는 자신과 가장 가까운 로컬 네임 서버에게
<code>&quot;너 혹시 www.example.com IP 주소 알아?&quot;</code>라고 물어본다.
로컬 서버가 캐시에 정보가 있다면 바로 알려주지만, 없다면 로컬 서버가 대신해서 다른 서버들에게 물으러 다닌다.</p>
<blockquote>
</blockquote>
<p><strong>2. 계층적 질의</strong></p>
<ul>
<li><strong>루트 네임 서버</strong>: 로컬 서버가 루트에게 물으면, 루트는 <code>&quot;난 모르지만 .com 서버 주소는 알려줄 수 있어.&quot;</code>라고 답한다.<blockquote>
</blockquote>
</li>
<li><strong>TLD 네임 서버</strong>: .com 서버에게 물으면, <code>&quot;난 모르지만 example.com의 관리를 맡은 네임 서버 주소는 알아!&quot;</code>라고 답한다.<blockquote>
</blockquote>
</li>
<li><strong>책임 네임 서버(Authoritative Server)</strong>: 드디어 해당 도메인을 직접 관리하는 서버에 도달한다. 여기서 최종적으로 &quot;그 주소의 IP는 <code>1.2.3.4</code>야!&quot;라는 답을 얻는다.<blockquote>
</blockquote>
</li>
<li><em>3. 결과 전달과 캐싱*</em>
로컬 서버는 알아낸 IP를 클라이언트에게 전달하고, 다음에 똑같은 질문을 받으면 바로 답할 수 있도록 이 정보를 캐시에 저장한다.</li>
</ul>
<h4 id="②-dns-캐시와-ttl">② DNS 캐시와 TTL</h4>
<p>반복적인 질의로 인한 트래픽을 줄이기 위해 네임 서버는 질의 결과를 임시 저장하는 <strong>DNS 캐시</strong>를 사용한다. 이때 캐시가 유지되는 시간을 <strong>TTL(Time To Live)</strong>이라고 한다.</p>
<h4 id="③-주요-dns-레코드-타입">③ 주요 DNS 레코드 타입</h4>
<blockquote>
<h4 id="서버-배포-dns-자원-레코드로-주소-연결하기">서버 배포: DNS 자원 레코드로 주소 연결하기</h4>
<p>📍 내가 만든 서버를 사람들이 <code>도메인 네임(예: boxbox.kr)</code>으로 접속하게 만들려면 다음의 과정을 거쳐야 한다.</p>
</blockquote>
<ol>
<li><strong>도메인 구매</strong>
먼저 DNS 서비스 업체에서 원하는 도메인 네임을 구입한다.<blockquote>
</blockquote>
</li>
<li><strong>📍네임 서버에 등록</strong>
도메인만 산다고 바로 접속되는 것이 아니다‼️</li>
</ol>
<p><strong>&quot;이 도메인은 이 IP 주소로 가세요&quot;</strong>라는 정보를 네임 서버에 알려줘야 한다.</p>
<blockquote>
</blockquote>
<ol start="3">
<li><strong>DNS 자원 레코드(DNS Resource Record) 추가</strong>
네임 서버에 저장하는 설정 정보를 DNS 레코드라고 부른다.
해당 레코드 안에는 특정 IP 주소가 어떤 도메인 네임에 대응되는지 등 도메인 관리에 필요한 각종 정보가 담긴다.</li>
</ol>
<table>
<thead>
<tr>
<th>레코드 유형</th>
<th>설명</th>
<th>예시</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>A</strong></td>
<td>특정 호스트에 대한 도메인 네임과 <strong>IPv4</strong> 주소 매핑</td>
<td>192.0.2.1</td>
<td>&quot;naver.com은 이 숫자 주소야.&quot;</td>
</tr>
<tr>
<td><strong>AAAA</strong></td>
<td>특정 호스트에 대한 도메인 네임과 <strong>IPv6</strong> 주소 매핑</td>
<td>2001:db8::1</td>
<td>&quot;IPv6 주소 버전으로는 이거야.&quot;</td>
</tr>
<tr>
<td><strong>CNAME</strong></td>
<td>호스트 네임에 대한 <strong>별칭(Alias)</strong> 지정</td>
<td>example.com</td>
<td>&quot;<a href="http://www.example.com%EC%9D%80">www.example.com은</a> 사실 example.com과 같아&quot;</td>
</tr>
<tr>
<td><strong>NS</strong></td>
<td>특정 도메인의 IP를 찾을 수 있는 <strong>네임 서버</strong> 지정</td>
<td>ns1.naver.com</td>
<td>&quot;이 도메인의 진짜 정보는 이 서버가 쥐고 있어.&quot;</td>
</tr>
<tr>
<td><strong>MX</strong></td>
<td>해당 도메인과 연동된 <strong>메일 서버</strong></td>
<td>aspmx.l.google.com</td>
<td>이 주소로 메일을 보내면 이 서버로 배달해줘.</td>
</tr>
<tr>
<td><code>*www.naver.com을 입력해도 naver.com으로 연결되는 이유는 www가 붙은 주소를 별명(CNAME)으로 등록하고, 실제 주소인 naver.com을 진짜 이름(Canonical Name)으로 지정했기 때문이다.</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>*naver.com의 IP 주소가 바뀌더라도, A 레코드 하나만 수정하면 별명인 www 주소는 자동으로 바뀐 IP를 따라간다. (CNAME 사용 이유)</code></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<h2 id="2-자원과-uriurl">2. 자원과 URI/URL</h2>
<p>웹상에서 정보를 주고받기 위해서는 식별을 위한 정보가 필요하다.</p>
<p>자원을 식별하기 위한 방식으로는 <strong>URI</strong>, <strong>URL</strong>, <strong>URN</strong>이 있고, 오늘날 인터넷 환경에서 더 많이 사용되는 방법은 <strong>URL</strong>이다.
<code>*자원: 네트워크 상의 메시지를 통해 주고받는 최종 대상을 의미한다.</code></p>
<h3 id="2-1-uri--url--urn">2-1. URI / URL / URN</h3>
<ul>
<li><strong>URI(Uniform Resource Identifier):</strong> 자원을 식별하기 위한 통일된 방식의 총칭이다.</li>
<li>📍<strong>URL(Uniform Resource Locator):</strong> 자원의 <strong>위치</strong>를 기반으로 식별한다. 오늘날 가장 널리 쓰인다.</li>
<li><strong>URN(Uniform Resource Name):</strong> 위치와 상관없이 자원에 부여된 고유한 <strong>이름</strong>으로 식별한다. (예: <code>urn:isbn:0451450523</code>)</li>
</ul>
<h3 id="2-2-📍url의-구조">2-2. 📍URL의 구조</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/f19d60a7-82cb-4b03-9cfb-400f4cac4557/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>① Scheme</strong></td>
<td>자원에 접근하는 방법(프로토콜). <code>http</code>, <code>https</code> 등</td>
</tr>
<tr>
<td><strong>② Authority</strong></td>
<td>호스트를 특정하는 IP/도메인 네임과 포트 번호가 명시됨</td>
</tr>
<tr>
<td><strong>③ Path</strong></td>
<td>자원이 위치한 경로를 계층적으로 표현</td>
</tr>
<tr>
<td><strong>④ Query</strong></td>
<td>키=값 형태의 데이터로, 자원에 대한 추가적인 매개변수 전달</td>
</tr>
<tr>
<td><strong>⑤ Fragment</strong></td>
<td>자원의 일부분(특정 섹션 등)을 가리키기 위한 정보</td>
</tr>
</tbody></table>
<blockquote>
<h4 id="예시-쿼리-문자열">예시) 쿼리 문자열</h4>
<p>쿼리 문자열은 물음표(?)로 시작되는 &lt;키=값&gt; 형태의 데이터로, 앰퍼샌드(&amp;)를 사용해 여러 쿼리 문자열을 연결할 수 있다.![]<img src="https://velog.velcdn.com/images/w_dw_r/post/aa5b37cd-0785-4bff-84d2-7a933210a933/image.png" alt=""></p>
</blockquote>
<hr>
<h2 id="3-http의-특징과-메시지-구조">3. HTTP의 특징과 메시지 구조</h2>
<p>HTTP의 목적은 데이터 형식에 구애받지 않고 다양한 애플리케이션 데이터를 네트워크를 통해 주고받는 것이다.</p>
<h3 id="3-1-http의-4가지-주요-특징">3-1. HTTP의 4가지 주요 특징</h3>
<h4 id="①-요청-응답-기반-프로토콜">① 요청-응답 기반 프로토콜</h4>
<p>HTTP는 기본적으로 요청 메시지를 보내는 클라이언트와 이에 대한 응답 메시지를 보내는 서버가 서로 상호작용하는 구조로 동작한다.</p>
<h4 id="②-미디어-독립적-프로토콜-mime-타입">② 미디어 독립적 프로토콜 (MIME 타입)</h4>
<p>데이터의 형식에 특별한 제한을 두지 않고, 주고받는 자원의 종류를 <strong>미디어 타입(MIME 타입)</strong>으로 명시하여 처리한다.</p>
<ul>
<li><strong>타입/서브타입</strong> 형식으로 구성된다.</li>
<li><strong>대표 예시</strong>: <code>text/html</code>, <code>image/png</code>, <code>application/json</code>, <code>video/mp4</code> 등</li>
</ul>
<h4 id="③-스테이트리스stateless-프로토콜">③ 스테이트리스(Stateless) 프로토콜</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/cbf7e19c-5885-425a-8848-4b030a3ef1a9/image.png" alt=""></p>
<p>서버가 클라이언트의 이전 상태를 기억하지 않는 방식이다.</p>
<ul>
<li>서버가 클라이언트 상태를 관리할 부담이 적어 확장성(Scalability)과 견고성(Robustness)이 높다.
<code>*서버를 늘리기가 쉬워지고, 서버 하나가 고장 나도 서비스가 멈추지 않는다.</code></li>
<li>모든 요청은 독립적인 요청으로 간주되며, 필요한 경우 클라이언트가 상태 정보를 매번 포함하여 전송해야 한다.</li>
</ul>
<p><em>➡️ 서버가 클라이언트를 기억할 필요가 없기 때문에, 언제든 서버를 쉽게 늘릴 수 있고(확장성), 특정 서버가 고장 나도 서비스가 멈추지 않는다(견고성).</em></p>
<blockquote>
<h4 id="스테이트리스의-단점과-해결책">스테이트리스의 단점과 해결책</h4>
<p>Stateless는 모든 요청에 필요한 정보를 담아야 하기에 <strong>데이터 중복 전송</strong>과 <strong>개발의 번거로움</strong>이라는 단점을 가진다.</p>
</blockquote>
<p>하지만 이를 통해 서버가 클라이언트를 기억할 필요가 없어져 <strong>서버 확장성</strong>과 <strong>시스템 견고성</strong>이라는 큰 이득을 얻을 수 있다.</p>
<blockquote>
</blockquote>
<p><strong>기억력 부재</strong>로 인한 불편함은 <code>쿠키</code>, <code>세션</code>, <code>토큰</code> 기술을 도입해 보완함으로써, 프로토콜의 장점은 살리고 사용자의 편의성도 동시에 챙긴다.</p>
<h4 id="④-지속-연결-프로토콜">④ 지속 연결 프로토콜</h4>
<p><code>초기 HTTP(1.0 이하)</code>는 쓰리 웨이 핸드셰이크를 통해 TCP 연결을 수립한 후, 요청-응답마다 연결을 맺고 끊는 <strong>비지속 연결</strong>을 제공했지만, <code>현대 HTTP</code>는 효율을 위해 연결을 일정 기간 유지하는 <strong>지속 연결</strong>을 제공한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/a74e0760-a8bc-4ec6-b7a0-d7a3a28fe272/image.png" alt=""></p>
<p><code>*킵 얼라이브(Keep-alive): 지속 연결의 다른 표현으로, 하나의 TCP 연결을 통해 여러 개의 요청과 응답을 처리하는 기술이다.</code></p>
<h3 id="3-2-http-버전별-특징">3-2. HTTP 버전별 특징</h3>
<p>| 버전 | 기반 프로토콜 | 주요 특징 | 
| --- | --- | --- | --- |
| <strong>HTTP 1.1</strong> | TCP | 지속 연결 공식 지원, 메시지를 텍스트(평문)로 주고받음 |<br>| <strong>HTTP 2.0</strong> | TCP | <strong>바이너리 데이터</strong> 기반 송수신, <strong>헤더 압축</strong>, <strong>서버 푸시</strong>, <strong>멀티플렉싱</strong> 지원 |<br>| <strong>HTTP 3.0</strong> | <strong>UDP (QUIC)</strong> | TCP 대신 <strong>UDP</strong> 기반의 QUIC 프로토콜을 사용하여 연결 지연을 줄이고 속도를 개선 |<br><code>*HTTP 3.0은 비교적 가장 최근에 등장하여 사용 비중이 점차 높아지고 있는 프로토콜이다.</code></p>
<blockquote>
<h4 id="http-20의-멀티플렉싱">HTTP 2.0의 멀티플렉싱</h4>
<p>여러 독립적인 스트림을 통해 요청/응답을 병렬로 처리하여, 앞선 요청이 지연될 때 뒤의 요청도 막히는 <strong>HOL 블로킹</strong> 문제를 완화한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/0a38d2f8-1d71-4953-8b20-d33554cfbc9d/image.png" alt=""></p>
<h3 id="3-3-http-메시지-구조">3-3. HTTP 메시지 구조</h3>
<p>HTTP 메시지는 크게 <strong>시작 라인</strong>, <strong>필드 라인(헤더)</strong>, <strong>메시지 본문</strong>의 세 부분으로 구성된다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/53f418ad-bbe7-4ae4-9117-ecd869b0276d/image.png"
width=300/></p>
<h4 id="①-시작-라인-start-line">① 시작 라인 (Start-line)</h4>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/cabe7689-10e9-4d13-bbf0-bc200c018646/image.png"
width=500/></p>
<ul>
<li><strong>요청 라인(클라이언트→서버)</strong>: <code>메서드</code> + <code>요청 대상(URL)</code> + <code>HTTP 버전</code>으로 구성된다.</li>
<li><strong>상태 라인(서버→클라이언트)</strong>: <code>HTTP 버전</code> + <code>상태 코드</code> + <code>이유 구문</code>으로 구성된다.</li>
<li><em>예: HTTP/1.1 200 OK, HTTP/1.1 404 Not Found</em>
<code>*여기서 +는 (공백)을 의미한다.</code></li>
</ul>
<blockquote>
<h4 id="📍-요청-라인과-상태-라인">📍 요청 라인과 상태 라인</h4>
</blockquote>
<p>HTTP 메시지의 첫 번째 줄은 요청인지 응답인지에 따라 <strong>요청 라인</strong> 또는 <strong>상태 라인</strong>이 된다.</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>구분</th>
<th>필드 이름</th>
<th>설명</th>
<th>예시 및 특징</th>
</tr>
</thead>
<tbody><tr>
<td><strong>요청 라인</strong></td>
<td>📍<strong>메서드(method)</strong></td>
<td>클라이언트가 서버의 자원에 대해 수행할 작업의 종류</td>
<td><code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code> 등</td>
</tr>
<tr>
<td></td>
<td><strong>요청 대상(request-target)</strong></td>
<td>요청을 보낼 서버 자원의 경로(Path)</td>
<td><code>/hello?q=network</code></td>
</tr>
<tr>
<td></td>
<td><strong>HTTP 버전(HTTP-version)</strong></td>
<td>사용된 HTTP 버전</td>
<td><code>HTTP/1.1</code></td>
</tr>
<tr>
<td><strong>상태 라인</strong></td>
<td><strong>HTTP 버전(HTTP-version)</strong></td>
<td>사용된 HTTP 버전</td>
<td><code>HTTP/1.1</code></td>
</tr>
<tr>
<td></td>
<td>📍<strong>상태 코드(status code)</strong></td>
<td>요청에 대한 결과를 나타내는 3자리 정수</td>
<td><code>200</code> (성공), <code>404</code> (실패)</td>
</tr>
<tr>
<td></td>
<td>📍<strong>이유 구문(reason phrase)</strong></td>
<td>상태 코드에 대한 문자열 형태의 설명</td>
<td><code>OK</code>, <code>Not Found</code></td>
</tr>
</tbody></table>
<blockquote>
<h4 id="📍-이유-구문">📍 이유 구문</h4>
</blockquote>
<p>이유 구문은 상태 코드의 의미를 사람이 읽기 쉽게 설명해 주는 역할을 한다.</p>
<blockquote>
</blockquote>
<ul>
<li><strong>성공 응답:</strong> <code>HTTP/1.1 200 OK</code> (요청이 성공적으로 처리되었을 때)</li>
<li><strong>실패 응답:</strong> <code>HTTP/1.1 404 Not Found</code> (요청한 자원이 서버에 존재하지 않을 때)</li>
</ul>
<h4 id="②-필드-라인-http-헤더">② 필드 라인 (HTTP 헤더)</h4>
<p>메시지 전송과 관련된 부가 정보(메타데이터)를 담고 있으며, <strong>이름: 값</strong>의 쌍으로 구성된다.</p>
<ul>
<li><em>예: Content-Type: text/html, Content-Length: 648</em></li>
</ul>
<h4 id="③-메시지-본문-message-body">③ 메시지 본문 (Message Body)</h4>
<p>실제로 전송하고자 하는 데이터가 담기는 부분으로, 없을 수도 있다.</p>
<hr>
<blockquote>
<h4 id="📍총정리">📍총정리</h4>
<p><strong>1. DNS는 네트워크의 &#39;전화번호부&#39;이다.</strong>
사람이 이해하기 쉬운 문자를 컴퓨터가 이해하는 IP 주소로 바꿔주는 핵심 인프라이다.
<strong>2. 계층 구조가 성능과 관리를 보장한다.</strong>
도메인과 네임 서버가 계층적으로 분산되어 있어 전 세계적인 규모의 관리가 가능하며, 캐시와 TTL을 통해 효율적인 응답을 제공한다.
<strong>3. URL은 웹 자원의 &#39;상세 주소&#39;이다.</strong>
프로토콜(Scheme)부터 서버 위치(Authority), 상세 경로(Path), 상세 요청 정보(Query)까지 포함하여 웹상의 특정 정보를 명확히 식별한다.
<strong>4. HTTP는 &#39;독립적&#39;이다.</strong>
각 요청은 이전 기록에 얽매이지 않는 <strong>스테이트리스</strong> 방식을 취하며, 서버는 특정 클라이언트에 종속되지 않아 서버 확장이 용이하다.
<strong>5. HTTP는 &#39;효율적&#39;으로 진화했다.</strong>
텍스트 기반의 1.1에서 바이너리 기반의 2.0, 그리고 UDP를 활용한 3.0으로 발전하며 <strong>지연 시간을 줄이고 전송 효율을 극대화</strong>하는 방향으로 나아가고 있다.
<strong>6. 메시지는 &#39;명확한 규격&#39;을 가진다.</strong>
시작 라인을 통해 요청의 의도(메서드)나 결과(상태 코드)를 즉시 파악하고, 헤더를 통해 데이터의 성격(MIME 타입 등)을 규정하여 복잡한 자원도 안전하게 송수신한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-4 전송 계층 - TCP와 UDP (포트를 통한 프로세스 식별, (비)신뢰성과 (비)연결형, TCP의 연결 수립 )]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-4-%EC%A0%84%EC%86%A1-%EA%B3%84%EC%B8%B5-TCP%EC%99%80-UDP-%ED%8F%AC%ED%8A%B8%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8B%9D%EB%B3%84-%EB%B9%84%EC%8B%A0%EB%A2%B0%EC%84%B1%EA%B3%BC-%EB%B9%84%EC%97%B0%EA%B2%B0%ED%98%95-TCP%EC%9D%98-%EC%97%B0%EA%B2%B0-%EC%88%98%EB%A6%BD</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-4-%EC%A0%84%EC%86%A1-%EA%B3%84%EC%B8%B5-TCP%EC%99%80-UDP-%ED%8F%AC%ED%8A%B8%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8B%9D%EB%B3%84-%EB%B9%84%EC%8B%A0%EB%A2%B0%EC%84%B1%EA%B3%BC-%EB%B9%84%EC%97%B0%EA%B2%B0%ED%98%95-TCP%EC%9D%98-%EC%97%B0%EA%B2%B0-%EC%88%98%EB%A6%BD</guid>
            <pubDate>Mon, 02 Feb 2026 09:39:24 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
</blockquote>
<p>① 포트를 통한 프로세스 식별: 실제 프로세스를 찾아가기 위한 포트 번호의 종류와 역할
② NAT과 NAPT: 사설 IP와 공인 IP 간의 주소 변환 원리 및 포트를 활용한 N:1 대응(NAPT)
③ TCP와 UDP의 비교: 신뢰성/연결형(TCP)과 비신뢰성/비연결형(UDP) 프로토콜의 패킷 구조 및 특징
④ TCP의 신뢰성 보장: 확인 응답 번호(ACK)와 순서 번호(Seq)를 통한 데이터 전송 보장 원리
⑤ TCP 연결 수립: 쓰리 웨이 핸드셰이크(3-way handshake)를 통한 신뢰할 수 있는 통로 구축 과정
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
<hr>
<h2 id="1-tcp와-udp">1. TCP와 UDP</h2>
<p><strong>네트워크 계층</strong>에서 가장 중요한 프로토콜이 <code>IP</code>라면, <strong>전송 계층</strong>에서 가장 중요한 프로토콜 <code>TCP</code>와 <code>UDP</code>이다.</p>
<p>📍 <strong>TCP와 UDP의 패킷 구조와 동작 원리</strong>를 이해하면 <strong>전송 계층의 핵심</strong>을 이해할 수 있다. 매우 중요한 프로토콜이므로 <strong>각각 어떤 목적과 특징이 있는지</strong> 잘 기억해 두는 것이 좋다.</p>
<h3 id="1-1-포트를-통한-프로세스-식별">1-1. 포트를 통한 프로세스 식별</h3>
<p><code>IP 주소</code>와 <code>MAC 주소</code>는 <strong>패킷을 송수신하는 호스트를 특정</strong>할 수 있다.</p>
<p><em>➡️ 그런데 사실 <strong>패킷의 최종 송수신 대상</strong>은 호스트가 아니라 <strong>호스트가 실행하는 프로세스</strong>이다.</em></p>
<blockquote>
<p><strong>Q. 네트워크 상에서 호스트가 실행하는 프로세스는 어떻게 식별할 수 있을까?</strong></p>
</blockquote>
<p>A. <code>포트 번호</code>를 통해 식별할 수 있다.</p>
<blockquote>
</blockquote>
<p>네트워크 패킷을 주고 받는 프로세스에는 <code>포트 번호</code>가 할당되고,
<strong>IP 주소와 포트 번호의 조합</strong>을 통해 <strong>&#39;특정 호스트가 실행하는 특정 프로세스&#39;</strong>를 식별할 수 있다.</p>
<blockquote>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/6a1e263d-a6ea-4d25-9d11-240c74ff1c2f/image.png"
width=500/>       </p>
<p><code>*가령 하나의 호스트는 웹 브라우저, 게임, 채팅 프로그램 등 다양한 프로세스를 동시에 실행할 수 있고, 네트워크를 통해 주고 받는 패킷은 최종적으로 이러한 프로세스에 전달되어야 한다.</code></p>
<h4 id="①-tcp와-udp의-헤더">① TCP와 UDP의 헤더</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/5cb6b2f7-0791-44d5-81c7-0c53e8c90080/image.png" alt=""></p>
<p>전송 계층의 핵심 프로토콜인 <code>TCP</code>와 <code>UDP</code>는 <strong>포트를 통해 프로세스를 식별</strong>할 수 있다.</p>
<p><em>➡️ 따라서 <strong>TCP와 UDP 헤더</strong>를 살펴보면, 두 프로토콜 모두 포트 번호 필드인 <code>송신지 포트 번호</code>와 <code>수신지 포트 번호</code>를 포함하고 있다는 것을 알 수 있다.</em></p>
<h4 id="②-포트-번호">② 포트 번호</h4>
<p>개발자가 자주 다루는 정보 중 하나이므로 조금 더 자세히 알아두는 것이 좋다.</p>
<p><code>16비트</code>로 표현할 수 있는 <strong>포트 번호의 총 개수는 216, 즉 65536개</strong>이다.
<code>*0번부터 할당되으로 0번부터 65535번까지의 포트 번호를 할당할 수 있다.</code></p>
<p><strong>그리고 65536개의 포트 번호는 번호의 범위에 따라 3가지 종류로 나뉜다.</strong></p>
<table>
<thead>
<tr>
<th align="left">포트 종류</th>
<th align="left">포트 번호 범위</th>
</tr>
</thead>
<tbody><tr>
<td align="left">잘 알려진 포트</td>
<td align="left">0 ~ 1023</td>
</tr>
<tr>
<td align="left">등록된 포트</td>
<td align="left">1024 ~ 49151</td>
</tr>
<tr>
<td align="left">동적 포트</td>
<td align="left">49152 ~ 65535</td>
</tr>
</tbody></table>
<h4 id="잘-알려진-포트-well-known-port-0--1023">잘 알려진 포트 (well known port, 0 ~ 1023)</h4>
<p>이름 그대로 가장 대중적으로 사용되는 애플리케이션을 위한 포트 번호이다.
<code>범용적으로 사용되는 프로토콜</code>이 <strong>주로 사용하는 포트 번호 목록</strong>이라고 보아도 무방하다.</p>
<table>
<thead>
<tr>
<th align="left">잘 알려진 포트 번호</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">20, 21</td>
<td align="left">FTP</td>
</tr>
<tr>
<td align="left">22</td>
<td align="left">SSH</td>
</tr>
<tr>
<td align="left">23</td>
<td align="left">TELNET</td>
</tr>
<tr>
<td align="left">53</td>
<td align="left">DNS</td>
</tr>
<tr>
<td align="left">67, 68</td>
<td align="left">DHCP</td>
</tr>
<tr>
<td align="left">80</td>
<td align="left">HTTP</td>
</tr>
<tr>
<td align="left">443</td>
<td align="left">HTTPS</td>
</tr>
</tbody></table>
<h4 id="등록된-포트-registered-port-1024--49151">등록된 포트 (registered port, 1024 ~ 49151)</h4>
<p>등록된 포트는 <code>잘 알려진 포트에 비해서는 덜 범용적</code>이지만,
다음과 같이 <strong>흔하게 사용되는 애플리케이션 프로토콜에 할당하기 위한 포트 번호</strong>이다.</p>
<table>
<thead>
<tr>
<th align="left">등록된 포트 번호</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1194</td>
<td align="left">OpenVPN</td>
</tr>
<tr>
<td align="left">1433</td>
<td align="left">Microsoft SQL Server 데이터베이스</td>
</tr>
<tr>
<td align="left">3306</td>
<td align="left">MySQL 데이터베이스</td>
</tr>
<tr>
<td align="left">6379</td>
<td align="left">Redis</td>
</tr>
<tr>
<td align="left">8080</td>
<td align="left">HTTP 대체</td>
</tr>
</tbody></table>
<p><code>*잘 알려진 포트와 등록된 포트는 서버로 동작하는 프로그램 환경에서 자주 볼 수 있다.</code></p>
<h4 id="동적-포트-dynamic-portprivate-portephemeral-port-49152--65535">동적 포트 (dynamic port/private port/ephemeral port, 49152 ~ 65535)</h4>
<p><code>사설 포트</code> 또는 <code>임시 포트</code>라고도 불리는 동적 포트로,
<strong>비교적 자유롭게 사용 가능한 포트 번호이다.</strong></p>
<p>서버로서 동작하는 프로그램의 경우 주로 잘 알려진 포트와 등록된 포트가 할당되는 경우가 많지만, <code>클라이언트로서 동작하는 프로그램</code>의 경우에는 <strong>동적 포트 번호 중에서 임의의 번호가 할당</strong>되는 경우가 많다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/8c451457-d8b1-4f06-8389-95c79f464e21/image.png" alt=""></p>
<p>그 대표적인 예시가 <strong>웹 브라우저</strong>이다.</p>
<p>웹 브라우저를 통해 특정 웹 사이트에 접속하는 경우는
<code>웹 브라우저 프로그램</code>과 <code>서버 프로그램</code>이 <strong>서로 패킷을 주고받는 상황</strong>과 같다.</p>
<p><em>➡️ 이 경우, 웹 브라우저 프로그램에는 동적 포트 내 임의의 포트 번호가 자동으로 할당 된다.</em></p>
<h4 id="포트-활용-예시-1--mysql-데이터베이스-서버-연결">포트 활용 예시 1)  MySQL 데이터베이스 서버 연결</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/88a84be9-09a8-4bcb-a3c9-3a9061ddc3fc/image.png" alt=""></p>
<h4 id="포트-활용-예시-2-아파치-http-서버의-설정-파일">포트 활용 예시 2) 아파치 HTTP 서버의 설정 파일</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/bc2c76fa-6ab0-42ea-9835-72a9dcae0ddd/image.png" alt=""></p>
<p><code>*HTTP 프로토콜로 패킷을 송수신 할 경우 80번 포트를 이용하고, HTTPS 프로토콜로 패킷을 송수신 할 경우 443 포트를 이용한다</code></p>
<h4 id="③-nat과-napt-주소-변환">③ NAT과 NAPT (주소 변환)</h4>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/b8b3e51c-a486-47ae-8565-c397a7f5d508/image.png"
width=600/></p>
<ul>
<li><p><strong>NAT (Network Address Translation)</strong>
: 📍 네트워크 내부에서 사용하는 <code>사설 IP 주소</code>와 외부 네트워크에서 사용하는 <code>공인 IP 주소</code> 간의 주소를 <strong>변환</strong>해 주는 기술이다.</p>
<ul>
<li><strong>외부로 나갈 때</strong>: <code>사설 IP 주소</code> → <code>공인 IP 주소</code>로 변환 </li>
<li><strong>내부로 들어올 때</strong>: <code>공인 IP 주소</code> → <code>사설 IP 주소</code>로 변환 </li>
<li>기본적으로 IP 주소 간의 <code>일대일(1:1) 대응</code>을 원칙으로 한다.</li>
<li>📍 <strong>사설 IP 개수만큼 공인 IP가 필요</strong>하므로, IP 주소 부족 문제를 완전히 해결하기 어렵다.</li>
</ul>
</li>
</ul>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/c49a35eb-541e-4256-8bd0-bf4ad2b6d09a/image.png"
width=600/></p>
<ul>
<li><p><strong>NAPT (Network Address Port Translation)</strong>
: <code>IP 주소</code>뿐만 아니라 <code>포트 번호</code>까지 함께 고려하여 <strong>변환</strong>하는 기술로,
오늘날 대부분의 공유기에서 사용하는 방식이다.</p>
<ul>
<li>📍 <code>서로 다른 사설 IP</code>를 가진 호스트들이 <code>동일한 공인 IP</code>를 <strong>공유</strong>하되, <code>서로 다른 포트 번호</code>를 할당받아 <strong>구분</strong>한다.</li>
<li>하나의 공인 IP로 여러 개의 사설 IP 호스트를 처리하는 <code>다대일(N:1) 대응</code>을 원칙으로 한다.</li>
<li><strong>📍 공인 IP가 같더라도 포트 번호(예: 6200, 6201)가 다르면 내부의 어떤 호스트인지 특정할 수 있다.</strong></li>
<li>한정된 공인 IP 주소 자원을 매우 효율적으로 사용할 수 있어 IP 주소 부족 문제를 개선한다.</li>
</ul>
</li>
<li><p>📍 <strong>NAT vs NAPT</strong></p>
</li>
<li><table>
<thead>
<tr>
<th align="left">구분</th>
<th align="left">NAT (기본형)</th>
<th align="left">NAPT (포트 기반)</th>
</tr>
</thead>
<tbody><tr>
<td align="left">변환 대상</td>
<td align="left">IP 주소</td>
<td align="left">IP 주소 + 포트 번호</td>
</tr>
<tr>
<td align="left">대응 관계</td>
<td align="left">1:1 대응</td>
<td align="left">N:1 대응</td>
</tr>
<tr>
<td align="left">IP 절약 효과</td>
<td align="left">낮음</td>
<td align="left">매우 높음</td>
</tr>
<tr>
<td align="left">주요 용도</td>
<td align="left">단순 주소 변환</td>
<td align="left">공유기 등 다수 호스트 연결</td>
</tr>
</tbody></table>
</li>
</ul>
<blockquote>
<p><strong>즉, NAT과 NAPT를 통해</strong></p>
</blockquote>
<p><code>주소 부족 문제</code>를 해결하고,
내부 기기들을 <code>외부 공격</code>으로부터 보호하며,
<code>네트워크 관리</code>를 편하게 하기 위해 주소 변환을 수행한다.</p>
<hr>
<h3 id="1-2-비신뢰성과-비연결형">1-2. (비)신뢰성과 (비)연결형</h3>
<pre><code>TCP
 ├── 신뢰할 수 있는 통신 ─ 상태 관리, 흐름 제어, 오류 제어, 혼잡 제어 제공 🅾️
 └── 연결형 통신 ─────── 연결 수립, 종료 과정 🅾️ 

 UDP
 ├── 신뢰할 수 없는 통신 ─ 상태 관리, 흐름 제어, 오류 제어, 혼잡 제어 제공 ❎
 └── 연결형 통신 ─────── 연결 수립, 종료 과정 ❎</code></pre><p>전송 계층에서 프로토콜을 선택할 때,</p>
<p><strong>패킷의 유실 없는 송수신</strong>을 원한다면 UDP보다 <code>TCP</code>를 선택하는 것이 유리하고,
<strong>비교적 빠른 송수신</strong>을 원한다면 TCP보다 <code>UDP</code>를 선택하는 것이 유리하다.</p>
<p><code>*신뢰할 수 있는 연결형 송수신에는 시간과 연산이 소요되기 때문에 일반적으로 TCP가 UDP에 비해 송수신 속도가 느리다.</code></p>
<h4 id="①-헤더로-살펴보는-tcp와-udp의-특징">① 헤더로 살펴보는 TCP와 UDP의 특징</h4>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/6883b766-5188-41be-90a3-93df28d907c9/image.png"
width=400/></p>
<ul>
<li>송신지 포트: 송신 프로세스가 할당된 포트 번호</li>
<li>수신지 포트: 수신 프로세스가 할당된 포트 번호</li>
<li>길이: 헤더를 포함한 UDP 패킷(<code>UDP 데이터그램</code>)의 바이트 크기</li>
<li>체크섬: 송수신 과정에서의 데이터그램 훼손 여부를 알 수 있는 정보</li>
</ul>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/d8155de8-12d8-434e-a4f6-00f07d4c5dc6/image.png"
width=400/></p>
<ul>
<li>📍 <strong>순서 번호:</strong> TCP 패킷(<code>TCP 세그먼트</code>)의 올바른 송수신 순서를 보장하기 위해 세그먼트 첫 바이트에 매겨진 번호
<code>*순서 번호를 통해 현재 주고받는 TCP 세그먼트가 송수신하고자 하는 데이터의 몇 번째 바이트에 해당하는지 알 수 있다.</code></li>
<li>📍 <strong>확인 응답 번호:</strong> 상대 호스트가 보낸 세그먼트에 대한 응답으로, 다음으로 수신하길 기대하는 순서 번호 (일반적으로 <code>올바르게 수신한 순서번호 + 1</code> 값으로 설정)
<code>*순서 번호 필드와 확인 응답 번호 필드는 함께 사용되므로 한 쌍처럼 기억해 두는 것이 좋다.</code></li>
<li>📍 <strong>제어 비트(플래그 비트):</strong> 현재 세그먼트에 대한 부가 정보를 나타내는 정보로, 각 자리의 비트가 각기 다른 의미를 가진다. (<code>기본적으로 8비트로 구성</code>)<ul>
<li>ACK : 세그먼트의 승인을 나타내기 위한 비트</li>
<li>SYN : 연결을 수립하기 위한 비트</li>
<li>FIN : 연결을 종료하기 위한 비트</li>
</ul>
</li>
</ul>
<h4 id="②-tcp의-신뢰성-보장-확인-응답ack">② TCP의 신뢰성 보장: 확인 응답(ACK)</h4>
<p><code>TCP</code> 통신에서는 데이터를 단순히 보내는 데 그치지 않고,
📍 <strong>상대방이 잘 받았는지 확인하는 과정</strong>을 거친다.</p>
<p>이때 핵심 역할을 하는 것이 <code>확인 응답 번호</code>와 <code>ACK 플래그</code>다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/4a2916fe-84c0-4743-8d05-c53b77a44eb9/image.png"
width=400/></p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/44319641-2d99-4423-a16c-327dafb04f1d/image.png"
width=400/></p>
<table>
<thead>
<tr>
<th align="left">단계</th>
<th align="left">주체</th>
<th align="left">동작 및 내용</th>
<th align="left">의미</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1단계</td>
<td align="left">호스트 A</td>
<td align="left">순서 번호 <code>100</code> 전송</td>
<td align="left">100번 데이터를 보낸다.</td>
</tr>
<tr>
<td align="left">2단계</td>
<td align="left">호스트 B</td>
<td align="left">ACK 플래그 = 1 설정 (0/1)</td>
<td align="left">지금 응답(ACK) 보내는 중이야!</td>
</tr>
<tr>
<td align="left">3단계</td>
<td align="left">호스트 B</td>
<td align="left">확인 응답 번호 = 101 명시</td>
<td align="left">100번 잘 받았어. 다음엔 101번 줘.</td>
</tr>
<tr>
<td align="left">4단계</td>
<td align="left">호스트 A</td>
<td align="left">응답 수신 후 101번 전송 준비</td>
<td align="left">B가 잘 받았구나! 이제 101번을 보내자.</td>
</tr>
</tbody></table>
<blockquote>
<ul>
<li>TCP 패킷(세그먼트)이라는 봉투 안에는 여러 칸이 있는데, 그중 <code>ACK 플래그</code> 칸과 <code>확인 응답 번호</code> 칸이 따로 있다. </li>
</ul>
</blockquote>
<ul>
<li><code>확인 응답 번호의 +1</code>은 <strong>다음에 받을 데이터의 번호</strong>이다.</li>
<li><code>ACK 플래그 = 1</code>은 <strong>지금 이 패킷에 답장 정보가 들어있다는 신호</strong>를 이분법적으로 나타낸 것이다. (0/1)</li>
</ul>
<hr>
<h3 id="1-3-tcp의-연결-수립">1-3. TCP의 연결 수립</h3>
<p><code>TCP</code>는 <code>UDP</code>와 달리 <strong>송수신 이전에</strong> <code>연결</code>을 <strong>수립</strong>하고, <strong>송수신 이후에</strong>는 <code>연결</code>을 <strong>종료</strong>한다. <code>*송수신 전후로 상태라는 값을 관리하기도 한다.</code></p>
<blockquote>
<p>📍 TCP와 UDP의 차이는 <strong>&#39;전화&#39;</strong>와 <strong>&#39;우편&#39;</strong>의 차이와 같다.</p>
</blockquote>
<p><strong>TCP (전화 방식):</strong> 상대방과 먼저 통화를 연결(연결 수립)하고, 상대가 &quot;여보세요&quot;라고 확인한 뒤에야 말을 시작한다. (<code>연결이 끊기면 대화도 중단됨</code>)</p>
<blockquote>
</blockquote>
<p><strong>UDP (우편 방식):</strong> 상대방이 집에 있는지, 편지를 받을 준비가 되었는지 확인하지 않는다. (<code>그냥 봉투에 목적지 주소만 써서 우체통에 던져 넣는 식</code>)</p>
<p>📍 TCP의 연결 수립은 <strong>쓰리 웨이 핸드셰이크</strong>를 통해 이루어진다.</p>
<p>이는 쓰리 웨이라는 이름처럼 <strong>세 단계로 이루어진 TCP의 연결 수립 과정</strong>을 뜻한다.</p>
<p>가령 호스트 A가 호스트 B에게 처음 연결 요청을 보낸다고 가정했을 때 각각의 단계는 다음과 같다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/6a65ad30-cd63-4188-96cc-d50fb67bb02b/image.png"
width=400/></p>
<ul>
<li>액티브 오픈: 호스트 A처럼 처음 연결을 시작하는 과정</li>
<li>패시브 오픈: 호스트 B처럼 연결 요청을 수신한 뒤 그에 대한 연결을 수립하는 과정
<code>*ACK : 세그먼트의 승인을 나타내기 위한 비트</code>
<code>*SYN : 연결을 수립하기 위한 비트</code></li>
</ul>
<p><strong>① 1단계: 연결 요청 (SYN)</strong></p>
<blockquote>
<p>&quot;저기요, 대화 가능할까요?
제 번호표는 3588415412번부터 시작할게요!&quot;</p>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/00c2793f-8a46-458c-a384-4ff9168b191e/image.png"
width=500/></p>
<p>보내는 사람: 192.168.0.1 (포트: 49859 - 임의의 동적 포트)
받는 사람: 10.10.10.1 (포트: 80 - HTTP 서버)</p>
<p>주요 정보:</p>
<ul>
<li>Flags: <code>SYN = 1</code> (연결을 시작하겠다는 신호)</li>
<li>순서 번호(Sequence Number): 3588415412 (생성된 난수값)</li>
</ul>
<p><strong>② 2단계: 요청 수락 및 맞요청 (SYN + ACK)</strong></p>
<blockquote>
<p>&quot;네, 잘 들려요! 방금 주신 건 잘 받았고요(3588415413번 주세요).
저도 대화하고 싶어요, 제 번호표는 697411256번부터예요!&quot;</p>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/f0f97696-6eb6-4c18-9179-2697a530d930/image.png"
width=500/></p>
<p>보내는 사람: 10.10.10.1 (서버)
받는 사람: 192.168.0.1 (클라이언트)</p>
<p>주요 정보:</p>
<ul>
<li>Flags: <code>SYN = 1</code>, <code>ACK = 1</code> (수락과 동시에 나도 연결하겠다는 뜻)</li>
<li>순서 번호: 697411256 (서버가 정한 시작 번호)</li>
<li>확인 응답 번호(Acknowledgment Number): 3588415413 (상대가 보낸 번호, 3588415412 + 1)</li>
</ul>
<p><strong>③ 최종 확인 (ACK)</strong></p>
<blockquote>
<p>&quot;알겠습니다! 서버님 번호표도 잘 확인했어요(697411257번 주시면 되죠?).
이제 진짜 시작합니다!&quot;</p>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/97ab4be1-ac5b-4498-9547-6d165348e9d6/image.png"
width=500/></p>
<p>보내는 사람: 192.168.0.1 (클라이언트)
받는 사람: 10.10.10.1 (서버)</p>
<p>주요 정보:</p>
<ul>
<li>Flags: <code>ACK = 1</code> (최종 승인)</li>
<li>순서 번호: 3588415413 (아까 서버가 달라고 했던 번호)</li>
<li>확인 응답 번호: 697411257 (서버가 보낸 번호 697411256 + 1)</li>
</ul>
<hr>
<p>지금까지의 과정을 그림으로 표현하면 다음과 같다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/a8a66797-9a40-4614-bc85-01a532576cc7/image.png"
width=400/></p>
<p><em>➡️ TCP가 이 복잡한 과정을 거치는 진짜 이유는 <strong>&quot;상대방과 대화할 준비가 완벽히 되었는지 확인&quot;</strong>하고, <strong>&quot;데이터가 중간에 유실되지 않도록 순서 번호를 맞추기 위해서&quot;</strong>이다.</em></p>
<hr>
<blockquote>
<p>내용이 복잡해서 총정리를 해보자면...</p>
</blockquote>
<p><strong>1. 포트(Port): &quot;누구에게 전달할 것인가?&quot;</strong>
IP 주소가 <code>아파트 주소</code>라면, 포트 번호는 <code>호스트 내 특정 프로세스(동·호수)</code>를 찾아가는 이표이다.</p>
<blockquote>
</blockquote>
<p><code>NAPT</code> 기술은 이 <strong>포트 번호</strong>를 활용해 하나의 공인 IP를 여러 사설 IP가 공유할 수 있게 해서 <strong>IP 부족 문제를 해결</strong>한다.</p>
<blockquote>
</blockquote>
<p><strong>2. TCP vs UDP: &quot;어떤 방식으로 보낼 것인가?&quot;</strong>
<code>TCP(신뢰성/연결형)</code>: 전화처럼 먼저 연결을 확인하고 데이터를 주고받는다. 유실 없는 전송이 중요할 때 사용한다.</p>
<blockquote>
</blockquote>
<p><code>UDP(비신뢰성/비연결형)</code>: 우편처럼 일단 던지고 본다. 속도가 생명인 실시간 스트리밍이나 게임에 유리하다.</p>
<blockquote>
</blockquote>
<p><strong>3. 쓰리웨이 핸드셰이크: &quot;대화할 준비 됐나요?&quot;</strong>
TCP가 데이터 송수신 전에 거치는 <strong>3단계 연결 수립 과정</strong>이다.</p>
<blockquote>
</blockquote>
<p>📍 단순히 연결을 맺는 것을 넘어, 서로의 <strong>순서 번호(Sequence Number)</strong>를 동기화하고 <code>데이터를 받을 준비가 되었는지</code> 최종적으로 확인해서 전송의 <strong>신뢰성</strong>을 확보한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-3 네트워크 계층 - IP (공인 IP 주소와 사설 IP 주소, IP 주소의 할당, ICMP, ARP)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-3-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5-IP-%EA%B3%B5%EC%9D%B8-IP-%EC%A3%BC%EC%86%8C%EC%99%80-%EC%82%AC%EC%84%A4-IP-%EC%A3%BC%EC%86%8C-IP-%EC%A3%BC%EC%86%8C%EC%9D%98-%ED%95%A0%EB%8B%B9-ICMP-ARP</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-3-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5-IP-%EA%B3%B5%EC%9D%B8-IP-%EC%A3%BC%EC%86%8C%EC%99%80-%EC%82%AC%EC%84%A4-IP-%EC%A3%BC%EC%86%8C-IP-%EC%A3%BC%EC%86%8C%EC%9D%98-%ED%95%A0%EB%8B%B9-ICMP-ARP</guid>
            <pubDate>Tue, 27 Jan 2026 07:36:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
</blockquote>
<p>① 공인 IP와 사설 IP
② IP 할당 방식: 정적 할당과 DHCP를 통한 동적 할당
③ ICMP 프로토콜: IP의 비연결성을 보완하는 피드백 메시지와 TTL, 홉(Hop)
④ ARP 프로토콜: IP 주소를 기반으로 MAC 주소를 알아내는 방법과 ARP 테이블
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
<hr>
<h2 id="1-공인-ip-주소와-사설-ip-주소">1. 공인 IP 주소와 사설 IP 주소</h2>
<p>호스트의 IP 주소는 네트워크 설정이나 명령어를 통해 확인할 수도 있고, 간단한 온라인 검색을 통해 확인할 수도 있다.</p>
<p><strong>① Mac OS - <code>ifconfig | grep</code> 명령어</strong>
결과: <code>inet 172.xx.x.x</code></p>
<p><strong>② 온라인 검색</strong>
결과: <code>61.84.xx.x</code></p>
<p>그런데 나처럼 이 두 방식으로 확인한 IP 주소가 다른 사람들이 있을 것이다.</p>
<p>이에 대해 아래처럼 생각할 수도 있다.</p>
<blockquote>
<p><em>호스트에 할당한 IP 주소가 유일하고 고유하지 않았던 걸까?</em></p>
</blockquote>
<p><strong>이 생각은 반만 맞는 말이다.</strong></p>
<p>고유한 IP 주소도 있고, 고유하지 않은 IP 주소도 있다.
그리고 이 두 종류의 IP 주소는 함께 사용되는 경우가 많다.</p>
<h3 id="1-1-공인-ip-주소">1-1. 공인 IP 주소</h3>
<p>전세계에서 <strong>고유한 IP 주소</strong>를 뜻하며, <code>인터넷을 비롯한 네트워크 간 통신</code>에서 사용되는 IP 주소가 바로 공인 IP 주소이다.</p>
<p>📍 앞서 구글이나 네이버 등의 검색 사이트를 통해 확인했던 IP 주소가 바로 공인 IP 주소이다.</p>
<p><em>➡️ 검색 사이트의 서버와 패킷을 주고 받으려면 호스트가 속한 네트워크 밖에서 사용할 공인 IP 주소를 사용해야 하기 때문이다.</em></p>
<p><code>*공인 IP 주소는 ISP나 공인 IP 주소 할당 기관을 통해 할당받을 수 있다.</code></p>
<h3 id="1-2-사설-ip-주소">1-2. 사설 IP 주소</h3>
<p><code>사설 네트워크</code>에서 사용하기 위한 IP 주소를 뜻하며, <strong>고유하지 않은 IP 주소</strong>이기도 하다.</p>
<p><code>*사설 네트워크: 외부 네트워크에 공개되지 않은 네트워크</code></p>
<p>사설 IP 주소는 일반적으로 <code>라우터(공유기)</code>를 통해 할당되므로, <code>라우터(공유기)</code>를 중심으로 구성된 LAN 대부분은 사설 네트워크에 해당한다.</p>
<blockquote>
<p>📍 IP 주소 공간 중에서 사설 IP 주소로 사용하도록 <strong>특별히 예약된 IP 주소 공간</strong>이 있다. </p>
</blockquote>
<ul>
<li>10.0.0.0/8 (10.0.0.0 ~ 10.255.255.255)</li>
<li>172.16.0.0/12 (172.16.0.0 ~ 172.31.255.255)</li>
<li>192.168.0.0/16 (192.168.0.0 ~ 192.168.255.255)<blockquote>
</blockquote>
<code>*위의 예약 IP 주소 범위에 속하는 IP 주소는 사설 IP 주소로 간주하기로 약속된 주소이다.</code></li>
</ul>
<p><em>➡️ 📍 사설 IP 주소는 해당 호스트가 속한 사설 네트워크 상에서만 유효한 주소이므로 얼마든지 다른 네트워크 상의 사설 IP 주소와 중복될 수 있다.</em></p>
<hr>
<h2 id="2-ip-주소의-할당">2. IP 주소의 할당</h2>
<p>호스트에 IP 주소를 할당하는 방법으로는 정적 할당과 동적 할당이 있다.</p>
<p><code>정적 할당</code>은 <strong>수작업</strong>을 통해 이루어지고, <code>동적 할당</code>은 일반적으로 <strong>DHCP</strong>라는 프로토콜을 통해 이루어진다.</p>
<h3 id="2-1-정적-할당">2-1. 정적 할당</h3>
<p>직접 <strong>수작업</strong>으로 IP 주소를 부여하는 방식으로, 정적 할당을 통해 할당된 IP 주소를 <code>정적 IP 주소(Static IP Address)</code>라고 한다.</p>
<p><code>*모든 운영체제는 IP 주소를 수동으로 설정 가능하며, 일반적으로 부여하고자 하는 IP 주소와 서브넷 마스크, 게이트웨이(라우터) 주소, DNS 주소 등이 필요하다.</code></p>
<p><strong>① Mac OS 예시</strong>
<img src="https://velog.velcdn.com/images/w_dw_r/post/ea976762-4671-410e-8592-326d6cd93150/image.png" alt=""></p>
<p><strong>② Windows OS 예시</strong>
<img src="https://velog.velcdn.com/images/w_dw_r/post/d28de4cd-5563-4bad-a5ad-e44a579be560/image.png" alt=""></p>
<blockquote>
<h4 id="ip-할당에서의-게이트웨이-기본-게이트웨이">IP 할당에서의 게이트웨이(= 기본 게이트웨이)</h4>
<p><code>기본 게이트웨이(Default Gateway)</code>: 컴퓨터가 다른 네트워크(인터넷 등)로 데이터를 보낼 때 거치는 <strong>관문 라우터</strong></p>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/98938deb-7353-4b13-90b7-bc6fb6148245/image.png"
width=400/></p>
<ul>
<li><code>기본 게이트웨이</code>는 네트워크 외부와 연결된 <strong>라우터(공유기)의 주소</strong>를 의미하는 경우가 많다.</li>
<li>호스트가 속한 네트워크의 외부로 나가기 위한 <strong>첫 기본 경로</strong>이기 때문이다.<blockquote>
</blockquote>
따라서 <strong>IP 할당</strong>의 맥락에서 사용되는 <code>게이트웨이</code>는 주로 <code>기본 게이트 웨이</code>를 의미하므로, 📍 게이트웨이(라우터) 주소에 기본 게이트웨이의 역할을 하는 <strong>라우터(공유기)의 주소</strong>를 적어주면 된다.<blockquote>
</blockquote>
<code>*게이트웨이(Gateway): 일반적으로 서로 다른 네트워크를 연결하는 하드웨어적/소프트웨어적 수단</code></li>
</ul>
<blockquote>
<h4 id="ip-할당에서의-dns-주소">IP 할당에서의 DNS 주소</h4>
<p>기본적으로 호스트끼리 패킷을 주고받기 위해서는 IP 주소가 사용되지만, 통신을 주고받는 모든 호스트의 IP 주소를 기억하기는 어렵다.</p>
</blockquote>
<p>이런 이유에서 <strong>≪도메인 네임, IP 주소≫ 쌍</strong>을 저장하는 <code>DNS 서버(네임 서버)</code>에 질의를 보내, 호스트가 도메인 네임을 토대로 이에 대응되는 IP 주소를 알 수 있도록 해야 한다.</p>
<blockquote>
</blockquote>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/2437b3ab-7eaf-4b5f-bd1e-c6328c757d40/image.png"
width=600/></p>
<blockquote>
</blockquote>
<p>📍 DNS 주소에 마땅히 적을 입력값이 없다면 누구나 사용할 수 있도록 <strong>공개된 대표적인 네임 서버 주소(<code>8.8.8.8</code>, <code>1.1.1.1</code> 등)를 입력</strong>하면 된다.</p>
<blockquote>
</blockquote>
<p><code>*도메인 네임: &#39;~.com&#39;, &#39;~.co.kr&#39;처럼 호스트를 식별하기 위해 IP 주소에 대응되는 기억할 수 있는 문자열</code>
<code>*DNS 주소: 호스트가 도메인 네임을 토대로 IP 주소를 알아내기 위해 질의하는 서버의 주소</code></p>
<h3 id="2-2-동적-할당-dhcp">2-2. 동적 할당 (DHCP)</h3>
<p>동적 할당은 프로토콜을 통해 <strong>자동</strong>으로 IP 주소를 부여하는 방식이다.
이렇게 할당된 주소를 <code>동적 IP 주소(Dynamic IP Address)</code>라고 부른다.</p>
<p>일상적으로 동적 IP 주소가 많이 사용되는 만큼 , <strong>DHCP</strong> 또한 빈번히 사용된다.</p>
<h4 id="①-dhcp-dynamic-host-configuration-protocol">① DHCP (Dynamic Host Configuration Protocol)</h4>
<p>: 네트워크상의 호스트(컴퓨터, 스마트폰 등)가 IP 주소를 요청하면, <code>DHCP 서버</code>가 <strong>관리 중인 IP 주소 목록 중에서 하나를 빌려주는 방식</strong>을 말한다.</p>
<p><em>➡️ 즉, 호스트와 서버가 메시지를 주고받으며 자동으로 IP 설정을 완료한다.</em></p>
<p><code>*DHCP 서버: 할당 가능한 IP 주소 목록을 관리하고 요청에 따라 배분하는 주체</code>
<code>*일반적으로 라우터/공유기가 DHCP 서버 역할을 수행</code></p>
<h4 id="②-동적-ip-주소의-임대와-갱신">② 동적 IP 주소의 &#39;임대&#39;와 &#39;갱신&#39;</h4>
<blockquote>
</blockquote>
<h4 id="📍동적-할당-시-유의해야-할-점">📍동적 할당 시 유의해야 할 점</h4>
<p>동적 IP 주소에는 <code>사용 가능한 기간(임대 기간)</code>이 정해져 있다.
동적 IP 주소는 할당받을 때마다 <code>이전과 다른 주소</code>를 받을 수 있다.</p>
<blockquote>
</blockquote>
<p>DHCP를 통한 할당은 마치 집을 빌리는 것과 같아서 <strong>&#39;IP 주소의 임대&#39;</strong>라고 표현하기도 한다.</p>
<ul>
<li><p><strong>임대/반납</strong>: 사용되지 않거나 임대 기간이 만료된 IP 주소는 다시 DHCP 서버로 회수된다.</p>
</li>
<li><p><strong>임대 갱신 (Lease Renewal)</strong>: 임대 기간이 끝나기 전에 사용 기간을 연장하는 과정이다.</p>
</li>
</ul>
<p><em>➡️ 보통 자동으로 두 차례 갱신을 시도하고, 만약 두 번의 갱신 시도가 모두 실패하면, 해당 IP 주소는 서버로 최종 반납된다.</em></p>
<hr>
<h2 id="3-icmp-internet-control-message-protocol">3. ICMP (Internet Control Message Protocol)</h2>
<p>IP는 기본적으로 <strong>&#39;비연결형&#39;</strong>이자 <strong>&#39;신뢰할 수 없는&#39;</strong> 프로토콜이다.
이는 <code>성능(속도와 효율)</code>을 위한 선택이지만, 때로는 <code>전송 과정의 상태</code>를 확인해야 할 필요가 있다.</p>
<p>이때 도움을 주는 것이 바로 <strong>ICMP</strong>이다!</p>
<h3 id="icmp는">ICMP는</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/5a85b803-e8ae-41de-a3cc-c863e1a9230f/image.png" alt=""></p>
<ul>
<li>IP 패킷 전송 과정에서 발생하는 문제나 네트워크 상태에 대한 <strong>피드백 메시지</strong>를 전달한다.</li>
<li>📍 ICMP는 <strong>오류</strong>를 알릴 뿐, 전송 계층(TCP 등)처럼 <code>데이터의 신뢰성을 완전히 책임지지는 않는다.</code></li>
<li>IP의 가벼운 특성을 유지하면서도 <strong>최소한의 진단</strong> 기능을 제공한다.</li>
</ul>
<blockquote>
<h4 id="icmp-메시지의-주요-유형">ICMP 메시지의 주요 유형</h4>
<p>① 오류 보고 (Error Reporting)
② 네트워크 진단 (Network Diagnostics)</p>
</blockquote>
<h3 id="3-1-오류-보고-error-reporting">3-1. 오류 보고 (Error Reporting)</h3>
<p>패킷 전송 중에 아래와 같은 문제가 생겼을 때 송신 측에 이를 알린다.</p>
<table>
<thead>
<tr>
<th>오류 보고</th>
</tr>
</thead>
<tbody><tr>
<td>① 네트워크 도달 불가</td>
</tr>
<tr>
<td>② 호스트 도달 불가</td>
</tr>
<tr>
<td>③ 프로토콜 도달 불가, 수신지에서 특정 프로토콜을 사용할 수 없음</td>
</tr>
<tr>
<td>④ 포트 도달 불가</td>
</tr>
<tr>
<td>⑤ 단편화가 필요하지만 DF가 1로 설정되어 단편화할 수 없음</td>
</tr>
<tr>
<td>⑥ TTL 만료</td>
</tr>
</tbody></table>
<h3 id="3-2-네트워크-진단-network-diagnostics">3-2. 네트워크 진단 (Network Diagnostics)</h3>
<p><code>Echo 요청/응답</code>을 통해 네트워크 상태를 <strong>점검</strong>하고 정보를 <strong>수집</strong>한다.</p>
<table>
<thead>
<tr>
<th>네트워크 상의 정보 제공</th>
</tr>
</thead>
<tbody><tr>
<td>① Echo 요청</td>
</tr>
<tr>
<td>② Echo 응답</td>
</tr>
</tbody></table>
<p><code>*에코 요청/응답 (Echo Request/Reply): 상대방 호스트가 살아있는지 확인</code></p>
<h3 id="3-3-홉hop과-ttl">3-3. 홉(Hop)과 TTL</h3>
<p>📍 IP 패킷이 목적지를 찾지 못하고 네트워크 위를 영원히 떠돌게 된다면, 네트워크 자원은 금방 고갈될 것이다‼️</p>
<p><em>➡️ 이를 방지하기 위한 안전장치가 바로 TTL과 ICMP이다.</em></p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/aa39adee-c5da-4df7-bbce-f925f7880eb5/image.png" alt=""></p>
<ul>
<li><strong>홉 (Hop):</strong> 패킷이 라우터나 호스트를 한 번 거쳐 전달되는 단위를 말한다.</li>
<li><strong>TTL (Time To Live):</strong> 무의미한 패킷이 네트워크상에 지속적으로 남아있는 것을 방지하기 위한 수명값이다. </li>
<li>라우터를 거칠 때마다 <strong>TTL 값이 1씩 감소</strong>한다.</li>
<li>TTL이 0이 되면 패킷은 폐기되고 송신자에게 <code>ICMP &#39;시간 초과&#39; 메시지</code>가 전달된다.</li>
</ul>
<blockquote>
<h4 id="쉽게-정리하면">쉽게 정리하면</h4>
</blockquote>
<ul>
<li><strong>홉</strong>은 네트워크 세계에서 패킷이 목적지를 향해 가는 <code>👣(한 걸음)</code>이고,</li>
<li><strong>TTL</strong>은 패킷의 <code>💣(폭탄)</code>같은 존재이고,</li>
<li><strong>ICMP</strong>는 그 폭탄이 터졌을 때 어디서 왜 터졌는지 알려주는 <code>📑(보고서)</code> 역할을 한다.</li>
</ul>
<h3 id="3-4-icmp를-활용한-대표적인-명령어">3-4. ICMP를 활용한 대표적인 명령어</h3>
<table>
<thead>
<tr>
<th>도구</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>ping</strong></td>
<td>특정 호스트와의 연결성 및 지연 시간을 확인한다.</td>
</tr>
<tr>
<td><strong>traceroute</strong></td>
<td>(Windows: <code>tracert</code>) 목적지까지 가는 경로와 각 홉에서의 지연 시간을 추적한다.</td>
</tr>
</tbody></table>
<p>네트워크 상태를 점검할 때 우리가 자주 사용하는 명령어들은 ICMP를 기반으로 작동한다❗️</p>
<hr>
<h2 id="4-arp-address-resolution-protocol">4. ARP (Address Resolution Protocol)</h2>
<p>통신 과정에서는 <code>IP 주소</code>와 <code>MAC 주소</code>가 함께 사용되지만, 📍 상대 호스트의 IP 주소는 알고 MAC 주소는 모르는 상황이 발생할 수 있다.</p>
<p>이때 <strong>IP 주소를 통해 MAC 주소를 알아내는 프로토콜</strong>이 바로 <strong>ARP</strong>이다.</p>
<h3 id="arp는">ARP는</h3>
<p>ARP는 <strong>ARP 요청(Request)</strong>과 <strong>ARP 응답(Reply)</strong> 과정을 통해 상대방의 주소를 식별한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/9143e5a0-849d-4a66-b633-c82ce1feac7f/image.png" alt=""></p>
<ul>
<li><strong>ARP 요청 (브로드캐스트):</strong> 네트워크 내의 모든 호스트에게 <code>&quot;이 IP 주소를 가진 호스트의 MAC 주소는 무엇인가요?&quot;</code>라고 외치는 과정이다. 이 메시지는 브로드캐스트 형식이므로 네트워크 내 <strong>모든 호스트</strong>가 수신한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/9291d459-37d4-4b18-9d25-f6e963c14906/image.png" alt=""></p>
<ul>
<li><strong>ARP 응답 (유니캐스트?):</strong> 요청 메시지에 포함된 IP 주소가 자신의 IP 주소와 <strong>일치하는 호스트만</strong> 자신의 MAC 주소를 담아 응답 메시지를 전송한다. 관련 없는 호스트들은 해당 메시지를 무시한다.</li>
</ul>
<h3 id="4-1-arp-테이블-arp-table">4-1. ARP 테이블 (ARP Table)</h3>
<p>호스트는 매번 ARP 요청을 보내는 번거로움을 피하기 위해서 통신을 통해 알게 된 <strong><code>&lt;IP 주소, MAC 주소&gt;</code> 쌍을 메모리에 기록</strong>해 둔다.</p>
<p><em>➡️ 이를 <strong>ARP 테이블</strong>이라고 한다.</em></p>
<ul>
<li>한 번 통신한 상대의 정보를 <strong>기억</strong>해 두어 동일한 대상에게 패킷을 보낼 때 📍<strong>반복적인 ARP 요청을 방지</strong>한다.</li>
<li>ARP 테이블의 항목은 일정 시간이 지나면 <strong>삭제</strong>되고, 필요에 따라 임의로 삭제할 수도 있다.</li>
</ul>
<h3 id="4-2-arp-테이블-확인-방법">4-2. ARP 테이블 확인 방법</h3>
<p>간단한 명령어를 통해 현재 내 컴퓨터에 저장된 ARP 테이블을 확인할 수 있다.</p>
<p><strong>Mac / Windows OS - <code>arp -a</code></strong>
<img src="https://velog.velcdn.com/images/w_dw_r/post/6dafdd76-3712-4fda-a140-e4b2e72fd844/image.png" alt=""></p>
<p>위의 명령어를 사용하면 내 컴퓨터와 통신했던 대상들의 <code>인터넷 주소(IP)</code>와 그에 대응하는 <code>물리적 주소(MAC)</code>, 그리고 할당 유형(동적/정적)을 볼 수 있다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-2 물리 계층과 데이터 링크 계층 (전파와 WiFi, NIC, 허브와 스위치)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-2-%EB%AC%BC%EB%A6%AC-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A7%81%ED%81%AC-%EA%B3%84%EC%B8%B5-%EC%A0%84%ED%8C%8C%EC%99%80-WiFi-NIC-%ED%97%88%EB%B8%8C%EC%99%80-%EC%8A%A4%EC%9C%84%EC%B9%98</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-2-%EB%AC%BC%EB%A6%AC-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A7%81%ED%81%AC-%EA%B3%84%EC%B8%B5-%EC%A0%84%ED%8C%8C%EC%99%80-WiFi-NIC-%ED%97%88%EB%B8%8C%EC%99%80-%EC%8A%A4%EC%9C%84%EC%B9%98</guid>
            <pubDate>Sun, 11 Jan 2026 05:38:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
</blockquote>
<p>① 무선 매체 전파와 Wi-Fi의 특징 (2.4GHz vs 5GHz)
② 네트워크 인터페이스(NIC)의 역할과 동작 원리
③ 물리 계층의 장비: 허브(Hub)의 특성과 콜리전 도메인
④ 데이터 링크 계층의 장비: 스위치(Switch)와 MAC 주소 학습
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
<hr>
<h2 id="1-무선-매체---전파와-wi-fi">1. 무선 매체 - 전파와 Wi-Fi</h2>
<p>네트워크에서 데이터를 실어 나르기 위해서는 <code>통신 매체(통로)</code>가 필요하다.
유선 LAN이 <code>구리선(케이블)</code>을 매체로 삼는다면, 무선 LAN은 <code>전파</code>를 매체로 삼는다.</p>
<p>무선 LAN에서 가장 대중적으로 활용되는 기술은 <strong>와이파이(Wi-Fi)</strong>이다.</p>
<ul>
<li><p><strong>전파(Radio wave):</strong></p>
<ul>
<li>선이 없는 공간에서 데이터를 전달하는 물리적 통로</li>
<li><code>약 3KHz부터 3THz 사이의 진동수</code>를 갖는 전자 기파</li>
</ul>
</li>
<li><p><strong>무선 LAN(Wi-Fi):</strong> 전파라는 통로 위에서 데이터를 어떻게 주고받을지 약속한 표준 규격 <code>IEEE 802.11</code>을 따르는 기술</p>
</li>
</ul>
<h3 id="1-1-wi-fi-표준과-세대">1-1. Wi-Fi 표준과 세대</h3>
<p>와이파이는 4, 5, 6, 7 등 숫자로 세대를 구분하며, 세대에 따라 지원 규격(802.11n, 11ac, 11ax, 11be 등)과 최대 속도, 주파수 대역이 달라진다.</p>
<table>
<thead>
<tr>
<th align="center">세대 이름</th>
<th align="center">표준 규격</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Wi-Fi 7</td>
<td align="center">IEEE 802.11be</td>
</tr>
<tr>
<td align="center">Wi-Fi 6</td>
<td align="center">IEEE 802.11ax</td>
</tr>
<tr>
<td align="center">Wi-Fi 5</td>
<td align="center">IEEE 802.11ac</td>
</tr>
<tr>
<td align="center">Wi-Fi 4</td>
<td align="center">IEEE 802.11n</td>
</tr>
</tbody></table>
<p><code>*SSID(Service Set Identifier): 서비스 셋 식별자로, 흔히 와이파이 이름으로 불리는 정보이다. AP(Access Point)를 중심으로 구성된 무선 네트워크를 식별한다.</code></p>
<h3 id="1-2-주파수-대역과-채널-24ghz-vs-5ghz">1-2. 주파수 대역과 채널 (2.4GHz vs 5GHz)</h3>
<p>와이파이에서 주로 사용되는 주파수 대역은 2.4GHz 혹은 5GHz이다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/dd20a51a-0b83-4ac2-bc4b-fd297ee0d2de/image.png"
width=500/></p>
<ul>
<li><strong>2.4GHz 대역:</strong> 장애물 통과에 유리하지만, 여러 무선 네트워크가 같은 주파수를 사용할 경우 신호 간섭이 발생하기 쉽다. 성능 저하를 방지하려면 <code>📍 1, 6, 11번처럼 중첩되지 않는 채널을 사용하는 것이 중요하다.</code></li>
<li><strong>5GHz 대역:</strong> 2.4GHz에 비해 채널 간 간섭이 적고 더 넓은 대역폭을 제공하여 통신 성능이 우수하다.</li>
</ul>
<p><code>*채널(channel): 동일한 주파수 대역을 사용하는 서로 다른 무선 네트워크를 구분하고 간섭 없이 통신하기 위해, 하나의 커다란 주파수 대역을 여러 개의 하위 주파수 대역으로 쪼개어 사용하는데, 이를 채널이라 일컫는다.</code></p>
<blockquote>
<p>⚠️ 같은 주파수 대역을 사용하는 여러 무선 네트워크가 존재할 수 있다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/49fa2beb-efb7-4c6a-a77b-9fa7d9c0bcc5/image.png" alt=""></p>
</blockquote>
<p>같은 지역 내에 2.4GHz 대역을 사용하는 무선 네트워크가 여러 개 존재하거나 5GHz 대역을 사용하는 무선 네트워크가 여러 개 존재할 수 있다.</p>
<p>대신 별개의 무선 네트워크는 같은 주파수 대역을 사용하더라도 서로의 신호에 간섭하지 않아야 한다‼️</p>
<hr>
<h2 id="2-네트워크-인터페이스-nic-network-interface-controller">2. 네트워크 인터페이스: NIC (Network Interface Controller)</h2>
<p>네트워크상에서 노드와 통신 매체가 연결되는 지점을 <strong>네트워크 인터페이스</strong>라 하고, 이를 담당하는 하드웨어가 <strong>NIC</strong>이다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/16b34cf8-e8a9-4bd7-91d6-9458faeed81a/image.png"
width=200/></p>
<h3 id="2-1-nic의-주요-기능">2-1. NIC의 주요 기능</h3>
<ul>
<li><strong>물리적 주소 할당:</strong> NIC마다 고유한 물리적 주소인 <strong>MAC 주소</strong>가 부여된다.</li>
<li><strong>신호 변환:</strong> 통신 매체의 신호를 호스트가 이해하는 <strong>프레임</strong>으로 변환하거나, 그 반대의 역할을 수행한다.</li>
</ul>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/da9a6702-74d7-44a1-81ef-4a1e964c1b07/image.png"
width=500/></p>
<ul>
<li><strong>입출력 방식:</strong> 패킷 송신은 &#39;출력&#39;, 수신은 &#39;입력&#39;이라 부르며, 운영체제의 시스템 콜을 통해 작동한다. 대부분 <code>DMA(Direct Memory Access)</code>를 지원하여 CPU의 부하를 줄인다.</li>
</ul>
<h3 id="2-2-티밍과-본딩">2-2. 티밍과 본딩</h3>
<p>여러 개의 물리적인 NIC를 하나의 논리적인 NIC처럼 묶어 사용하는 기술이다.</p>
<ul>
<li><strong>티밍(Teaming):</strong> 주로 윈도우 운영체제에서 사용하는 용어이다.</li>
<li><strong>본딩(Bonding):</strong> 주로 리눅스 운영체제에서 사용하는 용어이다.</li>
</ul>
<p><em>➡️ 이를 통해 대역폭을 확장해 송수신 성능을 높이고, 하나의 NIC에 문제가 생겨도 안정적인 통신을 유지할 수 있다.</em></p>
<hr>
<h2 id="3-물리-계층과-데이터-링크-계층의-네트워크-장비">3. 물리 계층과 데이터 링크 계층의 네트워크 장비</h2>
<h3 id="3-1-물리-계층의-허브-hub">3-1. 물리 계층의 허브 (Hub)</h3>
<p>여러 대의 호스트를 연결하는 장치로, <code>리피터 허브</code> 또는 <code>이더넷 허브</code>라고도 불린다.</p>
<p>전달받은 신호를 어떤 판단도 하지 않고 연결된 <strong>모든 포트</strong>로 단순 복제하여 내보낸다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/210499cc-f0d1-4c82-a4b5-780b237b415b/image.png" alt=""></p>
<ul>
<li><strong>반이중(Half-duplex) 통신:</strong> 송신과 수신을 동시에 할 수 없고, 무전기처럼 한쪽이 송신할 때 다른 쪽은 수신만 가능하다.<blockquote>
<h4 id="콜리전-도메인collision-domain">콜리전 도메인(Collision Domain)</h4>
<p>반이중 모드와 모든 포트 전송 방식 때문에 충돌이 발생할 수 있는 영역이다. 허브에 연결된 모든 호스트가 하나의 콜리전 도메인에 속하게 된다.</p>
</blockquote>
<img src="https://velog.velcdn.com/images/w_dw_r/post/17f746a7-ffbb-45d5-9fe5-8e51b7dac038/image.png" alt=""></li>
</ul>
<h3 id="3-2-데이터-링크-계층의-스위치-switch">3-2. 데이터 링크 계층의 스위치 (Switch)</h3>
<p>허브의 한계를 보완하기 위해 2계층에서 사용하는 장비로, <code>L2 스위치</code>라고도 한다.</p>
<p><code>*데이터 링크 계층의 상위 계층에서 사용되는 스위치는 L3 스위치, L4 스위치로 불린다.</code></p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/d77ae70e-c609-455f-bbd2-bb6bd4c36fe1/image.png"
width=500/></p>
<h4 id="①-mac-주소-학습-및-테이블-관리">① MAC 주소 학습 및 테이블 관리</h4>
<p>스위치는 전달받은 신호를 원하는 포트에만 내보낼 수 있는데, 이는 스위치의 <strong>MAC 주소 학습</strong> 기능 덕분이다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/2ffc84ed-9561-4ec8-bdc3-17b72352e032/image.png"
width=500/></p>
<ul>
<li><strong>MAC 주소 테이블 생성:</strong> 프레임 헤더에 명시된 MAC 주소를 보고, 어떤 포트에 어떤 호스트가 연결되어 있는지 파악해 <code>&#39;포트-MAC 주소&#39;</code> 대응 관계를 <strong>메모리(MAC 주소 테이블)</strong>에 저장한다.</li>
<li>📍 <strong>선택적 전달:</strong> 학습된 테이블을 참조하여 모든 포트가 아닌, <strong>목적지 호스트가 연결된 포트</strong>로만 신호를 내보낸다.</li>
<li>송수신이 동시에 가능한 <strong>전이중(Full-duplex) 통신</strong>을 지원하고, 콜리전 도메인을 좁혀 네트워크 성능을 높인다.</li>
</ul>
<h4 id="②-vlan-virtual-lan">② VLAN (Virtual LAN)</h4>
<p>MAC 주소 학습 외에도 스위치는 <strong>VLAN</strong>이라는 가상 LAN 기능을 가지고 있다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/8420411d-e083-4787-832b-85b6b1e3db60/image.png"
width=400/></p>
<ul>
<li><strong>논리적 네트워크 분할:</strong> 물리적으로는 하나의 스위치에 연결되어 있더라도, 호스트들을 여러 개의 논리적인 네트워크로 나눌 수 있다.</li>
<li><strong>브로드캐스트 제어:</strong> 서로 다른 VLAN에 속한 호스트끼리는 브로드캐스트 메시지가 도달하지 않아 네트워크를 격리할 수 있다.</li>
<li><strong>통신 제약:</strong> VLAN1과 VLAN2처럼 서로 다른 네트워크로 간주되는 호스트 간에 통신을 하려면 네트워크 계층(L3) 이상의 장비가 반드시 필요하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 05-1 네트워크 의 큰 그림 (TCP/IP, 캡슐화와 역캡슐화, 계층별 주요 프로토콜 및 하드웨어 장비)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-1-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%98-%ED%81%B0-%EA%B7%B8%EB%A6%BC-TCPIP-%EC%BA%A1%EC%8A%90%ED%99%94%EC%99%80-%EC%97%AD%EC%BA%A1%EC%8A%90%ED%99%94-%EA%B3%84%EC%B8%B5%EB%B3%84-%EC%A3%BC%EC%9A%94-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B0%8F-%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4-%EC%9E%A5%EB%B9%84</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-05-1-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%98-%ED%81%B0-%EA%B7%B8%EB%A6%BC-TCPIP-%EC%BA%A1%EC%8A%90%ED%99%94%EC%99%80-%EC%97%AD%EC%BA%A1%EC%8A%90%ED%99%94-%EA%B3%84%EC%B8%B5%EB%B3%84-%EC%A3%BC%EC%9A%94-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B0%8F-%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4-%EC%9E%A5%EB%B9%84</guid>
            <pubDate>Mon, 29 Dec 2025 12:38:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
</blockquote>
<p>① 네트워크 참조 모델 (OSI vs TCP/IP 비교)
② 캡슐화와 역캡슐화의 메커니즘
③ 계층별 주요 프로토콜 및 하드웨어 장비
④ 응용 계층의 심화 기술 (HTTP, 보안, 안정성)
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
<hr>
<h2 id="1-네트워크-참조-모델의-상세-구조">1. 네트워크 참조 모델의 상세 구조</h2>
<p>네트워크 통신 과정을 계층적으로 분리하여 관리하는 모델이다. 이론적 지침인 OSI 모델과 실제 구현 중심의 TCP/IP 모델로 나뉜다.</p>
<h3 id="1-1-tcpip-4계층-모델">1-1. TCP/IP 4계층 모델</h3>
<p><image src= "https://velog.velcdn.com/images/w_dw_r/post/da8e2ae4-faeb-46db-821b-0c3d62973804/image.png"
width=300/>       </p>
<ol>
<li><strong>응용 계층 (Application Layer):</strong> 사용자와 프로그램이 직접 맞닿는 계층으로, 서비스 구현에 필요한 프로토콜(HTTP, DNS 등)이 정의된다.</li>
<li><strong>전송 계층 (Transport Layer):</strong> 송수신 프로세스 간의 통신을 담당하며, 데이터의 신뢰성을 보장하거나(TCP) 빠른 전송(UDP)을 관리한다.</li>
<li><strong>인터넷 계층 (Internet Layer):</strong> 네트워크상에서 패킷을 목적지까지 전달하기 위한 경로 설정(Routing) 및 주소 지정(IP)을 수행한다.</li>
<li><strong>네트워크 액세스 계층 (Network Access Layer):</strong> 물리적인 네트워크 매체(케이블, 무선 신호)를 통해 데이터를 전송하며, 하드웨어적인 주소(MAC 주소)를 사용한다.</li>
</ol>
<h3 id="1-2-참조-모델-간의-대응-관계">1-2. 참조 모델 간의 대응 관계</h3>
<p><image src= "https://velog.velcdn.com/images/w_dw_r/post/edbef1ff-0217-4e5d-bb54-43e3b080ed78/image.png"
width=500/> </p>
<ul>
<li><strong>TCP/IP 모델의 응용 계층</strong>은 OSI 7계층의 세션, 표현, 응용 계층을 통합한 기능을 수행한다.</li>
<li><strong>TCP/IP 모델의 네트워크 액세스 계층</strong>은 OSI의 물리 계층과 데이터 링크 계층을 합친 개념으로 이해된다.</li>
<li>책에서는 학습의 편의를 위해 TCP/IP 모델에 물리 계층을 추가한 <strong>&#39;TCP/IP 모델 확장판&#39;</strong>을 기준으로 설명하고 있다.</li>
</ul>
<hr>
<h2 id="2-캡슐화와-역캡슐화-encapsulation--decapsulation">2. 캡슐화와 역캡슐화 (Encapsulation &amp; Decapsulation)</h2>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/af1118a8-451c-4b1e-a4e1-5da0b4e8a112/image.png" alt=""></p>
<h3 id="2-1-캡슐화-데이터-전송의-원리">2-1. 캡슐화: 데이터 전송의 원리</h3>
<p>데이터를 송신할 때는 상위 계층에서 하위 계층으로 정보를 내려보낸다.</p>
<p>이때 각 계층은 상위 계층으로부터 받은 데이터를 <strong>페이로드(Payload)</strong>로 취급하고, 자신의 계층에서 필요한 정보(주소, 제어 정보 등)를 담은 <strong>헤더(Header)</strong>를 덧붙인다. 이를 <strong>캡슐화</strong>라고 한다.</p>
<h3 id="2-2-역캡슐화-수신-및-복원-과정">2-2. 역캡슐화: 수신 및 복원 과정</h3>
<p>데이터를 수신할 때는 하위 계층에서 상위 계층으로 정보를 올린다.</p>
<p>각 계층은 자신에게 해당하는 헤더를 확인하여 필요한 처리를 수행한 뒤 해당 헤더를 제거(Strip)한다. 이를 <strong>역캡슐화</strong>라고 하고, 최종적으로 수신측 응용 프로그램은 원래의 메시지만을 받게 된다.</p>
<h3 id="2-3-계층별-데이터-명칭-pdu">2-3. 계층별 데이터 명칭 (PDU)</h3>
<table>
<thead>
<tr>
<th>계층</th>
<th>데이터 명칭</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><strong>그 이상의 계층</strong></td>
<td><strong>데이터/메시지</strong></td>
<td>사용자가 주고받고자 하는 순수 정보</td>
</tr>
<tr>
<td><strong>전송 계층</strong></td>
<td><strong>세그먼트(TCP)/데이터그램(UDP)</strong></td>
<td>포트 번호와 제어 정보가 포함된 단위</td>
</tr>
<tr>
<td><strong>네트워크</strong></td>
<td><strong>패킷/데이터그램</strong></td>
<td>IP 주소 정보가 포함된 단위</td>
</tr>
<tr>
<td><strong>데이터 링크</strong></td>
<td><strong>프레임</strong></td>
<td>MAC 주소와 에러 검출(트레일러) 정보 포함</td>
</tr>
<tr>
<td><strong>물리 계층</strong></td>
<td><strong>비트/심볼</strong></td>
<td>전기 신호나 광신호 등의 물리적 형태</td>
</tr>
</tbody></table>
<hr>
<h2 id="3-네트워크-지도-network-map">3. 네트워크 지도 (Network Map)</h2>
<h3 id="3-1-하위-계층-물리--데이터-링크">3-1. 하위 계층 (물리 &amp; 데이터 링크)</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/5e62e012-225c-4208-8ced-92a53c3003c7/image.png" alt=""></p>
<ul>
<li><strong>이더넷(Ethernet):</strong> 오늘날 네트워크 환경의 근간이 되는 공통 기술이다.</li>
<li><strong>장비:</strong> * <strong>NIC:</strong> 네트워크 연결을 위한 하드웨어 인터페이스.</li>
<li><strong>허브(Hub):</strong> 물리 계층의 대표 장비로 신호를 복제/전달한다.</li>
<li><strong>스위치(Switch):</strong> 데이터 링크 계층 장비로 MAC 주소를 기반으로 데이터를 전달한다.</li>
</ul>
<h3 id="3-2-네트워크-계층">3-2. 네트워크 계층</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/c8aa4447-6cc1-497e-af9b-a432e59d3845/image.png" alt=""></p>
<ul>
<li><strong>IP 주소:</strong> 주소 체계(클래스풀, 클래스리스)와 서브넷 마스크를 통해 네트워크 규모를 관리한다.</li>
<li><strong>할당 방식:</strong> 수동으로 부여하는 정적 할당과 서버가 자동으로 부여하는 <strong>DHCP(동적 할당)</strong>가 있다.</li>
<li><strong>기타 프로토콜:</strong> 네트워크 상태를 확인하는 <strong>ICMP</strong>, IP 주소를 MAC 주소로 바꾸는 <strong>ARP</strong> 등이 있다.</li>
</ul>
<h3 id="3-3-전송-계층">3-3. 전송 계층</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/405086f8-67a5-4566-af92-d57bcb617e9a/image.png" alt=""></p>
<ul>
<li><strong>TCP:</strong> 신뢰성을 중시한다. 연결 수립/종료, 오류·흐름·혼잡 제어 및 상태 관리를 수행한다.</li>
<li><strong>UDP:</strong> 신속성을 중시하며, TCP가 제공하는 복잡한 제어 기능 없이 단순한 전송을 담당한다.</li>
</ul>
<hr>
<h2 id="4-응용-계층-및-인프라-최적화">4. 응용 계층 및 인프라 최적화</h2>
<h3 id="4-1-http와-보안-https">4-1. HTTP와 보안 (HTTPS)</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/f2de993a-b424-451a-a963-cdb0b8290404/image.png" alt=""></p>
<ul>
<li><strong>HTTP:</strong> 메시지 구조(메서드, 상태 코드, 헤더)를 기반으로 통신하며, 쿠키와 캐시, 콘텐츠 협상 기술을 사용하여 사용자 경험을 개선한다.</li>
<li><strong>HTTPS:</strong> 보안을 위해 SSL/TLS 프로토콜을 사용하여 HTTP 메시지를 안전하게 암호화하여 송수신한다.</li>
</ul>
<h3 id="4-2-프록시와-트래픽-관리">4-2. 프록시와 트래픽 관리</h3>
<p>네트워크의 안정성을 높이기 위해 서버와 클라이언트 사이에 중간 서버를 배치한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/fd05fbac-64de-408f-8056-7505b31a7dcf/image.png" alt=""></p>
<ul>
<li><strong>프록시 서버:</strong> 포워드 프록시와 리버스 프록시로 구분되어 보안 및 성능 향상에 기여한다.</li>
<li><strong>가용성(Availability):</strong> 시스템이 중단 없이 돌아가는 정도를 뜻하며, <strong>로드 밸런싱</strong>을 통해 트래픽을 분산하고, <strong>스케일링(인업/아웃)</strong>을 통해 시스템 규모를 조절하여 이를 확보한다.</li>
</ul>
<h3 id="4-3-네트워크-전체-구조">4-3. 네트워크 전체 구조</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/28231563-e53e-4197-9441-032eb8428be1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 04-5&6 트리와 그래프 (이진 탐색 트리, RB 트리, 그래프 구현)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-56-%ED%8A%B8%EB%A6%AC%EC%99%80-%EA%B7%B8%EB%9E%98%ED%94%84-%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-%ED%8A%B8%EB%A6%AC-RB-%ED%8A%B8%EB%A6%AC-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-56-%ED%8A%B8%EB%A6%AC%EC%99%80-%EA%B7%B8%EB%9E%98%ED%94%84-%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-%ED%8A%B8%EB%A6%AC-RB-%ED%8A%B8%EB%A6%AC-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Mon, 22 Dec 2025 08:20:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💡-주요-내용">💡 주요 내용</h2>
<p>① 이진 트리의 종류 (포화 이진 트리, 완전 이진 트리)
② 탐색과 힙 (이진 탐색 트리, 편향 트리, 최대/최소 힙)
③ 자가 균형 트리 (RB 트리의 조건, 왼쪽/오른쪽 회전, B/B+ 트리)
④ 그래프의 기초 (정점과 간선, 트리와의 차이, 실무 사례)
⑤ 그래프의 구현 (연결, 방향/가중치 그래프, 서브 그래프)
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-이진-트리의-종류">1. 이진 트리의 종류</h2>
<p>이진 트리는 자식 노드의 개수와 배치 형태에 따라 다양하게 분류된다.</p>
<h3 id="1-1-포화-이진-트리-perfect-binary-tree">1-1. 포화 이진 트리 (Perfect Binary Tree)</h3>
<p>리프 노드를 제외한 모든 노드들이 자식 노드를 <strong>2개씩</strong> 가지고 있고, 모든 리프 노드의 레벨이 동일한 이진 트리를 말한다.</p>
<ul>
<li>모든 리프 노드의 레벨이 같아야 하므로, 트리가 완벽한 삼각형 형태를 띤다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/0f9a0c38-7071-4f55-9579-311cf3e6c42a/image.png" alt=""></p>
<p><code>*리프 노드: 트리의 최하위 노드 , 자식 노드가 없는 노드</code></p>
<h3 id="1-2-완전-이진-트리-complete-binary-tree">1-2. 완전 이진 트리 (Complete Binary Tree)</h3>
<p>마지막 레벨을 제외한 모든 레벨이 2개의 자식 노드를 가지고 있으며, 마지막 레벨의 모든 노드들이 <strong>왼쪽부터 순서대로 존재</strong>하는 이진 트리를 말한다.</p>
<ul>
<li><strong>중요</strong>: 마지막 레벨이 다 채워지지 않아도 되지만, 빈틈없이 왼쪽부터 채워져야만 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/722b0bdb-4b11-4fa1-b99e-77565be9b961/image.png" alt=""></p>
<h3 id="1-3-포화-이진-트리-vs-완전-이진-트리">1-3. 포화 이진 트리 vs 완전 이진 트리</h3>
<p>두 트리는 이름이 비슷해 보이지만, <strong>&#39;노드가 채워지는 조건&#39;</strong>에서 큰 차이가 있다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>포화 이진 트리 (Perfect)</th>
<th>완전 이진 트리 (Complete)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>핵심 조건</strong></td>
<td>모든 레벨이 <strong>빈 공간 없이</strong> 꽉 차야 한다.</td>
<td>마지막 레벨 전까지는 꽉 차고, 마지막 레벨은 <strong>왼쪽부터</strong> 채워져야 한다.</td>
</tr>
<tr>
<td><strong>노드 개수</strong></td>
<td>높이가 $h$일 때 항상 $2^h - 1$개</td>
<td>포화 이진 트리보다 적거나 같다.</td>
</tr>
<tr>
<td><strong>특징</strong></td>
<td>완벽한 삼각형 형태</td>
<td>마지막 레벨의 오른쪽은 비어 있을 수 있다.</td>
</tr>
</tbody></table>
<h4 id="📍-꼭-알아두기">📍 꼭 알아두기!</h4>
<ul>
<li><strong>모든 포화 이진 트리는 완전 이진 트리이다?</strong> → <strong>YES!</strong> (왼쪽부터 꽉 차 있기 때문)</li>
<li><strong>모든 완전 이진 트리는 포화 이진 트리이다?</strong> → <strong>NO!</strong> (마지막 레벨이 덜 찼을 수도 있기 때문)</li>
</ul>
<blockquote>
<p><strong>💡 면접 Tip</strong> &gt; &quot;완전 이진 트리는 <strong>배열을 이용한 구현</strong> 시 인덱스 사이에 빈틈이 생기지 않는다는 점이 중요하고, 이는 <strong>힙(Heap)</strong> 자료구조의 구조적 기반이 됨을 뜻한다.&quot;</p>
</blockquote>
<hr>
<h2 id="2-탐색과-정렬-이진-탐색-트리와-힙">2. 탐색과 정렬: 이진 탐색 트리와 힙</h2>
<h3 id="2-1-이진-탐색-트리-bst-binary-search-tree">2-1. 이진 탐색 트리 (BST, Binary Search Tree)</h3>
<p>특정 노드의 <strong>왼쪽 서브트리</strong>에는 해당 노드보다 <strong>작은 값</strong>이, <strong>오른쪽 서브트리</strong>에는 해당 노드보다 <strong>큰 값</strong>이 위치하는 구조이다.</p>
<ul>
<li><strong>장점</strong>: $O(\log n)$의 시간 복잡도로 원하는 값을 빠르게 찾을 수 있다.</li>
<li><strong>예시</strong>: 만약 &#39;15&#39;를 찾는다면, 루트(8)보다 크므로 오른쪽으로, 그 다음 노드인 &#39;10&#39;보다도 크므로 다시 오른쪽으로 이동하며 효율적으로 탐색한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/46f580c4-7009-4a3f-b169-05d9e3f6273e/image.png" alt=""></p>
<blockquote>
<p><strong>⚠️ 편향 트리 (Skewed Tree)</strong>
<code>이진 탐색 트리(BST)</code>에 데이터가 삽입될 때, 자가 균형 알고리즘이 없어 <strong>한쪽 방향으로만</strong> 치우쳐 자라는 트리를 말한다.</p>
</blockquote>
<ul>
<li><strong>원인</strong>: 데이터가 정렬된 상태(예: 1, 2, 3, 4...)로 삽입될 경우</li>
<li><strong>발생 형태</strong>: 모든 노드가 <code>왼쪽 혹은 오른쪽 자식 노드만</code> 가지는 선형 구조</li>
<li><strong>탐색 속도</strong>: O(N)<blockquote>
</blockquote>
<image src="https://velog.velcdn.com/images/w_dw_r/post/1fc00ab0-b9de-40c1-ba6b-3770d3b325c1/image.png"
width=300/>       <blockquote>
</blockquote>
<em>➡️ 트리의 가장 큰 장점은 <strong>나누어 정복(Divide and Conquer)</strong>이지만, 편향 트리는 이러한 장점을 가지지 않는다.</em><blockquote>
</blockquote>
</li>
<li><code>일반적인 균형 트리</code>는 한 번 비교할 때마다 탐색 범위가 <strong>절반($1/2$)씩</strong> 줄어들지만, <code>편향 트리</code>는 구조적으로 <strong>연결 리스트(Linked List)</strong>와 동일해지기 때문이다.</li>
<li>데이터가 $n$개 있을 때, 가장 끝에 있는 데이터를 찾으려면 루트 노드부터 시작해 모든 노드를 하나씩 방문해야 하기 때문이다.</li>
</ul>
<h3 id="2-2-힙-heap">2-2. 힙 (Heap)</h3>
<p><strong>최댓값이나 최솟값</strong>을 빠르게 찾아내기 위해 고안된 완전 이진 트리이다.</p>
<p><image src ="https://velog.velcdn.com/images/w_dw_r/post/fa8ba7bb-28b4-43f6-a7a6-08b7bb9b0fc3/image.png"
width=400/>                                                                                         </p>
<ul>
<li><strong>최대 힙 (Max Heap)</strong>: 부모 노드의 값이 자식보다 항상 크거나 같다.</li>
<li><strong>최소 힙 (Min Heap)</strong>: 부모 노드의 값이 자식보다 항상 작거나 같다.</li>
<li><strong>탐색 속도</strong>: $O(\log n)$</li>
</ul>
<blockquote>
<p>💡 Tip &gt; 노드 간 크기(크다/작다)의 비교는 <strong>숫자</strong>만 가능한 것이 아니다. <strong>문자</strong> 간의 비교도 가능하고, 때때로 원하는 <strong>우선 순위를 직접 지정</strong>할 수도 있다.</p>
</blockquote>
<blockquote>
<h4 id="우선순위-큐와-최대-힙의-관계">우선순위 큐와 최대 힙의 관계</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/9d680013-38f5-4d76-a954-f9f098619cc7/image.png" alt=""></p>
</blockquote>
<p><code>*우선순위 큐는 최대 힙으로 구현할 수 있다. 최대 힙을 구현하면 최상단 루트 노드는 언제나 우선 순위가 가장 높은 값을 가지게 되기 때문이다.</code></p>
<blockquote>
</blockquote>
<p><code>*우선순위 큐에 데이터가 어떤 순서로 저장되었든 우선 순위 큐에서 데이터를 빼낼 때는 우선 순위가 높은 데이터순으로 얻어낼 수 있다.</code></p>
<hr>
<h2 id="3-자가-균형-이진-탐색-트리-self-balancing-bst">3. 자가 균형 이진 탐색 트리 (Self-Balancing BST)</h2>
<p>이진 탐색 트리는 삽입과 삭제 연산을 반복하는 과정에서 편향 트리가 될 수도 있다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/063c6fc6-4ef5-4170-ab7e-a2ede8cc7527/image.png" alt=""></p>
<p><em>➡️ 같은 노드의 집합으로 구성된 트리여도 연산의 순서에 따라 편향 트리가 될 수 있다.</em></p>
<p>이러한 <strong>편향성</strong>을 극복하기 위해, 삽입/삭제 연산 시 스스로 높이 균형을 맞추는 특별한 트리들이 등장했는데, 대표적으로 AVL 트리와 <strong>RB 트리(Red-Black Tree)</strong>가 있다.</p>
<h3 id="3-1-rb-트리-red-black-tree">3-1. RB 트리 (Red-Black Tree)</h3>
<p>노드에 <strong>색상(Red/Black)</strong> 속성을 부여하여 특정 규칙을 강제함으로써 트리의 균형을 유지하는 트리를 말한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/815376a1-c181-4c15-aed4-174eabb04a9b/image.png" alt=""></p>
<p>RB 트리는 노드에 색을 칠하는 규칙을 통해 왼쪽 서브 트리와 오른쪽 서브 트리의 높이 균형을 맞춘다. 이때 주의할 점은 RB 트리의 <strong>리프 노드(Leaf Node)</strong>에 대한 정의이다.</p>
<p><em>➡️ 즉, 노드에 색을 칠하는 규칙과 노드에 칠해진 색을 기준으로 왼쪽 서브 트리 높이와 오른쪽 서브 트리 높이의 균형을 맞춘다.</em></p>
<ul>
<li><strong>NIL 노드</strong>: RB 트리에서 리프 노드는 실제 데이터가 저장되지 않는 가상의 노드인 NIL(Null Leaf) 노드로 간주한다. 트리의 끝을 명시적으로 나타내며, 균형을 계산하는 기준점이 된다.</li>
</ul>
<h3 id="3-2-rb-트리의-4가지-핵심-조건">3-2. RB 트리의 4가지 핵심 조건</h3>
<ol>
<li><strong>모든 노드</strong>는 레드(Red) 혹은 블랙(Black)이다.</li>
<li><strong>루트 노드</strong>와 <strong>리프 노드(NIL)</strong>는 항상 블랙이다.</li>
<li><strong>레드 노드의 자식</strong>은 반드시 블랙이다. (레드 노드가 연속해서 나타날 수 없다)</li>
<li>임의의 노드에서 리프 노드에 이르는 경로상의 <strong>블랙 노드 수</strong>는 모두 같다.</li>
</ol>
<hr>
<h2 id="4-트리의-회전-rotation">4. 트리의 회전 (Rotation)</h2>
<p>RB 트리나 AVL 트리에서 데이터 삽입/삭제로 인해 균형이 깨졌을 때 수행하는 핵심 연산이다.</p>
<ul>
<li><strong>왼쪽 회전 (Left Rotation)</strong>: 기준 노드를 왼쪽 아래로 내리고, 오른쪽 자식을 부모 위치로 올린다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/149b1fbd-13c0-4c51-914b-b695ac2e9aaa/image.png" alt=""></p>
<ul>
<li><strong>오른쪽 회전 (Right Rotation)</strong>: 기준 노드를 오른쪽 아래로 내리고, 왼쪽 자식을 부모 위치로 올린다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/21d04c66-b1c7-429d-8791-6e7bfe763865/image.png" alt=""></p>
<hr>
<h2 id="5-대용량-데이터를-위한-b-트리-b-tree">5. 대용량 데이터를 위한 B 트리 (B-Tree)</h2>
<p>이진 탐색 트리와 달리, 한 노드가 여러 개의 자식 노드를 가질 수 있는 <strong>다진 탐색 트리(Multi-way Search Tree)</strong>이다. 주로 데이터베이스와 파일 시스템에서 대량의 데이터를 관리할 때 사용된다.</p>
<h3 id="5-1-m차-b-트리의-특징">5-1. M차 B-트리의 특징</h3>
<p>한 노드가 가질 수 있는 최대 자식 노드의 개수가 개인 B-트리를 <strong>M차 B-트리</strong>라고 부른다. B-트리는 노드의 분열과 합병을 통해 균형을 유지하고, 다음과 같은 제약 조건을 가진다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/d183f786-8824-4ebf-a43d-620a2d2e6a27/image.png" alt=""></p>
<ul>
<li><strong>자식 노드의 수 (Degree)</strong></li>
<li><strong>최대 자식 수</strong>: $M$개</li>
<li><strong>최소 자식 수</strong>: $\lceil M / 2 \rceil$개 (루트 노드와 리프 노드 제외)</li>
<li><strong>예</strong>: 5차 B-트리라면, 중간 노드들은 최소 3개($\lceil 5 / 2 \rceil = 3$)의 자식을 가져야 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/3218d1ec-8884-4b26-a284-aefcad72a4e7/image.png" alt=""></p>
<ul>
<li><strong>키(Key)의 특징</strong></li>
<li>각 노드에는 하나 이상의 키 값이 존재하며, 항상 <strong>오름차순</strong>으로 정렬되어 저장된다.</li>
<li>한 노드에 $k$개의 키가 있다면, 자식 노드의 수는 항상 $k+1$개여야 한다.</li>
<li>루트 노드에 <code>key1</code>, <code>key2</code>가 있다면 <code>key1 &lt; key2</code> 관계를 유지한다.</li>
</ul>
<h3 id="5-2-왜-b-트리를-사용할까">5-2. 왜 B-트리를 사용할까?</h3>
<p>B-트리는 모든 리프 노드들이 같은 레벨(높이)에 존재하도록 보장한다. 노드 하나에 여러 데이터를 담을 수 있어 트리의 높이를 낮게 유지할 수 있고, 대용량 데이터를 탐색할 때 디스크 접근 횟수를 획기적으로 줄여주는 장점이 된다.</p>
<blockquote>
<p>방대한 데이터를 다루는 <strong>데이터베이스(Index)</strong>나 <strong>파일 시스템</strong>에서 핵심적으로 사용된다. 노드 하나가 가질 수 있는 자식의 수가 많아 트리의 높이를 낮게 유지할 수 있기 때문이다.</p>
</blockquote>
<blockquote>
<h3 id="b-트리의-변형-b-트리">B 트리의 변형, B+ 트리</h3>
<p>📍 실무 데이터베이스에서 가장 많이 쓰인다고 한다...!</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/48c8657f-f455-4a1d-bf5f-559e1ad0cd20/image.png" alt=""></p>
</blockquote>
<ul>
<li><strong>B트리와의 차이</strong>: 실질적인 데이터가 오직 <strong>최하위 리프 노드</strong>에만 위치한다.</li>
<li><strong>연결 리스트</strong>: 리프 노드들이 서로 연결 리스트 형태로 이어져 있어, 범위 스캔(Range Scan) 연산 시 부모 노드로 돌아갈 필요 없이 옆 노드로 바로 이동할 수 있어 매우 효율적이다.</li>
</ul>
<h3 id="5-3-b-트리-vs-b-트리">5-3. B-트리 vs B+ 트리</h3>
<p>📍 <strong>B+트리</strong>는 <strong>내부 노드</strong>에 데이터를 <strong>중복</strong>해서 저장(인덱스로 활용)하기 때문에 <strong>B-트리보다 공간을 조금 더 차지하는 것은 맞다.</strong></p>
<p>하지만 실무(특히 <strong>Database 인덱스, File System</strong>)에서 B+트리를 선호하는 이유는 그 단점을 압도하는 <strong>효율성</strong> 때문이다.</p>
<h4 id="①-노드-당-더-많은-key를-담을-수-있다-높이-최소화">① 노드 당 더 많은 Key를 담을 수 있다 (높이 최소화)</h4>
<p>B-트리와 B+트리의 결정적인 차이는 <strong>&quot;데이터(Value)가 어디에 저장되는가&quot;</strong>이다.</p>
<ul>
<li><strong>B-트리</strong>: 내부 노드(Internal Node)가 <strong>Key와 Data를 모두</strong> 가진다.</li>
<li><strong>B+트리</strong>: 내부 노드는 <strong>Key(가이드 역할)</strong>만 가지고, 실제 <strong>Data는 오직 리프 노드</strong>에만 저장한다.</li>
</ul>
<blockquote>
<p>📍 <strong>이게 왜 중요할까?</strong>
하나의 노드(페이지) 크기는 고정되어 있다. B+트리의 내부 노드는 데이터가 없기 때문에 그만큼 <strong>더 많은 Key</strong>를 채울 수 있다.</p>
</blockquote>
<p>결과적으로 트리의 <strong>분기 수(Fan-out)</strong>가 훨씬 커지며, 트리의 전체 <strong>높이(Height)</strong>가 낮아진다. 디스크 I/O가 성능의 병목인 시스템에서 높이가 1단계 낮아지는 것은 엄청난 성능 향상을 의미한다.</p>
<h4 id="②-전체-탐색full-scan과-범위-탐색range-scan의-압도적-유리함">② 전체 탐색(Full Scan)과 범위 탐색(Range Scan)의 압도적 유리함</h4>
<p><strong>&#39;인접 리스트&#39;</strong> 개념이 바로 여기서 핵심적인 역할을 한다.</p>
<ul>
<li><strong>B-트리</strong>: 모든 데이터를 순회하려면 <code>트리를 타고 위아래로 왔다 갔다(In-order Traversal)</code> 해야 한다. 이 과정에서 디스크 헤드가 계속 움직여야 하므로 매우 느리다.</li>
<li><strong>B+트리</strong>: 위 이미지에서 보듯 <strong>모든 리프 노드가 연결 리스트(Linked List)</strong>로 이어져 있다.</li>
<li>&quot;10번부터 50번까지 찾아줘&quot;라고 하면 10번 위치만 찾은 뒤, 그다음부터는 <strong>옆으로 쭉 읽기만 하면 된다.</strong></li>
<li>이 방식은 <code>순차적 읽기(Sequential Read)</code>에 최적화되어 있어 데이터베이스의 범위 조회에서 성능 차이가 극명하게 벌어진다.</li>
</ul>
<h4 id="③-캐시-효율성-cache-hit">③ 캐시 효율성 (Cache Hit)</h4>
<p>내부 노드에는 데이터 없이 인덱스(Key) 정보만 있기 때문에, 메모리(RAM)의 한정된 공간에 <strong>더 많은 인덱스 정보</strong>를 올릴 수 있다. 이는 원하는 데이터가 메모리 안에 있을 확률(Cache Hit)을 높여주어, 느린 디스크로 직접 가는 횟수를 대폭 줄여준다.</p>
<hr>
<h4 id="q-그냥-인접-리스트-인접-리스트로-구성하면-안-될까">Q. 그냥 &#39;인접 리스트-인접 리스트&#39;로 구성하면 안 될까?</h4>
<p>단순히 모든 데이터를 인접 리스트(연결 리스트)로만 관리하면, <strong>특정 데이터를 찾는 &#39;탐색&#39;</strong>이 $O(n)$이 된다. 100만 번째 데이터를 찾으려면 앞의 99만 개를 다 거쳐야 한다...</p>
<p>그래서 📍 <strong>B+트리는 &quot;탐색은 트리 구조()로 빠르게 하고, 범위 출력은 리스트 구조(옆으로 이동)로 빠르게 하는&quot;</strong> 두 자료구조의 장점을 결합한 형태라고 이해하면 된다.‼️</p>
<h4 id="q-왜-b트리일까">Q. 왜 B+트리일까?</h4>
<table>
<thead>
<tr>
<th>특징</th>
<th>B-트리</th>
<th>B+트리</th>
</tr>
</thead>
<tbody><tr>
<td><strong>데이터 저장</strong></td>
<td>모든 노드에 저장</td>
<td>오직 리프 노드에만 저장</td>
</tr>
<tr>
<td><strong>내부 노드 크기</strong></td>
<td>큼 (Key + Data)</td>
<td>작음 (Key만 존재) → <strong>더 많은 분기 가능</strong></td>
</tr>
<tr>
<td><strong>범위 탐색</strong></td>
<td>트리를 순회해야 함 (느림)</td>
<td>리프 간 연결로 <strong>옆으로 이동</strong> (매우 빠름)</td>
</tr>
<tr>
<td><strong>실무 사용</strong></td>
<td>일반적인 인덱스</td>
<td><strong>DB 인덱스(MySQL, Oracle 등)의 표준</strong></td>
</tr>
</tbody></table>
<blockquote>
<p>&quot;B+트리는 공간을 조금 더 사용하더라도, 디스크 I/O 횟수를 줄이고 범위 검색 성능을 극대화하기 위해 설계된 실무 지향적 자료구조이다.&quot;</p>
</blockquote>
<hr>
<h2 id="6-그래프-graph">6. 그래프 (Graph)</h2>
<p>그래프는 사물이나 개념 간의 <strong>연결 관계</strong>를 표현하는 자료구조이다.</p>
<p>주로 네트워크, 운영체제 등 다양한 분야에서 범용적으로 사용된다 ❗️</p>
<h3 id="6-1-그래프의-정의와-트리와의-차이점">6-1. 그래프의 정의와 트리와의 차이점</h3>
<p>그래프는 <strong>정점(Vertex)</strong>이라 불리는 데이터와 이들을 잇는 <strong>간선(Edge)</strong> 혹은 링크(Link)로 연결된 형태를 말한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/c41ca74d-5226-473f-94e5-bcccdf096dc4/image.png" alt=""></p>
<ul>
<li><strong>트리와의 차이</strong>: 트리는 사이클을 형성하지 않고 연결된 노드 간에 상하 관계를 갖는 반면, 그래프는 사이클을 형성할 수 있고 이웃한 정점끼리 상하 관계를 갖지 않는 더 일반적인 형태이다.</li>
<li><strong>사이클(Cycle)</strong>: 특정 정점에서 출발해 다시 처음 출발했던 정점으로 되돌아오는 경로를 의미한다.</li>
</ul>
<hr>
<h3 id="6-2-그래프의-실무-예시">6-2. 그래프의 실무 예시</h3>
<p>우리가 일상에서 접하는 많은 연결 관계가 그래프로 표현될 수 있다.</p>
<ul>
<li><strong>지하철 노선도</strong>: 역을 정점으로, 역과 역 사이를 연결하는 경로를 간선으로 본다.</li>
<li><strong>컴퓨터 네트워크</strong>: 다양한 통신 기기(정점)를 케이블이나 와이파이 같은 연결 매체(간선)로 연결한 형태이다.</li>
</ul>
<hr>
<h3 id="6-3-간선의-특징에-따른-그래프의-종류">6-3. 간선의 특징에 따른 그래프의 종류</h3>
<p>간선이 어떤 형태로 정점을 연결하느냐에 따라 그래프의 유형이 달라진다.</p>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/2c7dedf2-83fc-4f8c-afb3-b9ef0296952e/image.png"
width=600/>      </p>
<table>
<thead>
<tr>
<th>종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>연결/비연결 그래프</strong></td>
<td>임의의 두 정점 사이에 경로가 존재하면 연결 그래프, 존재하지 않는 정점이 있으면 비연결 그래프이다.</td>
</tr>
<tr>
<td><strong>방향/무방향 그래프</strong></td>
<td>간선에 방향성이 있어 한쪽으로만 갈 수 있으면 방향 그래프, 양방향 이동이 가능하면 무방향 그래프이다.</td>
</tr>
<tr>
<td><strong>가중치 그래프</strong></td>
<td>간선에 특정 &#39;비용(Weight)&#39; 값이 부여된 그래프이다. 예: 지하철 역 사이의 거리.</td>
</tr>
<tr>
<td><strong>서브그래프</strong></td>
<td>특정 그래프의 정점과 간선의 일부분으로만 이루어진 부분 그래프이다.</td>
</tr>
</tbody></table>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/3c18ce63-05be-4f09-860f-b863d84061f8/image.png"
width=400/></p>
<hr>
<blockquote>
<h4 id="참고자료">참고자료</h4>
</blockquote>
<ul>
<li>이진 트리(binary tree)와 이진 탐색 트리(binary search tree): <a href="https://chamdom.blog/binary-tree/">https://chamdom.blog/binary-tree/</a></li>
<li>[자료 구조] 힙 (Heap): <a href="https://chaeyami.tistory.com/174">https://chaeyami.tistory.com/174</a></li>
<li>[자료구조/균형트리] B-트리, B+트리란?: <a href="https://suyeonme.tistory.com/102">https://suyeonme.tistory.com/102</a></li>
<li>[MySQL] B-tree, B+tree란? (인덱스와 연관지어서): <a href="https://zorba91.tistory.com/293">https://zorba91.tistory.com/293</a></li>
<li>[자료구조] 간단히 알아보는 B-Tree, B+Tree, B*Tree: <a href="https://ssocoit.tistory.com/217">https://ssocoit.tistory.com/217</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 04-4 해시 테이블(해시 함수, 해시 충돌)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-4-%ED%95%B4%EC%8B%9C-%ED%85%8C%EC%9D%B4%EB%B8%94%ED%95%B4%EC%8B%9C-%ED%95%A8%EC%88%98-%ED%95%B4%EC%8B%9C-%EC%B6%A9%EB%8F%8C</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-4-%ED%95%B4%EC%8B%9C-%ED%85%8C%EC%9D%B4%EB%B8%94%ED%95%B4%EC%8B%9C-%ED%95%A8%EC%88%98-%ED%95%B4%EC%8B%9C-%EC%B6%A9%EB%8F%8C</guid>
            <pubDate>Mon, 15 Dec 2025 11:09:57 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 해시 테이블의 개념 (정의, 구조, 원리)
② 해시 함수 (특징, 활용 사례, 사용 이유)
③ 해시 충돌 (무결성 훼손, 데이터 위조, 체이닝, 개방 주소법)
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-해시-테이블">1. 해시 테이블</h2>
<blockquote>
<p>📍 해시 테이블은 <strong>운영체제 내부, 네트워크, 데이터베이스</strong>에서도 <strong>자주 사용</strong>된다. <code>개발 실무에서 반드시 접하거나 사용하게 될 개념</code>이기 때문에 꼼꼼히 공부하자❗️</p>
</blockquote>
<p>키 <code>key</code>와 값 <code>value</code>의 대응으로 이루어진 <strong>표(테이블)</strong>와 같은 형태의 자료구조를 말한다.</p>
<p>키는 해시 테이블에 대한 <strong>입력</strong>, 값은 키를 통해 얻고자 하는 <strong>데이터</strong>라고 볼 수 있다. 이러한 대응 관계를 갖는 데이터는 일상에서 쉽게 찾아볼 수 있다.</p>
<p>대표적인 예시로 <strong>전화번호부</strong>가 있다.
이름을 키로, 그에 대응되는 전화번호를 값으로 삼을 수 있다. <strong>책</strong>도 마찬가지다.
책마다 부여받은 <code>ISBN</code>이라는 공유한 도서 번호를 <strong>키</strong>, <code>책 제목</code>을 <strong>값</strong>으로 대응할 수 있다.</p>
<table>
<thead>
<tr>
<th align="left">ISBN(키)</th>
<th align="left">책 제목(값)</th>
</tr>
</thead>
<tbody><tr>
<td align="left">9791162243091</td>
<td align="left">혼자 공부하는 컴퓨터 구조 + 운영체제</td>
</tr>
<tr>
<td align="left">9791162243664</td>
<td align="left">혼자 공부하는 머신러닝 + 딥러닝</td>
</tr>
<tr>
<td align="left">9791162245651</td>
<td align="left">혼자 공부하는 파이썬</td>
</tr>
</tbody></table>
<h3 id="1-1-해시-테이블의-구조">1-1. 해시 테이블의 구조</h3>
<p><image src="https://velog.velcdn.com/images/w_dw_r/post/70d165e3-e19f-4bc0-964c-82ac6461bdb7/image.png"
width=500/></p>
<pre><code>해시 테이블 구조
 ├── 키 (Key)
 ├── 해시 함수 (Hash Function)
 └── 버킷 배열 (Bucket Array)
     ├── 인덱스 (Index)
     └── 데이터 (value) </code></pre><ul>
<li><strong>키</strong>: 데이터를 검색하거나 저장하는 데 사용되는 입력 값</li>
<li><strong>해시 함수</strong>: 키를 입력받아 버킷 배열 내의 유효한 인덱스를 계산</li>
<li><strong>버킷 배열</strong>: 키를 통해 얻고자 하는 데이터를 버킷에 저장하는 역할<ul>
<li>인덱스 (Index): 해시 함수의 결과, 데이터가 저장될 배열의 위치</li>
<li>데이터 (value): 해당 키와 연결되어 실제 저장되는 정보</li>
</ul>
</li>
</ul>
<p><em>➡️ 버킷은 여러 개 존재할 수 있고, 여러 버킷들이 모여 배열을 형성함</em></p>
<h3 id="1-2-해시-테이블의-원리">1-2. 해시 테이블의 원리</h3>
<ul>
<li><strong>저장 과정:</strong> <code>키</code> $\xrightarrow{\text{해시 함수}}$ <code>인덱스</code> $\xrightarrow{\text{접근}}$ <code>버킷</code> $\xrightarrow{\text{저장}}$ <code>데이터(값)</code></li>
<li><strong>검색 과정:</strong> <code>키</code> $\xrightarrow{\text{해시 함수}}$ <code>인덱스</code> $\xrightarrow{\text{접근}}$ <code>버킷</code> $\xrightarrow{\text{획득}}$ <code>데이터(값)</code></li>
<li><strong>로드 팩터:</strong> (저장된 데이터 수) $\div$ (버킷 배열의 수)</li>
</ul>
<p><code>*로드 팩터: 해시 테이블이 현재 얼마나 가득 차 있는지에 대한 지표, 로드 팩터가 클수록 해시 테이블의 성능이 떨어짐</code></p>
<hr>
<h2 id="2-해시-함수-hash-function">2. 해시 함수 (Hash Function)</h2>
<p>📍 임의의 길이를 지닌 데이터를 <strong>고정된 길이</strong>의 데이터로 변환하는 <strong>단방향 함수</strong>이다.</p>
<p>📍 단방향 함수이기 때문에 <strong>특정 입력 데이터를 고정된 길이의 해시 값으로 변환</strong>할 수는 있어도, 반대로 <strong>해시 값을 토대로 어떤 데이터가 입력되었는지를 도출하기는 어렵다.</strong></p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/abea11da-4938-46a4-b84a-63d8b31de7a3/image.png" alt=""></p>
<p>해시 함수의 연산 방법은 <strong>해시 알고리즘(Hash Algorithm)</strong>이라고 한다.
해시 알고리즘은 대표적으로 <code>MD5</code>, <code>SHA-1</code>. <code>SHA-256</code>, <code>SHA-512</code>, <code>SHA3</code>, <code>HMAC</code> 등이 있다.</p>
<p>** 📍 같은 데이터라 하더라도 적용된 해시 알고리즘이 다르면 도출되는 해시 값의 길이나 값이 달라진다.**</p>
<h3 id="2-1-해시-함수의-주요-특징">2-1. 해시 함수의 주요 특징</h3>
<h4 id="📍-sha-256-알고리즘으로-아래-문자열들을-해시한-결과">📍 SHA-256 알고리즘으로 아래 문자열들을 해시한 결과</h4>
<ul>
<li><p><strong>&#39;hanbit&#39; 문자열</strong>
3f5e2cf9fe54c5c8df8589d53f6f787f66b7cc556b1543d5cd002c29d8b12b28</p>
</li>
<li><p><strong>&#39;hanbit media&#39; 문자열</strong>
f6c3a369cb093a0d8975b74a94035a75266f5c2032712b471443bf17e469a5ef</p>
</li>
<li><p><strong>&#39;hanbit media &#39; 문자열</strong>
7b860e4e58c1b4c86de890837b6a4653ba5a0a31ec6f4b66e1b6f438a26512ea</p>
</li>
</ul>
<p><em>➡️ 문자열에 따라 해시 값이 아예 달라지는 것을 확인할 수 있다.</em></p>
<blockquote>
<p>⚠️ 해시 값은 문자열이 <strong>한 글자만 달라져도 크게 달라질 수 있다.</strong>
&#39;hanbit media&#39; 문자열에 공백 하나를 추가해 &#39;hanbit media &#39; 문자열에 대한 해시 값을 구하면 <strong>완전히 다른 결과</strong>가 나온다.</p>
</blockquote>
<p><code>*눈사태 효과 (Avalanche Effect): 해시 함수에서 Input Data가 1bit만 차이를 보여도 Output Data는 다르게 나타난다.</code></p>
<blockquote>
<p>📍 해시 함수는 이러한 특징으로 인해 <strong>무작위 값</strong>을 만들거나 <strong>단방향 암호</strong>를 만들 때, <strong>데이터의 무결성</strong>을 검증하기 위해 사용되기도 한다.</p>
</blockquote>
<h3 id="2-2-해시-함수의-활용-사례">2-2. 해시 함수의 활용 사례</h3>
<h4 id="1-데이터-송수신">1) 데이터 송수신</h4>
<p>데이터를 전송하기 전에 <strong>송신하는 쪽에서</strong> 보낼 데이터에 대한 <strong>해시 값을 계산</strong>한 뒤, 이를 <strong>데이터와 함께 수신자에게 전달</strong>했다고 가정해보자.</p>
<p>그리고 <strong>수신하는 쪽에서</strong> 받은 데이터에 대한 <strong>해시 값을 계산</strong>한 뒤, 계산된 해시 값을 <strong>전달받은 해시 값과 비교</strong>해보자.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/41f7aa4d-9fd0-4ad9-89f7-bb497c264b86/image.png" alt=""></p>
<p>전송 당시의 해시 값과 수신된 데이터에 대한 해시 값을 비교했을 때, <strong>두 값이 일치하면 바르게 전송되었다고 볼 수 있다.</strong></p>
<p>반면, 전송 과정에서 <strong>조금이라도 정보가 왜곡되거나 훼손</strong>되었다면 <strong>전혀 다른 해시 값이 도출</strong>되므로 <strong>잘못된 데이터</strong>가 전송되었음을 쉽게 파악할 수 있다.</p>
<h4 id="2--웹-프레임-워크의-로그인-및-회원-정보-저장">2)  웹 프레임 워크의 로그인 및 회원 정보 저장</h4>
<p>해시 함수를 이용한 해시 값은 웹 프레임워크에서 <strong>비밀번호를 안전하게 저장</strong>할 때 핵심적으로 사용된다.</p>
<p>우리가 웹 서비스에 접속하여 <code>아이디(또는 이메일)</code>와 <code>비밀번호</code>를 입력할 때, </p>
<p>😱 대부분의 사람들은 <strong>웹 서비스 관리자가 자신의 비밀번호를 그대로 알 수 있을 것</strong>이라고 생각한다.</p>
<p><strong>📍 그러나, 해당 웹 서비스의 관리자는 실제 사용자의 비밀번호를 알 수 없다.</strong></p>
<p><em>➡️ 이는 <code>비밀번호를 비롯한 개인 정보</code>가 웹 사이트 <strong>데이터베이스에 저장</strong>될 때, 법적 규제와 보안 관행에 따라 <strong>단방향 암호화 (해시 함수 적용)</strong>를 거쳐 저장되기 때문이다.</em></p>
<ul>
<li>실제로 서비스 배포를 했었던 <code>boxbox</code> 웹의 <code>login</code> 테이블
<image src = "https://velog.velcdn.com/images/w_dw_r/post/9794616c-eb55-4ac7-88c8-a46899f9db78/image.png"
width=600/></li>
</ul>
<p><code>*이러한 비밀번호 암호화 용도로 사용되는 대표적인 해시 함수로는 bcrypt, PBKDF2, scrypt, argon2 등이 있다.</code></p>
<blockquote>
<p>즉, 사용자가 입력한 비밀번호 <strong>원본(Plaintext)은 저장되지 않고,</strong> 오직 되돌릴 수 없는 <strong>해시 값(Hash Value)</strong>만 데이터베이스에 <strong>저장</strong>된다. 이로 인해 관리자나 해커가 데이터베이스에 접근하더라도 <strong>원본 비밀번호를 탈취하는 것이 거의 불가능하다.</strong></p>
</blockquote>
<h3 id="2-3-해시-테이블을-사용하는-이유">2-3. 해시 테이블을 사용하는 이유</h3>
<p>다시 해시 테이블 이야기로 돌아와서, 해시 테이블을 사용하는 이유는 명백하다.</p>
<p><strong>빠른 검색 속도</strong> 때문이다.</p>
<p>📍 일반적인 상황에서 <strong>해시 테이블을 활용한 검색, 삽입, 삭제 연산의 시간 복잡도는 O(1)</strong>이다.</p>
<p><em>➡️ 이는 <code>입력과 무관하게 항상 일정한 속도를 보장</code>한다는 의미이며, 이례적일 정도로 뛰어난 성능이다</em>.</p>
<h4 id="q-그렇다면-해시-테이블은-모든-자료구조의-성능을-능가하는-최고의-자료구조일까--❌">Q. 그렇다면 해시 테이블은 모든 자료구조의 성능을 능가하는 최고의 자료구조일까?  ❌</h4>
<p>해시 테이블은 <strong>속도가 빠른 만큼 상대적으로 많은 <code>메모리 공간</code>이 소모</strong>된다.</p>
<p><strong>데이터가 매우 많을 경우</strong> <code>공간 복잡도</code>가 <code>시간 복잡도</code>만큼 우수하지 않다. 뿐만 아니라 아래 그림과 같은 <strong>📍 해시 충돌</strong>이라는 문제도 해결해야 한다. </p>
<p><image src = "https://velog.velcdn.com/images/w_dw_r/post/f8d20503-ea3a-4803-975d-82eb08352a9f/image.png"
width=500/>       </p>
<hr>
<h2 id="3-해시-충돌-hash-collaion">3. 해시 충돌 (Hash Collaion)</h2>
<p><strong>서로 다른 키</strong>에 대해 <strong>같은 해시 값</strong>이 <strong>대응</strong>되는 상황을 의미한다.</p>
<p>이는 <code>다른 이름</code>에 <code>같은 전화번호</code>가 대응된 상황, 혹은 <code>다른 ISBN</code>에 <code>같은 책</code>이 대응된 상황과도 같다.</p>
<h4 id="q-해시-충돌로-인해-어떤-문제가-발생할-수-있을까">Q. 해시 충돌로 인해 어떤 문제가 발생할 수 있을까?</h4>
<p>대표적인 해시 함수 중 하나인 <code>SHA-1</code> 해시 충돌 사례를 통해 생각해보자.</p>
<p>구글과 CWT 암스테르담 연구소는 <code>SHA-1</code> 해시 함수가 사용하는 알고리즘에 해시 충돌이 발생할 수 있음을 입증했는데,</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/28feb7eb-0107-47d6-9d35-768afce03376/image.png" alt=""></p>
<p><code>shattered-1.pdf</code>와 <code>shattered-2.pdf</code>는 분명 다른 Pdf 파일이지만, 두 파일 데이터에 대한 <strong>해시 값</strong>을 구해보면 다음과 같이 <strong>SHA-1 알고리즘에서만 동일한 해시 값이 도출</strong>된다.</p>
<p><em>➡️ <strong>충돌이 발생</strong>한 것이다.</em></p>
<p><strong>📍 해시 값은 데이터 무결성 검증에도 사용이 된다.</strong></p>
<p>매우 드문 사례일 수 있지만,
이와 같은 해시 충돌이 발생할 경우 <strong><code>shattered-1.pdf</code>와 <code>shattered-2.pdf</code>의 같은 해시 값을 토대로 두 파일을 같은 데이터라도 판단할 수 있다.</strong></p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/f34fca92-283a-44f3-96fc-c644929487b1/image.png" alt=""></p>
<p><em>➡️ 이렇게 되면 전송 과정에서 <strong>데이터를 가로채서 바꾸는 보안상의 위험도 발생할 수 있다.</strong></em></p>
<blockquote>
<h4 id="✏️-보안-관점에서의-추가-설명">✏️ 보안 관점에서의 추가 설명</h4>
<p>해당 사례는 해시 함수의 조건 중 <strong>📍 <code>제 2 프리 이미지 저항성</code>과 <code>충돌 저항성</code>에 위배</strong>되는 행위이다.</p>
<p><strong>제 2 프리 이미지 저항성 (Second Pre-image Resistance)</strong>
<image src = "https://velog.velcdn.com/images/w_dw_r/post/63979539-791b-4f7c-b286-000e30fa5c26/image.png" width=500/></p>
<ul>
<li>Input Data <code>x</code>가 주어졌을 때, 해시 값 <code>z</code>를 갖는 또 다른 Input Data <code>x’</code>의
발견이 어려워야 한다.</li>
</ul>
</blockquote>
<ul>
<li>주어진 <code>x</code>, <code>z</code>에 대해 <code>x</code>를 h()에 적용한 <code>z</code> = <code>h(x)</code>가 있을 경우, <code>z</code> = <code>h(x)</code> = <code>h(x’)</code>인 <code>x’</code>를 찾기가 어려워야 한다.<blockquote>
<p><strong>충돌 저항성 (Collision resistance)</strong></p>
<image src = "https://velog.velcdn.com/images/w_dw_r/post/3ad1e88f-5eab-4ab4-90c3-4a027f0dc80e/image.png" width=500/>

<ul>
<li>동일한 해시 값 <code>z</code>를 갖는 임의의 두 Input Data <code>x</code>, <code>x&#39;</code>을 찾는 것이
어려워야 한다.</li>
</ul>
</blockquote>
</li>
<li>주어진 정보가 없을 때, 해시 값 <code>z</code>에 대한 <code>h(x)</code> = <code>h(x&#39;)</code> = <code>z</code>를 만족하는 <code>(x, x&#39;)</code>을 찾는 것이 어려워야 한다.</li>
</ul>
<blockquote>
<p>📍 해시 테이블에서 이와 같은 해시 충돌이 발생하면 <strong>2개 이상의 키에 같은 데이터가 대응되는 상황이 발생한다.</strong></p>
</blockquote>
<p>이를 해결하기 위한 방법으로는 <strong>체이닝</strong>과 <strong>개발 주소법</strong>이 대표적이다.</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th align="left">방법</th>
<th align="left">주요 특징</th>
<th align="left">장점</th>
<th align="left">단점</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>체이닝 (Chaining)</strong></td>
<td align="left">같은 버킷에 연결 리스트로 데이터를 연결</td>
<td align="left">구현이 단순하고 삭제가 용이</td>
<td align="left">최악의 경우 $O(N)$ 성능, 메모리 오버헤드</td>
</tr>
<tr>
<td align="left"><strong>개방 주소법 (Open Addressing)</strong></td>
<td align="left">빈 다른 버킷을 찾아 데이터 저장</td>
<td align="left">추가적인 포인터 불필요, 캐시 효율성 좋음</td>
<td align="left">삭제 처리 복잡, 군집화(Clustering) 문제</td>
</tr>
</tbody></table>
<h3 id="3-1-체이닝-chaining">3-1. 체이닝 (Chaining)</h3>
<p>체이닝은 충돌이 발생한 데이터를 <strong>연결 리스트</strong>로 추가하는 방식이다.</p>
<p><image src = "https://velog.velcdn.com/images/w_dw_r/post/1f8e274d-adf7-406e-bf07-f7a0ada0fe73/image.png"
width=400/></p>
<p><strong>서로 다른 키가 같은 테이블 인덱스로 해시되더라도,</strong> 단순히 연결 리스트의 <strong>노드로 추가</strong>될 뿐이다.</p>
<p><em>➡️ 따라서 하나의 테이블 인덱스에 여러 데이터가 연결 리스트 형태로 존재할 수 있다.</em></p>
<ul>
<li><strong>장점:</strong> 구현이 단순하고, 테이블이 거의 가득 차더라도 데이터를 안정적으로 저장할 수 있다.</li>
<li><strong>단점:</strong> 충돌이 자주 발생하여 리스트가 길어진다면, 해시 테이블의 장점인 $O(1)$ 속도를 살리지 못하고 <strong>탐색 성능이 $O(N)$으로 떨어질 수 있다.</strong></li>
</ul>
<h3 id="3-2-개방-주소법-open-addressing">3-2. 개방 주소법 (Open Addressing)</h3>
<p>개방 주소법은 충돌이 발생했을 때, 충돌 위치가 아닌 <strong>다른 비어있는 인덱스(버킷)</strong>를 찾아 데이터를 저장하는 방법이다.</p>
<p>이때 비어있는 다른 버킷을 찾는 과정을 <strong>조사(Probing)</strong>라고 한다. 개방 주소법은 이 조사 방법에 따라 세부적으로 나뉜다.</p>
<h4 id="1-선형-조사법-linear-probing">1) 선형 조사법 (Linear Probing)</h4>
<p>선형 조사법은 가장 단순한 조사 방법이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/03e78cb4-cb8c-4b6e-9861-bbbfbc6b1434/image.png" alt=""></p>
<ul>
<li><strong>원리:</strong> 해시 값 <code>f(key)</code>에서 충돌이 발생하면, 다음 인덱스 <code>f(key) + 1, f(key) + 2, f(key) + 3, ...</code> 순으로 순차적으로 가용한 인덱스를 찾아 나선다.</li>
</ul>
<p><image src = "https://velog.velcdn.com/images/w_dw_r/post/d2aa7128-e4fa-4691-9cec-b2d59a31e470/image.png"
width=300/> </p>
<ul>
<li><strong>문제점:</strong> <code>데이터의 군집화(Clustering)</code> 현상이 발생한다. 해시 충돌이 발생하는 인덱스 인근에 여러 데이터가 몰리면서 순차 탐색이 길어지고 성능이 악화된다.</li>
</ul>
<blockquote>
<h4 id="이차-조사법-quadratic-probing">이차 조사법 (Quadratic Probing)</h4>
</blockquote>
<p>이차 조사법은 선형 조사법의 <strong>군집화 문제를 완화하는 방법</strong> 중 하나이다.</p>
<blockquote>
</blockquote>
<ul>
<li><strong>원리:</strong> 충돌이 발생한 인덱스에서 <strong>제곱수만큼 떨어진</strong> 거리에 위치한 인덱스를 찾는다. 즉, <code>f(key) + 1^2, f(key) + 2^2, f(key) + 3^2, ...</code> 순으로 가용한 버킷 인덱스를 탐색한다.</li>
<li>선형 조사법보다는 군집화 문제를 완화할 수 있지만, 제곱수의 규칙성 때문에 여전히 근본적인 해결 방법이라고 보기는 어렵다. </li>
</ul>
<h4 id="2-이중-해싱-double-hashing">2) 이중 해싱 (Double Hashing)</h4>
<p>이중 해싱(<code>double hashing</code>)은 가장 효과적으로 군집화 문제를 피하는 방법 중 하나이다.</p>
<ul>
<li><strong>원리:</strong> <strong>2개의 해시 함수</strong>를 사용한다. 충돌이 발생하면, 기본 해시 함수 <code>f(key)</code>에 <strong>보조 해시 함수 <code>g(key)</code>의 값</strong>을 더해서 다음 탐색 인덱스를 결정한다.</li>
<li><strong>탐색 순서:</strong> <code>f(key) + g(key), f(key) + 2g(key), f(key) + 3g(key), ...</code> 순으로 인덱스를 찾는다.</li>
<li><strong>장점:</strong> 해시 함수를 통해 <strong>무작위</strong>로 인덱스가 생성되는 효과를 얻을 수 있어, 선형 조사법의 군집화 문제를 상당 부분 해소할 수 있다.</li>
</ul>
<h3 id="3-3-프로그래밍-언어별-해시-테이블-구현">3-3. 프로그래밍 언어별 해시 테이블 구현</h3>
<p>많은 프로그래밍 언어에서 해시 테이블은 표준 라이브러리로 제공된다.</p>
<table>
<thead>
<tr>
<th align="left">프로그래밍 언어</th>
<th align="left">해시 테이블의 구현</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>C++</strong></td>
<td align="left"><code>std::unordered_map</code></td>
</tr>
<tr>
<td align="left"><strong>자바 (Java)</strong></td>
<td align="left"><code>HashTable</code>, <code>HashMap</code></td>
</tr>
<tr>
<td align="left"><strong>파이썬 (Python)</strong></td>
<td align="left"><code>dictionary</code></td>
</tr>
<tr>
<td align="left"><strong>자바스크립트 (JavaScript)</strong></td>
<td align="left"><code>Map</code></td>
</tr>
<tr>
<td align="left"><strong>Go</strong></td>
<td align="left"><code>map</code></td>
</tr>
</tbody></table>
<hr>
<p>학부생 시절 작성했던 네트워크 보안 과목의 요약 일부분,,,
<img src="https://velog.velcdn.com/images/w_dw_r/post/af4ec85a-2030-4f8e-b0fd-776953f0d6c6/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 03-4 가상 메모리(논리 주소/물리 주소, 페이징, 세그먼테이션, 요구 페이징)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%85%BC%EB%A6%AC-%EC%A3%BC%EC%86%8C%EB%AC%BC%EB%A6%AC-%EC%A3%BC%EC%86%8C-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%84%B8%EA%B7%B8%EB%A8%BC%ED%85%8C%EC%9D%B4%EC%85%98</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-04-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%85%BC%EB%A6%AC-%EC%A3%BC%EC%86%8C%EB%AC%BC%EB%A6%AC-%EC%A3%BC%EC%86%8C-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%84%B8%EA%B7%B8%EB%A8%BC%ED%85%8C%EC%9D%B4%EC%85%98</guid>
            <pubDate>Tue, 09 Dec 2025 10:38:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 가상 메모리
② 논리 주소 / 물리 주소
③ 페이징 (페이지 테이블, TLB, 계층적 페이징)
④ 세그먼테이션
⑤ 요구 페이징 (페이지 교체, 스레싱)
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-가상-메모리-운영체제의-메모리-관리-기법">1. 가상 메모리: 운영체제의 메모리 관리 기법</h2>
<p><code>CPU와 프로세스</code>는 <strong>메모리 몇 번지에 무엇이 저장되어 있는지</strong>까지 다 <strong>일일이 알고 있지는 않다.</strong> 이를 알기 위해서는 <code>CPU 내부의 저장 공간(레지스터)</code>이 <strong>메모리만큼 커야 할 텐데, 실제로는 그보다 훨씬 작은 용량을 갖고 있기 때문</strong>이다.</p>
<p>게다가 <strong>새로운 프로세스는 새롭게 메모리에 적재</strong>되고, <strong>사용되지 않는 프로세스는 메모리에서 삭제</strong>된다.</p>
<p><em>➡️ 메모리 정보는 <strong>시시 때때로 변경될 수 있다</strong>는 의미이다.</em></p>
<p>메모리에 적재된 모든 프로세스와 CPU가 이렇게 실시간으로 바뀌는 정보를 모두 기억하고 있기는 어렵다.</p>
<p>📍 <strong>그렇다면 CPU는 어떻게 메모리에 적재된 프로세스의 주소를 인식하고 관리할까?</strong></p>
<h3 id="1-1-가상-메모리-virtual-memory">1-1. 가상 메모리 (Virtual Memory)</h3>
<p><strong>운영체제의 메모리 관리 기법</strong> 중 하나로, <strong>실제 메모리(RAM)보다 더 큰 프로그램을 실행</strong>할 수 있도록 해주는 기술이다.</p>
<ul>
<li><strong>사용 환경:</strong> <code>프로그램(프로세스)</code>의 크기가 <strong>실제 물리 메모리 크기보다 클 때</strong> 주로 사용된다. <strong>(예: 4GB RAM에서 4GB 이상의 프로그램 실행)</strong></li>
<li><strong>작동 방식:</strong> 프로그램의 전체가 아닌 <code>일부</code>만 실제 메모리에 <strong>적재</strong>하고, 나머지는 <code>보조 기억 장치(하드 디스크 등)</code>에 <strong>저장</strong>하여 메모리가 실제보다 크게 보이게 한다.</li>
</ul>
<blockquote>
<p><em>논리 주소 공간(Virtual Address Space): 가상 메모리 기법으로 인해 생성된 주소 공간</em></p>
</blockquote>
<h3 id="1-2-물리-주소와-논리-주소">1-2. 물리 주소와 논리 주소</h3>
<p>📍 CPU와 프로세스는 실제 메모리 주소인 <strong>물리 주소</strong>가 아닌, 운영체제가 부여한 <strong>논리 주소</strong>를 사용하여 메모리에 접근한다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/bd5d21c0-4894-48d4-9e7c-bcf6a764bec0/image.png" alt=""></p>
<ul>
<li><p><strong>논리 주소 (Logical Address):</strong> 프로세스마다 <strong>0번지</strong>부터 시작하여 부여되는 <strong>가상의 주소</strong>
<em>➡️ 즉, <code>CPU나 프로세스</code>가 <strong>메모리에 접근할 때</strong> 이용하는 주소이다.</em></p>
</li>
<li><p><strong>물리 주소 (Physical Address):</strong> 실제 메모리(RAM)에 있는 <strong>정보가 실제로 저장된 주소</strong></p>
</li>
<li><p><strong>MMU (Memory Management Unit):</strong> <code>CPU와 메모리 사이에 위치</code>하며, CPU가 사용하는 <strong>논리 주소를</strong> 메모리가 이해하는 <strong>물리 주소로 변환</strong>하는 장치
<em>➡️ <code>CPU</code>는 논리 주소로 이야기하는데, <code>메모리</code>가 물리 주소로 이야기한다면 <strong>서로 원활하게 통신하기 어렵기 때문</strong>이다.</em></p>
</li>
</ul>
<blockquote>
<h4 id="⚠️-중복-가능한-논리-주소의-번지수">⚠️ 중복 가능한 논리 주소의 번지수</h4>
<p>CPU와 프로세스가 사용하는 주소 체계는 물리 주소가 아니라 논리 주소이기 때문에 📍 <strong>중복되는 물리 주소의 번지수는 존재하지 않지만, 중복되는 논리 주소의 번지수는 얼마든지 존재할 수 있다.</strong></p>
</blockquote>
<h3 id="1-3-스와핑-swapping">1-3. 스와핑 (Swapping)</h3>
<p>메모리에 적재된 프로세스 중 <strong>현재 사용되지 않는 프로세스</strong>를 보조 기억 장치인 <strong>스와프 영역 (Swap Space)</strong>으로 내보내고, 그 빈 공간에 새 프로세스를 적재하는 메모리 관리 방식이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/ffb7a2d5-e651-4900-8574-daba895a005b/image.png" alt=""></p>
<ul>
<li><strong>스와프 아웃 (Swap Out):</strong> 사용되지 않는 <code>프로세스</code>를 <strong>메모리에서 스와프 영역으로</strong> 옮기는 작업</li>
<li><strong>스와프 인 (Swap In):</strong> 스와프 아웃되었던 <code>프로세스</code>가 <strong>다시 메모리로</strong> 돌아오는 작업</li>
</ul>
<blockquote>
<p><em>스와프 아웃 되었던 프로세스가 다시 스와프 인 될 때는 스와프 아웃 되기 전의 물리 주소와는 다른 주소에 적재될 수 있다.</em></p>
</blockquote>
<p>📍 <strong>그런데 만약 메모리 내 빈 공간이 여러 개라면 어디에 프로세스를 배치해야 할까?</strong></p>
<hr>
<h2 id="2-메모리-할당의-문제점">2. 메모리 할당의 문제점</h2>
<p>가상 메모리 기법이 등장하게 된 배경에는 <strong>기존의 메모리 할당 방식에서 발생하는 비효율적인 문제가 있었기 때문</strong>이다.</p>
<h3 id="2-1-연속-메모리-할당-contiguous-memory-allocation">2-1. 연속 메모리 할당 (Contiguous Memory Allocation)</h3>
<p>프로세스를 메모리에 <strong>연속적인</strong> 공간에 할당하는 방식이다.</p>
<img src="https://velog.velcdn.com/images/w_dw_r/post/64ef9bc0-07c3-4f3f-b73d-c6e40a49ef96/image.png" width="300" />

<p>언뜻 보기에는 당연하고 보편적인 방식이라고 느껴질 수 있지만, 사실 연속 메모리 할당은 메모리를 효율적으로 사용하는 방법은 아니다.</p>
<h3 id="2-2-외부-단편화-external-fragmentation">2-2. 외부 단편화 (External Fragmentation)</h3>
<p><strong>아래 그림과 같은 상황을 가정해 보자!</strong></p>
<img src="https://velog.velcdn.com/images/w_dw_r/post/91f11299-0143-4068-9f90-d6961bfc2a87/image.png" width="300"/>

<p>현재 이 <code>메모리</code>에 새로운 프로세스가 적재될 수 있는 <strong>빈 공간은 총 50MB</strong>이다.</p>
<p><strong>하지만</strong> 남아있는 빈 공간의 총합이 50MB라고 하더라도 <strong>크기가 50MB인 프로세스를 적재하는 것은 불가능하다.</strong></p>
<p><em>➡️ <code>메모리</code>에 남아있는 공간이 각각 <code>30MB</code>와 <code>20MB</code>으로 연속된 공간으로 존재하지 않고, 분산되어 있다.</em></p>
<h3 id="2-3-스와핑과-연속-메모리-할당이-내포하는-2가지-문제">2-3. 스와핑과 연속 메모리 할당이 내포하는 2가지 문제</h3>
<ul>
<li><strong>외부 단편화:</strong> 프로세스가 실행과 종료를 반복하며 프로세스 <strong>사이</strong>에 크고 작은 빈 공간이 생기고, 이 빈 공간들의 <strong>합</strong>은 충분하더라도 <code>하나의 큰 프로세스를 적재할 연속된 공간이 없어 메모리 낭비가 발생</code>하는 현상</li>
<li><strong>큰 프로그램 실행 불가:</strong> 프로그램이 메모리보다 크면 <code>연속적인 할당 공간을 찾을 수 없어 실행할 수 없다.</code></li>
</ul>
<hr>
<h2 id="3-가상-메모리의-주요-기법">3. 가상 메모리의 주요 기법</h2>
<p>외부 단편화 문제를 해결하고 메모리보다 큰 프로세스도 실행 가능하게 하는 가상 메모리의 대표적인 기법은 <strong>페이징</strong>과 <strong>세그먼테이션</strong>이다.</p>
<h3 id="3-1-페이징-paging">3-1. 페이징 (Paging)</h3>
<p><code>논리 주소 공간</code>을 <strong>일정한 크기</strong>의 <strong>페이지 (Page)</strong>로 나누고, <code>물리 주소 공간</code>을 페이지와 <strong>동일한 크기</strong>의 <strong>프레임 (Frame)</strong>으로 나누어 프로세스를 메모리에 할당하는 기법이다.</p>
<img src="https://velog.velcdn.com/images/w_dw_r/post/6aefece0-241a-438d-8814-55afd8384bf0/image.png" width="400"/>

<ul>
<li><p><strong>핵심 원리:</strong> 프로세스를 구성하는 페이지들을 <strong>물리 메모리 내부에 불연속적으로 배치</strong>할 수 있다.</p>
</li>
<li><p><strong>장점:</strong> 프로세스가 불연속적으로 배치될 수 있기 때문에 <strong>외부 단편화가 발생하지 않는다.</strong>
<em>➡️ 이로 인해 연속 메모리 할당처럼 <code>프로세스 바깥에 빈 공간이 생길 일이 없다.</code></em></p>
</li>
<li><p><strong>페이징에서의 스와핑:</strong> 페이징을 사용하는 시스템에서는 프로세스 전체가 아닌 <strong>페이지 단위</strong>로 스와프 인/아웃이 일어난다. <code>(페이지 아웃/인)</code></p>
</li>
</ul>
<blockquote>
<h4 id="📍-같은-프로세스를-이루는-페이지-중-일부만-페이지-아웃인이-된다면">📍 같은 프로세스를 이루는 페이지 중 일부만 페이지 아웃/인이 된다면?</h4>
</blockquote>
<img src="https://velog.velcdn.com/images/w_dw_r/post/a269e5fb-c451-4032-ba4c-793101cf1535/image.png" width="400"/>
>
➡️ 프로세스의 **일부**는 `메모리`에 적재되고, **일부**는 `보조 기억 장치`에 적재 되었다는 것을 의미한다.
>
이를 달리 말하면 **📍 프로세스를 실행하기 위해 전체 프로세스가 메모리에 적재될 필요는 없다**는 점을 시사한다.
>
CPU 입장에서 바라본 논리 메모리의 크기가 실제 메모리보다 클 수 있다는 것이다. **📍 페이징을 통해 물리 메모리보다 큰 크기의 프로세스 실행도 가능해진 것이다.**

<blockquote>
<h4 id="📍-불연속적-배치가-야기하는-또다른-문제">📍 불연속적 배치가 야기하는 또다른 문제</h4>
</blockquote>
<p>앞서 페이지는 물리 메모리 내에 불연속적으로 배치될 수 있다고 설명했다.</p>
<blockquote>
</blockquote>
<p>그런데, 물리 메모리 내에 페이지가 불연속적으로 배치되어 있다면, <strong><code>CPU</code> 입장에서는 다음으로 실행할 페이지의 위치를 찾기가 어렵다.</strong></p>
<blockquote>
</blockquote>
<p><code>CPU</code>가 프로세스를 이루는 <code>어떤 페이지</code>가 <code>어떤 프레임</code>에 <code>적재되어 있는지</code>를 <strong>모두 알고 있기는 어렵기 때문</strong>이다.</p>
<h4 id="1-페이지-테이블-page-table">1) 페이지 테이블 (Page Table)</h4>
<p><strong>프로세스의 페이지 번호</strong>와 해당 페이지가 실제 <strong>물리 메모리의 어느 프레임에 적재</strong>되었는지를 짝지어 기록하는 정보이다.</p>
<img src="https://velog.velcdn.com/images/w_dw_r/post/0fb3e748-db02-4d5f-96e4-ecae1fa402e7/image.png" width="500"/>

<ul>
<li><strong>역할:</strong> <code>CPU</code>가 논리 주소를 물리 주소로 변환하기 위해 <strong>페이지 테이블을 참조</strong>하여 페이지가 <code>실제 메모리의 어느 프레임에 위치하는지</code>를 찾는다.</li>
</ul>
<img src="https://velog.velcdn.com/images/w_dw_r/post/3fd42169-28e1-407f-806e-5c86cf597e3f/image.png" width="500"/>

<ul>
<li><strong>논리 주소 구성:</strong> 기본적으로 <strong><code>&lt;페이지 번호, 변위&gt;</code></strong> 형태로 이루어진다.<ul>
<li><strong>페이지 번호:</strong> 몇 번째 페이지에 접근하는지</li>
<li><strong>변위 (Offset):</strong> 페이지의 시작 번지로부터 얼마나 떨어져 있는지</li>
</ul>
</li>
</ul>
<blockquote>
<h4 id="📍-페이지-테이블의-위치를-가리키는-레지스터-ptbr">📍 페이지 테이블의 위치를 가리키는 레지스터 (PTBR)</h4>
<p>각 프로세스의 페이지 테이블은 메모리에 적재되어 있으며, 운영체제는 이 페이지 테이블의 위치를 관리해야 한다.</p>
<p><strong>PTBR (Page Table Base Register):</strong> 특정 프로세스의 페이지 테이블이 <strong>메모리에 적재된 시작 위치 (베이스 주소)</strong>를 가리키는 특별한 레지스터이다.</p>
</blockquote>
<image src="https://velog.velcdn.com/images/w_dw_r/post/9b832558-dab0-4c9d-9782-64dd197462c4/image.png" width=500/>
>
> * **관리:** PTBR은 프로세스마다 가지는 정보이므로 각 `PCB (Process Control Block)`에 기록된다.
> * **업데이트:** 다른 프로세스로의 `문맥 교환 (Context Switching)`이 발생할 때, 새로 실행될 프로세스의 PCB에서 PTBR 정보를 불러와 `변경`된다.

<blockquote>
<h4 id="q-cpu가-논리-주소-52에-접근한다면-실제로-cpu가-접근하게-될-물리-주소는">Q. CPU가 논리 주소 &lt;5,2&gt;에 접근한다면 실제로 CPU가 접근하게 될 물리 주소는?</h4>
</blockquote>
<img src="https://velog.velcdn.com/images/w_dw_r/post/4f0123d8-56aa-47d0-a307-b09b6db7a01e/image.png" width="500"/>
> 위의 `페이지 테이블`에서 현재 **5번 페이지는 1번 프레임에** 있다.
> 따라서 `CPU`는 **1번 프레임, 변위 2에 접근**하게 된다.
>
_➡️ 1번 프레임은 물리 주소 공간의 **8번지부터 시작**하므로 결국 `CPU`는 **10번지에 접근**하게 되는 것이다._

<h4 id="2-페이지-테이블-엔트리-pte">2) 페이지 테이블 엔트리 (PTE)</h4>
<p><strong>페이지 테이블의 각 행</strong>을 뜻하며, <code>페이지 번호</code>와 <code>프레임 번호</code> 외에 <code>제어 정보</code>를 포함한다.</p>
<img src="https://velog.velcdn.com/images/w_dw_r/post/7803db9e-c7c1-4c96-b52b-522ed71ff35d/image.png" width="600"/>

<table>
<thead>
<tr>
<th align="center">비트 명칭</th>
<th align="left">설명</th>
<th align="left">발생 가능한 문제</th>
<th align="left">발생 원인</th>
<th align="left">해결 방법</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>유효 비트<br>(Valid Bit)</strong></td>
<td align="left">현재 페이지가 메모리에 적재되어 있는지 (1),<br>아니면 보조 기억 장치에 있는지 (0)를 알려주는 비트이다.</td>
<td align="left"><strong>페이지 폴트 (page fault):</strong> CPU가 메모리에 적재되지 않은 페이지, 즉 <strong>유효 비트가 0인 페이지에 접근</strong>하려고 하면 발생하는 예외</td>
<td align="left"><strong>CPU는 보조 기억 장치에 저장된 페이지에 곧장 접근할 수 없다.</strong> 보조 기억 장치 속 페이지를 메모리로 적재한 뒤에 접근해야 한다.</td>
<td align="left">① 기존 작업 내역을 <strong>백업</strong>한다.<br>② 페이지 폴트 처리 루틴을 실행한다.<br><strong>(원하는 페이지를 메모리로 가져와 유효 비트를 1로 변경해 주는 작업)</strong><br>③ 페이지 폴트 처리 루틴 실행 후, 메모리에 적재된 <strong>페이지를 실행</strong>한다.</td>
</tr>
<tr>
<td align="center"><strong>보호 비트<br>(Protection Bit)</strong></td>
<td align="left">페이지에 대한 접근 권한 (읽기 <code>r</code>, 쓰기 <code>w</code>, 실행 <code>x</code>)을 알려준다.</td>
<td align="left">-</td>
<td align="left">-</td>
<td align="left">-</td>
</tr>
<tr>
<td align="center"><strong>참조 비트<br>(Reference Bit)</strong></td>
<td align="left">해당 페이지에 접근한 적이 있는지 여부를 나타낸다.<br>적재된 후 CPU가 건드렸다면 1로 설정된다.</td>
<td align="left">-</td>
<td align="left">-</td>
<td align="left">-</td>
</tr>
<tr>
<td align="center"><strong>수정 비트<br>(Modified/Dirty Bit)</strong></td>
<td align="left">해당 페이지의 데이터가 메모리에서 수정된 적이 있는지 여부를 알려준다.<br>1이면 수정된 페이지, 0이면 수정되지 않은 페이지이다.</td>
<td align="left">-</td>
<td align="left">-</td>
<td align="left">-</td>
</tr>
</tbody></table>
<h4 id="3-페이징이-야기하는-문제-1️⃣---내부-단편화-internal-fragmentation">3) 페이징이 야기하는 문제 1️⃣ - 내부 단편화 (Internal Fragmentation)</h4>
<p>페이징은 프로세스의 논리 주소 공간을 <strong>일정한 크기의 페이지</strong> 단위로 나누는 방식이다. 하지만 프로세스의 크기가 페이지 크기의 <strong>정확한 배수가 아닐 경우</strong> 문제가 발생한다.</p>
<image src="https://velog.velcdn.com/images/w_dw_r/post/9dc86db5-33cb-473c-b92e-a8bd80697e1d/image.png" width=500/>

<ul>
<li><strong>원인:</strong> 프로세스의 마지막 페이지가 페이지 크기보다 작을 경우, 그 페이지가 할당되는 <strong>프레임 전체</strong>는 해당 프로세스에게 배정되지만, 실제로 사용되는 공간은 페이지 크기보다 작아 남는 공간이 발생한다.</li>
<li><strong>결과:</strong> 이처럼 <strong>할당된 공간 내부</strong>에 사용되지 않고 남는 메모리 조각이 생기는 것을 <strong>내부 단편화</strong>라고 한다.</li>
<li><strong>예시:</strong> 페이지 크기가 10KB인데 프로세스의 크기가 107KB인 경우, 마지막 페이지는 7KB만 사용하고 3KB의 메모리가 낭비된다.</li>
</ul>
<blockquote>
<p>📍 <strong>페이지 크기</strong>는 내부 단편화와 반비례한다. 페이지 크기가 작을수록 내부 단편화도 줄어든다.</p>
</blockquote>
<h4 id="4-페이징이-야기하는-문제-2️⃣---메모리-접근-횟수-문제-tlb-miss">4) 페이징이 야기하는 문제 2️⃣ - 메모리 접근 횟수 문제 (TLB Miss)</h4>
<p>CPU가 메모리에 접근할 때 <strong>페이지 테이블</strong>을 참조해야 하므로 메모리 접근 횟수가 증가하는 문제가 발생한다.</p>
<blockquote>
<h4 id="메모리-접근-횟수-증가-원리">메모리 접근 횟수 증가 원리</h4>
<p>CPU가 메모리에 접근할 때 <strong>페이지 테이블</strong>을 참조해야 하기 때문에, 메모리 접근 횟수가 증가하는 문제가 발생한다.</p>
<p>⬇️ CPU가 논리 주소를 물리 주소로 변환하기 위해 필요한 단계</p>
<p>① <strong>페이지 테이블 접근:</strong> 페이지 테이블에서 페이지 번호에 해당하는 프레임 번호를 찾기 위해 <code>메모리에 접근</code>한다.
② <strong>실제 데이터 접근:</strong> 찾아낸 프레임 번지를 이용해 실제 데이터에 접근하기 위해 <code>메모리에 다시 접근</code>한다.
📍 <strong>결과:</strong> 메모리 접근 횟수가 <code>두 배</code>로 늘어나 <strong>성능이 저하</strong>된다.</p>
</blockquote>
<h4 id="📍-tlb-translation-look-aside-buffer">📍 TLB (Translation Look-Aside Buffer)</h4>
<p>이 문제를 해결하기 위해 도입된 것이 <strong>TLB</strong>이다. TLB는 <strong>페이지 테이블의 캐시 메모리</strong>로, 최근에 자주 사용된 참조 영역의 내용을 저장한다.</p>
<image src="https://velog.velcdn.com/images/w_dw_r/post/2873930c-f507-4517-9043-1312738e2506/image.png" width=500/>

<ul>
<li><strong>TLB 히트 (TLB Hit):</strong> CPU가 요청한 <code>페이지 번호가 TLB에 있는 경우</code>를 말한다. 이 경우 TLB에서 곧바로 프레임 번호를 알 수 있어 <strong>한 번만 메모리에 접근</strong>하면 된다.</li>
<li><strong>TLB 미스 (TLB Miss):</strong> CPU가 요청한 <code>페이지 번호가 TLB에 없는 경우</code>를 말한다. 이 경우 TLB를 통해 프레임 번호를 알 수 없으므로, 결국 메모리 내의 페이지 테이블에 접근해야 한다. TLB 미스 시에는 <strong>추가적인 메모리 접근이 필요</strong>하다.</li>
</ul>
<h4 id="5-페이징이-야기하는-문제-3️⃣---메모리-용량-문제-페이지-테이블-크기">5) 페이징이 야기하는 문제 3️⃣ - 메모리 용량 문제 (페이지 테이블 크기)</h4>
<p>프로세스의 크기가 커질수록 해당 프로세스의 <strong>페이지 테이블</strong> 크기 또한 <code>커지게 된다.</code></p>
<p>페이지 테이블 전체를 메모리에 적재하는 것은 <strong>큰 메모리 낭비</strong>로 이어진다.</p>
<h4 id="📍-계층적-페이징-hierarchical-paging">📍 계층적 페이징 (Hierarchical Paging)</h4>
<p><strong>페이지 테이블을 나누어</strong> 메모리 낭비를 줄이는 기법이다.</p>
<image src ="https://velog.velcdn.com/images/w_dw_r/post/03c4e573-9648-4bd8-831b-9a4128cca3a0/image.png" width=300/>

<ul>
<li><strong>원리:</strong> 페이지 테이블을 <strong>페이지처럼 나누어</strong> 여러 단계의 페이지를 두는 방식이다.</li>
<li><strong>구조:</strong> 페이지 테이블을 <strong>Outer 페이지 테이블</strong>과 <strong>Inner 페이지 테이블</strong> 등으로 계층화하여 구성한다.<ul>
<li><strong>Outer 페이지 테이블:</strong> CPU와 가까운 쪽에 위치하며, <strong>항상</strong> 메모리에 유지된다.</li>
<li><strong>Inner 페이지 테이블 (장기 페이지 테이블):</strong> Outer 페이지 테이블의 엔트리가 가리키는 페이지 테이블로, <strong>전체</strong>가 메모리에 유지될 필요는 없다. 자주 사용되지 않는 Inner 페이지 테이블의 일부는 <code>보조 기억 장치</code>에 둘 수 있다.</li>
</ul>
</li>
<li><strong>장점:</strong> 페이지 테이블 전체를 메모리에 유지할 필요가 없어 메모리 용량을 절약할 수 있다.</li>
</ul>
<h3 id="3-2-세그먼테이션-segmentation">3-2. 세그먼테이션 (Segmentation)</h3>
<p>페이징이 일정한 크기의 페이지로 나누는 반면, 세그먼테이션은 코드를 이루는 <strong>의미 있는 논리적 단위</strong>인 <strong>세그먼트 (Segment)</strong>로 프로세스를 나누어 메모리에 할당하는 기법이다.</p>
<image src="https://velog.velcdn.com/images/w_dw_r/post/55cac885-360d-4f33-aada-08137ec59bea/image.png" width=400/>

<ul>
<li><strong>세그먼트 예시:</strong> 코드 영역, 데이터 영역, 스택 영역 등</li>
<li><strong>특징:</strong> 세그먼트의 크기는 <strong>가변적</strong>이다.</li>
<li><strong>단점:</strong> 세그먼트의 크기가 일정하지 않기 때문에 <strong>외부 단편화가 발생</strong>할 수 있다.</li>
</ul>
<h3 id="3-3-요구-페이징-demand-paging">3-3. 요구 페이징 (Demand Paging)</h3>
<p>프로세스를 구성하는 <strong>모든 페이지를 메모리에 적재하지 않고</strong>, 실제로 CPU가 <strong>요구하는 (필요로 하는)</strong> 페이지들만 메모리에 적재하는 기법이다.</p>
<ul>
<li><strong>페이지 폴트 (Page Fault):</strong> CPU가 특정 페이지에 접근하라는 명령을 내렸는데, 해당 페이지가 <strong>현재 메모리에 없는 경우 (유효 비트=0)</strong> 발생하는 예외<ul>
<li><strong>처리 과정:</strong> 페이지 폴트가 발생하면, 페이지 폴트 처리 루틴이 해당 페이지를 보조 기억 장치에서 메모리로 가져와 적재하고 유효 비트를 <strong>1</strong>로 변경한 후, 메모리에 적재된 프로세스를 다시 실행한다.</li>
</ul>
</li>
<li><strong>장점:</strong> 필요한 페이지만 메모리에 올리므로, 물리 메모리보다 훨씬 큰 프로세스를 실행할 수 있게 되고, 시스템의 <strong>다중 프로그래밍 정도(Multiprogramming Degree)</strong>를 높일 수 있다.</li>
</ul>
<h4 id="1-📍-페이지-교체-알고리즘-page-replacement-algorithm">1) 📍 페이지 교체 알고리즘 (Page Replacement Algorithm)</h4>
<p>메모리가 가득 찬 상태에서 새로운 페이지를 적재해야 할 때, 메모리에서 내보낼 페이지(스와프 아웃)를 선택하는 알고리즘이다.</p>
<ul>
<li><strong>FIFO (First-In, First-Out):</strong> 메모리에 <strong>가장 먼저 적재된</strong> 페이지를 스와프 아웃한다.</li>
<li><strong>OPT (Optimal Page Replacement):</strong> 앞으로 <strong>가장 오랫동안 사용되지 않을</strong> 페이지를 스와프 아웃한다. <code>*최적의 알고리즘이지만, 미래 예측이 불가능하여 실제 구현은 어렵다.</code></li>
<li><strong>LRU (Least Recently Used):</strong> <strong>가장 오랫동안 사용하지 않은</strong> 페이지를 스와프 아웃한다. (페이지 교체 알고리즘의 원형이다)</li>
</ul>
<h4 id="2-스레싱-thrashing">2) 스레싱 (Thrashing)</h4>
<ul>
<li><strong>스레싱 (Thrashing):</strong> 페이지 교체가 너무 빈번하게 발생하여 CPU가 실제 작업보다 페이지 폴트 처리에 더 많은 시간을 보내 성능이 저하되는 문제이다.</li>
</ul>
<hr>
<blockquote>
<h4 id="참고하면-좋은-블로그">참고하면 좋은 블로그</h4>
</blockquote>
<ul>
<li>페이징①: <a href="https://charles098.tistory.com/106">https://charles098.tistory.com/106</a></li>
<li>페이징②: <a href="https://ddongwon.tistory.com/49">https://ddongwon.tistory.com/49</a></li>
<li>페이지 교체 알고리즘①: <a href="https://rob-coding.tistory.com/37">https://rob-coding.tistory.com/37</a></li>
<li>페이지 교체 알고리즘②: <a href="https://wishlee0204.tistory.com/335">https://wishlee0204.tistory.com/335</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 03-3 동기화와 교착 상태(공유 자원, 임계 구역, 경쟁 상태, 동기화)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-03-3-%EB%8F%99%EA%B8%B0%ED%99%94%EC%99%80-%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C%EA%B3%B5%EC%9C%A0-%EC%9E%90%EC%9B%90-%EC%9E%84%EA%B3%84-%EA%B5%AC%EC%97%AD-%EA%B2%BD%EC%9F%81-%EC%83%81%ED%83%9C-%EB%8F%99%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-03-3-%EB%8F%99%EA%B8%B0%ED%99%94%EC%99%80-%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C%EA%B3%B5%EC%9C%A0-%EC%9E%90%EC%9B%90-%EC%9E%84%EA%B3%84-%EA%B5%AC%EC%97%AD-%EA%B2%BD%EC%9F%81-%EC%83%81%ED%83%9C-%EB%8F%99%EA%B8%B0%ED%99%94</guid>
            <pubDate>Thu, 27 Nov 2025 08:12:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 공유 자원과 임계 구역: 경쟁 상태
② 동기화: 동기화의 목적, 기법
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<h2 id="1-공유-자원와-임계-구역">1. 공유 자원와 임계 구역</h2>
<h3 id="1-1-공유-자원-shared-resource">1-1. 공유 자원 (Shared Resource)</h3>
<p><strong>프로세스 혹은 스레드가 공유하는 자원</strong>이다.</p>
<p>공유 자원은 <code>메모리</code>나 <code>파일</code>이 될 수도 있고, <code>전역 변수</code>나 <code>입출력장치</code>가 될 수도 있다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/4ca1ae7a-6fc8-429b-96a1-9a268ae05d8c/image.png" alt=""></p>
<p><em>➡️ 공유 자원을 두고 동시다발적으로 실행되는 다수의 프로세스 혹은 스레드가 마구잡이로 실행되면 문제가 발생할 수도 있다.</em></p>
<h3 id="1-2-임계-구역-critical-section">1-2. 임계 구역 (Critical Section)</h3>
<p><code>공유 자원에 접근하는 코드</code> 중 <strong>동시에 실행했을 때 문제가 발생할 수 있는 코드 영역</strong>을 의미한다.</p>
<p><em>➡️ 동시에 실행되는 프로세스나 스레드가 동시에 <strong>임계 구역에 진입하여 실행</strong>되면 문제가 발생할 수 있다.</em></p>
<h3 id="1-3-경쟁-상태-race-condition">1-3. 경쟁 상태 (Race Condition)</h3>
<p>임계 구역에 대한 동시 접근 시, <strong>실행 순서에 따라 최종 결과가 달라져 데이터의 일관성이 깨지거나 손상될 수 있는 상황</strong>을 말한다.</p>
<h4 id="⚠️-순차-실행과-제어권-전환의-함정">⚠️ 순차 실행과 제어권 전환의 함정</h4>
<ul>
<li><p><strong>📍단일 CPU 환경</strong>에서는 <strong>멀티 프로세스와 멀티 스레드 모두 물리적으로 동시에 실행되지 않는다.</strong></p>
</li>
<li><p>대신, 운영체제는 CPU 제어권을 계속해서 <strong>전환(Context Switching)</strong>하며 <strong>📍순차적으로 번갈아 가며 실행한다.</strong></p>
</li>
<li><p>이 제어권 전환이 임계 구역 작업의 중간에 발생하면서 <strong>데이터 유실, 데이터 불일치 같은 문제를 야기</strong>한다.</p>
</li>
</ul>
<blockquote>
<h4 id="🚨-주의사항">🚨 주의사항</h4>
<p>아래 그림들은 경쟁 상태(Race Condition)의 원리를 설명하고자 만들어진 <code>논리적/개념적 자료</code>이기 때문에, <strong>📍 실행 시간과 흐름으로 물리적으로 받아들이면 안 된다!</strong></p>
</blockquote>
<h4 id="1-멀티프로세스의-경우---실행-순서-제어-동기화-필요">1) 멀티프로세스의 경우 - 실행 순서 제어 동기화 필요</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/4f3cefa0-a7af-4b27-bae8-4e9536167cf3/image.png" alt=""></p>
<p>해당 그림은 <strong>문맥 교환으로 인해 프로세스 간의 공유 자원 접근 순서가 엇갈리면서 데이터 불일치가 발생</strong>하는 <code>경쟁 상태(Race Condition)</code>를 보여준다.</p>
<p><em>➡️ 예시처럼 제어권 전환이 임계 구역 작업 중간에 발생하면 <strong>의도치 않은 데이터 접근이나 결과 불일치가 발생</strong>한다.</em></p>
<blockquote>
<h4 id="문맥-교환context-switching">문맥 교환(Context Switching)</h4>
</blockquote>
<ul>
<li>운영체제가 하나의 CPU에서 여러 프로세스 또는 스레드를 번갈아 가며 실행하기 위해 현재 실행 중인 프로세스의 상태를 저장하고, 다음에 실행할 프로세스의 상태를 불러오는 작업</li>
<li>CPU가 하나뿐인 환경에서 <strong>멀티태스킹(Multitasking)</strong>을 구현하는 핵심 원리</li>
</ul>
<h4 id="2-멀티스레드의-경우---실행-순서-동기화-필요-확장-버전">2) 멀티스레드의 경우 - 실행 순서 동기화 필요 확장 버전</h4>
<p><strong>각 스레드들이 파일을 수정하는 과정</strong>은 <code>읽기, 계산, 쓰기</code>의 세 단계로 쪼개진다:</p>
<p>❶ 파일을 읽어 들이고 <strong>(읽기)</strong>
❷ 원하는 내용을 작성한 뒤 <strong>(계산)</strong>
❸ 작성한 내용을 저장한다 <strong>(쓰기)</strong></p>
<p><em>➡️ 이 단계들이 엇갈리면 다음과 같이 데이터가 훼손된다.</em>
<img src="https://velog.velcdn.com/images/w_dw_r/post/fc8ee31a-2544-4cda-bbef-a7db7d4f3617/image.png" alt=""></p>
<p>그런데, 다음과 같이 스레드 <strong>A와 B가 동시에 수행될 경우, 스레드 A의 작업 내역은 반영되지 않을 수 있다.</strong></p>
<ul>
<li><strong>최종 결과:</strong> 최종적으로 파일에는 스레드 B가 저장한 <code>&quot;first thread B&quot;</code>만 남게 된다.</li>
<li><strong>유실된 데이터:</strong> 스레드 A가 저장했던 <code>&quot;first thread A&quot;</code>는 스레드 B의 저장 작업에 의해 <strong>덮어씌워져 유실</strong>된다.</li>
</ul>
<h4 id="q-왜-이런-현상이-일어날까">Q. 왜 이런 현상이 일어날까?</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/c92611f0-8f57-4732-9fc1-0e3015794ff4/image.png" alt=""></p>
<h4 id="동작-원리">동작 원리</h4>
<table>
<thead>
<tr>
<th align="center">순서 (시간 흐름)</th>
<th align="center">스레드 주체</th>
<th align="left">동작</th>
<th align="center">스레드 A 버퍼</th>
<th align="center">스레드 B 버퍼</th>
<th align="center">공유 파일 내용</th>
<th align="left">결과 및 설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>시작</strong></td>
<td align="center">-</td>
<td align="left">초기 상태</td>
<td align="center"><code>first</code></td>
<td align="center"><code>first</code></td>
<td align="center"><code>first</code></td>
<td align="left">파일의 초기 내용은 <code>&quot;first&quot;</code>이다.</td>
</tr>
<tr>
<td align="center"><strong>1</strong></td>
<td align="center"><strong>A</strong></td>
<td align="left"><strong>① 파일 읽기</strong></td>
<td align="center"><code>first</code></td>
<td align="center">-</td>
<td align="center"><code>first</code></td>
<td align="left">A가 공유 파일을 읽어 자신의 <strong>버퍼</strong>로 가져온다.</td>
</tr>
<tr>
<td align="center"><strong>2</strong></td>
<td align="center"><strong>A</strong></td>
<td align="left"><strong>② 파일 쓰기</strong> <br>(계산)</td>
<td align="center"><code>first thread A</code></td>
<td align="center">-</td>
<td align="center"><code>first</code></td>
<td align="left">A가 가져온 내용을 <strong><code>&quot;first thread A&quot;</code></strong>로 수정한다. <br>(공유 파일에 직접 반영되지 않음)</td>
</tr>
<tr>
<td align="center"><strong>3</strong></td>
<td align="center"><strong>B</strong></td>
<td align="left"><strong>① 파일 읽기</strong></td>
<td align="center"><code>first thread A</code></td>
<td align="center"><code>first</code></td>
<td align="center"><code>first</code></td>
<td align="left"><strong>[문맥 교환 발생]</strong> B가 실행된다. B가 공유 파일(<code>&quot;first&quot;</code>)을 읽어 자신의 버퍼로 가져온다.</td>
</tr>
<tr>
<td align="center"><strong>4</strong></td>
<td align="center"><strong>B</strong></td>
<td align="left"><strong>② 파일 쓰기</strong> <br>(계산)</td>
<td align="center"><code>first thread A</code></td>
<td align="center"><code>first thread B</code></td>
<td align="center"><code>first</code></td>
<td align="left">B가 가져온 내용을 <strong><code>&quot;first thread B&quot;</code></strong>로 수정한다.</td>
</tr>
<tr>
<td align="center"><strong>5</strong></td>
<td align="center"><strong>A</strong></td>
<td align="left"><strong>③ 파일 저장</strong></td>
<td align="center"><code>first thread A</code></td>
<td align="center"><code>first thread B</code></td>
<td align="center"><code>first thread A</code></td>
<td align="left"><strong>[문맥 교환 발생]</strong> A가 다시 실행된다. A가 자신의 버퍼 내용(<code>&quot;first thread A&quot;</code>)을 <strong>공유 파일에 저장</strong>한다.</td>
</tr>
<tr>
<td align="center"><strong>6</strong></td>
<td align="center"><strong>B</strong></td>
<td align="left"><strong>③ 파일 저장</strong></td>
<td align="center"><code>first thread A</code></td>
<td align="center"><code>first thread B</code></td>
<td align="center"><code>first thread B</code></td>
<td align="left"><strong>[문맥 교환 발생]</strong> B가 다시 실행된다. B가 자신의 버퍼 내용(<code>&quot;first thread B&quot;</code>)을 <strong>공유 파일에 저장</strong>한다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>원인:</strong> 스레드 A가 <strong>읽기-계산-쓰기</strong>의 세 단계를 <strong>원자적(Atomic)</strong>으로 완료하기 전에 <strong>문맥 교환</strong>이 발생하여 스레드 B가 A의 중간 과정을 무시한 채 작업했기 때문이다.</li>
<li><strong>해결:</strong> 이 세 단계를 <strong>임계 구역</strong>으로 지정하고, <strong>뮤텍스</strong>나 <strong>세마포어</strong> 같은 <strong>동기화 기법</strong>을 사용하여 한 번에 하나의 스레드만 접근하도록 <strong>상호 배제</strong>를 적용해야 한다.</li>
</ul>
<blockquote>
<h4 id="🚨-주의사항-1">🚨 주의사항</h4>
<p>166쪽 파일 수정 예시는 <code>책에서는 실행 순서 제어가 필요하다고 분류</code>하지만, <code>근본적으로는 파일 수정 임계 구역에 대한 상호 배제가 가장 확실한 해결책이다.</code></p>
</blockquote>
<h4 id="3-자바-코드로-살펴보는-경쟁-상태---상호-배제-동기화-필요">3) 자바 코드로 살펴보는 경쟁 상태 - 상호 배제 동기화 필요</h4>
<pre><code>public class Race {

    // 0. 공유 데이터 (초기값 0)
    static int sharedData = 0;

    // 1. Increment 스레드: 공유 데이터를 100,000번 증가시킴
    static class Increment implements Runnable {
        public void run() {
            for (int i = 0; i &lt; 100000; i++) {
                // sharedData++ 는 &#39;읽기-계산-쓰기&#39; 3단계로 이루어져 원자성이 보장되지 않음
                sharedData++; // 공유 데이터 증가
            }
        }
    }

    // 2. Decrement 스레드: 공유 데이터를 100,000번 감소시킴
    static class Decrement implements Runnable {
        public void run() {
            for (int i = 0; i &lt; 100000; i++) {
                // sharedData-- 또한 원자성이 보장되지 않음
                sharedData--; // 공유 데이터 감소
            }
        }
    }

    public static void main(String[] args) {
        // Increment 작업을 수행하는 스레드 생성
        Thread thread1 = new Thread(new Increment());
        // Decrement 작업을 수행하는 스레드 생성
        Thread thread2 = new Thread(new Decrement());

        // 두 스레드 시작
        thread1.start(); // 첫 번째 스레드 시작
        thread2.start(); // 두 번째 스레드 시작

        try {
            // 메인 스레드는 두 스레드가 작업을 완료할 때까지 대기
            thread1.join(); // 첫 번째 스레드 종료 대기
            thread2.join(); // 두 번째 스레드 종료 대기
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 최종 공유 데이터 값 출력 (예상값은 0이지만, 경쟁 상태로 인해 다른 값이 나옴)
        System.out.println(&quot;Final value of sharedData: &quot; + sharedData);
    }
}</code></pre><p>이 코드에서 <code>0</code>이 출력될 것을 기대할 수 있지만, <strong>실제로는 아래와 같이 일정하지 않은 결과가 도출</strong>되는 것을 확인할 수 있다.</p>
<blockquote>
<h4 id="출력-결과">출력 결과</h4>
</blockquote>
<pre><code>$ java Race
Final value of sharedData: -3394
$ java Race
Final value of sharedData: -3457
$ java Race
Final value of sharedData: 1848</code></pre><blockquote>
</blockquote>
<p>_➡️ 레이스 컨디션(경쟁 상태) 발생 _</p>
<h4 id="q-왜-이런-현상이-일어날까-1">Q. 왜 이런 현상이 일어날까?</h4>
<h4 id="1-레이스-컨디션이-발생하지-않았다면">1) 레이스 컨디션이 발생하지 않았다면</h4>
<ul>
<li><strong>스레드 1 (<code>Increment</code>)</strong>: <code>sharedData++</code> 연산을 <strong>100,000번</strong> 수행한다.<ul>
<li>총 증가량: $+100,000$</li>
</ul>
</li>
<li><strong>스레드 2 (<code>Decrement</code>)</strong>: <code>sharedData--</code> 연산을 <strong>100,000번</strong> 수행한다.<ul>
<li>총 감소량: $-100,000$</li>
</ul>
</li>
</ul>
<p><code>sharedData</code> 변수의 초기값은 $0$ 이다.</p>
<p>$$
\text{최종 값} = \text{초기값} + \text{총 증가량} + \text{총 감소량}
$$</p>
<p>$$
\text{최종 값} = 0 + (+100,000) + (-100,000) = 0
$$</p>
<p>논리적으로나 수학적으로, 100,000번의 $+1$ 연산과 100,000번의 $-1$ 연산이 어떤 순서로든 수행되더라도 <strong>최종 결과는 반드시 $0$이 되어야 한다.</strong></p>
<h4 id="2-1-레이스-컨디션이-발생했다면">2-1) 레이스 컨디션이 발생했다면</h4>
<p>사실 이 코드는 스레드 A가 값을 <strong>읽고 저장하기 직전</strong>에 문맥 교환이 일어나 <strong>B의 감소 작업이 유실</strong>되는 경우를 보여준다.</p>
<ul>
<li><strong>공유 자원:</strong> <code>sharedData</code> (초기값: 0)</li>
<li><strong>스레드 A 목표:</strong> <code>sharedData++</code> (읽기 $\to$ +1 계산 $\to$ 쓰기)</li>
<li><strong>스레드 B 목표:</strong> <code>sharedData--</code> (읽기 $\to$ -1 계산 $\to$ 쓰기)</li>
</ul>
<table>
<thead>
<tr>
<th align="center">순서 (T)</th>
<th align="center">스레드 A (++ 실행)</th>
<th align="center">스레드 B (-- 실행)</th>
<th align="center"><code>sharedData</code> 값</th>
<th align="left">결과 및 설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>시작</strong></td>
<td align="center">-</td>
<td align="center">-</td>
<td align="center">0</td>
<td align="left">초기 상태: <code>sharedData</code>는 0이다.</td>
</tr>
<tr>
<td align="center"><strong>1</strong></td>
<td align="center"><strong>읽기:</strong> 0을 레지스터에 복사</td>
<td align="center">-</td>
<td align="center">0</td>
<td align="left">A가 현재 값 <code>0</code>을 읽어 레지스터에 복사한다. <br>(A는 0을 1로 만들 준비)</td>
</tr>
<tr>
<td align="center"><strong>2</strong></td>
<td align="center"><strong>계산:</strong> 레지스터 값 <code>1</code>로 수정</td>
<td align="center">-</td>
<td align="center">0</td>
<td align="left">A가 레지스터 값을 1로 계산한다. 아직 공유 변수에는 저장되지 않았다.</td>
</tr>
<tr>
<td align="center"><strong>3</strong></td>
<td align="center">-</td>
<td align="center"><strong>[문맥 교환] 읽기:</strong> 0을 레지스터에 복사</td>
<td align="center">0</td>
<td align="left"><strong>[문맥 교환 발생]</strong> B가 실행된다. B는 공유 변수에서 <strong>아직 0인 값</strong>을 가져온다. <br>(A의 1을 모름)</td>
</tr>
<tr>
<td align="center"><strong>4</strong></td>
<td align="center">-</td>
<td align="center"><strong>계산:</strong> 레지스터 값 -1로 수정</td>
<td align="center">0</td>
<td align="left">B가 레지스터 값을 -1로 계산한다.</td>
</tr>
<tr>
<td align="center"><strong>5</strong></td>
<td align="center"><strong>[문맥 교환] 쓰기:</strong> 레지스터 값 1을 저장</td>
<td align="center">-</td>
<td align="center"><strong>1</strong></td>
<td align="left"><strong>[문맥 교환 발생]</strong> A가 다시 실행된다. A가 자신의 로컬 값 <strong>1</strong>을 <code>sharedData</code>에 저장한다.</td>
</tr>
<tr>
<td align="center"><strong>6</strong></td>
<td align="center">-</td>
<td align="center"><strong>쓰기:</strong> 레지스터 값 -1을 저장</td>
<td align="center"><strong>-1</strong></td>
<td align="left">B가 실행을 재개하여 자신의 로컬 값 <strong>-1</strong>을 저장한다.</td>
</tr>
<tr>
<td align="center"><strong>7</strong></td>
<td align="center"><strong>쓰기:</strong> 레지스터 값 1을 저장</td>
<td align="center">-</td>
<td align="center"><strong>1</strong></td>
<td align="left">A가 실행을 재개하여 자신의 로컬 값 <strong>1</strong>을 저장한다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>참고:</strong> 위 표는 경쟁 상태를 설명하기 위한 가상의 시나리오이며, 실제로는 <strong>OS의 스케줄링</strong>에 따라 무수히 많은 순서가 가능하다.</li>
</ul>
<blockquote>
<p>두 스레드가 모두 100,000번의 증감 연산을 수행했으므로 최종적으로 0이 되어야 하지만, <code>경쟁 상태 때문에 다음과 같은 상황이 반복되어 최종 결과가 0에서 크게 벗어난다.</code></p>
<p>결국 <strong>10만 번의 반복</strong> 중 문맥 교환으로 인해 유실된 <strong>증가 연산</strong>과 <strong>감소 연산</strong>의 개수 차이만큼 최종 값이 0에서 벗어나게 되어, 실행할 때마다 <code>1848</code>, <code>-3394</code> 등 <strong>일정하지 않은 결과가 도출</strong>되는 것이다.</p>
</blockquote>
<h4 id="2-2-레이스-컨디션을-유발한-코드는-어느-부분일까">2-2) 레이스 컨디션을 유발한 코드는 어느 부분일까?</h4>
<pre><code>// Increment 스레드의 run() 메서드 내부
for (int i = 0; i &lt; 100000; i++) {
    📍 sharedData++; // &lt;-- 💥 여기가 임계 구역
    // 공유 데이터 증가
}

// Decrement 스레드의 run() 메서드 내부
for (int i = 0; i &lt; 100000; i++) {
    📍 sharedData--; // &lt;-- 💥 여기가 임계 구역
    // 공유 데이터 감소
}</code></pre><p>위의 자바 코드에서 <strong>임계 구역(Critical Section)</strong>에 해당하는 코드는 공유 변수 sharedData에 접근하여 증가/감소 연산을 수행하는 부분이다.</p>
<p><code>*임계구역: 공유 자원에 접근하는 코드 중 동시에 실행했을 때 문제가 발생할 수 있는 코드 영역</code></p>
<h2 id="2-동기화">2. 동기화</h2>
<h3 id="2-1-동기화의-목적">2-1. 동기화의 목적</h3>
<p>레이스 컨디션을 방지하면서 <strong>임계 구역을 관리</strong>하기 위해서는 프로세스와 스레드가 <strong>동기화</strong> 되어야 한다. </p>
<p>프로세스 혹은 스레드의 동기화란 다음의 <strong>2가지 조건을 준수하며 실행</strong>하는 것을 의미한다.</p>
<pre><code>동기화의 종류
 ├── 실행 순서 제어를 위한 동기화
 └── 상호 배제를 위한 동기화      </code></pre><ul>
<li><strong>실행 순서 제어</strong>: 프로세스 및 스레드를 올바른 순서로 실행하기</li>
<li><strong>상호 배제</strong>: 동시에 접근해서는 안 되는 자원에 하나의 프로세스 및 스레드만 접근하기</li>
</ul>
<blockquote>
<h4 id="추가-설명">추가 설명</h4>
</blockquote>
<ul>
<li><code>166p 멀티프로세스 예시</code>에서 발생했던 레이스 컨디션의 문제는 <strong>프로세스들이 공유 자원을 두고 올바른 순서로 실행되지 않았던 것이 원인</strong>
(실행 순서 제어를 위한 동기화가 필요한 경우)</li>
<li><code>166p 멀티스레드 예시</code>에서 발생했던 레이스 컨디션의 문제는 </li>
<li><em>원자성이 깨진 작업 중간에 문맥 교환이 발생한 것이 원인*</em>
(<code>📍 책에선 실행 순서 제어로 분류하지만 일반적으로는 상호 배제 동기화에 해당함</code>)<blockquote>
</blockquote>
<em>즉, A가 작업을 끝내기 전에 B가 작업을 시작하지 못하도록 순서를 제어하지 않았던 것이 원인</em></li>
<li><code>167p C++/Java 코드 예시</code>에서 발생했던 레이스 컨디션의 문제는 <strong>동시에 공유 자원에 접근했던 것이 원인</strong>
(상호 배제를 위한 동기화가 필요한 경우)</li>
</ul>
<h3 id="2-2-동기화의-기법">2-2. 동기화의 기법</h3>
<p>이제부터 설명할 동기화 기법은 많은 프로그래밍 언어에서 제공하고 있는 기능이라는 점에서 유의하며 학습을 이어나가길 바란다...</p>
<h4 id="1-1-뮤텍스-락-mutex-lock">1-1) 뮤텍스 락 (Mutex Lock)</h4>
<p>뮤텍스는 동시에 접근해서는 안 되는 자원에 <strong>동시 접근이 불가능하도록</strong> 상호 배제를 보장하는 도구이다.</p>
<blockquote>
<p><strong>임계 구역에 접근하고자 한다면 반드시 락(lock)을 획득(acquire)해야 하고, 임계 구역에서의 작업이 끝났다면 락을 해제(release)해야 한다.</strong></p>
</blockquote>
<ul>
<li><strong>상호 배제 (Mutual Exclusion):</strong> 뮤텍스의 기본 원리는 <code>lock</code> (잠금)과 <code>release</code> (해제)를 통해 상호 배제를 구현하는 것이다.</li>
<li><strong>작동 방식:</strong><ol>
<li>프로세스나 스레드는 임계 구역 진입 전에 <strong><code>lock.acquire()</code></strong> 함수를 호출하여 락을 <strong>획득</strong>한다.</li>
<li>락을 획득한 스레드만 임계 구역에 진입할 수 있으며, 다른 스레드는 락이 해제될 때까지 <strong>대기</strong>한다.</li>
<li>임계 구역 내의 작업이 끝나면 <strong><code>lock.release()</code></strong> 함수를 호출하여 락을 <strong>해제</strong>한다. 대기 중이던 스레드는 락을 획득하고 임계 구역에 진입하게 된다.</li>
</ol>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/fc4f6be5-d6d0-4eec-b462-37250e4b53ce/image.png" alt=""></p>
<p>공유 자원은 1개이고, <code>P1</code>, <code>P2</code>가 공유 자원에 접근하려는 프로세스라고 할 때 <strong>P1, P2의 순서로 임계 구역에 접근한다고 가정</strong>해보자. 뮤텍스 락을 사용하면 위와 같은 순서로 프로세스가 실행되게 된다.</p>
<h4 id="1-2-자바-코드로-살펴보는-뮤텍스-락">1-2) 자바 코드로 살펴보는 뮤텍스 락</h4>
<p>아래 코드는 위에서 <code>경쟁 상태가 발생했던 자바 코드에 뮤텍스 락을 추가한 경우</code>이다.</p>
<pre><code>import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MutexRace {

    // 0. 공유 데이터 (초기값 0)
    static int sharedData = 0;

    // 1. 뮤텍스 락 객체 생성 (ReentrantLock 사용)
    static Lock lock = new ReentrantLock(); // 락 선언

    // Increment 스레드: 공유 데이터를 100,000번 증가시킴
    static class Increment implements Runnable {
        public void run() {
            for (int i = 0; i &lt; 100000; i++) {
                // 📍 임계 구역 진입 전에 락 획득 (lock())
                lock.lock(); 
                try {
                    // 💥 여기가 임계 구역: 한 번에 하나의 스레드만 접근 가능
                    sharedData++; // 공유 데이터 증가
                } finally {
                    // 📍 임계 구역을 벗어날 때 락 해제 (unlock())
                    lock.unlock(); 
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(new Increment());
        Thread thread2 = new Thread(new Decrement());

        thread1.start(); 
        thread2.start(); 

        try {
            // 메인 스레드는 두 스레드가 작업을 완료할 때까지 대기
            thread1.join(); 
            thread2.join(); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

         // 📍 최종 공유 데이터 값 출력 (예상값 0이 출력됨)
        System.out.println(&quot;Final value of sharedData: &quot; + sharedData);
    }
}</code></pre><h4 id="2-1-세마포세마포어-semaphore">2-1) 세마포/세마포어 (Semaphore)</h4>
<pre><code>세마포
 ├── 바이너리 세마포 (Binary Semaphore)
 └── 카운팅 세마포 (Counting Semaphore)</code></pre><p>세마포는 뮤텍스와 비슷하지만, <strong>공유 자원의 개수가 하나 이상일 때</strong>도 동기화를 구현할 수 있는 도구이다.</p>
<p>이는 정수형 변수 <code>S</code>와 두 가지 함수 <code>wait(P)</code>와 <code>signal(V)</code>로 구성된다.</p>
<pre><code>wait()
// 임계 구역
signal()</code></pre><ul>
<li><img src="https://velog.velcdn.com/images/w_dw_r/post/ee05214b-dd16-4677-a2e1-7e8e8d2236fe/image.png" alt=""></li>
<li><code>wait()</code>: 임계 구역 진입 전에 호출되며, 사용 가능한 공유 자원의 개수를 <code>1</code> 감소시킨다. 값이 <code>0</code>보다 작아지면 프로세스/스레드는 <strong>대기 상태</strong>가 된다.</li>
<li><img src="https://velog.velcdn.com/images/w_dw_r/post/39d9274b-a10e-403d-a1b1-68142dadbacd/image.png" alt=""></li>
<li><code>signal()</code>: 임계 구역 작업 후 호출되며, 자원의 개수를 <code>1</code> 증가시키고 <strong>대기 중이던 프로세스/스레드를 깨워준다.</strong></li>
</ul>
<h4 id="동작-원리-1">동작 원리</h4>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/41931033-03b4-4496-ad9b-f10e880066cf/image.png" alt=""></p>
<h4 id="2-2-자바-코드로-살펴보는-세마포">2-2) 자바 코드로 살펴보는 세마포</h4>
<p>세마포도 역시 뮤텍스 락처럼 여러 프로그래밍 언어에서 지원하고 있다.</p>
<p>다음 코드를 살펴보면 <strong>세마포의 사용 방식도 뮤텍스 락과 유사하다는 것을 확인할 수 있다.</strong></p>
<pre><code>import java.util.concurrent.Semaphore;

public class Sem {

    static int sharedData = 0; // 공유 데이터 
    // 세마포어 객체 생성 및 공유 자원 개수 1개로 초기화
    static Semaphore semaphore = new Semaphore(1); // 세마포어 선언, 공유 자원 개수 1개

    public static void main(String[] args) {
        Thread thread1 = new Thread(new ThreadIncrement());
        Thread thread2 = new Thread(new ThreadDecrement());

        thread1.start(); 
        thread2.start(); 

        try {
            // 메인 스레드는 두 스레드가 작업을 완료할 때까지 대기
            thread1.join(); 
            thread2.join(); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 최종 공유 데이터 값 출력 (경쟁 상태가 해소되어 0이 출력됨)
        System.out.println(&quot;Final value of sharedData: &quot; + sharedData);
    }

    static class ThreadDecrement implements Runnable {
        public void run() {
            for (int i = 0; i &lt; 100000; i++) {
                try {
                    // 세마포어 획득 (wait() 또는 acquire() 역할)
                    semaphore.acquire(); // 세마포어 획득

                    // 💥 임계 구역
                    sharedData--; // 공유 데이터 감소
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 세마포어 해제 (signal() 또는 release() 역할)
                    semaphore.release(); // 세마포어 해제
                }
            }
        }
    }
}</code></pre><h4 id="2-3-세마포-종류">2-3) 세마포 종류</h4>
<table>
<thead>
<tr>
<th align="center">바이너리 세마포</th>
<th align="center">카운팅 세마포</th>
</tr>
</thead>
<tbody><tr>
<td align="center">자원의 개수가 1개로 고정된 세마포로,<br><strong>상호 배제</strong> 목적으로 뮤텍스와 유사하게 사용된다.</td>
<td align="center">자원의 개수가 여러 개인 경우에 사용된다.<br><strong>실행 순서 제어</strong>와 여러 개의 자원 관리에 유용하다.</td>
</tr>
</tbody></table>
<h4 id="3-뮤텍스-락과-세마포의-차이점">3) 뮤텍스 락과 세마포의 차이점</h4>
<table>
<thead>
<tr>
<th align="center">특징</th>
<th align="left">뮤텍스 락 (Mutex Lock)</th>
<th align="left">세마포 (Semaphore)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>목적</strong></td>
<td align="left"><strong>상호 배제 (Mutual Exclusion) 전용</strong></td>
<td align="left"><strong>상호 배제</strong> 및 <strong>실행 순서 제어</strong> 모두 가능</td>
</tr>
<tr>
<td align="center"><strong>자원 개수 (값)</strong></td>
<td align="left"><strong>1개</strong> (잠금/해제 상태만 표현)</td>
<td align="left"><strong>N개</strong><br>(사용 가능한 공유 자원의 개수)</td>
</tr>
<tr>
<td align="center"><strong>임계 구역 진입</strong></td>
<td align="left"><strong>한 번에 오직 하나의</strong> 프로세스/스레드만 진입 가능</td>
<td align="left"><strong>N개까지</strong> 동시에 진입 가능<br>(N은 세마포어 초기값)</td>
</tr>
<tr>
<td align="center"><strong>종류</strong></td>
<td align="left">단일 종류</td>
<td align="left">바이너리 세마포어 (값=1)와 카운팅 세마포어 (값&gt;1)로 나뉨</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 03-2 프로세스와 스레드(멀티프로세스와 멀티스레드)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-03-2-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-03-2-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C</guid>
            <pubDate>Mon, 24 Nov 2025 12:56:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 멀티프로세스와 멀티스레드
② 프로세스 간 통신: 공유 메모리 / 메시지 전달 / 시그널
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-멀티프로세스와-멀티스레드">1. 멀티프로세스와 멀티스레드</h2>
<p>한 프로세스를 구성하는 코드를 동시에 실행하는 방법에는 <strong>멀티프로세스와 멀티스레드</strong>가 있다.</p>
<h3 id="1-1-멀티프로세스-동시에-여러-프로세스가-실행되는-것">1-1. 멀티프로세스: 동시에 여러 프로세스가 실행되는 것</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/731d98e0-07b2-49d1-aa3f-36b645d0a62f/image.png" alt=""></p>
<ul>
<li><strong>독립적인 실행:</strong> <code>각기 다른 프로세스</code>는 기본적으로 <code>자원을 공유하지 않고</code>, 독립적으로 실행된다.</li>
<li><strong>PID 및 자원 할당:</strong> 같은 작업을 수행하더라도 각각 <code>고유한 PID(프로세스 ID)</code> 값을 가진다. 또한, 프로세스별로 <code>파일, 메모리, 입출력 장치</code> 등의 자원이 독립적으로 할당된다.</li>
<li><strong>영향 최소화:</strong> 이러한 독립성 덕분에 한 프로세스의 실행 과정에서 문제가 발생하더라도 다른 프로세스에 <code>직접적인 영향을 거의 끼치지 않는다.</code></li>
</ul>
<p>➡️ 이는 프로세스가 서로 <strong>남남처럼</strong> 실행되는 특성 때문이다.</p>
<blockquote>
<p>Ex) 웹 브라우저 탭
<img src="https://velog.velcdn.com/images/w_dw_r/post/8c78828d-a627-46b8-9860-687de7b47ed4/image.png" alt=""></p>
</blockquote>
<h3 id="1-2-멀티스레드-프로세스-내에서-동시에-실행되는-여러-스레드">1-2. 멀티스레드: 프로세스 내에서 동시에 실행되는 여러 스레드</h3>
<pre><code>스레드
 ├── 스레드 ID (고유 식별 정보)
 ├── 프로그램 카운터 (다음에 실행할 명령어 주소)
 ├── 레지스터 값 (연산 과정의 임시 저장 값)
 └── 스택 (함수 호출 정보 등)</code></pre><p><img src="https://velog.velcdn.com/images/w_dw_r/post/e00c1593-9646-4663-90f1-506e4c6878a6/image.png" alt=""></p>
<ul>
<li><strong>독립된 정보:</strong> <code>스레드마다 각각의 프로그램 카운터 값과 스택을 가지고 있기 때문에</code>, 스레드별로 <strong>다음에 실행할 주소</strong>를 가질 수 있고, <strong>연산 과정의 임시 저장 값</strong>을 가질 수 있다.</li>
</ul>
<blockquote>
<p>Ex) 멀티스레드 </p>
</blockquote>
<pre><code class="language-java">// 함수 foo, bar, baz에 해당하는 작업을 정의하는 클래스 (Runnable 구현)
class Task implements Runnable {
    private String taskName;
&gt;
&gt;    public Task(String name) {
        this.taskName = name;
    }
&gt;
    // 각 스레드가 실행할 로직
    @Override
    public void run() {
        // 1. 현재 프로세스의 ID(PID)를 가져온다.
        // ProcessHandle은 Java 9 이상에서 사용 가능
        long pid = ProcessHandle.current().pid();
&gt;
        // 2. 현재 스레드의 ID(TID)를 가져온다.
        long tid = Thread.currentThread().getId();
&gt;
        System.out.println(
                String.format(&quot;%s: PID={%d}, Thread ID={%d}&quot;, taskName, pid, tid)
        );
    }
}
&gt;
public class MultiThreadingExample {
    public static void main(String[] args) {
&gt;
        // 1. 첫 번째 스레드 생성, 실행할 함수는 foo (Task(&quot;foo&quot;)에 해당)
        Thread thread1 = new Thread(new Task(&quot;foo&quot;));
        // 2. 두 번째 스레드 생성, 실행할 함수는 bar (Task(&quot;bar&quot;)에 해당)
        Thread thread2 = new Thread(new Task(&quot;bar&quot;));
        // 3. 세 번째 스레드 생성, 실행할 함수는 baz (Task(&quot;baz&quot;)에 해당)
        Thread thread3 = new Thread(new Task(&quot;baz&quot;));
&gt;
        // 첫 번째 스레드 실행
        thread1.start();
        // 두 번째 스레드 실행
        thread2.start();
        // 세 번째 스레드 실행
        thread3.start();
&gt;
        // main 스레드의 PID와 TID를 출력하려면 다음과 같이 추가할 수 있습니다.
        long mainPid = ProcessHandle.current().pid();
        long mainTid = Thread.currentThread().getId();
        System.out.println(
                String.format(&quot;main: PID={%d}, Thread ID={%d}&quot;, mainPid, mainTid)
        );
    }
}
&gt;</code></pre>
<pre><code>foo: PID={6510}, Thread ID={21}
baz: PID={6510}, Thread ID={23}
main: PID={6510}, Thread ID={1}
bar: PID={6510}, Thread ID={22}
&gt;
Process finished with exit code 0</code></pre><h3 id="1-3-멀티프로세스와-멀티스레드의-차이점">1-3. 멀티프로세스와 멀티스레드의 차이점</h3>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/2ccda457-bbd0-48da-b71d-c7ecc3f72a9c/image.png" alt=""></p>
<table>
<thead>
<tr>
<th align="left">유형</th>
<th align="left">멀티프로세스 (Multi-Process)</th>
<th align="left">멀티스레드 (Multi-Thread)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>📍자원 공유📍</strong></td>
<td align="left"><strong>기본적으로 자원을 공유하지 않음</strong> <br>(독립적 실행)</td>
<td align="left"><strong>프로세스의 자원을 공유함</strong></td>
</tr>
<tr>
<td align="left"><strong>공유 영역</strong></td>
<td align="left"><strong>독립된 주소 공간</strong><br>(코드, 데이터, 힙, 스택 모두 분리)</td>
<td align="left">동일한 주소 공간의 <strong>코드, 데이터, 힙 영역을 공유</strong><br>(스택은 분리)</td>
</tr>
<tr>
<td align="left"><strong>협력/통신</strong></td>
<td align="left"><strong>IPC</strong> 필요, 비교적 복잡</td>
<td align="left">자원 공유로 인해 <strong>쉽게 협력하고 통신</strong>할 수 있음</td>
</tr>
<tr>
<td align="left"><strong>문제 발생 시 영향</strong></td>
<td align="left">한 프로세스에 문제가 생겨도 <strong>다른 프로세스에는 지장이 없거나 적음</strong></td>
<td align="left">한 스레드에 생긴 문제가 <strong>프로세스 전체의 문제</strong>가 될 수 있음</td>
</tr>
<tr>
<td align="left"><strong>생성/Context Switching</strong></td>
<td align="left"><strong>비용이 큼</strong><br>(독립된 자원을 할당해야 함)</td>
<td align="left"><strong>비용이 적음</strong><br>(프로세스의 자원을 공유하여 가볍게 동작)</td>
</tr>
</tbody></table>
<h2 id="2-프로세스-간-통신-ipc">2. 프로세스 간 통신: IPC</h2>
<p>프로세스는 기본적으로 자원을 공유하지 않지만, <strong>필요에 따라 프로세스 간에도 자원을 공유하고 데이터를 주고받을 수 있는 방법이 있다</strong>.</p>
<p>이를 <code>IPC (Inter-Process Communication)</code>라고 한다.</p>
<pre><code>IPC (Inter-Process Communication)
 ├── 공유 메모리 (Shared Memory)
 ├── 메시지 전달 (Message Passing)
 └── 시그널 (Signal) - 비동기 통신</code></pre><p><img src="https://velog.velcdn.com/images/w_dw_r/post/5b2680ee-c84f-456b-b3ab-e0852054a0d0/image.png" alt=""></p>
<h3 id="2-1-공유-메모리-shared-memory">2-1. 공유 메모리 (Shared Memory)</h3>
<p><strong>공유 메모리</strong> 기반 IPC는 프로세스들이 공유하는 메모리 영역을 통해 데이터를 주고받는 통신 방식이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/e71dc819-0ff0-41bc-a7e4-4c2bd1bc2289/image.png" alt=""></p>
<ul>
<li><p><strong>원리:</strong></p>
<ul>
<li><p>통신할 프로세스들이 <strong>공통적으로 사용할 메모리 영역</strong>을 할당하여, 이 영역을 통해 직접 데이터를 읽고 쓰면서 통신을 수행한다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/efcbfd29-b423-4928-b0a6-bef118883280/image.png" alt=""></p>
</li>
<li><p>이는 프로세스 A가 자신에게 할당된 메모리 공간을 떼어내어 프로세스 B에게 할당된 메모리 공간에 <strong>매핑(Mapping)</strong>시킨 것과 같다.</p>
</li>
</ul>
</li>
<li><p><strong>특징:</strong></p>
<ul>
<li>데이터를 주고받는 과정에 <strong>커널의 개입이 최소화</strong>되므로, 데이터 전송 <strong>속도가 빠르다</strong>.</li>
<li>데이터 일관성 문제인 <strong>경쟁 상태(Race Condition)</strong>가 발생할 수 있어, <strong>동기화</strong>가 필수적으로 요구된다.</li>
</ul>
</li>
</ul>
<h3 id="2-2-메시지-전달-message-passing">2-2. 메시지 전달 (Message Passing)</h3>
<p><strong>메시지 전달</strong> 기반 IPC는 데이터를 메시지의 형태로 주고받는 방식이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/dcb3b97c-ad6e-4d2f-9da9-88dd8542de91/image.png" alt=""></p>
<ul>
<li><strong>원리:</strong><ul>
<li>데이터를 주고받을 프로세스들이 <strong>시스템 콜</strong>을 통해 커널에 접근하여 통신을 수행한다.</li>
<li>일반적으로 메시지를 보내는 시스템 콜 <strong><code>send()</code></strong>와 메시지를 받는 시스템 콜 <strong><code>recv()</code></strong> 등을 이용해 통신한다.</li>
</ul>
</li>
<li><strong>특징:</strong><ul>
<li>데이터 전달을 <strong>커널이 대신 처리</strong>해 주기 때문에 복잡한 <strong>동기화 문제를 고민할 필요가 없다</strong>.</li>
<li>커널의 개입으로 인한 오버헤드가 발생하므로, 공유 메모리 기반 IPC보다 <strong>속도가 느리다</strong>.</li>
<li><strong>파이프(Pipe)</strong>, <strong>메시지 큐(Message Queue)</strong>, <strong>원격 프로시저 호출(RPC)</strong> 등이 대표적인 통신 수단이다.</li>
</ul>
</li>
</ul>
<h4 id="공유-메모리-vs-메시지-전달">공유 메모리 vs 메시지 전달</h4>
<table>
<thead>
<tr>
<th align="left">구분</th>
<th align="center">공유 메모리 (Shared Memory)</th>
<th align="center">메시지 전달 (Message Passing)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>통신 방식</strong></td>
<td align="center"><strong>메모리 영역</strong>을 공유하여 데이터를 직접 읽고 쓴다.</td>
<td align="center"><strong>메시지</strong> 형태로 데이터를 주고받는다.<br>(커널 경유)</td>
</tr>
<tr>
<td align="left"><strong>커널 개입</strong></td>
<td align="center"><strong>최소화</strong><br>(메모리 설정 시에만 개입)</td>
<td align="center"><strong>잦음</strong><br>(데이터 전송 시마다 시스템 콜 사용)</td>
</tr>
<tr>
<td align="left"><strong>속도</strong></td>
<td align="center"><strong>빠르다</strong><br>(데이터를 사용자 영역에서 직접 접근)</td>
<td align="center"><strong>느리다</strong><br>(시스템 콜 호출 오버헤드 발생)</td>
</tr>
<tr>
<td align="left"><strong>📍동기화📍</strong></td>
<td align="center"><strong>필수적으로 요구됨</strong><br>(경쟁 상태 방지)</td>
<td align="center"><strong>필요 없음</strong><br>(커널이 데이터 전달을 관리)</td>
</tr>
<tr>
<td align="left"><strong>구현 난이도</strong></td>
<td align="center">동기화 구현 때문에 <strong>상대적으로 복잡하다</strong>.</td>
<td align="center"><strong>상대적으로 간단하다</strong>.<br>(메시지 함수만 사용)</td>
</tr>
</tbody></table>
<h3 id="2-3-시그널-signal">2-3. 시그널 (Signal)</h3>
<p><strong>시그널</strong>은 프로세스에게 특정 <strong>이벤트가 발생했음</strong>을 알리는 <strong>비동기식 신호</strong>이다.</p>
<p>IPC 기법 중 하나로, <code>메시지를 직접 주고받지는 않지만 통신을 수행하는 역할</code>을 한다.</p>
<ul>
<li><strong>작동 방식:</strong> 시그널이 프로세스에 전달되면, 프로세스는 하던 일을 잠시 멈추고 시그널을 처리하는 <strong>시그널 핸들러</strong>를 실행한다.</li>
<li><strong>비동기적 통신:</strong> 시그널은 비동기적으로 동작하는 통신 수단이며, 프로세스 간에 원하는 동작을 수행하도록 <strong>간접적인 통신</strong>을 수행할 수 있다.</li>
</ul>
<h4 id="주요-시그널-예시">주요 시그널 예시</h4>
<table>
<thead>
<tr>
<th align="left">시그널</th>
<th align="left">설명</th>
<th align="left">기본 동작</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>SIGHUP</strong></td>
<td align="left">터미널 연결 끊김</td>
<td align="left">프로세스 종료</td>
</tr>
<tr>
<td align="left"><strong>SIGKILL</strong></td>
<td align="left">프로세스 강제 종료 (<strong>처리 불가</strong>)</td>
<td align="left">종료</td>
</tr>
<tr>
<td align="left"><strong>SIGINT</strong></td>
<td align="left">키보드 인터럽트 (Ctrl + C)</td>
<td align="left">종료</td>
</tr>
<tr>
<td align="left"><strong>SIGSEGV</strong></td>
<td align="left">잘못된 메모리 접근</td>
<td align="left">코어 덤프 생성 후 종료</td>
</tr>
<tr>
<td align="left"><strong>SIGTERM</strong></td>
<td align="left">프로세스 종료 요청 (소프트웨어적 종료)</td>
<td align="left">종료</td>
</tr>
</tbody></table>
<h4 id="1-시그널-핸들러-signal-handler">(1) 시그널 핸들러 (Signal Handler)</h4>
<ul>
<li><p>프로세스는 특정 시그널이 발생했을 때 미리 정의해둔 동작을 수행하도록 <strong>시그널 핸들러</strong>를 지정할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/9b29bc31-16b4-4c12-8668-e71cb7f9430e/image.png" alt=""></p>
</li>
<li><p>예를 들어, **<code>signal(SIGINT, handler)</code>**와 같이 설정하여 <code>SIGINT</code>가 발생했을 때 <strong>기본 동작(종료)</strong> 대신 특정 <strong><code>handler</code> 함수</strong>가 실행되도록 재정의할 수 있다.</p>
</li>
</ul>
<h4 id="2-코어-덤프-core-dump">(2) 코어 덤프 (Core Dump)</h4>
<ul>
<li><code>SIGSEGV</code>나 <code>SIGILL</code> 등 치명적인 오류가 발생하면, 대부분 <strong>코어 덤프</strong>를 생성하며 종료한다.</li>
<li><strong>코어 덤프</strong>는 프로그램이 비정상적으로 종료되었을 때, <strong>CPU 레지스터 값, 메모리 상태</strong> 등 오류 발생 시점의 메모리 정보를 파일로 기록한 것으로, 이는 디버깅 목적으로 사용된다.</li>
</ul>
<hr>
<h3 id="면접-예상-질문">면접 예상 질문</h3>
<h4 id="q1-공유-자원-접근">Q1. 공유 자원 접근</h4>
<blockquote>
<p>Q. 멀티스레드 환경에서 공유 자원 접근 시 발생하는 문제와 이를 해결하는 동기화 기법에 대해 설명해 주십시오.</p>
</blockquote>
<ul>
<li>발생하는 문제: 둘 이상의 스레드가 동시에 접근해서는 안 되는 코드 영역을 <strong>임계 영역(Critical Section)</strong>이라고 하는데, 여기에 동시에 접근할 때 <strong>경쟁 상태(Race Condition)</strong>가 발생하여 <code>데이터의 일관성이 깨질 위험이 있다.</code></li>
<li>해결 방법: <strong>동기화(Synchronization) 기법</strong>. 동기화는 <code>여러 스레드가 동시에 임계 영역에 접근하는 것을 막는 기법</code>이다.</li>
</ul>
<h4 id="꼬리-질문-동기화-기법-종류">꼬리 질문) 동기화 기법 종류</h4>
<ul>
<li><strong>뮤텍스(Mutex):</strong> <strong>상호 배제</strong>를 통해 <code>오직 하나의 스레드만 임계 영역에 접근하도록 허용</code>하는 도구이다. ➡️ 임계 영역의 접근을 잠그는 <code>자물쇠</code>와 같은 역할</li>
<li><strong>세마포어(Semaphore)</strong>는 임계 영역에 접근할 수 있는 스레드의 수를 <strong>특정 개수(카운트)</strong>로 제한하는 도구이다. ➡️ <code>주차장의 빈자리 카운트</code>와 유사하게 동작한다.</li>
</ul>
<h4 id="q2-데드락">Q2. 데드락</h4>
<blockquote>
<p>Q. 데드락(Deadlock, 교착 상태)은 무엇인지 설명해 주십시오.</p>
</blockquote>
<ul>
<li>정의: <strong>데드락</strong>이란 두 개 이상의 스레드가 <strong>각자 다른 스레드가 점유하고 있는 자원을 서로 기다리면서</strong> 무한히 대기하는 상태를 말한다. ➡️ <code>병목 현상 발생</code></li>
</ul>
<h4 id="꼬리-질문-데드락-발생-필수-조건-4가지">꼬리 질문) 데드락 발생 필수 조건 4가지</h4>
<ul>
<li><strong>상호 배제 (Mutual Exclusion):</strong> 자원은 한 번에 하나의 프로세스(스레드)만이 사용할 수 있어야 한다.</li>
<li><strong>점유와 대기 (Hold and Wait):</strong> 자원을 최소한 하나 점유한 상태에서 다른 프로세스(스레드)가 점유하고 있는 자원을 얻기 위해 대기해야 한다.</li>
<li><strong>비선점 (No Preemption):</strong> 다른 프로세스(스레드)에게 할당된 자원은 해당 프로세스가 사용을 끝낼 때까지 강제로 뺏을 수 없어야 한다.</li>
<li><strong>환형 대기 (Circular Wait):</strong> 자원을 기다리는 프로세스들이 순환 형태로 자원을 기다리고 있어야 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 02 컴퓨터 구조(주요 개념 정리 및 면접 대비)]]></title>
            <link>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-02-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0%EC%A3%BC%EC%9A%94-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC-%EB%B0%8F-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84</link>
            <guid>https://velog.io/@w_dw_r/%EC%9D%B4%EA%B2%83%EC%9D%B4-%EC%B7%A8%EC%97%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B3%BC%ED%95%99%EC%9D%B4%EB%8B%A4-with-CS-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-02-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0%EC%A3%BC%EC%9A%94-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC-%EB%B0%8F-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84</guid>
            <pubDate>Mon, 17 Nov 2025 11:45:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 데이터 표현 및 인코딩: 부동 소수점 및 UTF-8
② CPU 제어 및 성능: 명령어 사이클, 인터럽트, <strong>명령어 병렬 처리</strong>, CPU/GPU 비교
③ 메모리 전략: 캐시 계층 구조 및 히트/미스
④ 보조기억장치: RAID 및 입출력 제어 방식
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였다.</code></p>
</blockquote>
<hr>
<h2 id="1-데이터-표현의-기초-및-인코딩">1. 데이터 표현의 기초 및 인코딩</h2>
<h3 id="1-1-부동-소수점-floating-point">1-1. 부동 소수점 (Floating Point)</h3>
<p><strong>부동 소수점</strong>은 <strong>소수점이 고정되지 않고 이동할 수 있는 방식</strong>으로 $m \times 2^n$ 형태로 표현하는 방식이다. <strong>IEEE 754 표준</strong>에 따라 <strong>부호 비트, 지수부, 가수부</strong>로 구성된다.</p>
<p>➡️ 가수부의 정밀도 한계 때문에 오차가 발생한다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">부동 소수점 오차가 발생하는 근본적인 이유를 설명해 주세요.</td>
<td align="left"><strong>10진수 소수가 2진수로 변환될 때 무한 소수</strong>가 되기 때문이다. 한정된 저장 공간(가수부)에 의해 <strong>일부 절삭(Rounding)</strong>이 일어나 정밀도 손실이 발생한다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">$0.1 + 0.2 \neq 0.3$을 해결하려면 어떻게 해야 하나요?</td>
<td align="left">금융 계산 등 정밀도가 중요한 곳에서는 <strong>고정 소수점</strong> 방식이나, Java의 <code>BigDecimal</code>과 같은 <strong>소프트웨어 라이브러리</strong>를 사용해야 한다. 또는 <strong>매우 작은 허용 오차 ($\epsilon$)</strong>를 두고 비교한다.</td>
</tr>
</tbody></table>
<hr>
<h3 id="1-2-인코딩-방식">1-2. 인코딩 방식</h3>
<p>인코딩은 <strong>다국어를 표현</strong>하고, 인터넷 환경에서 <strong>효율적으로 데이터를 전송</strong>하기 위함해 사용된다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">오늘날 웹 환경에서 가장 많이 사용되는 문자 인코딩 방식은 무엇이며, 그 이유는 무엇인가요?</td>
<td align="left"><strong>UTF-8</strong>이다. <strong>유니코드</strong> 표준을 따르며, 영어는 1바이트, 한글/한자는 3바이트를 사용하는 <strong>가변 길이 인코딩</strong> 방식이기 때문에, 저장 및 네트워크 전송 효율이 높다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">Base64 인코딩은 언제 사용하며, 왜 64진법을 쓰나요?</td>
<td align="left"><strong>이진 데이터(이미지, 파일)를 텍스트 기반의 통신 채널</strong> (예: 이메일, HTTP 헤더)로 안전하게 전송하기 위해 사용한다. 64는 $2^6$이므로 <strong>6비트</strong> 단위로 데이터를 인코딩하며, 아스키(ASCII) 문자 64개로 모든 이진 데이터를 표현할 수 있다.</td>
</tr>
</tbody></table>
<hr>
<h2 id="2-cpu의-동작-및-제어">2. CPU의 동작 및 제어</h2>
<h3 id="2-1-명령어-사이클과-레지스터의-역할">2-1. 명령어 사이클과 레지스터의 역할</h3>
<p><strong>명령어 사이클</strong>은 CPU가 프로그램을 실행하는 <strong>정형화된 흐름 (인출 → 해석 → 실행 → 결과 저장)</strong>이고, 그 흐름은 <strong>레지스터</strong>가 제어한다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">명령어 사이클의 3단계를 순서대로 설명하고, 각 단계에 관여하는 주요 레지스터를 말해주세요.</td>
<td align="left"><strong>인출(Fetch)</strong>: PC(Program Counter)가 메모리 주소 지정. <strong>해석(Decode)</strong>: IR(Instruction Register)에 명령어를 저장 및 해석. <strong>실행(Execute)</strong>: ALU가 연산을 수행한다.</td>
</tr>
<tr>
<td align="center"><strong>꼬리</strong></td>
<td align="left">프로그램 카운터(PC)는 항상 증가만 하나요?</td>
<td align="left">아니다. PC는 기본적으로 다음 명령어 주소로 1씩 증가하지만, <strong>조건문, 반복문, 함수 호출, 인터럽트 발생</strong> 시에는 실행 흐름이 바뀌어 PC 값이 <strong>임의의 주소로 변경</strong>된다.</td>
</tr>
</tbody></table>
<hr>
<h3 id="2-2-인터럽트의-이해">2-2. 인터럽트의 이해</h3>
<p><strong>인터럽트</strong>는 CPU의 <strong>정상적인 실행 흐름을 일시 중단시키는 신호</strong>이다.</p>
<p><strong>동기 인터럽트(예외, System Call)</strong>와 <strong>비동기 인터럽트(하드웨어 I/O)</strong>가 있다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">인터럽트가 필요한 가장 큰 이유를 설명해 주세요.</td>
<td align="left"><strong>CPU의 효율적인 자원 활용</strong>과 <strong>멀티태스킹 환경 구현</strong>을 위해서이다. 입출력 장치의 느린 작업이 완료될 때까지 CPU가 기다리지 않고 다른 작업을 하다가, 완료 신호(인터럽트)를 받으면 그때 처리하여 <strong>CPU 사이클 낭비를 최소화</strong>한다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">인터럽트 발생 시 CPU는 어떤 작업을 수행하나요?</td>
<td align="left">CPU는 <strong>Context Switching</strong>을 수행한다. 현재 작업의 <strong>Context (PC, 레지스터 상태)</strong>를 <strong>스택</strong>에 백업하고, <strong>인터럽트 벡터</strong>를 참조하여 해당 인터럽트를 처리할 <strong>ISR(Interrupt Service Routine)</strong>을 실행한다. 처리 후 Context를 복구한다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>Context Switching:</strong> CPU가 다른 프로세스/스레드로 제어권을 넘기기 위해 현재 실행 중인 상태(Context)를 저장하고 복원하는 작업이다.</li>
<li><strong>ISR (Interrupt Service Routine):</strong> 인터럽트 처리를 위한 프로그램이다.</li>
<li><strong>인터럽트 벡터:</strong> 인터럽트 서비스 루틴의 시작 주소를 식별하기 위한 정보이다.</li>
</ul>
<hr>
<h3 id="2-3-파이프라이닝을-통한-명령어-병렬-처리">2-3. 파이프라이닝을 통한 명령어 병렬 처리</h3>
<p><strong>파이프라이닝</strong>은 CPU 성능 향상 기법 중 하나로, <strong>명령어를 여러 단계로 쪼개어</strong> 각 단계를 겹쳐서 동시에 처리하여 CPU의 처리 성능을 높이는 기술이다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>중간</strong></td>
<td align="left">파이프라이닝이란 무엇이며, 어떻게 CPU의 성능을 향상시키는지 설명해 보세요.</td>
<td align="left">파이프라이닝은 하나의 명령어를 처리하는 과정을 비슷한 시간 간격으로 쪼갠 뒤, 쪼개진 각각의 단계에서 동시에 실행 가능한 단계를 겹쳐 실행해 CPU의 처리 성능을 높이는 방식이다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>명령어 병렬 처리 (ILP, Instruction-Level Parallelism):</strong> 여러 명령어를 동시에 처리하여 CPU를 쉬지 않고 작동하게 함으로써 성능을 높이는 기법이다.</li>
</ul>
<hr>
<h3 id="2-4-cpu와-gpu의-차이">2-4. CPU와 GPU의 차이</h3>
<p><strong>CPU</strong>는 <strong>범용성(Latency)</strong>에, <strong>GPU</strong>는 <strong>병렬성(Throughput)</strong>에 초점을 맞춘 아키텍처이다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">CPU와 GPU의 구조적 차이를 코어 개수를 중심으로 설명해 주세요.</td>
<td align="left"><strong>CPU</strong>는 <strong>소수(Few)</strong>의 강력한 코어를 가지고 복잡하고 순차적인 연산을 빠르게 처리한다. <strong>GPU</strong>는 <strong>수천 개(Many)</strong>의 약한 코어를 가지고 단순하고 반복적인 대규모 연산을 동시에 처리한다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">인공지능 학습이나 빅데이터 처리에서 GPU가 CPU보다 월등한 성능을 내는 이유는 무엇인가요?</td>
<td align="left">해당 작업들은 행렬 연산 등 <strong>단순한 계산을 대량으로 병렬 처리</strong>하는 것이 핵심이다. GPU는 <strong>SIMD(Single Instruction Multiple Data)</strong> 구조에 최적화되어 있어, CPU보다 훨씬 많은 코어를 활용해 <strong>처리율(Throughput)을 극대화</strong>할 수 있기 때문이다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>Latency:</strong> 작업 하나를 완료하는 데 걸리는 시간이다.</li>
<li><strong>Throughput:</strong> 단위 시간당 처리할 수 있는 작업의 양이다.</li>
<li><strong>SIMD (Single Instruction Multiple Data):</strong> 하나의 명령어로 여러 데이터를 동시에 처리하는 병렬 처리 방식이다.</li>
</ul>
<hr>
<h2 id="3-메모리-및-캐시-전략">3. 메모리 및 캐시 전략</h2>
<h3 id="3-1-메모리-계층-구조와-참조-지역성">3-1. 메모리 계층 구조와 참조 지역성</h3>
<p><strong>메모리 계층 구조</strong>는 <strong>속도와 비용 효율성</strong>을 위해 레지스터부터 보조기억장치까지 계층적으로 메모리를 구성하는 방식이다.</p>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/bce20caf-a2e3-419e-b383-cf31ce99eeda/image.png" alt=""></p>
<p><strong>참조 지역성(시간적/공간적)</strong>을 활용해 상위 계층 메모리(캐시)를 효율적으로 사용한다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">메모리 계층 구조를 위에서부터 아래로 나열하고, 이 구조를 사용하는 목적을 설명해 주세요.</td>
<td align="left"><strong>레지스터 - 캐시(L1/L2/L3) - RAM - 보조기억장치</strong> 순이다. 목적은 <strong>CPU와 메인 메모리 간의 속도 불일치(Gap)</strong>를 줄이고, 전체 시스템의 비용 효율성을 극대화하기 위해서이다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">참조 지역성의 두 가지 종류를 설명하고, 캐시에 어떻게 적용되는지 말해주세요.</td>
<td align="left"><strong>시간적 지역성</strong>은 최근 사용된 데이터가 다시 사용될 확률, <strong>공간적 지역성</strong>은 참조된 데이터 근처의 데이터가 사용될 확률을 의미한다. 캐시는 이 원리에 따라 데이터를 <strong>미리 가져오고(공간적)</strong>, <strong>오래 보관한다(시간적)</strong>.</td>
</tr>
</tbody></table>
<hr>
<h3 id="3-2-캐시-메모리-및-히트미스">3-2. 캐시 메모리 및 히트/미스</h3>
<p><strong>캐시 메모리</strong>는 CPU에 가까운 <strong>고속 메모리</strong>로, <strong>캐시 히트(Hit)</strong>와 <strong>미스(Miss)</strong> 발생에 따라 성능이 결정된다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">캐시 히트와 캐시 미스는 무엇이며, 성능에 어떤 영향을 미치나요?</td>
<td align="left"><strong>캐시 히트</strong>는 CPU가 찾는 데이터가 캐시에 존재하는 경우이고, <strong>캐시 미스</strong>는 없는 경우이다. 히트율이 높을수록 CPU는 느린 메인 메모리에 접근할 필요가 없어 <strong>시스템 성능이 향상</strong>된다.</td>
</tr>
<tr>
<td align="center"><strong>꼬리</strong></td>
<td align="left">캐시 매핑 방식 중 집합-연관 매핑이 가장 많이 쓰이는 이유가 무엇인가요?</td>
<td align="left"><strong>직접 매핑</strong>의 속도와 <strong>완전 연관 매핑</strong>의 유연성 및 히트율을 절충했기 때문이다. 캐시를 <strong>집합(Set)</strong>으로 나누어 효율적인 검색이 가능하면서도, 충돌 미스 발생률을 낮춘다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>캐시 히트:</strong> CPU가 원하는 데이터가 캐시에 존재하는 경우이다.</li>
<li><strong>캐시 미스:</strong> CPU가 원하는 데이터가 캐시에 존재하지 않아 메인 메모리에 접근해야 하는 경우이다.</li>
<li><strong>집합-연관 매핑:</strong> 캐시를 여러 집합으로 나누고, 특정 메모리 블록이 해당 집합 내의 아무 위치에나 저장될 수 있도록 하는 방식이다.</li>
</ul>
<hr>
<h2 id="4-보조기억장치-및-입출력">4. 보조기억장치 및 입출력</h2>
<h3 id="4-1-보조기억장치-raid">4-1. 보조기억장치 RAID</h3>
<p><strong>RAID</strong>는 여러 개의 디스크를 묶어 데이터의 <strong>안정성(Fault Tolerance)</strong>과 <strong>성능(Performance)</strong>을 높이는 기술이다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">RAID가 무엇이며, 가장 기본적인 RAID 0과 RAID 1을 비교해 주세요.</td>
<td align="left"><strong>RAID</strong>는 여러 디스크를 논리적으로 결합하여 데이터 안정성/성능을 높이는 기술이다. <strong>RAID 0</strong>은 <strong>스트라이핑(분할)</strong>으로 <strong>성능을 극대화</strong>하지만 안정성은 없다. <strong>RAID 1</strong>은 <strong>미러링(복사)</strong>으로 <strong>안정성을 극대화</strong>하지만 용량 효율이 낮다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">실무에서 가장 일반적으로 사용되는 RAID 레벨은 무엇이며 그 이유는요?</td>
<td align="left"><strong>RAID 5</strong>이다. <strong>데이터와 패리티(오류 검증 정보)</strong>를 분산 저장하여 <strong>디스크 하나가 고장 나도 복구 가능</strong>하며, 읽기/쓰기 성능도 적절히 유지하여 안정성과 성능의 균형을 잡았기 때문이다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>스트라이핑 (Striping):</strong> 데이터를 여러 디스크에 분산하여 저장하는 방식이다.</li>
<li><strong>미러링 (Mirroring):</strong> 데이터를 디스크에 복사하여 이중화하는 방식이다.</li>
<li><strong>패리티 (Parity):</strong> 오류 검증을 위한 정보이다.</li>
</ul>
<hr>
<h3 id="4-2-보조기억장치-입출력-제어-방식">4-2. 보조기억장치 입출력 제어 방식</h3>
<p><strong>보조기억장치 입출력 제어 방식</strong>은 CPU와 입출력 장치 간의 <strong>통신 방식을 제어</strong>하여 CPU의 개입 정도와 효율성을 결정한다.</p>
<table>
<thead>
<tr>
<th align="center">난이도</th>
<th align="left">면접 질문</th>
<th align="left">답변 (핵심 키워드)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>쉬움</strong></td>
<td align="left">DMA(Direct Memory Access)는 무엇이며, 왜 필요한가요?</td>
<td align="left"><strong>DMA</strong>는 CPU 개입 없이 <strong>입출력 장치가 메인 메모리에 직접 접근</strong>하여 데이터를 전송하는 방식이다. CPU가 대용량 I/O 작업을 처리하는 데 낭비되는 시간을 줄여 <strong>CPU의 부하를 최소화</strong>하기 위해 필요하다.</td>
</tr>
<tr>
<td align="center"><strong>중간</strong></td>
<td align="left">폴링 방식과 인터럽트 기반 I/O 방식의 효율 차이를 설명해 주세요.</td>
<td align="left"><strong>폴링</strong>은 CPU가 주기적으로 장치의 상태를 확인하여 <strong>CPU 자원을 낭비</strong>한다. <strong>인터럽트 기반 I/O</strong>는 장치 완료 시에만 CPU에 신호를 보내므로 <strong>CPU 유휴 시간을 최소화</strong>하여 훨씬 효율적이다.</td>
</tr>
</tbody></table>
<ul>
<li><strong>DMA (Direct Memory Access):</strong> CPU의 개입 없이 입출력 장치가 메모리에 직접 데이터를 전송하는 방식이다.</li>
<li><strong>폴링 (Polling):</strong> CPU가 주기적으로 입출력 장치의 상태를 확인하는 방식이다.</li>
<li><strong>인터럽트 기반 I/O:</strong> 입출력 장치가 작업 완료 시 CPU에 신호를 보내는 방식이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접] 02-3 CPU(레지스터, 인터럽트, 성능향상, 파이프라이닝)]]></title>
            <link>https://velog.io/@w_dw_r/02-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-03-CPU%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0-%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EC%84%B1%EB%8A%A5-%ED%96%A5%EC%83%81-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B4%EB%8B%9D</link>
            <guid>https://velog.io/@w_dw_r/02-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-03-CPU%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0-%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EC%84%B1%EB%8A%A5-%ED%96%A5%EC%83%81-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B4%EB%8B%9D</guid>
            <pubDate>Sun, 09 Nov 2025 11:33:50 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="주요-내용">주요 내용</h2>
<p>① 레지스터: CPU의 데이터 저장 및 제어
② 인터럽트: CPU 실행 흐름의 전환과 관리
③ 성능 향상 설계: CPU 클럭 및 멀티코어/스레드
④ 파이프라이닝: ILP 구현과 RISC/CISC 비교
<code>⚠️ 모든 내용은 &#39;이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접&#39; 책을 참고하여 작성하였습니다.</code></p>
</blockquote>
<hr>
<h2 id="1-레지스터">1. 레지스터</h2>
<p><strong>레지스터</strong>는 CPU 안에 있는 작은 임시 저장 장치이다.
CPU 내부에는 다양한 레지스터들이 있고, 각기 다른 이름과 역할이 있다.</p>
<table>
<thead>
<tr>
<th align="left">대표적인 주요 레지스터</th>
</tr>
</thead>
<tbody><tr>
<td align="left">프로그램 카운터 (Program Counter, PC)</td>
</tr>
<tr>
<td align="left">명령어 레지스터 (Instruction Register, IR)</td>
</tr>
<tr>
<td align="left">범용 레지스터 (General Purpose Register)</td>
</tr>
<tr>
<td align="left">플래그 레지스터 (Flag Register)</td>
</tr>
<tr>
<td align="left">스택 포인터 (Stack Pointer, SP)</td>
</tr>
</tbody></table>
<h3 id="1-1-프로그램-카운터-명령어-포인터">1-1. 프로그램 카운터 (명령어 포인터)</h3>
<p>메모리에서 다음으로 읽어들일 명령어의 주소를 저장한다.</p>
<p>일반적으로 <strong>프로그램 카운터는 1씩 증가</strong>하며, 이는 <strong>다음으로 읽어들일 메모리 주소가 1씩 증가하는 것과 같다.</strong>
➡️ 이로 인해 메모리에 저장된 프로그램이 <strong>순차적으로 실행</strong>될 수 있다.</p>
<blockquote>
<p><strong>🚨 프로그램 카운터가 언제나 증가만 하는 것은 아니다.</strong></p>
</blockquote>
<ul>
<li>조건이 참이 되거나, 리턴문을 실행하는 경우에는 프로그램이 순차적으로 실행되지 않는다. ❌</li>
<li>이때, 프로그램 카운터 값은 임의의 위치로 변경된다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/a225a82b-9e90-4118-97f3-e47272bc0305/image.png" alt="">
<img src="https://velog.velcdn.com/images/w_dw_r/post/fffa45c8-a8a2-4526-9cce-d23d44cc2540/image.png" alt=""></li>
</ul>
<h3 id="1-2-명령어-레지스터">1-2. 명령어 레지스터</h3>
<p>메모리에서 방금 읽어들인 <strong>명령어(해석할 명령어)를 저장</strong>한다.</p>
<p><strong>명령어를 해석한 뒤에</strong> ALU로 하여금 <strong>연산하도록 시키거나,</strong> 다른 부품으로 <strong>제어 신호를 보내 해당 부품을 작동시킨다.</strong>
<code>*ALU: 사칙 연산, 논리 연산과 같은 연산을 수행할 회로로 구성되어 있는 일종의 계산기이다.</code></p>
<h3 id="1-3-범용-레지스터">1-3. 범용 레지스터</h3>
<p>다양하고 일반적인 상황에서 자유롭게 사용 가능하며, <strong>데이터와 명령어, 주소를 모두 저장한다.</strong></p>
<p>일반적으로 CPU 안에는 여러 개의 범용 레지스터가 존재한다.</p>
<h3 id="1-4-플래그-레지스터">1-4. 플래그 레지스터</h3>
<p>연산의 결과 혹은 CPU 상태에 대한 부가 정보인 플래그 값을 저장한다.
<code>*플래그: CPU가 명령어를 처리하는 과정에서 반드시 참조해야 할 상태 정보를 의미하는 비트이다.</code></p>
<table>
<thead>
<tr>
<th align="left">플래그 레지스터의 플래그(비트) 구성</th>
</tr>
</thead>
<tbody><tr>
<td align="left">부호 플래그</td>
</tr>
<tr>
<td align="left">제로 플래그</td>
</tr>
<tr>
<td align="left">캐리 플래그</td>
</tr>
<tr>
<td align="left">오버플로우 플래그</td>
</tr>
<tr>
<td align="left">인터럽트 플래그</td>
</tr>
<tr>
<td align="left">슈퍼바이저 플래그</td>
</tr>
</tbody></table>
<h3 id="1-5-스택-포인터">1-5. 스택 포인터</h3>
<p>메모리 내 스택 영역의 <strong>최상단 스택 데이터 위치</strong>를 가리키는 특별한 레지스터이다.
스택 포인터는 <strong>마지막으로 저장된 데이터의 위치</strong>를 가리키는 레지스터이자, <strong>스택이 채워진 정도</strong>를 나타내는 레지스터이다.</p>
<p><code>*메모리에는 실행 중인 프로그램들이 적재되어 있고, 실행 중인 각 프로그램들은 스택과 같은 형태로 사용 가능한 주소 공간을 하나 이상 가지고 있다.</code></p>
<blockquote>
<p>즉, 스택에서 데이터를 꺼낸다면 <strong>가장 꼭대기에 있는 스택 데이터를 꺼내고</strong>, 스택 포인터는 <strong>그 다음 스택 데이터가 저장된 주소를 가리킨다.</strong>
<img src="https://velog.velcdn.com/images/w_dw_r/post/adb6a8e1-a2e3-44bf-bde6-5a5278d47c14/image.png" alt=""></p>
</blockquote>
<hr>
<h2 id="2-인터럽트-cpu의-작업을-방해하는-신호">2. 인터럽트: CPU의 작업을 방해하는 신호</h2>
<p>CPU가 수행 중인 작업은 방해를 받아 잠시 중단될 수 있다.
이때, CPU의 작업을 방해하는 신호를 보내는 게 <strong>인터럽트</strong>이다.</p>
<pre><code>인터럽트
 ├── 동기 인터럽트 (예외) 
 └── 비동기 인터럽트 (하드웨어 인터럽트)
      ├── 마스크 가능 인터럽트 (Maskable Interrupt, MIR)
      └── 마스크 불가능 인터럽트 (Non-Maskable Interrupt, NMI)</code></pre><h3 id="2-1-동기-인터럽트-예외">2-1. 동기 인터럽트 (예외)</h3>
<p>CPU에 의해 발생하는 인터럽트이다.
가령 CPU가 프로그래밍 오류와 같은 예외적인 상황을 마주쳤을 때 발생한다.</p>
<pre><code>동기 인터럽트 (예외, Exception)
 ├── 폴트 (Fault)
 ├── 트랩 (Trap)
 ├── 중단 (Abort)
 └── 소프트웨어 인터럽트 (Software Interrupt)</code></pre><ul>
<li><p><strong>폴트:</strong> 예외를 처리한 직후에 <strong>예외가 발생한 명령어부터 실행을 재개</strong>하는 예외이다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/6385b7d2-a4fb-4669-85b6-8e03904f3fdb/image.png" alt=""></p>
</li>
<li><p><strong>트랩:</strong> 예외를 처리한 직후에 <strong>예외가 발생한 명령어의 다음 명령어부터 실행을 재개</strong>하는 예외이다.</p>
</li>
<li><p><strong>중단:</strong> CPU가 실행 중인 프로그램을 강제로 중단시킬 수밖에 없는 <strong>심각한 오류를 발견했을 때 발생</strong>하는 예외이다.</p>
</li>
<li><p><strong>소프트웨어 인터럽트:</strong> <strong>시스템 콜이 발생했을 때 발생</strong>하는 예외이다.</p>
</li>
</ul>
<h3 id="2-2-비동기-인터럽트-하드웨어-인터럽트">2-2. 비동기 인터럽트 (하드웨어 인터럽트)</h3>
<p><strong>주로 입출력 장치에 의해 발생</strong>하는 인터럽트이다.</p>
<p>작업이 끝나기를 마냥 기다릴 필요 없이 <strong>작업이 진행되는 동안 온전히 다른 작업을 처리</strong>할 수 있다.
<code>➡️ CPU 사이클 낭비 최소화 + 효율적 명령어 처리</code></p>
<blockquote>
<p>쉽게 말해 비동기 인터럽트는 <strong>알림의 역할</strong>을 한다.
(예: 세탁기의 세탁 완료 알림, 프린터의 작업 완료 알림 등)</p>
</blockquote>
<table>
<thead>
<tr>
<th align="left">일반적으로 CPU가 하드웨어 인터럽트를 처리하는 순서</th>
</tr>
</thead>
<tbody><tr>
<td align="left">① 입출력 장치는 CPU에게 <strong>인터럽트 요청 신호</strong>를 보낸다.</td>
</tr>
<tr>
<td align="left">② CPU는 실행 사이클이 끝나고 명령어를 인출하기 전에 항상 인터럽트 여부를 확인한다.</td>
</tr>
<tr>
<td align="left">③ CPU는 인터럽트 요청을 확인하고, <strong>인터럽트 플래그</strong>를 통해 현재 인터럽트의 수용 가능 여부를 확인한다.</td>
</tr>
<tr>
<td align="left">④ 인터럽트를 받아들일 수 있다면 CPU가 지금까지의 작업을 백업한다.</td>
</tr>
<tr>
<td align="left">⑤ CPU는 <strong>인터럽트 벡터</strong>를 참조하여 <strong>인터럽트 서비스 루틴</strong>을 실행한다.</td>
</tr>
<tr>
<td align="left">⑥ 인터럽트 서비스 루틴 실행이 끝나면 ④에서 백업해둔 작업을 복구하여 실행을 재개한다.</td>
</tr>
</tbody></table>
<h4 id="1-인터럽트-요청-신호">(1) 인터럽트 요청 신호</h4>
<p>인터럽트 하기 전에 CPU에게 인터럽트의 가능 여부를 확인하는 과정이다.</p>
<p><strong><em>이 과정이 필요한 이유는,</em></strong> <code>인터럽트 처리</code>는 결국 <strong>CPU의 정상적인 실행 흐름을 끊는 것</strong>이기 때문이다.</p>
<h4 id="2-인터럽트-플래그">(2) 인터럽트 플래그</h4>
<p>하드웨어 인터럽트를 받아들일지, 무시할지를 결정하는 플래그이다.</p>
<p><strong>CPU가 인터럽트 요청을 수용하기 위해서는</strong> 플래그 레지스터의 <strong>인터럽트 플래그가 활성화</strong>되어 있어야 한다.
⚠️ <strong>만약 비활성화 되어 있을 시, CPU는 해당 요청을 무시하니 유의해야 한다.</strong></p>
<blockquote>
<p>🚨 다만, <strong>모든 하드웨어 인터럽트를 인터럽트 플래그로 막을 수 있는 것은 아니다.</strong></p>
</blockquote>
<p>인터럽트 플래그가 <code>불가능(비활성화)으로 설정되어 있더라도 무시할 수 없는 인터럽트 요청도 있다.</code>
(가장 우선 순위가 높고, 가장 먼저 처리해야 하는 정전이나 하드웨어 고장으로 인한 인터럽트는 무시할 수 없다.)</p>
<h4 id="3-인터럽트-서비스-루틴-isr">(3) 인터럽트 서비스 루틴 (ISR)</h4>
<p>인터럽트를 처리하기 위한 프로그램이다.</p>
<p>어떤 인터럽트가 발생했을 때 <strong>해당 인터럽트를 어떻게 처리하고 작동해야 할지에 대한 정보(설명서)</strong> 를 나타낸다.</p>
<p> 인터럽트는</p>
<p>1) <strong>인터럽트 서비스 루틴을 실행</strong>하고
2) <strong>본래 수행하던 작업으로 다시 돌아오는 방식</strong>으로 작동된다.</p>
<blockquote>
<p>📑 가구마다 조립 설명서가 다르듯이,
입출력 장치마다 인터럽트를 처리하기 위한 동작이 다르기 때문에, <code>입출력 장치들은 각기 다른 서비스 루틴을 가진다.</code>
<img src="https://velog.velcdn.com/images/w_dw_r/post/8105337b-56ad-4055-b2fd-4708a8d4cf42/image.png" alt="">
<img src="https://velog.velcdn.com/images/w_dw_r/post/35f5f013-01a6-4cbd-a3c5-9e87816e1caa/image.png" alt=""></p>
</blockquote>
<h4 id="4-인터럽트-벡터">(4) 인터럽트 벡터</h4>
<p><strong>인터럽트 서비스 루틴을 식별하기 위한 정보</strong>이다.
어떤 입출력 장치에서 인터럽트가 발생한 건지, 그 장치의 인터럽트 서비스 루틴은 뭔지 알 수 있다.</p>
<p><code>*CPU가 인터럽트 서비스 루틴을 실행하려면 인터럽트 서비스 루틴의 시작 주소를 알아야 하며, 이는 인터럽트 벡터를 통해 알 수 있다.</code></p>
<blockquote>
<p>🚨 만약 <strong>CPU가 작업을 수행하는 도중에 프린터에서 인터럽트가 발생하면</strong></p>
<ul>
<li>CPU는 전달받은 인터럽트 벡터를 참조하여 프린터의 인터럽트 서비스 루틴의 시작 주소를 알아낸다.</li>
<li>그 다음 서비스 루틴의 시작 주소부터 실행하면서 프린터의 인터럽트 서비스 루틴을 실행한다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/8c550a7d-717d-4143-b3d2-32e78646c401/image.png" alt=""></li>
</ul>
</blockquote>
<hr>
<h2 id="3-cpu-성능-향상을-위한-설계">3. CPU 성능 향상을 위한 설계</h2>
<h3 id="3-1-cpu-클럭-속도">3-1. CPU 클럭 속도</h3>
<ul>
<li><strong>클럭:</strong> 컴퓨터의 부품을 움직일 수 있게 하는 시간의 단위이다.</li>
<li><strong>클럭 속도:</strong> 클럭이 1초에 몇 번 반복되는지를 <code>헤르츠 단위(Hz)</code>로 나타낸다.
<img src="https://velog.velcdn.com/images/w_dw_r/post/0c71ec54-0489-49ae-8d2b-3593122449ba/image.png" alt=""></li>
</ul>
<p><code>클럭 속도 ⬆️ ➡️ 명령어 사이클 반복 속도 ⬆️ ➡️ 다른 부품들의 동작 속도 ⬆️</code></p>
<p>실제로 클럭 속도가 높은 CPU는 일반적으로 성능이 높다. 클럭 속도는 CPU 속도의 단위로 간주되기도 한다.</p>
<h3 id="3-2-멀티-코어와-멀티-스레드">3-2. 멀티 코어와 멀티 스레드</h3>
<ul>
<li><strong>코어 (Core):</strong> CPU 내에서 명령어를 읽어들이고, 해석하고, 실행하는 부품을 의미한다.
<code>*원칙적으로 CPU는 하나만 존재할 수 있었지만, 기술 발전으로 코어가 여러 개 존재할 수 있게 되었다.</code>
<img src="https://velog.velcdn.com/images/w_dw_r/post/05c7d548-dafe-470d-9e19-5e2683edbcb5/image.png" alt=""></li>
</ul>
<blockquote>
<p>어떤 CPU를 설명하는 글에 코어가 8개라고 명시되어 있다면 CPU가 8개라는 이야기이다.</p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">코어 개수</th>
<th align="left">명칭</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="left">싱글 코어 (Single-Core)</td>
</tr>
<tr>
<td align="center">2</td>
<td align="left">듀얼 코어 (Dual-Core)</td>
</tr>
<tr>
<td align="center">4</td>
<td align="left">쿼드 코어 (Quad-Core)</td>
</tr>
<tr>
<td align="center">6</td>
<td align="left">헥사 코어 (Hexa-Core)</td>
</tr>
<tr>
<td align="center">8</td>
<td align="left">옥타 코어 (Octa-Core)</td>
</tr>
<tr>
<td align="center">10</td>
<td align="left">데카 코어 (Deca-Core)</td>
</tr>
<tr>
<td align="center">12</td>
<td align="left">도데카 코어 (Dodeca-Core)</td>
</tr>
</tbody></table>
<ul>
<li><strong>스레드 (Thread):</strong> 실행 흐름의 단위이다.</li>
<li><strong>하드웨어 스레드 (논리 프로세서):</strong> 하나의 코어가 동시에 처리하는 명령어의 단위이다.</li>
<li><strong>멀티 스레드 프로세서 / 멀티 스레드 CPU:</strong> 하나의 코어로 여러 명령어를 동시에 처리하는 CPU이다.</li>
</ul>
<blockquote>
<ul>
<li>CPU가 한 번에 하나의 명령어를 처리 ➡️ 1코어 1스레드 CPU</li>
<li>CPU 2개가 한 번에 4개의 명령어를 처리 ➡️ 2코어 4 스레드 CPU
<img src="https://velog.velcdn.com/images/w_dw_r/post/dd217460-c865-4c37-9bb0-441cd2643dcb/image.png" alt=""></li>
</ul>
</blockquote>
<p>하드웨어 스레드 입장에서는 한 번에 하나의 명령어를 처리하는 1개의 CPU와 다를 바 없다.
<code>&quot;1개의 CPU&quot; 는 코어 전체나 물리적인 CPU 칩을 뜻하는 것이 아니라, &quot;실행 주체(Execution Unit)&quot; 를 비유적으로 표현한 것이다!</code></p>
<p>마찬가지로 2코어 4스레드 CPU는 메모리 입장에서는 한 번에 하나의 명령어를 처리하는 4개의 CPU가 있는 것처럼 보인다.
<code>&quot;2코어 4스레드 CPU&quot;에서 4라는 숫자는 &quot;CPU가 외부에 약속하는, 동시에 명령어를 받아 처리할 수 있는 실행 흐름의 총 개수&quot; 를 의미한다. 그래서 메모리(OS) 입장에서는 4개의 CPU가 있는 것처럼 보이는 것이다. 실제 CPU의 수를 뜻하는 게 아니다. X</code></p>
<ul>
<li><strong>소프트웨어 스레드:</strong> 하나의 프로그램에서 독립적으로 실행되는 단위이다.</li>
</ul>
<h4 id="하드웨어-스레드-vs-소프트웨어-스레드">하드웨어 스레드 vs 소프트웨어 스레드</h4>
<table>
<thead>
<tr>
<th align="left">스레드 종류</th>
<th align="left">구현 목표</th>
<th align="left">역할</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>하드웨어 스레드</strong></td>
<td align="left"><strong>병렬성 (Parallelism)</strong></td>
<td align="left">작업을 물리적으로 동시에 실행하는 CPU 코어의 논리적 분할이다.</td>
</tr>
<tr>
<td align="left"><strong>소프트웨어 스레드</strong></td>
<td align="left"><strong>동시성 (Concurrency)</strong></td>
<td align="left">자원을 공유하며, OS 스케줄링을 통해 번갈아 가며 실행되는 논리적인 실행 단위이다.</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/8d71229f-dfd5-4aca-a369-51959b6066e0/image.png" alt=""></p>
<h4 id="프로세스와-소프트웨어-스레드의-관계">프로세스와 소프트웨어 스레드의 관계</h4>
<table>
<thead>
<tr>
<th align="left">개념</th>
<th align="left">비유</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>프로세스</strong></td>
<td align="left">공장 (자원 소유 경계)</td>
<td align="left">독립적인 메모리 공간과 자원(코드, 데이터, 힙)을 소유하는 작업의 독립 단위이다.</td>
</tr>
<tr>
<td align="left"><strong>소프트웨어 스레드</strong></td>
<td align="left">공장 내 작업 라인 (실행 흐름)</td>
<td align="left">프로세스의 자원을 공유하며, CPU를 할당받아 명령을 실행하는 가장 작은 실행 단위이다.</td>
</tr>
</tbody></table>
<h4 id="프로그램-vs-프로세서-vs-프로세스">프로그램 vs 프로세서 vs 프로세스</h4>
<table>
<thead>
<tr>
<th align="left">용어</th>
<th align="left">쉬운 비유</th>
<th align="left">역할</th>
<th align="left">상태</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>프로그램 (Program)</strong></td>
<td align="left">요리 레시피 📖</td>
<td align="left">실행되기 전의 정적인 명령어 묶음 (코드 파일)이다.</td>
<td align="left">정적</td>
</tr>
<tr>
<td align="left"><strong>프로세서 (Processor)</strong></td>
<td align="left">요리사 🧑‍🍳</td>
<td align="left">명령을 실제로 읽고 실행하는 하드웨어 장치 (CPU)이다.</td>
<td align="left">주체</td>
</tr>
<tr>
<td align="left"><strong>프로세스 (Process)</strong></td>
<td align="left">요리 중인 상태 🔥</td>
<td align="left">메모리에 로드되어 실행 중인 프로그램의 작업 단위이다.</td>
<td align="left">동적</td>
</tr>
</tbody></table>
<blockquote>
<ul>
<li>스레드의 사전적 정의만을 암기했다면 <code>&quot;1코어 1스레드 CPU가 여러 스레드로 만들어진 프로그램을 실행할 수 있다&quot;</code>는 말을 납득하기 어려울 것이다.</li>
<li><code>아래 사진은 메모리 공간 내에 실행 흐름(스레드)이 존재하거나, 여러 흐름이 존재하는 프로세스 내부의 실행 단위인 소프트웨어 스레드를 시각적으로 표현</code>한 것</li>
<li>따라서, <strong>하드웨어적인 스레드와 소프트웨어적인 스레드의 의미를 구분해서 기억해 두는 것이 좋다.</strong>
<img src="https://velog.velcdn.com/images/w_dw_r/post/b336d278-2aed-415e-8f64-4066266b908d/image.png" alt=""></li>
</ul>
</blockquote>
<hr>
<h2 id="4-파이프라이닝을-통한-명령어-병렬-처리">4. 파이프라이닝을 통한 명령어 병렬 처리</h2>
<h3 id="4-1-명령어-병렬-처리-ilp-instruction-level-parallelism">4-1. 명령어 병렬 처리 (ILP, Instruction-Level Parallelism)</h3>
<p><code>여러 명령어를 동시에 처리하여 CPU를 쉬지 않고 작동하게 함</code>으로써 성능을 높이는 기법이다.</p>
<p>이 ILP를 구현하는 핵심 기술이 바로 <strong>명령어 파이프라이닝</strong>이다.</p>
<h3 id="4-2-명령어-파이프라이닝-instruction-pipelining">4-2. 명령어 파이프라이닝 (Instruction Pipelining)</h3>
<p>명령어 파이프라이닝은 <strong>공장의 생산 라인</strong>처럼 명령어를 여러 단계로 쪼개어 각 단계를 겹쳐서 동시에 처리하는 기법이다.</p>
<p>하나의 명령어가 처리되는 과정은 일반적으로 네 단계로 나뉜다.</p>
<table>
<thead>
<tr>
<th align="left">단계</th>
<th align="left">명칭</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>① IF</strong></td>
<td align="left"><strong>명령어 인출 (Instruction Fetch)</strong></td>
<td align="left">메모리에서 다음에 실행할 명령어를 가져오는 단계이다.</td>
</tr>
<tr>
<td align="left"><strong>② ID</strong></td>
<td align="left"><strong>명령어 해석 (Instruction Decode)</strong></td>
<td align="left">가져온 명령어가 무엇을 해야 하는지(연산 종류, 대상) 해석하는 단계이다.</td>
</tr>
<tr>
<td align="left"><strong>③ EX</strong></td>
<td align="left"><strong>명령어 실행 (Execute Instruction)</strong></td>
<td align="left">해석된 명령어에 따라 ALU를 이용해 실제 연산을 수행하는 단계이다.</td>
</tr>
<tr>
<td align="left"><strong>④ WB</strong></td>
<td align="left"><strong>결과 저장 (Write Back)</strong></td>
<td align="left">연산 결과를 레지스터에 저장하는 단계이다.</td>
</tr>
</tbody></table>
<blockquote>
<p><strong>핵심 원리:</strong> 같은 단계만 겹치지 않는다면, CPU는 이 단계를 <strong>동시에</strong> 실행할 수 있다.
<code>예를 들어, 명령어 1이 실행 단계일 때, 명령어 2는 해석 단계, 명령어 3은 인출 단계에 들어갈 수 있다.</code>
<img src="https://velog.velcdn.com/images/w_dw_r/post/256a7a54-91aa-42a5-95fe-690480f3842f/image.png" alt=""></p>
</blockquote>
<h3 id="4-3-슈퍼스칼라-superscalar">4-3. 슈퍼스칼라 (Superscalar)</h3>
<p>파이프라이닝이 <strong>하나의 생산 라인</strong>이라면, <strong>슈퍼스칼라</strong>는 <strong>여러 개의 생산 라인(파이프라인)</strong> 을 동시에 두는 구조를 말한다.</p>
<p>  <code>*대부분의 현대 CPU는 여러 개의 파이프라인을 내부에 포함하는 &quot;슈퍼스칼라 구조&quot;를 채택하여, 명령어 처리량을 극대화한다.</code>
  <img src="https://velog.velcdn.com/images/w_dw_r/post/5f7ae85e-ef5d-4bad-bf6c-b9cfd89a9cbe/image.png" alt=""></p>
<h3 id="4-4-cisc-vs-risc">4-4. CISC vs. RISC</h3>
<p>명령어 병렬 처리에 최적화된 구조를 논할 때, 명령어 집합의 유형인 <strong>CISC</strong>와 <strong>RISC</strong>의 차이가 중요하다.</p>
<table>
<thead>
<tr>
<th align="left">유형</th>
<th align="left">RISC (Reduced Instruction Set Computer)</th>
<th align="left">CISC (Complex Instruction Set Computer)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>특징</strong></td>
<td align="left">짧고 규격화된 명령어<br>(1 클럭 내외 실행 지향)</td>
<td align="left">복잡하고 기능이 다채로운 명령어<br>(여러 클럭 필요)</td>
</tr>
<tr>
<td align="left"><strong>파이프라이닝 적합성</strong></td>
<td align="left"><strong>최적화</strong><br>(규격화된 크기/시간 덕분에 파이프라인 관리가 용이하다).</td>
<td align="left"><strong>비효율적</strong><br>(실행 시간이 길고 불규칙하여 파이프라인을 멈추게 할 위험이 높다).</td>
</tr>
<tr>
<td align="left"><strong>예시</strong></td>
<td align="left">Apple M1/M2 CPU 등 (ARM 기반)이다.</td>
<td align="left">Intel x86/x86-64 CPU 이다.</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/w_dw_r/post/b3f27e2e-ec57-4d33-8018-814c066c6242/image.png" alt=""></p>
<h3 id="4-5-파이프라인-위험-pipeline-hazard">4-5. 파이프라인 위험 (Pipeline Hazard)</h3>
<p>파이프라이닝은 성능을 높이지만, 명령어들이 겹쳐 실행되면서 문제가 발생할 수 있다.</p>
<h4 id="1-데이터-위험-data-hazard">(1) 데이터 위험 (Data Hazard)</h4>
<ul>
<li><strong>원인:</strong> 명령어 간의 <strong>데이터 의존성</strong> 때문에 발생한다.</li>
<li><strong>상황:</strong> 이전 명령어의 <strong>결과</strong>가 다음 명령어의 <strong>입력</strong>으로 사용되어야 하는데, 다음 명령어가 이전 명령어가 결과를 저장하기 전에 먼저 실행되려고 할 때 발생한다.
<code>*예시: 명령어 2가 명령어 1의 결과(R1)를 필요로 할 때, 명령어 2는 명령어 1이 &quot;결과 저장(WB)&quot;을 완료할 때까지 기다려야 한다.*</code></li>
</ul>
<h4 id="2-제어-위험-control-hazard">(2) 제어 위험 (Control Hazard)</h4>
<ul>
<li><strong>원인:</strong> <strong>프로그램 카운터(PC)</strong> 의 흐름이 갑작스럽게 변경될 때 발생한다.</li>
<li><strong>상황:</strong> <strong>JUMP</strong>나 <strong>인터럽트</strong> 등으로 인해 실행 흐름이 바뀌면, 이미 파이프라인에 인출되거나 해석 중이던 명령어들은 모두 <strong>쓸모없어지며</strong> 버려진다.</li>
</ul>
<h4 id="3-구조적-위험-structural-hazard">(3) 구조적 위험 (Structural Hazard)</h4>
<ul>
<li><strong>원인:</strong> 서로 다른 명령어들이 <strong>같은 CPU 부품</strong>을 동시에 사용하려고 할 때 발생한다. (<strong>자원 위험</strong>이라고도 한다.)</li>
<li><strong>상황:</strong> 명령어 1이 레지스터에 결과를 저장하는 단계인데, 명령어 2가 동시에 레지스터를 읽으려고 할 때 충돌한다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>