<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>거짓말같은 벨로그 부계</title>
        <link>https://velog.io/</link>
        <description>양치기소녀</description>
        <lastBuildDate>Mon, 25 May 2026 20:28:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>거짓말같은 벨로그 부계</title>
            <url>https://velog.velcdn.com/images/cold_as_hell/profile/87e205f1-414b-41e7-8c14-d813733434bc/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 거짓말같은 벨로그 부계. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/cold_as_hell" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[복습] 다리를 지나는 트럭]]></title>
            <link>https://velog.io/@cold_as_hell/%EB%B3%B5%EC%8A%B5-%EB%8B%A4%EB%A6%AC%EB%A5%BC-%EC%A7%80%EB%82%98%EB%8A%94-%ED%8A%B8%EB%9F%AD</link>
            <guid>https://velog.io/@cold_as_hell/%EB%B3%B5%EC%8A%B5-%EB%8B%A4%EB%A6%AC%EB%A5%BC-%EC%A7%80%EB%82%98%EB%8A%94-%ED%8A%B8%EB%9F%AD</guid>
            <pubDate>Mon, 25 May 2026 20:28:43 GMT</pubDate>
            <description><![CDATA[<p>복습은 학습한 내용을 단기 기억에서 장기 기억으로 전환하여 기억력을 극대화하고, 지식의 활용도를 높여준다.
시스터디 또한 이러한 학습 효과를 경험하기 위해 1주일 동안 복습하는 시간도 가져보기로 했다.</p>
<hr>
<h1 id="문제">문제</h1>
<p>오늘 복습해 볼 문제는 2월에 과제로 받았던 다리를 지나는 트럭이다.
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/42583">링크</a></p>
<h2 id="문제-요약">문제 요약</h2>
<blockquote>
<p>다리의 길이와 무게를 기준으로 두고 모든 트럭이 다리를 건너려면 최소 몇 초가 필요한지 구한다.</p>
</blockquote>
<pre><code class="language-python">##  예시 ## 

# bridge_length=2, weight=10, truck_weights=[7,4,5,6]
# 초기큐 : queue=[0,0], truck_weights =[7,4,5,6], total=0
# 1초: queue=[0,7], truck_weights[4,5,6], total=7
# 2초: queue=[7,0], truck_weights=[4,5,6], total=7 (4는 무게초과로 대기)
# 3초: queue=[0,4], truck_weights=[5,6], total=4```</code></pre>
<hr>
<h1 id="이전-풀이">이전 풀이</h1>
<pre><code class="language-python">from collections import deque
def solution(bridge_length, weight, truck_weights):
    # 다리를 나타내는 큐 (다리 길이만큼 0으로 초기화 - 0은 빈 공간)
    queue = deque([0] * bridge_length)

    # 대기 중인 트럭들을 큐로 관리
    orders = deque(truck_weights)

    # 경과 시간
    time = 0

    # 현재 다리 위에 있는 트럭들의 총 무게
    total = 0

    # 1. 대기 중인 트럭이 없어질 때까지 1초씩 시뮬레이션
    while orders:
        time += 1

        # 2. 1초가 지났으므로 다리 위 모든 트럭이 한 칸 앞으로 이동
        #    맨 앞 칸(queue[0])이 다리를 완전히 벗어나므로 총 무게에서 제거
        total -= queue[0]
        queue.popleft()

        # 3. 대기 중인 첫 번째 트럭이 다리에 올라갈 수 있는지 확인
        #    현재 다리 위 총 무게 + 다음 트럭 무게가 제한 무게를 초과하면
        #    트럭을 올리지 않고 빈 공간(0)으로 채워 다리 길이를 유지
        if total + orders[0] &gt; weight:
            queue.append(0)
        else:
            # 4. 무게 제한 이하이면 대기 트럭을 다리에 올림
            #    대기 큐에서 트럭을 꺼내 다리 큐에 추가하고 총 무게 갱신
            w = orders.popleft()
            total += w
            queue.append(w)

    # 마지막 트럭이 다리를 완전히 건너는 시간 추가
    return time + bridge_length</code></pre>
<hr>
<h1 id="새-풀이">새 풀이</h1>
<blockquote>
<p>큐에 0을 넣지 않아도 풀 수 있다.</p>
</blockquote>
<p>이전 코드는 트럭이 다리에 올라가지 못할 때 deque에 0을 넣고, 올라갈 수 있을 때까지 반복했다. </p>
<p>그러나 트럭이 다리에 올라갈 때마다 무게, 나가는 시간을 저장한다면 불필요한 반복 연산시간을 줄일 수 있을 것이다.</p>
<p>예상되는 효과는 아래와 같다.</p>
<p>(1) 대기 시간을 매 루프마다 소비하지 않고 앞 트럭이 나가는 시간으로 바로 점프해 불필요한 반복을 제거할 수 있다</p>
<p>(2) 나가는 시간이 미리 저장되어 있어 마지막에 time + bridge_length 를 별도로 계산하지 않고 바로 반환할 수 있다.</p>
<pre><code class="language-python">from collections import deque

def solution(bridge_length, weight, truck_weights):
    # 빈 큐로 시작 - 0으로 채울 필요 없이 (무게, 나가는 시간)으로 관리
    bridge_queue = deque()

    # 대기 중인 트럭들 관리
    waiting_trucks = deque(truck_weights)

    # 현재 시간
    current_time = 0

    # 현재 다리 위 총 무게
    current_weight = 0

    while waiting_trucks:

        # 1. 나가는 시간이 된 트럭만 골라서 제거
        while bridge_queue and bridge_queue[0][1] &lt;= current_time:
            current_weight -= bridge_queue.popleft()[0]

        # 2. 다음 트럭을 올려도 무게 제한을 넘지 않는 경우
        if current_weight + waiting_trucks[0] &lt;= weight:

            # 대기 트럭 꺼내기
            truck_weight = waiting_trucks.popleft()

            # 현재 다리 무게 증가
            current_weight += truck_weight

            # 트럭이 다리에 올라가는 시간
            current_time += 1

            # 3. (무게, 나가는 시간)을 함께 저장
            # 나가는 시간 = 현재 시간 + 다리 길이
            bridge_queue.append(
                (truck_weight, current_time + bridge_length)
            )

        else:
            # 4. 다음 트럭을 못 올리는 경우

            # 앞 트럭이 나가는 시간으로 바로 점프
            if bridge_queue:
                current_time = bridge_queue[0][1]

            # 예외 처리용
            else:
                current_time += 1

    # 마지막으로 저장했던 트럭이 다리를 완전히 건너는 시간 출력
    return bridge_queue[-1][1]</code></pre>
<hr>
<h1 id="주요-자료구조">주요 자료구조</h1>
<blockquote>
<p><strong>deque</strong></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/8349d72f-5e28-4329-ae2b-6159320dac30/image.png" alt=""></p>
<pre><code class="language-python"># &lt;파이썬 알고리즘 인터뷰&gt; p.266, 책만, 2020</code></pre>
<p>일반적인 큐는 뒤에서만 삽입이 이루어지고 앞에서만 인출이 가능한 반면, 데크(Deque)는 양쪽에서 모두 삽입과 삭제가 가능해 스택과 큐의 특징을 모두 갖고 있다. </p>
<p>물론 이 문제에서 양쪽 삽입과 삭제를 활용하지는 않았지만, 일반적인 리스트의 삭제 연산인 pop(0)보다 popleft()가 빠르기에 성능 최적화에 도움이 되었다.</p>
<hr>
<h2 id="pop0-vs-popleft">pop(0) vs popleft()</h2>
<pre><code class="language-python"># list.pop(0) → O(n)
lst = [1, 2, 3, 4, 5]
lst.pop(0)
# [1, 2, 3, 4, 5]
#  ↑ 제거
# [2, 3, 4, 5]
#  ↑ ↑ ↑ ↑ 나머지 요소를 전부 한 칸씩 앞으로 당김 → 요소 수만큼 연산 발생

# deque.popleft() → O(1)
from collections import deque
dq = deque([1, 2, 3, 4, 5])
dq.popleft()
# [1, 2, 3, 4, 5]
#  ↑ 제거
#     ↑ 포인터만 다음 요소로 이동 → 요소 수와 무관하게 연산 1번</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[트래픽이 갑자기 10배 늘어나면 가장 먼저 걱정할 것은 무엇인가요?]]></title>
            <link>https://velog.io/@cold_as_hell/%ED%8A%B8%EB%9E%98%ED%94%BD%EC%9D%B4-%EA%B0%91%EC%9E%90%EA%B8%B0-10%EB%B0%B0-%EB%8A%98%EC%96%B4%EB%82%98%EB%A9%B4-%EA%B0%80%EC%9E%A5-%EB%A8%BC%EC%A0%80-%EA%B1%B1%EC%A0%95%ED%95%A0-%EA%B2%83%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94</link>
            <guid>https://velog.io/@cold_as_hell/%ED%8A%B8%EB%9E%98%ED%94%BD%EC%9D%B4-%EA%B0%91%EC%9E%90%EA%B8%B0-10%EB%B0%B0-%EB%8A%98%EC%96%B4%EB%82%98%EB%A9%B4-%EA%B0%80%EC%9E%A5-%EB%A8%BC%EC%A0%80-%EA%B1%B1%EC%A0%95%ED%95%A0-%EA%B2%83%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94</guid>
            <pubDate>Sun, 24 May 2026 11:34:06 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>진정한 테토 <del>호소인</del> 는 선크림도 바르지 않고, 걱정도 하지 않는다.
그치만 언니가 고민해 보라고 했으니 고민이라는 것을 해보겠다.</p>
<hr>
<h1 id="트래픽이-증가한다">트래픽이 증가한다</h1>
<p>트래픽은 서버의 데이터 전송량을 의미한다. 외부에서 해당 서버에 접속하는 사용자가 많아질수록 트래픽은 증가한다.</p>
<p>만약 서버가 감당할 수 있는 한계를 초과한 트래픽이 지속적으로 유입되면, 서버는 정상적으로 동작하지 못하고 결국 다운된다.</p>
<p><strong>따라서 평소보다 트래픽이 10배 이상 급증한다면, 별도의 대비가 없는 서버는 분명히 다운된다.</strong></p>
<hr>
<h1 id="nextjs에서-트래픽-증가">Next.js에서 트래픽 증가</h1>
<p>Next.js를 사용한다고 가정해보자.</p>
<p>Next.js는 싱글 스레드 기반의 자바스크립트 런타임인 Node.js 위에서 동작하며, 서버에서 리소스를 미리 렌더링한 뒤 브라우저에 전달하는 SSR(Server Side Rendering) 방식을 지원한다. Node.js는 I/O 작업에는 뛰어난 성능을 보이지만, CPU 중심 작업에서는 단일 스레드만 사용하기 때문에 적절한 구성 없이 많은 작업을 처리할 경우 성능 문제가 발생할 수 있다.</p>
<p><strong>(1) 서버 병목현상</strong>
또한 싱글 스레드 환경에서는 병렬 처리가 제한되므로 작업을 순차적으로 처리하게 된다. 따라서 복잡한 페이지를 SSR하는 동안 서버는 다른 요청을 즉시 처리하지 못하고 대기 상태에 놓일 수 있다.</p>
<p><strong>(2) 대규모 트래픽 처리 한계</strong>
소수의 요청만 처리할 때는 큰 문제가 없지만, 초당 수백 명 이상의 사용자가 동시에 접속하는 상황에서는 순차 처리로 인해 응답 시간이 증가하고 서버가 다운될 가능성도 존재한다. 결국 단일 스레드 기반 환경에서는 병목 현상과 블로킹 현상이 발생할 수 있으며, 과도한 서버 부하는 렌더링 성능 저하로 이어질 수 있다.</p>
<hr>
<h1 id="해결책">해결책</h1>
<p> <strong>캐싱 전략</strong>을 사용하면, 서버가 동일한 데이터를 반복적으로 렌더링하지 않아도 되어 서버 부하를 줄일 수 있고, 응답 속도가 개선되어 대규모 트래픽 상황에서도 안정적인 서비스 운영이 가능해진다. </p>
<p><em>캐싱전략 : 자주 사용하는 데이터를 빠르게 접근할 수 있도록 저장해 성능을 최적화하는 전략</em></p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/e063b618-8d3a-4167-aff5-b185622234bf/image.svg" alt=""></p>
<hr>
<h2 id="강제캐싱force-cache">강제캐싱(force-cache)</h2>
<p>우리가 fetch API로 캐싱을 수행할 때 별도의 옵션을 지정하지 않으면, 브라우저는 사용자가 이전에 동일한 요청을 보낸 적이 있는지 HTTP 캐시를 먼저 확인한다.</p>
<ul>
<li>HTTP 캐시에 최신 데이터가 있다면 : 서버 요청 없이 캐시 데이터를 즉시 반환</li>
<li>HTTP 캐시에 오래된 데이터가 있다면 : 서버에서 데이터 변경 여부를 확인한 뒤 캐시를 사용하거나 갱신할 수 있는 조건부요청 발신</li>
<li>일치하는 캐시가 없다면 : 서버에 새 요청을 보내 응답 데이터를 캐시에 저장</li>
</ul>
<p>하지만 이러한 과정에서는 캐시의 최신 여부를 검사하기 위한 추가 요청이 발생하므로 일정한 시간이 소요된다.</p>
<p>따라서, <code>강제캐싱 (force-cache)</code> 을 사용한다면,</p>
<ul>
<li>서버로부터 받은 응답 데이터를 캐시에 저장</li>
<li>최신화되었는지 여부를 판단하지 않고, 사용자 요청시 일치하는 데이터가 있다면 즉시 반환</li>
</ul>
<p>하여 위 과정을 축소하고 서버로 보내는 요청 수를 줄여 서버 부하를 줄일 수 있다.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-js">// 강제캐싱을 헤더에 사용하는 경우
fetch(&#39;/api&#39;, { cache: &#39;no-store&#39; })

// 강제캐싱을 응답에 사용하는 경우
fetch(&quot;some.json&quot;, { cache: &quot;force-cache&quot; }).then((response) =&gt; {
  /* 상세 생략 */
});
</code></pre>
<hr>
<h2 id="revalidation">Revalidation</h2>
<p>강제 캐싱은 서버 요청 수를 줄여 성능을 향상시킬 수 있지만, 캐시된 데이터의 최신성을 보장하지는 않는다. 
따라서 데이터 변동성이 높은 서비스에서는 일정 주기마다 캐시를 재검증하고 갱신하는 Revalidation 전략을 사용하여 이를 보완할 수 있다.</p>
<p><em>※ 재검증 과정에서 추가적인 서버 요청이 발생하므로 강제 캐싱에 비해 응답 속도가 조금 느려질 수 있다.
감안하여 사용하자.</em></p>
<h3 id="예시-1">예시</h3>
<pre><code class="language-js">// 30초간 캐싱하고, 이후에는 새로운 요청보내기
fetch(&#39;/a&#39;, { next: { revalidate: 30 } })</code></pre>
<hr>
<h2 id="정리">정리</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>강제 캐싱 (<code>force-cache</code>)</th>
<th>Revalidation (<code>revalidate</code>)</th>
</tr>
</thead>
<tbody><tr>
<td>동작 방식</td>
<td>캐시 데이터를 우선적으로 사용</td>
<td>일정 시간이 지나면 캐시를 갱신</td>
</tr>
<tr>
<td>최신 데이터 확인</td>
<td>확인하지 않음</td>
<td>지정된 시간마다 재검증</td>
</tr>
<tr>
<td>서버 요청</td>
<td>캐시가 있으면 서버 요청 없이 반환</td>
<td>재검증 시 서버 요청 발생</td>
</tr>
<tr>
<td>성능</td>
<td>매우 빠름</td>
<td>상대적으로 약간 느림</td>
</tr>
<tr>
<td>서버 부하</td>
<td>매우 적음</td>
<td>주기적으로 발생</td>
</tr>
<tr>
<td>데이터 최신성</td>
<td>낮을 수 있음</td>
<td>일정 수준 유지 가능</td>
</tr>
<tr>
<td>사용 목적</td>
<td>성능 최적화</td>
<td>성능 + 최신성 균형</td>
</tr>
<tr>
<td>적합한 데이터</td>
<td>공지사항, 정적 콘텐츠</td>
<td>게시글, 뉴스, 랭킹</td>
</tr>
<tr>
<td>Next.js 예시</td>
<td><code>cache: &#39;force-cache&#39;</code></td>
<td><code>next: { revalidate: 30 }</code></td>
</tr>
<tr>
<td>특징</td>
<td>오래된 데이터도 즉시 반환</td>
<td>일정 주기로 새 데이터 반영</td>
</tr>
</tbody></table>
<hr>
<h2 id="isrincremental-static-regeneration을-이용한-페이지-캐싱">ISR(Incremental Static Regeneration)을 이용한 페이지 캐싱</h2>
<p>웹 페이지를 미리 생성하는 렌더링 기법인 ISR(Incremental Static Regeneration)을 사용하면, 최초 요청 시 생성된 정적 페이지를 캐싱하여 빠르게 제공할 수 있다.</p>
<p>최초 렌더링 이후 변경되는 데이터는 필요한 시점에만 SSR(Server Side Rendering), CSR (Client Side Rendering) 등으로 다시 렌더링함으로써, 성능 최적화와 데이터 최신성을 모두 고려한 효율적인 렌더링이 가능하다.</p>
<h3 id="예시-2">예시</h3>
<p>※ ISR을 대규모 서비스 환경에서 안정적으로 운영하기 위해서는 데이터 요청 처리 외에도 Redis와 같은 별도의 캐싱 서버를 구축하여 캐싱된 페이지 데이터를 중앙에서 관리하는 작업이 필요하다. </p>
<p>여러 개의 Node.js 서버 인스턴스가 각각 독립적으로 캐시를 생성하고 관리하는 구조에서 발생할 수 있는 캐시 불일치 문제를 해결해야하기 때문이다.</p>
<pre><code class="language-js">
// 페이지 라우터

export const getStaticProps = async () =&gt; {

  // 데이터 요청
  const data = await fetch(&#39;/a&#39;)
    .then((res) =&gt; res.json())

  return {

    // 컴포넌트에 전달할 props
    props: { data },

    // 30초마다 페이지 재생성(Revalidation)
    revalidate: 30
  }
}

function Page({ data }) {

  // 캐싱된 정적 페이지 반환
  return &lt;div&gt;{data.title}&lt;/div&gt;
}</code></pre>
<pre><code class="language-js">
// 앱라우터

// → 해당 페이지를 30초 주기로 재생성

export const revalidate = 30

async function Page() {

  // fetch 결과를 캐싱
  const data = await fetch(&#39;/a&#39;)
    .then((res) =&gt; res.json())

  // 캐싱된 페이지 반환
  return &lt;div&gt;{data.title}&lt;/div&gt;
}

export default Page</code></pre>
<hr>
<h1 id="씨스터디-결론">씨스터디 결론</h1>
<blockquote>
<p> <strong>💚🌼 msms804 🌼💚 :</strong>  트래픽이 갑자기 10배 늘어나면 가장 먼저 걱정할 것은 무엇인가요?</p>
</blockquote>
<p><strong>Profitah :</strong> 평소보다 예측하기 어려운 수준의 트래픽이 발생한 만큼, 가장 먼저 우려되는 것은 과도한 서버 부하와 이로 인한 서버 다운 가능성입니다. 
사용자가 서비스 이용 중 불편을 겪으면 이탈로 이어지고, 이는 매출 감소로 직결될 수 있습니다. 
따라서 빠른 장애 대응과 안정적인 서비스 복구를 최우선으로 문제 해결에 집중하겠습니다.</p>
<p>우선 이상 트래픽이 감지되는 즉시 웹페이지를 일시적으로 제어하고 서버 점검 안내를 선제적으로 제공하여 사용자 불편을 최소화하겠습니다. 이어서 서버 사양을 높이고 대수를 늘리는 방식으로 급증한 트래픽을 분산 처리할 수 있는 환경을 구축하겠습니다.</p>
<p>서버가 안정화된 뒤에는 서비스 특성에 맞는 렌더링 방식과 캐싱 전략을 적용해 서버 부하를 줄이고 응답 속도를 개선하겠습니다. 최신 데이터 반영이 중요한 게시판은 서버 사이드 렌더링(SSR)을 적용하고, 데이터 변경이 적은 정적 페이지는 재검증 기반 캐싱(ISR) 또는 정적 사이트 생성(SSG)과 브라우저 캐싱을 활용해 서버 부담을 분산하겠습니다. </p>
<p>또한 요청 빈도가 높은 데이터는 Redis와 같은 캐싱 서버에서 중앙 관리하여 서버 간 캐시 불일치를 방지하고, 반복 요청을 줄여 낮은 비용으로 높은 성능 효율을 확보하겠습니다.</p>
<hr>
<h1 id="참고문서">참고문서</h1>
<p><a href="https://developer.mozilla.org/ko/docs/Web/API/Request/cache">Request: cache 속성</a></p>
<p><a href="https://youtu.be/5SojnABKBqA?si=MZD_hFXqufmqWcKU">프론트엔드 개발자의 대규모 트래픽 처리?? 🤔</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코드트리] 코딩테스트 준비, 갭체크부터 시작하기]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%ED%9B%84%EA%B8%B0-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A4%80%EB%B9%84-%EA%B0%AD%EC%B2%B4%ED%81%AC%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@cold_as_hell/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%ED%9B%84%EA%B8%B0-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A4%80%EB%B9%84-%EA%B0%AD%EC%B2%B4%ED%81%AC%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 18 May 2026 12:18:56 GMT</pubDate>
            <description><![CDATA[<h1 id="갭체크-후기">갭체크 후기</h1>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/b1feb72a-c115-4960-be65-12a5b2d5b72b/image.png" alt="">
<img src="https://velog.velcdn.com/images/cold_as_hell/post/591e9865-3de2-4bd6-9139-249befa90184/image.png" alt=""></p>
<p>청약통장 이벤트 진행을 위해 갭체크를 진행했는데, 시뮬레이션 유형에서 가장 많은 어려움을 느꼈다.
특히 제한 시간 내 문제를 해결하지 못해 2문제는 풀이를 마무리하지 못했으며, 이를 통해 시뮬레이션 유형에 대한 개념 이해와 문제 접근 방식이 부족하다는 점을 뼈저리게 실감했다.</p>
<hr>
<h1 id="시뮬레이션이란">시뮬레이션이란</h1>
<p>코딩테스트에서 시뮬레이션이란, 제시된 알고리즘이나 규칙을 한 단계씩 차례대로 직접 수행하여(모방하여) 정답을 도출하는 알고리즘 유형을 의미 한다.</p>
<hr>
<h2 id="예시유형">예시유형</h2>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/f1ff49ad-1793-4890-8d21-0cdd3f4274e2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/517fe328-62a1-49ba-85ce-fe4c2321ee8e/image.png" alt=""></p>
<p>위와 같이 구하고자 하는 값이 어떻게 구해지는지, 일정한 규칙을 찾으면 시뮬레이션을 정복할 수 있다.</p>
<hr>
<h1 id="문제풀이">문제풀이</h1>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/1495f1ba-07d5-4fff-a54f-9121708bc2f6/image.png" alt=""></p>
<pre><code class="language-python">a, b, c, d = map(int, input().split())

# Please write your code here.
start  = a * 60 + b   # 시작 시간(ab)를 분으로 변환
end = c * 60 + d     # 종료 시간 (cd)를 분으로 변환

# 뺄셈하여 구한 시간의 차이를 변수 gap 에 저장
gap = end - start

# 결과 출력
print(gap) </code></pre>
<p>시(hour)를 뜻하는 a c 에 60을 곱하여 분으로 변환하고 (1시간은 60분임으로)
종료시간에서 시작시간을 빼,
end에서 start까지 몇 분이 걸리는지 구하였다.</p>
<hr>
<h2 id="고민한-것">고민한 것</h2>
<pre><code class="language-python">a, b, c, d = map(int, input().split())

elapsed_time = 0

while True:
    if a == c and b == d:
        break

    elapsed_time += 1
    b += 1

    if b == 60:
        a += 1
        b = 0

print(elapsed_time)</code></pre>
<p>시작시점과 종료시점을 분으로 변환하지 않고 풀이하는 방법도 고민했지만, 
보다 직관적인 풀이를 위해 해당 방식은 사용하지 않았다.</p>
<p>이 풀이에서는 시작 시점부터 종료 시점까지 1씩 증가시키며, 
목표에 도달하기까지 몇 번 증가했는지를 계산하여 전체 경과 시간을 구하였다.</p>
<hr>
<h1 id="결론">결론</h1>
<p>시뮬레이션 문제는 다양한 방법으로 풀이할 수 있지만, 문제의 출제 의도와 연산 효율성, 그리고 코드의 가독성을 종합적으로 고려하여 핵심 규칙을 찾아 풀이하는 것이 가장 유의미하다고 생각한다.</p>
<p>뿐만 아니라 시뮬레이션적 사고를 키우는 것은 알고리즘 문제 풀이와 코딩 테스트의 핵심적인 가치 중 하나다. 
주어진 조건과 상태의 변화를 단계적으로 추적하고, 이를 코드로 정확하게 구현하는 능력을 기르는 데 중요한 역할을 하는 훈련은 단순히 문제를 푸는 행위를 넘어, 
복잡한 현실의 요구사항을 논리적으로 분해하고 재구성하는 문제 해결 능력으로 이어질 것이다.</p>
<blockquote>
<p><strong>1줄요약 :  시뮬레이션 문제 열심히 풀겠다.</strong></p>
</blockquote>
<hr>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/c7573fe1-5fb1-4360-92f9-e63e0e729351/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[성장에 대한 갈망]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%84%B1%EC%9E%A5%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%88%EB%A7%9D</link>
            <guid>https://velog.io/@cold_as_hell/%EC%84%B1%EC%9E%A5%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%88%EB%A7%9D</guid>
            <pubDate>Sun, 10 May 2026 23:48:51 GMT</pubDate>
            <description><![CDATA[<p>입사 이후 늘 새롭고 다양한 업무를 진행하고 있지만, 
회사 내부에서의 평가만 접해왔기 때문에 외부의 객관적인 평가를 들어보고 싶다는 생각이 들어 관련 컨설팅 활동을 찾아보던 중이였다.</p>
<p>그러다 부트캠프 동기들을 통해 이번 활동을 알게 됐다. 
나와 속도를 맞추어 함께 달려주었던 고마운 사람들이다. </p>
<p>이번 대외활동에 합류하게 된다면, 정글에서 그랬듯 단순히 지식을 쌓는 것을 넘어 서로 건강한 자극을 주고받으며 함께 성장할 수 있을 것 같아 기대된다.</p>
<p>아울러, 실무 경험이 풍부한 멘토님의 건강한 지도 아래에서 더 규칙적이고 좋은 루틴을 만들어갈 수 있을 것이라는 점 역시 기대하고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[캐시 불일치와 해결 전략]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%BA%90%EC%8B%9C-%EB%B6%88%EC%9D%BC%EC%B9%98%EC%99%80-%ED%95%B4%EA%B2%B0-%EC%A0%84%EB%9E%B5</link>
            <guid>https://velog.io/@cold_as_hell/%EC%BA%90%EC%8B%9C-%EB%B6%88%EC%9D%BC%EC%B9%98%EC%99%80-%ED%95%B4%EA%B2%B0-%EC%A0%84%EB%9E%B5</guid>
            <pubDate>Thu, 07 May 2026 03:57:12 GMT</pubDate>
            <description><![CDATA[<h1 id="들어가기에-앞서">들어가기에 앞서</h1>
<h2 id="캐시cache란">캐시(Cache)란?</h2>
<p>자주 사용하는 데이터를 미리 복사해 두는 임시 저장소.</p>
<p>자주 사용하는 데이터의 사본을 저장해 두고, 데이터나 값에 대한 요청이 들어오면 빠르게 처리할 수 있도록 도와주어  데이터를 가져오는 시간이 오래 걸리거나 재계산하는 시간이 오래 걸리는 작업 효율화에 도움을 준다.</p>
<h3 id="예시">예시</h3>
<p><strong>응답 속도 향상 + 서버 부하 감소 + 대규모 트래픽 분산 처리 + 외부 API 호출 비용 절감 효과를 위해 캐시를 활용한 서비스들</strong></p>
<ul>
<li><p>인스타그램 :  피드에 들어갔을 때 친구 게시물, DM, 릴스, 내 프로필 정보 등의 데이터를 미리 캐싱해 두고, 조회 요청이 들어오면 빠르게 읽을 수 있도록 해준다.</p>
</li>
<li><p>셋로그 : 메인 화면에서 시간대별 친구 영상 데이터와 영상에 대한 댓글 데이터를 미리 캐싱해 두고, 조회 요청이 들어오면 빠르게 읽을 수 있도록 해준다.</p>
</li>
</ul>
<hr>
<h1 id="캐시-불일치-cache-inconsistency">캐시 불일치 (Cache Inconsistency)</h1>
<p>캐시 불일치는 원본 데이터베이스에 저장된 데이터와 캐시에 저장된 데이터가 서로 다른 상황</p>
<h2 id="캐시와-db의-불일치는-왜-발생하나">캐시와 DB의 불일치는 왜 발생하나</h2>
<blockquote>
<p>서버 간 네트워크 문제, 비동기 처리로 인한 DB 저장과 캐시 갱신 간의 지연, 동시성 문제 등</p>
</blockquote>
<p>캐시는 DB의 데이터를 복사하여 저장하는 임시 저장소이기에 원본 데이터인 DB의 값이 변경되었을 때 캐시의 데이터가 함께 즉시 갱신되지 않으면 발생한다.</p>
<hr>
<h1 id="문제-해결을-위한-캐시-전략">문제 해결을 위한 캐시 전략</h1>
<h2 id="읽기read-전략">읽기(Read) 전략</h2>
<h3 id="cache-aside-lazy-loading">Cache Aside (Lazy Loading)</h3>
<p>캐시를 사용할 때 클라이언트가 데이터를 요청하면, 서버는 먼저 캐시에서 데이터를 조회한다.</p>
<p>이때 찾고자 하는 데이터가 캐시에 존재하면(Cache Hit) 캐시에서 데이터를 반환하고, 데이터가 존재하지 않으면(Cache Miss) 원본 데이터베이스(DB)에서 데이터를 조회하여 반환한 뒤 해당 데이터를 캐시에도 저장한다.</p>
<hr>
<h2 id="쓰기write-전략">쓰기(Write) 전략</h2>
<h3 id="write-through">Write Through</h3>
<blockquote>
<p>원본 데이터에 대한 변경분이 생긴 경우, 매번 캐시에 해당 데이터를 찾아 함께 변경하는 방식.</p>
</blockquote>
<p>2번 쓰기가 발생하지만, 캐시는 항상 최신 데이터를 가지게 된다.</p>
<p>그러나, 무작정 데이터를 갱신하거나 저장하는 방식은 리소스 낭비가 될 수 있다.
사용자가 잘 사용하지 않는 데이터마저 캐시에 저장되기 때문이다.</p>
<p>따라서 해당 방식을 사용할 경우, 캐시가 오랫동안 사용되지 않으면 자동으로 삭제되도록 TTL(Time To Live)과 같은 만료 시간을 함께 사용하는 것이 좋다.</p>
<hr>
<h3 id="cache-invalidation">Cache Invalidation</h3>
<blockquote>
<p>원본 데이터에 대한 변경분이 생긴 경우, 캐시 데이터를 만료시키는 방식</p>
</blockquote>
<p>Write Through 방식의 단점을 보완한 방식이며 캐시에 데이터가 삭제되니 캐시 불일치에 대한 걱정은 하지 않아도 된다.</p>
<p>Cache Miss 증가 → DB 접근률 증가 → DB 부하로 이어질 가능성이 있고
캐시 재생성 시간 증가로 인해 사용자가 체감하는 서비스 이용시간이 느릴 것이다.</p>
<hr>
<h3 id="write-back-write-behind">Write Back (Write Behind)</h3>
<blockquote>
<p>원본 데이터에 대한 변경분이 생긴 경우, 캐시를 먼저 업데이트한 이후 추후에 원본 데이터를 변경하는 방식</p>
</blockquote>
<p>즉,  디스크 쓰기 작업을 비동기 작업으로 수행하여 성능을 개선하는 방식이다.</p>
<p>이 방식은 쓰기 작업이 빈번하며 일시적인 캐시 불일치를 허용하는 서비스에서 유용하게 사용될 가능성이 높다. (데이터를 DB에 저장하는 것보다 캐시 저장이 훨씬 빠르기 때문)</p>
<hr>
<h2 id="일관성-수준-선택">일관성 수준 선택</h2>
<h3 id="강력한-일관성strong-consistency-vs-결과적-일관성eventual-consistency">강력한 일관성(Strong Consistency) vs 결과적 일관성(Eventual Consistency)</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>강력한 일관성 (Strong Consistency)</th>
<th>결과적 일관성 (Eventual Consistency)</th>
</tr>
</thead>
<tbody><tr>
<td>특징</td>
<td>모든 사용자가 즉시 최신 데이터를 조회 가능</td>
<td>일정 시간이 지나면 최종적으로 데이터 일치</td>
</tr>
<tr>
<td>장점</td>
<td>높은 데이터 정확성 보장</td>
<td>높은 성능과 확장성</td>
</tr>
<tr>
<td>단점</td>
<td>성능 저하 및 시스템 부하 증가 가능</td>
<td>일시적인 데이터 불일치 발생 가능</td>
</tr>
<tr>
<td>적합한 서비스</td>
<td>금융, 결제, 재고 관리</td>
<td>SNS, 조회 수, 추천 시스템, 통계 데이터</td>
</tr>
<tr>
<td>주로 사용하는 캐시 전략</td>
<td>Write Through, Cache Invalidation</td>
<td>Cache Aside, Write Back (Write Behind)</td>
</tr>
<tr>
<td>우선 가치</td>
<td>데이터 정확성</td>
<td>성능 및 확장성</td>
</tr>
<tr>
<td>서비스 특성에 따라 데이터 정확성을 우선할지, 성능과 확장성을 우선할지 적절한 캐시 전략과 일관성 수준을 선택하는 것이 중요하다.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<h1 id="결론">결론</h1>
<p>Q. 캐시를 도입하면 데이터가 DB와 달라지는 문제가 생기곤 하는데, 이런 불일치는 왜 발생하고 어떻게 해결하면 좋을까요?</p>
<p>A. 캐시는 DB의 데이터를 복사하여 저장하는 임시 저장소이기 때문에 원본 데이터인 DB의 값이 변경되었을 때 캐시의 데이터가 함께 즉각 갱신되지 않으면 캐시불일치가 발생합니다.</p>
<p>이러한 불일치 문제를 해결하기 위해서는 캐시와 DB 간 데이터 일관성을 유지할 수 있는 읽기 및 쓰기전략이 필요합니다.</p>
<p>예를 들어, 강력한 일관성이 필요한 경우에는 Write Through나 Cache Invalidation 전략을 사용하여 캐시와 DB의 데이터를 최대한 동일하게 유지하고</p>
<p>성능과 확장성이 더 중요한 서비스에서는 Cache Aside, Write Back(Write Behind)과 같은 결과적 일관성 기반 전략을 사용해야 합니다.</p>
<p>이러한 전략들을 서비스 특성에 맞게 잘 선택한다면</p>
<p>캐시 불일치 문제를 완화할 수 있으며,
상태 기반 렌더링과 대규모 트래픽 처리 등 사용자 경험에 최적화된 서비스를 
효율적으로 구현해 나갈 수 있을 것입니다.</p>
<p>이상!</p>
<hr>
<p><a href="https://www.maeil-mail.kr/question/121">참고자료</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS는 코스요리가 아니야]]></title>
            <link>https://velog.io/@cold_as_hell/CORS%EB%8A%94-%EC%BD%94%EC%8A%A4%EC%9A%94%EB%A6%AC%EA%B0%80-%EC%95%84%EB%8B%88%EC%95%BC</link>
            <guid>https://velog.io/@cold_as_hell/CORS%EB%8A%94-%EC%BD%94%EC%8A%A4%EC%9A%94%EB%A6%AC%EA%B0%80-%EC%95%84%EB%8B%88%EC%95%BC</guid>
            <pubDate>Tue, 05 May 2026 05:09:23 GMT</pubDate>
            <description><![CDATA[<h1 id="브라우저는-왜-특정-도메인에서-다른-자원을-가져올-수-없나">브라우저는 왜 특정 도메인에서 다른 자원을 가져올 수 없나</h1>
<h2 id="브라우저가-자원을-가져오는-방법">브라우저가 자원을 가져오는 방법</h2>
<p>브라우저 → 웹서버 요청 → 웹서버가 응답 → 브라우저가 랜더링</p>
<hr>
<h3 id="브라우저-→-웹서버-요청">브라우저 → 웹서버 요청</h3>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/822e0566-59ca-4acb-86d8-687668b8b0a7/image.png" alt=""></p>
<p>한때는 누군가의 가장 애정하는 프로젝트였지만, 불과 n주만에 그에게서 완전히 잊혀진 프로젝트 
<code>유씽크</code> 를 살펴보자.</p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/b90bd72e-457b-4fbf-a8af-dc9cc9383423/image.png" alt=""></p>
<p>브라우저에서 버튼을 클릭해 유튜브 영상과 관련된 상호작용을 시도한다.</p>
<hr>
<h3 id="웹서버-요청-→-웹서버가-응답">웹서버 요청 → 웹서버가 응답</h3>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/3884cbcd-2bc6-4c32-8150-98deadd115b4/image.png" alt=""></p>
<p>브라우저에서 버튼을 클릭했을 때 해당 웹서버에 요청헤더를 사용해 HTTP 요청이 전송되었다.
이때 요청 헤더에는 Content-Type, User-Agent 등 key-value 형태의 부가 정보가 담겨 전달되고,</p>
<p>웹서버는 요청을 처리한 뒤 응답을 돌려주는데, 
여기서 받은 200 OK는 요청이 정상적으로 처리되었고 응답 본문에 요청한 리소스가 포함되어 있다는 의미다.</p>
<hr>
<h3 id="웹서버가-응답-→-브라우저가-랜더링">웹서버가 응답 → 브라우저가 랜더링</h3>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/d6eb2602-56b3-4cf2-8a12-86d64445c919/image.png" alt=""></p>
<p>웹서버의 응답을 받은 브라우저는 
응답 헤더를 확인하고, 문제가 없으면 받은 리소스를 화면에 랜더링한다.</p>
<p>앞서 잠시 언급했지만 위의 예시 사진에서도 200 ok 상태코드가 있는 응답헤더를 받았으므로 
멋진 리소스가 랜더링 되었을 확률이 높다.</p>
<hr>
<h2 id="브라우저-보안정책">브라우저 보안정책</h2>
<p>200번대 상태코드 응답을 받았음에도 브라우저에 멋진 리소스가 랜더링 되었을 것이라고 확신할 수 없는 이유는 브라우저 보안정책 때문이다.</p>
<p>브라우저는 웹서버의 응답을 확인할 때 보안 검사도 함께 수행하는데, <strong>보안정책에 맞지 않는 응답을 받으면 웹서버에서 200~299의 성공 상태 코드가 있는 응답이 반환되더라도 브라우저는 해당 응답을 차단하여 랜더링하지 않는다.</strong></p>
<hr>
<h3 id="sop-same-origin-policy-동일-출처-정책">SOP (Same-Origin Policy, 동일 출처 정책)</h3>
<p>여러 브라우저 정책 중, 오늘은 SOP를 중점적으로 다뤄보자.
모든 브라우저는 기본적으로 같은 출처에서 온 리소스만 허용하고, 다른 출처의 리소스는 기본적으로 차단한다.</p>
<pre><code>http://yousync.kr/page/1</code></pre><p>여기서 Origin은 무엇일까? 
그렇다. <code>yousync.kr</code>이다. </p>
<p>스킴(프로토콜) + 도메인 + 포트번호를 합친것이 Origin 인 것이다.
SOP는 Origin의 구성요소 중 하나라도 다르면 다른 출처로 판단하여 리소스 접근을 차단한다.</p>
<pre><code>https://yousync.kr  vs  http://yousync.kr   → 스킴 달라 ❌
https://yousync.kr vs  https://yousing.kr    → 도메인 달라 ❌
https://yousync.kr  vs  https://yousync.kr:2025 → 포트 달라 ❌
</code></pre><hr>
<h1 id="서버는-어떻게-다른-도메인의-요청을-허락해주나">서버는 어떻게 다른 도메인의 요청을 허락해주나</h1>
<h2 id="cors">CORS</h2>
<p>브라우저가 다른 출처의 리소스 접근을 제한하는 정책<strong>(SOP, Same-Origin Policy)</strong>을 완화할 수 있도록, 서버가 특정 출처의 접근을 허가해주는 HTTP 헤더 기반 메커니즘</p>
<hr>
<h2 id="cors-헤더-동작-방식">CORS 헤더 동작 방식</h2>
<p>브라우저가 네트워크 요청을 처리하는 방식을 정의한 Fetch Standard 규약에 따르면, 브라우저는 서버 데이터 변형의 우려가 없는 요청은 <strong>Simple Request</strong> 로, 변형의 우려가 있는 요청은 <strong>Preflight Request</strong> 로 처리한다.</p>
<p>현대 API 통신은 대부분 <code>application/json</code> 을 사용하기 때문에 Simple Request 조건을 만족하는 경우는 거의 없고, 대부분 Preflight Request가 발생한다.</p>
<hr>
<h3 id="simple-request-단순요청">Simple Request (단순요청)</h3>
<p>서버 데이터 변형의 우려가 없는 요청으로, 아래 조건을 모두 만족할 때 Preflight 없이 바로 요청을 보낸다.</p>
<pre><code>메서드   : GET, POST, HEAD 중 하나
Content-Type : 아래 중 하나
               - text/plain
               - multipart/form-data
               - application/x-www-form-urlencoded</code></pre><hr>
<h3 id="preflight-request-사전요청">Preflight Request (사전요청)</h3>
<p>Simple Request 조건을 벗어난 요청으로, 본 요청 전에 OPTIONS 메서드로 서버에 먼저 허락을 구한다.</p>
<pre><code>메서드   : PUT, DELETE, PATCH 등
Content-Type : application/json 등
커스텀 헤더 : Authorization 등</code></pre><p>브라우저가 Preflight 요청을 보내면 서버는 아래 세 가지 헤더를 담아 응답해야 한다.</p>
<pre><code>Access-Control-Allow-Origin  : 허락할 출처
Access-Control-Allow-Methods : 허락할 메서드
Access-Control-Allow-Headers : 허락할 헤더</code></pre><p>※ OPTIONS :브라우저가 Preflight 상황에서 자동으로 보낼 것으로, 수동으로 요청을 보내는 코드는 작성하지 않아도 괜찮다.</p>
<hr>
<h3 id="요약">요약</h3>
<pre><code>Simple Request
- 브라우저 : 조건 일치 시 바로 요청
- 서버     : Access-Control-Allow-Origin 설정해야 함

Preflight Request
- 브라우저 : 조건 벗어나면 OPTIONS로 먼저 허락 구함
- 서버     : 세 가지 헤더 모두 설정해야 함
             Access-Control-Allow-Origin
             Access-Control-Allow-Methods
             Access-Control-Allow-Headers</code></pre><hr>
<h1 id="시스터디-결론">시스터디 결론</h1>
<blockquote>
<p>Q. &nbsp; CORS(Cross-Origin Resource Sharing)는 무엇이며 왜 필요한가요?</p>
</blockquote>
<p>A. </p>
<p>CORS는 다른 Origin의 리소스를 브라우저에서 렌더링할 수 있도록 보안 정책을 완화해주는 HTTP 헤더 기반 메커니즘입니다.</p>
<p>사랑과 전쟁으로 CORS를 설명하자면, 
브라우저는 남편, 다른 출처의 리소스는 여자친구, 보안 정책(SOP)은 시어머니, 서버는 시아버지입니다. </p>
<p>시어머니인 SOP로 인해 남편인 브라우저가 여자친구인 리소스를 만날 수 없을 때, 
전세계 모든 브라우저가 네트워크 요청을 처리하는 방식에 대해 정의 되어 있는 Fetch Standard 규약에 따라 서버 데이터 변형 여부를 고려하여 단순요청 또는 사전요청을 보내면, 시아버지인 서버가 특정 출처의 접근을 허가하는 응답 헤더를 함께 보내 브라우저가 다른 Origin의 리소스를 로드할 수 있도록 해줍니다.</p>
<p>CORS가 없었다면 YouTube 영상 리소스를 받아와야 했던 유씽크는 시작조차 하지 못했을 것입니다. </p>
<p>우리 모두가 좋아했던 유씽크를 위해 CORS는 반드시 필요합니다.</p>
<p>반박시 님 유씽크 싫어함
이상.</p>
<p>++ 비유가 난해했다는 피드백을 받음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[서드파티도구에 관한 고찰]]></title>
            <link>https://velog.io/@cold_as_hell/0430-%EA%B3%BC%EC%A0%9C</link>
            <guid>https://velog.io/@cold_as_hell/0430-%EA%B3%BC%EC%A0%9C</guid>
            <pubDate>Tue, 28 Apr 2026 12:12:31 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/4a07bb63-036c-4e6f-a323-bf42758bf880/image.png" alt=""></p>
<p><a href="https://it.chosun.com/news/articleView.html?idxno=2023092160669">&gt;&gt;&gt;&gt;&gt; 뉴스 링크 </a></p>
<hr>
<h1 id="뉴스-요약">뉴스 요약</h1>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/c4f4ecb3-3187-47a3-8f41-4d3f7e5793c5/image.png" alt=""></p>
<p>최근 서드파티 AI 도구인 Context.ai의 Google Workspace OAuth 앱이 외부 공격자에 의해 침해되었는데,
Vercel 직원이 해당 도구를 Google 계정과 연동해 두었다가, 공격자가 이 OAuth 앱을 통해 직원의 Google 계정 권한을 탈취했고,
그 결과 Vercel 내부 시스템까지 침입하게 되었다.
이로 인해 직원 명단과 암호화되지 않은 일반 환경 변수들이 모두 유출되었다.</p>
<hr>
<h1 id="이-뉴스가-웹도메인에-끼친-영향">이 뉴스가 웹도메인에 끼친 영향</h1>
<p>이 뉴스는 웹 개발에 있어</p>
<p>복잡한 기능을 직접 구현하지 않아도 되고 DB 서버 구축·관리 부담도 줄여주는
서드파티도구는 편리하지만,</p>
<p>서드파티도구의 내부 코드나 보안 수준에 관해서 통제할 수 없기에 
그에 따르는 위험도 고려해볼 필요가 있다는 것을 깊게 생각하게 해줌</p>
<pre><code>※ 서드파티도구 : 하드웨어 생산자(1st)나 서비스 제공자(2nd)가 아닌,
외부의 제3자 개발자/기업이 만든 소프트웨어나 솔루션</code></pre><hr>
<h1 id="생각">생각</h1>
<p>서드파티도구와의 연동 권한은 최소한으로 설정해 서드파티 보안 이슈를 예방할 수 있고
해당 도구가 해킹당했을 상황을 가정해 피해 범위를 사전에 제한하는 조치가 필요하다. (ex. API 키 등 민감 정보는 암호화해서 저장, OAuth 스코프 최소화, 토큰 만료 기간 및 자동 갱신 설정, 허용된 IP에서만 접근 가능하도록 제한 등)</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[si스터디 가는 길 ]]></title>
            <link>https://velog.io/@cold_as_hell/si%EC%8A%A4%ED%84%B0%EB%94%94-%EA%B0%80%EB%8A%94-%EA%B8%B8</link>
            <guid>https://velog.io/@cold_as_hell/si%EC%8A%A4%ED%84%B0%EB%94%94-%EA%B0%80%EB%8A%94-%EA%B8%B8</guid>
            <pubDate>Tue, 28 Apr 2026 10:38:46 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42898">🔗 문제 링크</a></p>
<blockquote>
<p>dp - 탑다운</p>
</blockquote>
<blockquote>
<p>(1,1)에서 오른쪽 혹은 아래쪽으로 1번씩 이동할 수 있을 때,
입력값(m,n)까지 이동하는 경우의 수를 모두 구하자.</p>
</blockquote>
<hr>
<h1 id="문제풀이">문제풀이</h1>
<h2 id="풀이흐름">풀이흐름</h2>
<blockquote>
<p>최종 목적지에 도달하기 위해서는,
최종 목적지 이전 중간 목적지들까지 오는 경우의 수를 먼저 알아야 한다.</p>
<p>재귀함수를 이용하면
점화식에 의해 각 위치의 경우의 수가 하향식으로 결정되며, 
계산된 결과는 메모이제이션으로 저장한다.</p>
</blockquote>
<p>메모제이션에 저장된 결과를 조합하면
최종 목적지까지 오는 전체 경우의 수를 구할 수 있다.</p>
<hr>
<h2 id="예시">예시</h2>
<p>최종 목적지: (2,2)</p>
<p>시작점 : (1, 1)</p>
<p>중간 목적지 : (1,2 / 2,1)</p>
<p>1,2 까지 경우의 수 : 1</p>
<p>2,1 까지 경우의 수 : 1</p>
<p>최종목적지까지 경우의수: 1 + 1 = 2</p>
<p>ex) 최종 목적지: (2,2) 
시작점 : (1, 1)
중간 목적지 : (1,2 / 2,1)
    1,2 까지 경우의 수 : 1
    2,1 까지 경우의 수 : 1</p>
<p>최종목적지까지 경우의수: 1 + 1 = 2</p>
<blockquote>
<p>점화식 : dp[i][j] = dp[i-1][j] + dp[i][j-1]</p>
</blockquote>
<hr>
<h2 id="정답-코드">정답 코드</h2>
<pre><code class="language-python">def solution(m, n, puddles):
    answer = 0  # (1,1)에서 (m,n)까지 이동하는 경우의 수

    # 시작점 (1,1)에서 한 번 이동한 두 칸의 경우의 수를 미리 초기값으로 설정.(점화식 적용을 위해)
    info = dict([((2, 1), 1), ((1, 2), 1)]) # 1,1로 시작하면  dp 점화식이 참조하는 값이 생기지 않아, 문제풀이를 할 수 없음.

    # # 웅덩이 좌표를 튜플로 변환하여 info 딕셔너리에 0으로 저장 (해당 위치로 갈 수 없음)
    for puddle in puddles: 
        info[tuple(puddle)] = 0 

    def func(m, n): # 탑다운(재귀+ 메모제이션) 방식으로 경우의 수 계산

        # 격자 밖이면 0 반환
        if m &lt; 1 or n &lt; 1:
            return 0

        # 이미 계산된 좌표면 바로 반환 (메모이제이션)
        if (m, n) in info:
            return info[(m, n)]

        # 현재 좌표 = 위에서 등교하는 경우 + 왼쪽에서 등교하는 경우
        return info.setdefault(
            (m, n),
            func(m - 1, n) + func(m, n - 1)
        )

    # 최종 결과는 MOD 적용
    return func(m, n) % 1000000007</code></pre>
<hr>
<h1 id="다른-풀이">다른 풀이</h1>
<blockquote>
<p>dp - 바텀업</p>
</blockquote>
<pre><code class="language-python">def solution(m, n, puddles):
    answer = 0
    route_map = [[0]*m for i in range(n)]
    memo = [[0]*m for i in range(n)]
    for p in puddles:
        route_map[p[1]-1][p[0]-1] = 1
    memo[0][0] = 1
    for i in range(n):
        for j in range(m):
            if i == 0 and j == 0:
                continue
            if route_map[i][j] == 1:
                memo[i][j] = 0
            elif i == 0:
                memo[i][j] = memo[i][j-1]
            elif j == 0:
                memo[i][j] = memo[i-1][j]
            else:
                memo[i][j] = memo[i-1][j] + memo[i][j-1]
    print(memo)
    answer = memo[n-1][m-1]
    return answer % 1000000007```
</code></pre>
<hr>
<h1 id="생각해-본-것">생각해 본 것</h1>
<p>다소 뻔한 말이지만,</p>
<p>DP 문제는 탑다운과 바텀업 두 방식 모두로 풀이가 가능하며,
상황에 따라 어떤 방식이 더 적합한지 고민해볼 필요가 있다.</p>
<p>찾아보니 일반적으로는 아래 기준으로 선택하면 좋다고 한다.</p>
<table>
<thead>
<tr>
<th>상황</th>
<th>추천 방식</th>
<th>이유</th>
</tr>
</thead>
<tbody><tr>
<td>시간/메모리 제한이 타이트함</td>
<td>바텀업</td>
<td>함수 호출 오버헤드가 없고 반복문 기반이라 성능이 안정적임</td>
</tr>
<tr>
<td>모든 상태를 다 확인해야 함</td>
<td>바텀업</td>
<td>순차적으로 dp 테이블을 채우는 방식이 가장 효율적임</td>
</tr>
<tr>
<td>필요한 부분만 골라 계산하고 싶음</td>
<td>탑다운</td>
<td>재귀 + 메모이제이션으로 필요한 경로만 탐색 가능 (가지치기 효과)</td>
</tr>
<tr>
<td>점화식이 복잡해 순서 잡기 힘듦</td>
<td>탑다운</td>
<td>결과에서 거꾸로 호출하며 생각하면 구조 이해가 쉬움</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[2026을 강타할 최고의 윤아]]></title>
            <link>https://velog.io/@cold_as_hell/2026%EC%9D%84-%EA%B0%95%ED%83%80%ED%95%A0-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%9C%A4%EC%95%84</link>
            <guid>https://velog.io/@cold_as_hell/2026%EC%9D%84-%EA%B0%95%ED%83%80%ED%95%A0-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%9C%A4%EC%95%84</guid>
            <pubDate>Fri, 24 Apr 2026 13:43:42 GMT</pubDate>
            <description><![CDATA[<p>는 바로 이윤아다.</p>
<p>요즘 나는 2026년을 누구보다 세게 강타하기 위해, 매일 IT 기술 관련 아티클을 읽고 스터디가 끝난 후에는 스터디 친구들과 AI 기술 및 발전에 대해 토의하는 시간을 갖고 있다.</p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/e8ec1e57-fca9-41e9-a5da-509d50f50ad4/image.png" alt=""></p>
<pre><code>아티클을 나누는 씨스터디의 디스코드 방</code></pre><p>여러 주제의 결론은 결국 하나, 
급변하는 세상에 대처하기 위해서도, 좋은 프로젝트를 하기 위해서도, 언제나 흔들리지 않을 탄탄한 기본기를 갖춰야 한다는 것.</p>
<p>친구들의 말을 깊이 새기며 기술을 익히되 흔들리지 않는 기본기를 쌓아가려 노력했고, 🐺
이를 기반으로 가장 개선하고 싶었던 부분들에서 약 6% 와 33% 그리고 그 이상의 개선을 이루어내고 있다. </p>
<p>앞으로는 기본기에 충실하며 다른 수치들도 더 개선해 나가고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쓰기와 읽기 관점에서의 성능]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%93%B0%EA%B8%B0%EC%99%80-%EC%9D%BD%EA%B8%B0-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C%EC%9D%98-%EC%84%B1%EB%8A%A5-4y142346</link>
            <guid>https://velog.io/@cold_as_hell/%EC%93%B0%EA%B8%B0%EC%99%80-%EC%9D%BD%EA%B8%B0-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C%EC%9D%98-%EC%84%B1%EB%8A%A5-4y142346</guid>
            <pubDate>Sat, 18 Apr 2026 14:23:03 GMT</pubDate>
            <description><![CDATA[<h1 id="웹페이지에서-쓰기와-읽기">웹페이지에서 쓰기와 읽기</h1>
<p>어느 웹사이트의 게시판에 &#39;<strong>스터디장, 미리 합격을 축하드려요</strong>&#39;라는 제목의 게시글을 작성하고, 동일한 내용의 ㅈㄱㄴ 게시글을 작성한뒤,
게시판으로 돌아가 해당 게시글을 조회한다고 가정해 보자.</p>
<hr>
<h2 id="쓰기-흐름">쓰기 흐름</h2>
<p>웹 브라우저(클라이언트)에서 글을 쓰고 저장 버튼을 클릭하면
POST 요청이 웹 서버로 전달되고, 웹 서버가 해당 데이터를 DB에 저장한다.</p>
<h2 id="읽기-흐름">읽기 흐름</h2>
<p>제목을 클릭하면 서버로 GET 요청이 발송되고, 서버가 요청을 처리한다.
데이터베이스에서 해당 게시글의 ID를 기준으로 조회하여
게시물의 제목과 내용을 반환한다.
<img src="https://velog.velcdn.com/images/cold_as_hell/post/4c93f4d5-5427-4ad3-a871-e110edbb1cc1/image.png" alt=""></p>
<hr>
<h2 id="성능-개선-방법">성능 개선 방법</h2>
<h3 id="쓰기">쓰기</h3>
<p>프론트엔드에서 저장 버튼이 한 번 눌리고 요청이 한번 간 뒤에도 버튼 클릭을 막지 않으면 사용자가 저장 버튼을 여러번 클릭해 post 요청을 여러번 보낼 수 있다.</p>
<p>이는 서버 부하 혹은 게시물 중복 저장을 야기한다.</p>
<ol>
<li>프론트엔드 단에서 버튼이 한번 클릭 되면 클릭 되지 않도록 막거나,</li>
<li>백엔드 단에서 한 유저가 게시글을 업로드 할 때
일정한 시간을 두고 같은 제목과 같은 내용의 게시물을 올릴 수 있도록 설정해두어야
문제를 방지할 수 있을 것이다.</li>
</ol>
<h3 id="읽기">읽기</h3>
<p>모든 문자열이 일치하는 게시물을 읽는 것은 시간적으로 비효율적이므로
게시물에 고유 ID를 부여하고, 데이터베이스의 인덱스(Index)를 이용하면
인덱스를 기준으로 게시물을 조회할 수 있다.</p>
<p>게시판을 만들 때는 댓글, 좋아요, 대댓글 등의 데이터를 저장하기 위해
주로 관계형 데이터베이스(RDBMS)를 사용하는데,
MySQL, PostgreSQL 등 대표적인 관계형 데이터베이스의 인덱스는
내부적으로 B+Tree 자료구조로 구현되어 있어
정렬된 상태를 유지하면서 빠른 탐색이 가능하다.</p>
<hr>
<h1 id="시씨스터디-결론">시?씨?스터디 결론</h1>
<blockquote>
<p>Q. 다음 주 면접 질문은</p>
<p><strong>성능을 쓰기와 읽기 관점으로 구분해서 설명해주세요.</strong></p>
</blockquote>
<p>입니다.</p>
<blockquote>
</blockquote>
<p>여러분의 <strong>지망 도메인에 맞게</strong> 준비하시면 됩니다.</p>
<blockquote>
<p>A .<strong>웹 도메인에서 쓰기와 읽기 관점의 성능은
클라이언트에서 전달된 데이터를 효율적으로 적재하고
빠른 시간내에 탐색할 수 있는가</strong> 입니다.</p>
</blockquote>
<p>성능이란, 기능성의 정도이며, 즉, 구현한 기능이 얼마나 잘 작동하는가를 의미합니다.</p>
<p>웹도메인의 핵심역할은 언제나 유저의 사용을 위하여 있으므로 웹도메인에서 쓰기와 읽기관점의 성능을 측정하기 위해서는 유저의 편의를 위한 쓰기와 읽기가 잘 되고 있는 지를 측정해야합니다.</p>
<p>따라서 쓰기와 읽기 성능을 높인다는 것은 곧 사용자가 데이터를 저장하고 조회하는 과정에서 불편함을 느끼지 않도록 하는 것이며, </p>
<p>이것이 웹 도메인에서 성능 최적화의 궁극적인 목표라고 할 수 있을것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[아 이번주 문제 누가 냄 ;;]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%95%84-%EC%9D%B4%EB%B2%88%EC%A3%BC-%EB%A9%B4%EC%A0%91-%EB%AC%B8%EC%A0%9C-%EB%88%84%EA%B0%80-%EB%83%84</link>
            <guid>https://velog.io/@cold_as_hell/%EC%95%84-%EC%9D%B4%EB%B2%88%EC%A3%BC-%EB%A9%B4%EC%A0%91-%EB%AC%B8%EC%A0%9C-%EB%88%84%EA%B0%80-%EB%83%84</guid>
            <pubDate>Mon, 13 Apr 2026 10:00:13 GMT</pubDate>
            <description><![CDATA[<h1 id="합류하고-싶은-기업">합류하고 싶은 기업</h1>
<h2 id="applibot-애플리봇">Applibot [애플리봇]</h2>
<blockquote>
<p>일본의 CyberAgent에 소속된 게임 제작사.</p>
</blockquote>
<h3 id="서비스-게임">서비스 게임</h3>
<table>
<thead>
<tr>
<th>작품</th>
<th>장르</th>
<th>서비스 개시일</th>
</tr>
</thead>
<tbody><tr>
<td>ジョーカー～ギャングロード～ (조커 <del>갱로드</del>)</td>
<td>만화 RPG</td>
<td>2014.10.26</td>
</tr>
<tr>
<td>파이널 판타지 VII 에버 크라이시스</td>
<td>RPG</td>
<td>2023.09.07</td>
</tr>
<tr>
<td>먼작귀 포켓</td>
<td>방치게임</td>
<td>2025.03.27</td>
</tr>
</tbody></table>
<p>출처 : 나무위키</p>
<hr>
<h1 id="선택한-서비스">선택한 서비스</h1>
<blockquote>
<p>먼작귀 포켓 </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/899509ca-e61d-4190-b6b3-f02bbc513f15/image.png" alt=""></p>
<h2 id="서비스-소개">서비스 소개</h2>
<blockquote>
<p>방치형 게임</p>
</blockquote>
<p>시간의 흐름에 따라 게임머니가 증가하고
게임을 실행시키지 않은 백그라운드에서도 게임머니가 증가한다.</p>
<p>이 게임머니로 캐릭터, 장비, 스킬 등을 강화해 레벨별 스테이지를 클리어 하는 게임인데,,, </p>
<p>귀여운 먼작귀들이 등장함에도 너무도 큰 단점이 있어 2일만에 게임을 접었다.</p>
<hr>
<h1 id="개선하거나-추가하고-싶은-기능">개선하거나 추가하고 싶은 기능</h1>
<h2 id="레벨업시-1씩-만-증가하는기능">레벨업시 +1씩 만 증가하는기능</h2>
<p>레벨업이 1씩만 가능하기 때문에 레벨업을 하는데 들어가는 시간이 크고,
유저 피로도가 높아진다.</p>
<h2 id="기술적-개선방법">기술적 개선방법</h2>
<blockquote>
<p>딕셔너리에 일괄적으로 상승시킬 능력치를 담아 일괄 레벨업 가능한 기능</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/34204e66-af29-40da-9a2a-cad45b856804/image.png" alt=""></p>
<pre><code>출처 : 구글</code></pre><p>위와 같이 일괄 레벨업이 가능하도록 하는 기능이 필요하다고 생각한다.
굳이 딕셔너리를 사용하려는 이유는 상태 : 레벨 형태의 정보를 서버로 전송하는 구조를 고려하고 있기 때문이다. like 메이플 스탯분배. ok?</p>
<p>또, 딕셔너리는 키 기반 구조이기에 이름(키) 기준으로 명확하게 관리할 수 있으며, 새로운 상태가 추가되거나 수정될 때 순서에 영향을 받지 않아 확장성과 유지보수 측면에서 유리하다고 판단된다.</p>
<pre><code class="language-python"># list (index 기반)
list_stats = [10, 8, 12]

# dict (key 기반)
dict_stats = {
    &quot;strength&quot;: 10,
    &quot;dexterity&quot;: 8,
    &quot;intelligence&quot;: 12
}

# index 기반 접근
list_stats[0] += 2

# key 기반 접근
dict_stats[&quot;strength&quot;] += 2</code></pre>
<p>++ 아 생각해보니 메이플 스탯도 일괄 레벨업이 아니구나...! ㅎㅎ
그치만 수정하기 귀찮네요... 일단 제가 하고 싶은 말은 잘 전달 되었으리라 믿어요.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[과제) 도파민 싹 돋는 잼컨찾기]]></title>
            <link>https://velog.io/@cold_as_hell/%EA%B3%BC%EC%A0%9C-%EB%8F%84%ED%8C%8C%EB%AF%BC-%EC%8B%B9-%EB%8F%8B%EB%8A%94-%EC%9E%BC%EC%BB%A8%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@cold_as_hell/%EA%B3%BC%EC%A0%9C-%EB%8F%84%ED%8C%8C%EB%AF%BC-%EC%8B%B9-%EB%8F%8B%EB%8A%94-%EC%9E%BC%EC%BB%A8%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Sun, 12 Apr 2026 10:07:54 GMT</pubDate>
            <description><![CDATA[<h1 id="이상한-장소-찾기---서울편">이상한 장소 찾기 - 서울편</h1>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/1b41c195-11ca-4cc9-b8c8-87eecd65865c/image.png" alt=""></p>
<p>서울 시내 이곳저곳을 탐험하다가 혼자서 쉬기 좋아보이는 장소를 하나 찾았습니다.<br>인터넷도 되고 전화도 터지며,<br>제가 아는 사람 중 이곳에 출입하는 사람은 저를 포함해 단 두 명뿐인 곳입니다.
<del>아리따운 여성들의 공간ㅎㅎ</del></p>
<p>여러분이 서울에서 조용히 머물 일이 있으시다면
위치를 공유해 드리도록 하겠습니다.</p>
<p>이상.</p>
<hr>
<h1 id="스패니쉬-스쿼트">스패니쉬 스쿼트</h1>
<p>사실 이 운동은 아직 시작하지 않았습니다.
몇 분 전에 추천받았기 때문입니다.</p>
<p>언젠가는 이 운동을 물리치료와 병행하며,
5/16이 된 4/25 회동 전까지 100만 번 하고 더 강해져서 참석하겠습니다.</p>
<p>다들 정말 보고 싶어요~ 
씨유 인 메이~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[14382) 숫자세는 양치기]]></title>
            <link>https://velog.io/@cold_as_hell/14382-%EC%88%AB%EC%9E%90%EC%84%B8%EB%8A%94-%EC%96%91%EC%B9%98%EA%B8%B0-7ouqacs5</link>
            <guid>https://velog.io/@cold_as_hell/14382-%EC%88%AB%EC%9E%90%EC%84%B8%EB%8A%94-%EC%96%91%EC%B9%98%EA%B8%B0-7ouqacs5</guid>
            <pubDate>Sat, 04 Apr 2026 04:15:50 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://www.acmicpc.net/problem/14382">🔗 문제 링크</a></p>
<blockquote>
<p>완전탐색</p>
</blockquote>
<blockquote>
<p>양이 잠에 들때 <strong>마지막으로 구한 숫자</strong>를 출력하라</p>
</blockquote>
<pre><code>예시) N=1692
      1N=1692  -&gt; {1,6,9,2}
      2N=3384  -&gt; {1,6,9,2,3,8,4}
      3N=5076  -&gt; {1,6,9,2,3,8,4,5,0,7} -&gt; 0~9 모두 수집 -&gt; 5076 출력
</code></pre><hr>
<h1 id="문제풀이">문제풀이</h1>
<blockquote>
<p>set을 사용해 중복값을 제거한뒤, 자릿수에서 1~9까지의 숫자가 나올때까지 완탐을 돈다</p>
</blockquote>
<pre><code class="language-python">
# 마지막 숫자를 구하는 함수
def find_last_number(n): #n을 인자로 받는데

    # 마지막 숫자를 구할 수 없는 경우를 우선 생각하자.
    if n == 0: # 만약 n이 0이면 무엇을 곱해도 0이 나오므로
        return &quot;INSOMNIA&quot; # &quot;INSOMNIA (= 불면증)&quot;를 반환하는 것으로 시작.

    # 이후에는
    number_0_9 = set() # 0~9까지의 숫자를 저장할 set을 만들고
    multiplier = 1 # 곱할 수를 1로 초기화한 후 (Nx1 부터 시작해야하니까)

    # 0~9까지의 숫자가 모두 나올 때까지 반복하는 while 루프를 시작한다.
    while len(number_0_9) &lt;=9: # number_0_9의 길이가 9 이하일때
        current = n * multiplier # n * multiplier를 current에 저장하며
        multiplier += 1 # multiplier를 1씩 증가시키고
        collect_digits(current, number_0_9) # 어떠한 함수를 써서 current값을 반환받는다. 
    return current # 이게 뭔지는 아래에 가서 자세히보자 

# current의 각 자릿수를 number_0_9에 추가해서 0~9까지의 숫자를 수집하는 함수
def collect_digits(current, number_0_9):
    for digit in str(current):  # current를 문자열로 변환해 한 글자씩 순회
        number_0_9.add(digit)   # 각 자릿수를 set에 추가 (이미 있으면 자동 무시)

# 입력 처리
def solve():
    t = int(input()) # 첫 번째 줄에서 테스트 케이스의 수 t를 입력받는다.

    for case_idx in range(1, t + 1): # 테스트 케이스에 맞는 출력을 위해 각 테스트 케이스에 대해 1부터 t까지 반복하면서 case_idx를 1씩 증가시킨다.
        n = int(input()) # 각 테스트 케이스마다 n을 입력받는다.
        result = find_last_number(n) # find_last_number 함수를 호출하여 n에 대한 결과를 result에 저장한다.
        print(f&quot;Case #{case_idx}: {result}&quot;) # 결과 출력


solve() # solve 함수를 호출하여 프로그램을 실행</code></pre>
<hr>
<h1 id="다른-풀이">다른 풀이</h1>
<blockquote>
<p>for문으로 <strong>범위를 고정하되, break로 조기 종료해 불필요한 탐색을 방지함</strong>
ㅁ</p>
</blockquote>
<pre><code class="language-python">import sys ; read = sys.stdin.readline
for n in range(int(read())):
    x = int(read())
    if x == 0 : print(f&quot;Case #{n+1}: INSOMNIA&quot;) ; continue
    r = [False]*10
    for i in range(1,4096):
        for j in range(10):
            if str(j) in str(i*x) : r[j] = True
        if all(r) : print(f&quot;Case #{n+1}: {i*x}&quot;) ; break</code></pre>
<hr>
<h1 id="생각해-본-것">생각해 본 것</h1>
<blockquote>
<p>탐색 범위가 주어지지 않은 코드를 작성할 때는
정확한 연산보다 실행시간과 메모리 관리를 우선적으로 고려할 필요가 있지 않을까?</p>
</blockquote>
<p>break 없이 for문으로 과도하게 넓은 범위를 전부 탐색한다면,
매 반복마다 str(i * x) 문자열이 생성되어 메모리 낭비가 심해진다.
이런 상황에서는 break나 while로 조건 만족 즉시 종료하는 것이 훨씬 효율적일 수 있을 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[BST, B-Tree, B+Tree]]></title>
            <link>https://velog.io/@cold_as_hell/BTree-a4hkbqsk</link>
            <guid>https://velog.io/@cold_as_hell/BTree-a4hkbqsk</guid>
            <pubDate>Sun, 29 Mar 2026 03:09:35 GMT</pubDate>
            <description><![CDATA[<h1 id="이진탐색트리">이진탐색트리</h1>
<p>이진 탐색 트리는 이진탐색의 개념을 트리 형태의 구조에 접목한 자료구조로, 선형시간이 소요되는 연결 리스트 자료구조의 수행시간을 향상하기 위한 자료구조이다.</p>
<p><em>※ 이진탐색 : 정렬된 데이터의 중간에 위치한 항목을 기준으로 데이터를 두 부분으로 나누어가며 특정항목을 찾는다.</em></p>
<hr>
<h2 id="구조">구조</h2>
<p>단순 연결 리스트에서는 각 노드가 다음 노드만을 가리키므로 이진 탐색을 적용하기 어렵다.</p>
<p>반면, 이진 탐색 트리는 각 노드가 왼쪽 자식 노드와 오른쪽 자식 노드를 가지며, 데이터의 크기에 따라 노드가 배치된다.</p>
<p>이러한 구조를 통해 탐색 시 매 단계마다 탐색 범위를 절반으로 줄일 수 있어 효율적인 탐색이 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/2af29b9a-a253-491f-9da4-3482878fca88/image.png" alt=""></p>
<hr>
<h2 id="이진탐색-트리-조건">이진탐색 트리 조건</h2>
<p>각 노드 n에 저장된 키가 n의 왼쪽 서브 트리에 있는 노드에 저장된 키보다 크고, n의 오른쪽 서브트리에 있는 노드의 키보다 작아야 한다.</p>
<p>즉,</p>
<blockquote>
<p>왼쪽 서브트리 &lt; 현재 노드 &lt; 오른쪽 서브트리</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/99a379cc-c2c5-4077-9833-a1a36f242aa0/image.png" alt=""></p>
<hr>
<h1 id="보완방법">보완방법</h1>
<p>이진 트리 형태의 자료구조는 대용량의 데이터 처리에 효율적이지 못하다.</p>
<p>이진트리가 가질 수 있는 최대 자식수는 2인데, 대용량 데이터를 처리하려면 트리의 높이가 높아지고 탐색시간이 길어지기 때문이다.</p>
<p>노드에 수백에서 수천개의 키를 저장하여 트리의 높이를 낮추고, 다방향 검색을 하면 이와같은 문제점을 해결할 수 있다.</p>
<hr>
<h2 id="b-tree">B-Tree</h2>
<blockquote>
<p>한 노드에 여러 키와 데이터를 저장하는 균형 트리</p>
</blockquote>
<p>1) 모든 노드는 동일한 깊이를 갖는다.
2) 루트가 아닌 각 노드의 자식 수는 ⌈M/2⌉ 이상 M 이하이다.
3) 루트의 자식 수는 2 이상이다.</p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/019f5467-0335-4fa1-b52a-72d0b2e68baa/image.png" alt=""></p>
<hr>
<h2 id="btree">B+Tree</h2>
<blockquote>
<p>모든 실제 데이터는 리프 노드에 저장되고, 내부 노드는 탐색을 위한 키만 가지는 균형 트리</p>
</blockquote>
<p>1) 모든 리프 노드는 동일한 깊이를 갖는다.
2) 내부 노드는 키와 자식 포인터만을 가지며, 탐색을 위한 인덱스 역할을 수행한다.
3) 모든 데이터는 리프 노드에만 저장된다.
4) 리프 노드들은 연결 리스트 형태로 서로 연결되어 있어 순차 탐색이 용이하다.
5) 각 노드의 자식 수는 B-Tree와 동일하게 최소 ⌈M/2⌉ 이상, 최대 M 이하를 만족한다.</p>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/6410f6f2-4222-4f99-9d89-f0c5e446eb1d/image.png" alt=""></p>
<h2 id="b-tree-vs-btree">B-Tree vs B+Tree</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th>B-Tree</th>
<th>B+Tree</th>
</tr>
</thead>
<tbody><tr>
<td>데이터 저장 위치</td>
<td>모든 노드에 분산</td>
<td>리프 노드에만 집중</td>
</tr>
<tr>
<td>내부 노드 구조</td>
<td>키 + 데이터 (무거움)</td>
<td>키만 (가벼움)</td>
</tr>
<tr>
<td>fan-out (자식 수)</td>
<td>작음</td>
<td>큼</td>
</tr>
<tr>
<td>트리 높이</td>
<td>높음</td>
<td>낮음</td>
</tr>
<tr>
<td>디스크 I/O</td>
<td>많음</td>
<td>적음</td>
</tr>
<tr>
<td>리프 노드 연결</td>
<td>없음</td>
<td>있음 (순차 접근 가능)</td>
</tr>
<tr>
<td>범위 검색</td>
<td>느림</td>
<td>빠름</td>
</tr>
</tbody></table>
<blockquote>
<p>내부 노드에서 데이터를 제거해 구조를 가볍게 만들면 더 많은 키를 담을 수 있어 리프노드에 담을 수 있는 자식수가 증가하고, 그 결과 트리의 높이가 낮아져 디스크 접근 횟수(I/O)가 줄어든다.</p>
</blockquote>
<blockquote>
<p>따라서 디스크 기반 대용량 데이터 환경에서는 B+Tree가 더 적합하다.</p>
</blockquote>
<hr>
<h1 id="시스터디-결론">시스터디 결론</h1>
<h2 id="질문">질문</h2>
<p>수천만 건의 회원 정보가 메모리에 다 올라가지 않고 디스크에 저장돼 있습니다. 회원번호 하나 찾기도 자주 하고, 100000번~200000번 회원을 순서대로 읽기 같은 작업도 자주 합니다. 어떤 자료구조가 좋을까요?</p>
<h2 id="답변">답변</h2>
<blockquote>
<p>리프 노드에 데이터가 집중되고, 리프 노드 간 연결을 통해 순차 접근이 가능하므로 단건 조회와 범위 조회가 모두 중요한 디스크 기반 대용량 데이터 환경에서는 B+Tree가 가장 적합합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[6603) 여러분을 만난 건, 제 인생 최고의 로또 당첨이에요^^ ]]></title>
            <link>https://velog.io/@cold_as_hell/6603-%EC%97%AC%EB%9F%AC%EB%B6%84%EC%9D%84-%EB%A7%8C%EB%82%9C%EA%B1%B4-%EC%A0%9C-%EC%9D%B8%EC%83%9D-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EB%A1%9C%EB%98%90-%EB%8B%B9%EC%B2%A8%EC%9D%B4%EC%98%80%EC%96%B4%EC%9A%94</link>
            <guid>https://velog.io/@cold_as_hell/6603-%EC%97%AC%EB%9F%AC%EB%B6%84%EC%9D%84-%EB%A7%8C%EB%82%9C%EA%B1%B4-%EC%A0%9C-%EC%9D%B8%EC%83%9D-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EB%A1%9C%EB%98%90-%EB%8B%B9%EC%B2%A8%EC%9D%B4%EC%98%80%EC%96%B4%EC%9A%94</guid>
            <pubDate>Fri, 27 Mar 2026 01:49:42 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://www.acmicpc.net/problem/6603">🔗 문제 링크</a></p>
<blockquote>
<p>완전탐색</p>
</blockquote>
<blockquote>
<p>k개의 숫자로 이루어진 집합 S가 주어졌을 때,
집합 S에서 숫자 6개를 선택하는 모든 조합을 구할 것.</p>
</blockquote>
<hr>
<h1 id="문제풀이">문제풀이</h1>
<blockquote>
<p>combinations 내장함수+완전탐색을 사용해 수월하게 조합을 구하였다.</p>
</blockquote>
<pre><code class="language-python">from itertools import combinations 

while True: 
    data = list(map(int, input().split())) # data라는 리스트 요소값을 공백을 기준으로 구분, 정수로 입력받아 넣음. 

    if data[0] == 0:  # 첫 번째 값(k)이 0이면
        break # while루프 종료

    k = data[0] # 리스트 data의 첫번째 값을 k라 칭하고
    nums = data[1:] #나머지 data 요소는 nums라 칭한 뒤 

    for comb in combinations(nums, 6):  # nums에서 6개를 뽑는 모든 조합 순서대로(오름차순) 탐색
        print(*comb)  # 조합을 공백으로 구분해서 한 줄 출력
    print()  # 각 테스트케이스 사이 빈 줄 출력</code></pre>
<hr>
<h1 id="다른-풀이">다른 풀이</h1>
<blockquote>
<p>combinations 대신 permutations 내장함수를 사용한 코드이다.</p>
</blockquote>
<pre><code class="language-python">from itertools import permutations 

while True: 
    data = list(map(int, input().split())) # data라는 리스트 요소값을 공백을 기준으로 구분, 정수로 입력받아 넣음. 

    if data[0] == 0:  # 첫 번째 값(k)이 0이면
        break # while루프 종료

    k = data[0] # 리스트 data의 첫번째 값을 k라 칭하고
    nums = data[1:] 나머지 data 요소는 nums라 칭한 뒤 

    for per in permutations(nums, 6):  # nums에서 6개를 뽑는 모든 조합 순서대로(오름차순) 탐색
        print(*per)  # 조합을 공백으로 구분해서 한 줄 출력
    print()  # 각 테스트케이스 사이 빈 줄 출력</code></pre>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/9a7240a1-83ca-4249-a0dd-0c770b81cada/image.png" alt=""></p>
<hr>
<h1 id="생각해-본-것">생각해 본 것</h1>
<blockquote>
<p>combinations 대신 permutations를 쓰면 왜 출력 초과가 뜰까?</p>
</blockquote>
<p>두 함수는 모두 itertools에서 가져올 수 있지만,
combinations는 순열을 고려하지 않고, permutations는 순열을 모두 고려하여 결과를 반환한다.</p>
<p>permutations는 문제에서 요구하는 것 보다 지나치게 많은 결과를 출력해 출력 초과가 발생한 것이다.</p>
<p><strong>순열을 고려하지 않아도 되는 문제라면 combinations를 사용하자.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정보 엔트로피]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%A0%95%EB%B3%B4-%EC%97%94%ED%8A%B8%EB%A1%9C%ED%94%BC</link>
            <guid>https://velog.io/@cold_as_hell/%EC%A0%95%EB%B3%B4-%EC%97%94%ED%8A%B8%EB%A1%9C%ED%94%BC</guid>
            <pubDate>Tue, 24 Mar 2026 11:48:03 GMT</pubDate>
            <description><![CDATA[<h1 id="정보-엔트로피란">정보 엔트로피란</h1>
<p>데이터의 통신, 처리, 추출, 응용을 연구하는 정보이론에서 확률변수의 불확실성(uncertainty)을 정량화하는 척도.</p>
<blockquote>
<p>즉, 정보 엔트로피는 데이터가 얼마나 다양하고 복잡하며 예측하기 어려운지를 의미한다.</p>
</blockquote>
<hr>
<h2 id="정보-엔트로피가-높다는-것">정보 엔트로피가 높다는 것</h2>
<p>픽셀값이 다양하고 복잡한 이미지이다!</p>
<pre><code>예시
1) 노이즈 이미지
2) 랜덤한 픽셀 값
= 색이 들쭉날쭉하고 규칙이 없음</code></pre><hr>
<h2 id="정보-엔트로피가-낮다는-것">정보 엔트로피가 낮다는 것</h2>
<p>픽셀값이 단순하고 반복적인 이미지이다!</p>
<pre><code>예시
1) 단색 이미지 (완전 흰색, 검은색)
2) 반복 문자열 AAAAAA
= 단순한 구조</code></pre><hr>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/4412e277-1711-4833-af3c-92f2637512ad/image.png" alt=""></p>
<pre><code>엔트로피 높다! → 엔트로피 낮다!</code></pre><hr>
<h2 id="데이터-압축과-정보엔트로피">데이터 압축과 정보엔트로피</h2>
<p>데이터 압축은 원래 표현보다 더 적은 비트를 사용하여 정보를 부호화하는 과정이다.
이때 압축의 목표는 데이터 내의 중복성(Redundancy)을 제거하여, 데이터 크기를 이론적 최소 정보량인 <strong>정보 엔트로피(Information Entropy)</strong>에 최대한 수렴시키는 것.</p>
<p>즉, 불필요한 데이터를 압축해
저장 공간의 효율적 활용, 전송 속도 향상 및 비용 절감, 그리고 데이터 관리 및 배포의 편의성을 극대화하는 것이다.</p>
<p>이때 모든 압축 방식은 데이터 복원 여부에 따라 무손실(Lossless) 또는 손실(Lossy) 압축으로 나뉜다.</p>
<hr>
<h3 id="무손실-압축">무손실 압축</h3>
<blockquote>
<p>무손실 압축은 데이터 내 반복 패턴, 출현 빈도, 문구 중복과 같은 통계적 중복성을 제거하거나 짧은 기호 및 위치 정보(인덱스)로 치환하여, 데이터 크기를 이론적 최소 정보량인 엔트로피에 수렴시키는 과정</p>
</blockquote>
<p>즉, 데이터의 내용을 단 1비트도 손실하지 않고 크기만 줄이는 방식이며(그러나 엔트로피 이하로는 압축이 불가능하다)
압축을 복원하면 원래의 원본 데이터와 100% 일치한다.</p>
<pre><code>예시
1. PNG
2. ZIP
3. GIF</code></pre><hr>
<h4 id="무손실-압축에서의-치환">무손실 압축에서의 치환</h4>
<p><strong>원본 값을 유지하면서</strong> 데이터를 더 짧은 코드로 표현하는 방식이다.</p>
<pre><code>예시
A → 1
B → 01
C → 001</code></pre><ul>
<li>하프만 코딩 같은 방식을 사용하여 자주 등장하는 데이터일수록 더 짧게 표현해 <strong>복원 시 원본과 완전히 동일</strong></li>
</ul>
<hr>
<h4 id="무손실-압축에서의-반복-제거-패턴-압축">무손실 압축에서의 반복 제거 (패턴 압축)</h4>
<p>반복되는 데이터를 값과 횟수로 표현하여 압축한다.</p>
<pre><code>예시
AAAAAA → A6
00000000 → (0, 8)</code></pre><ul>
<li><strong>원본 데이터는 그대로 유지되며</strong> 표현만 변경됨</li>
</ul>
<hr>
<h4 id="무손실-압축에서의-참조-방식-사전-기반">무손실 압축에서의 참조 방식 (사전 기반)</h4>
<p>이미 등장한 데이터를 다시 저장하지 않고 위치를 참조한다. 당연히 <strong>원본 데이터는 그대로 유지</strong> 되며 
이후 반복 문자열을 재사용하여 압축한다 (=zip)</p>
<pre><code>예시
ABABABAB
→ [AB][AB][AB][AB]
→ [1][1][1][1]</code></pre><hr>
<h3 id="손실압축">손실압축</h3>
<blockquote>
<p>인위적으로 일부 정보를 제거하여 데이터의 복잡도(엔트로피)를 낮추는 과정.</p>
</blockquote>
<p>데이터의 일부를 영구적으로 삭제하여 파일 크기를 획기적으로 줄인다.
압축을 풀었을 때 원본과 유사해 보이지만, <strong>실제 데이터는 이미 변형된 상태</strong>이다.</p>
<pre><code>예시
1. JPEG 
2. MP3 
3. MP4 </code></pre><hr>
<h3 id="손실-압축에서의-제거">손실 압축에서의 제거</h3>
<p>사람이 인지하기 어려운 정보(덜 중요한 데이터)를 제거한다.</p>
<pre><code>예시
1) 이미지 색상 단순화
   256색 → 64색으로 감소

2) JPEG에서 고주파(디테일) 제거
   → 머리카락, 잔디 등의 세밀한 부분 일부 삭제</code></pre><hr>
<h3 id="손실-압축에서의-치환">손실 압축에서의 치환</h3>
<p>원본 데이터를 <strong>유사한 값(근사값)으로 변환한다.</strong></p>
<pre><code>예시
1) 픽셀 값 평균화
   [101, 102, 103] → [102, 102, 102]

2) 색상 근사화
   RGB(123, 201, 98)
   → RGB(120, 200, 100)

3) 오디오 압축 (MP3)
   → 사람이 잘 듣지 못하는 주파수 제거 후 재구성
</code></pre><hr>
<h1 id="씨스터디-결론">씨스터디 결론</h1>
<p>Q. 1000x1000 해상도의 JPEG 파일이 두 장 있습니다. 하나는 &#39;파란 하늘&#39;이고, 다른 하나는 &#39;나뭇잎&#39; 사진입니다. 이 두 파일의 용량을 논리적으로 추론하고, 같은 해상도임에도 용량 차이가 발생하는 이유를 설명하세요. </p>
<p>A. Jpeg 파일은 압축될 때 원본값이 제거되거나 삭제되는 손실압축방식을 채택합니다.</p>
<p>손실압축 방식은  중요하지 않은 데이터는 삭제하거나 근사값으로 치환하여 데이터의 복잡도를 낮추는데,</p>
<p>파란 하늘 사진은  픽셀값의 변화가 적고 중복값이 많은 데이터이지만
나뭇잎 사진은 픽셀값의 변화가 크고 중복값이 적은 데이터이기에</p>
<p>파란하늘의 압축 효율이 높아 나뭇잎 이미지보다 파일 용량이 더 작아질 가능성이 큽니다!!</p>
<p>찡긋 😉</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[제발 대방어를 사게 해주세요]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%A0%9C%EB%B0%9C-%EB%8C%80%EB%B0%A9%EC%96%B4%EB%A5%BC-%EC%82%AC%EA%B2%8C-%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94</link>
            <guid>https://velog.io/@cold_as_hell/%EC%A0%9C%EB%B0%9C-%EB%8C%80%EB%B0%A9%EC%96%B4%EB%A5%BC-%EC%82%AC%EA%B2%8C-%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94</guid>
            <pubDate>Mon, 02 Mar 2026 14:56:57 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/1d6b40ad-72c0-47ef-9b6b-1fa432857983/image.png" alt=""></p>
<p>,,,,!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발에 AI 잘 써먹는법]]></title>
            <link>https://velog.io/@cold_as_hell/%EA%B0%9C%EB%B0%9C%EC%97%90-AI-%EC%9E%98-%EC%8D%A8%EB%A8%B9%EB%8A%94%EB%B2%95</link>
            <guid>https://velog.io/@cold_as_hell/%EA%B0%9C%EB%B0%9C%EC%97%90-AI-%EC%9E%98-%EC%8D%A8%EB%A8%B9%EB%8A%94%EB%B2%95</guid>
            <pubDate>Sun, 01 Mar 2026 07:30:57 GMT</pubDate>
            <description><![CDATA[<p>수정중</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[시스템콜은 무엇이며 언제 발생하나요]]></title>
            <link>https://velog.io/@cold_as_hell/%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%A9%B0-%EC%96%B8%EC%A0%9C-%EB%B0%9C%EC%83%9D%ED%95%98%EB%82%98%EC%9A%94-q6y8o73u</link>
            <guid>https://velog.io/@cold_as_hell/%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%A9%B0-%EC%96%B8%EC%A0%9C-%EB%B0%9C%EC%83%9D%ED%95%98%EB%82%98%EC%9A%94-q6y8o73u</guid>
            <pubDate>Sun, 01 Mar 2026 04:27:55 GMT</pubDate>
            <description><![CDATA[<h1 id="시스템콜의-정의">시스템콜의 정의</h1>
<blockquote>
<p>유저모드에서 직접 수행할 수 없는 보호된 자원에 접근하기 위해 운영체제의 커널 루틴을 호출하여 서비스를 이용하는 것.</p>
</blockquote>
<blockquote>
<p>프로그램이 커널의 기능을 요청하기 위해 운영체제를 호출하는 방식.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/1b3e7a2b-9ae0-4d6f-8c9e-aa53bfe19f82/image.png" alt=""></p>
<p>시스템 콜은 정글 보안팀과 같은 역할을 한다. <del>왜인지 왜곡된 그곳의 이미지는 잊자</del></p>
<p>프로그램은 유저모드에서 실행되므로 파일, 메모리, 프로세스, 네트워크와 같은 보호된 자원과 하드웨어에 직접 접근할 수 없다.</p>
<p>따라서 파일 처리, 프로세스 생성, 메모리 관리등으로 보호된 자원에 접근이 필수적인 작업이 필요할 경우 커널모드로 전환하여 운영체제의 기능을 요청해야 한다.</p>
<p>이때 운영체제의 커널 루틴을 호출하여 서비스를 제공받는 방식을 시스템 콜이라고 한다.</p>
<hr>
<h2 id="기능">기능</h2>
<ol>
<li>유저 모드에 있는 응용 프로그램이 커널의 기능을 사용할 수 있도록 한다.</li>
<li>시스템 호출을 하면 유저 모드에서 커널 모드로 바뀐다.</li>
<li>커널에서 시스템 호출을 처리하면 커널 모드에서 유저 모드로 돌아가 작업을 계속한다.</li>
</ol>
<hr>
<h2 id="시스템-호출의-유형">시스템 호출의 유형</h2>
<p>1.프로세스 제어(process control)
2. 파일 조작(file manipulation)
3. 장치 관리(device management)
4. 정보 유지(information maintenance)
5. 통신(communication)</p>
<hr>
<h1 id="시스템콜의-발생">시스템콜의 발생</h1>
<p>유저 모드에서 실행 중인 어플리케이션에서 커널에게 어떤 서비스를 요청할 때 발생함.</p>
<hr>
<h1 id="더-알아보기">더 알아보기</h1>
<h2 id="유저모드-vs-커널모드">유저모드 vs 커널모드</h2>
<p>운영체제는 시스템의 안정성과 보안을 위해 CPU(중앙처리장치) 실행 권한을 두 가지 모드로 나누어 관리한다.</p>
<h3 id="유저모드">유저모드</h3>
<p>일반 응용 프로그램이 실행되는 모드로 제한된 권한만을 가진다.</p>
<h3 id="커널모드">커널모드</h3>
<p>운영체제가 실행되는 모드. 모든 하드웨어 자원에 접근 가능</p>
<h3 id="특징">특징</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>유저모드 (User Mode)</th>
<th>커널모드 (Kernel Mode)</th>
</tr>
</thead>
<tbody><tr>
<td>실행 주체</td>
<td>일반 응용 프로그램</td>
<td>운영체제의 커널</td>
</tr>
<tr>
<td>접근 권한</td>
<td>제한적 권한</td>
<td>모든 권한</td>
</tr>
<tr>
<td>하드웨어 접근</td>
<td>직접 접근 불가</td>
<td>직접 접근 가능</td>
</tr>
<tr>
<td>메모리 접근</td>
<td>자기 프로세스 영역만 접근 가능</td>
<td>모든 메모리 영역 접근 가능</td>
</tr>
<tr>
<td>시스템 자원 제어</td>
<td>직접 제어 불가</td>
<td>CPU, 메모리, 디스크 등 직접 제어</td>
</tr>
<tr>
<td>안정성</td>
<td>오류 발생 시 해당 프로세스만 영향</td>
<td>오류 발생 시 시스템 전체에 영향 가능</td>
</tr>
<tr>
<td>모드 전환</td>
<td>시스템 콜, 인터럽트 발생 시 커널모드로 전환</td>
<td>작업 완료 후 유저모드로 복귀</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA 스터디를 마치며]]></title>
            <link>https://velog.io/@cold_as_hell/JAVA-%EC%8A%A4%ED%84%B0%EB%94%94%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0-ywu5e9qb</link>
            <guid>https://velog.io/@cold_as_hell/JAVA-%EC%8A%A4%ED%84%B0%EB%94%94%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0-ywu5e9qb</guid>
            <pubDate>Mon, 23 Feb 2026 11:36:05 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/cold_as_hell/post/00b24a14-6b4d-4e72-984e-6db71cedfc82/image.png" alt=""></p>
<hr>
<h1 id="눈을-감아-멈춰있던-나를-깨워">눈을 감아 멈춰있던 나를 깨워</h1>
<p>즐거운 Java 스터디가 종강을 맞이했다.
정글 졸업 이후 한동안 공부를 손에서 놓고 있었는데,
그간 멋진 Java 스터디 덕분에 오랜만에 공부에 집중하며 새로운 지식을 쌓을 수 있어 좋았다.</p>
<hr>
<h1 id="낯선-세계를-들여다보다">낯선 세계를 들여다보다</h1>
<p>Java, 객체지향……
내게는 너무나 멀게만 느껴지던 세계였는데, 스터디를 통해 비로소 들여다볼 용기가 생긴 것 같다.
여럿이 함께 공부한 덕분에 큰 원동력이 생기고,
서로를 보며 좋은 자극을 주고받을 수 있었기에 가능한 일이었다.</p>
<hr>
<h1 id="고마운-스터디-멤버들에게">고마운 스터디 멤버들에게</h1>
<p>늘 내게 좋은 영향을 주는 고마운 정글 여친,
스터디의 진행을 도맡아 가장 고생 많았던 스터디장
🩷🤍🩷 jaykxo 🩷🤍🩷 언니,</p>
<p>스터디 대리 진행을 시도하던 중 음향 장비 이슈가 터져 난감했는데, 능숙하게 대신 진행해 주신 혜림님,
좋은 문제를 꼼꼼히 준비해 주신 윤지님,
백엔드 현직자의 경험으로 알짜배기 지식을 전파해 주신 강현님,
부트캠프를 떠나기 전에도, 떠난 후에도 든든한 버팀목이 되어 준 지희님,</p>
<p>저마다의 색깔로 함께했던 모든 순간을 빛내준 이 스터디를,
영원토록 뜨겁게 지지 않을 이 계절을
오래도록 기억할 것 같다.</p>
]]></description>
        </item>
    </channel>
</rss>