<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>venyclxx__b.log</title>
        <link>https://velog.io/</link>
        <description>백앤드 개발자 아직은 지망생?!</description>
        <lastBuildDate>Tue, 19 May 2026 08:16:26 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>venyclxx__b.log</title>
            <url>https://velog.velcdn.com/images/venyclxx__d/profile/4d8f10bc-b31a-444e-a1ba-9a52bfd728da/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. venyclxx__b.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/venyclxx__d" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[간단한 CBT 오답 체크 파일]]></title>
            <link>https://velog.io/@venyclxx__d/%EA%B0%84%EB%8B%A8%ED%95%9C-CBT-%EC%98%A4%EB%8B%B5-%EC%B2%B4%ED%81%AC-%ED%8C%8C%EC%9D%BC</link>
            <guid>https://velog.io/@venyclxx__d/%EA%B0%84%EB%8B%A8%ED%95%9C-CBT-%EC%98%A4%EB%8B%B5-%EC%B2%B4%ED%81%AC-%ED%8C%8C%EC%9D%BC</guid>
            <pubDate>Tue, 19 May 2026 08:16:26 GMT</pubDate>
            <description><![CDATA[<p>오늘은 초 간단으로 가볍게 CBT?를 만들어봤다.
이번에 정보처리기사 시험을 치는데 기존 CBT 웹사이트에는 22년도 기출문제까지밖에 지원하지 않는 것을 보고 만들기로 결심하였다.</p>
<p>급하게 만들어야해서 완전한 바이브코딩으로 만들었으며, 제작 시간은 2시간정도 걸렸다. 현재는 window만 지원되는 상태라 정처기 시험 끝나고 나면 나중에 수정을 좀 해야겠다.</p>
<p><a href="https://github.com/VenyVince/CBT-Alone">깃허브 링크</a>를 추가해놓겠다.</p>
<p><a href="https://github.com/VenyVince/CBT-Alone">https://github.com/VenyVince/CBT-Alone</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동시성 문제와 동기화 기법]]></title>
            <link>https://velog.io/@venyclxx__d/%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94-%EA%B8%B0%EB%B2%95</link>
            <guid>https://velog.io/@venyclxx__d/%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94-%EA%B8%B0%EB%B2%95</guid>
            <pubDate>Mon, 18 May 2026 10:34:50 GMT</pubDate>
            <description><![CDATA[<p>우리는 여태까지
프로세스/스레드 -&gt; CPU 스케쥴링 -&gt; 동기/비동기 -&gt; 블로킹/논블로킹
의 흐름으로 OS에 대해서 알아보았다.</p>
<p>이 내용들을 알고 있을 때 우리는 &#39;멀티스레드 상태에서 CPU가 특정 변수를 동시에 수정하게되면 문제가 생기지 않는가&#39; 하는 질문을 던져볼 수 있다.</p>
<p>예를 들면 이런 상황이다
만약 쇼핑몰에서 상품 데이터에 접근을 한다고 해보자.
상품 하나가 구매된다면 상품의 재고는 하나가 줄어들것이다.
그런데 사용자 2명이 동시에 상품을 하나씩 구매한다면 어떻게 될까?</p>
<p>우리의 생각대로라면 당연하게도 2개의 재고가 줄어드는데 맞다.
멀티 스레드를 사용하게 되면 CPU는 우리의 생각대로 행동하지 않는다. CPU는</p>
<pre><code>1. 메모리에서 상품 재고 확인
2. 기존 재고에서 -1 계산
3. 재고 저장</code></pre><p>의 세가지 단계를 가지게 된다.</p>
<p>그런데 이때 A와 B, 두 개의 스레드가 동시에 재고에 접근하게 되면 어떻게 될까?
<img src="https://velog.velcdn.com/images/venyclxx__d/post/865c2474-9b40-40e7-8ecd-d2a05743c4a3/image.png" alt=""></p>
<p>사진과 같은 단계를 거치게 되어 A와 B의 결과값은 우리가 기대하는 <code>기존 재고 -2</code>가 아닌 <code>기존 재고 -1</code>의 값을 갖게 될 것이다.</p>
<p>이러한 문제는 <strong><em>동시성 문제</em></strong> 라고 칭하는 것들 중 하나이다.
여기서  문제가 되는 공유 자원에 접근하는 코드 영역을 <strong><em>임계영역(Critical Section)</em></strong>이라고 칭하는데 임계영역은 동시에 여러 스레드가 실행하게되면 문제를 발생시키는 영역이다.</p>
<h3 id="동시성-문제">동시성 문제</h3>
<ul>
<li>멀티 스레드 환경에서는 여러 스레드가 같은 자원에 동시에 접근이 가능하다. stack을 제외하면 변수나 메모리, 파일, DB 데이터 등 여러가지 자원을 공유하고 있기 때문이다.</li>
</ul>
<p>앞서 예시든 데이터의 일관성 문제를 가진 상태를 <strong><em>Race Condition(경쟁상태)</em></strong> 라고 한다.</p>
<p>Race Condition의 경우 여러 스레드가 공유 자원에 접근하여 동시에 수정하기 때문에 발생한다. 그렇다면 이외에 또 다른 문제가 있을까?</p>
<p>대표적으로 <strong><em>DeadLock</em></strong>과 저번에 언급되었던 <strong><em>Starvation</em></strong>이 있다.</p>
<p><strong><em>DeadLock(교착 상태)</em></strong>
데드락은 서로 Lock을 잡고 기다리다가 영원히 멈추는 것을 이야기한다. </p>
<ul>
<li>Lock은 공유 자원에 접근할 때 다른 스레드가 접근하지 못하도록 잠그는 장치이다.</li>
</ul>
<p>만약 자원 A와 B를 필요로하는 스레드 1과 2가 있다고 해보자.
스레드1은 자원 A를 먼저 접근하고 B를 필요로 한다.
스레드2는 자원 B를 먼저 접근하고 A를 필요로 한다.
이러한 상황에서 DeadLock은 아래와 같은 단계로 벌어지게 된다.
<img src="https://velog.velcdn.com/images/venyclxx__d/post/876c9fc3-e08a-44ca-abc6-87c9a238bc0f/image.png" alt="">
둘은 영원히 닿을 수 없는 평행 상태에서 닿고자 계속해서 뻗어가는 상태라고 볼 수 있겠다.
이러한 문제로 인해 프로그램이 멈추게 된다.</p>
<p>DeadLock의 경우 네가지 조건을 동시에 만족할 때 발생한다.</p>
<pre><code>1. 상호 배제: 한 번에 한 프로세스만 자원을 사용하는 것.
2. 점유 대기: 자원을 점유한 채로 다른 자원을 기다리는 것.
3. 비선점: 다른 프로세스가 점유한 자원을 강제로 빼앗을 수 없는 것.
4. 순환 대기: 프로세스들이 서로 순환하며 자원을 기다리는 것.</code></pre><p><strong><em>Starvation(기아 상태)</em></strong>
기아상태는 앞서 말했듯 계속해서 실행되지 않는 문제이다.
예를 들면, 저번시간에 이야기한 우선순위 스케쥴링에서 높은 우선순위 작업만 계속해서 실행되는 바람에 낮은 우선순위 작업은 영원히 대기될 수도 있는 경우를 뜻한다.</p>
<ul>
<li>이외에도 LiveLock이나 Priority Inversion이라는 문제가 존재한다. 간략하게 설명하면 LiveLock은 서로 양보만 하다가 아무 작업도 진행이 안되는 것이며 Priority Inversion은 낮은 우선순위가 락을 잡고 있어서 높은 우선 순위 작업이 기다리는 문제이다. 이는 실시간 시스템에서 중요하다.</li>
</ul>
<p>여러 스레드가 동시에 접근하고 실행 순서에 따라 결과가 달라지는 동시성 문제의 핵심이다.</p>
<p>이것을 해결하기 위해 우리는 저번 시간에 알아봤던 <strong><em>동기화</em></strong>라는 것을 통해 한 번에 하나에만 접근하게 할 수 있게 된다.</p>
<h3 id="동기화-lock기반-기법">동기화 Lock기반 기법</h3>
<p><strong><em>Mutex</em></strong></p>
<p>가장 기본적인  Lock을 활용한 동기화 기법이다.
단 하나의 키를 가지고있는 방에 접근한다고 생각을 하면 쉽다.
A라는 사람이 방에 접근한다고 해보자. 화분 밑에서 키를 가지고 방에 들어가게 된다.
그렇다면 B라는 사람은 어떻게 방에 들어갈 수 있을까?
A가 문을 열어주지 않는 이상 B는 방에 들어갈 수 없다.</p>
<p>이처럼 뮤텍스 기법은 Lock을 통해 오직 하나만 접근 가능한 <strong><em>상호 배제(Mutual Exlusion)</em></strong> 하는 기법이다.</p>
<p>그러나 스레드가 Lock을 얻지 못하면 대기상태로 들어가기 때문에 OS가 스케쥴링과 Context Switching을 수행해야한다. 이러한 이유로 Lock은 비용이 존재한다.</p>
<p><strong><em>Semaphore</em></strong></p>
<p>Mutex의 확장 버전이다.
<img src="https://velog.velcdn.com/images/venyclxx__d/post/082bbc58-795c-4059-b3a6-635dce8628a9/image.png" alt="">
Mutex는 단 하나의 키를 가지고 있는 방이라면 Semaphore은 여러 개의 키를 가지고 있는 방이다.
<br>
<br>
Semaphore는 Binary와 Counting 방식이 있다.
<img src="https://velog.velcdn.com/images/venyclxx__d/post/cc002f35-1937-45c2-98b7-e475eb21b4b9/image.png" alt=""></p>
<p>Binary 방식은 값을 0과 1만 가지고 있어 사실상 Mutex와 동일하게 동작한다.
공유 자원에 오직 하나의 스레드만 접근해야 할 때 다른 스레드를 완전히 차단하기 위해 사용된다.
Counting 방식은 값을 0부터 N까지 여러개 가질 수 있어 N개의 스레드가 동시 접근을 허용한다.
Counting 방식의 경우 DB에서 최대 연결 수를 제한하거나 스레드 풀에서 동시 실행 가능한 작업 수를 제한할 때 등에서 사용하게 된다.</p>
<ul>
<li>Binary Semaphore vs Mutex: Mutex는 소유권의 개념이 존재하고 Binary Semaphore은 소유권의 개념이 존재하지 않는다. 그래서 Mutex의 경우 Lock을 건 스레드가 Lock을 해제할 수 있고 Binary Semaphore의 경우 Lock을 걸지 않은 다른 스레드가 Lock을 해제할 수 있다.</li>
<li>Counting Semaphore은 Mutex나 Binary Semaphore방식이 데이터 일관성을 보호하기 위한 목적을 가지고 있는 것과 달리 시스템 자원의 고갈을 방지하기 위해 사용된다. 예를들어, DB서버가 감당하지 못할 1억개의 요청이 동시에 들어오게 되면 서버는 다운된다. 그러나 DB서버가 감당할 수 있는 1000개의 요청만 먼저 처리하도록 하게 된다면 서버가 다운되지 않고 순차적으로 처리된다.</li>
</ul>
<p><strong><em>Synchronized</em></strong></p>
<p>Java에서 가장 기본적이고 많이 사용하는 동기화 방식이다.<br>여러 스레드가 동시에 같은 데이터에 접근할 때, 한 번에 한 스레드만 작업하도록 막아준다.</p>
<p>예를 들어 은행 계좌에 동시에 입금이 일어난다고 가정해보자.<br>두 사람이 동시에 같은 계좌 금액을 수정하면 계산이 꼬일 수 있다.</p>
<p>Synchronized는 이런 상황에서 “지금 이 작업은 한 사람만 사용 가능합니다.”라고 문 앞에 잠금장치를 거는 느낌이다.</p>
<p>Java에서는 아래처럼 간단하게 사용할 수 있다.</p>
<pre><code class="language-java">public synchronized void income() {
    balance += 500000;
}</code></pre>
<p>메서드가 실행되면 Java가 자동으로 Lock(잠금)을 걸고,<br>작업이 끝나면 자동으로 Lock을 해제한다.</p>
<p>그래서 사용법이 매우 간단하고 실수할 가능성이 적다.</p>
<p>다만 단점도 있다.</p>
<p>누군가 작업 중이면 다른 스레드는 기다려야 하기 때문에,<br>동시에 요청이 많아지면 성능 비용이 발생할 수 있다.</p>
<p>즉, 안전하지만 사람이 많아지면 줄 서서 기다리는 방식이다.</p>
<p><strong><em>ReentrantLock</em></strong></p>
<p><code>ReentrantLock</code>도 역할 자체는 비슷하다.<br>여러 스레드가 동시에 데이터를 수정하지 못하도록 막는다.</p>
<p>하지만 <code>Synchronized</code>보다 조금 더 “직접 제어”하는 방식이다.</p>
<pre><code class="language-java">lock.lock();

try {
    balance += 500000;
} finally {
    lock.unlock();
}</code></pre>
<p>여기서는 개발자가 직접:</p>
<ul>
<li>Lock을 걸고</li>
<li>작업이 끝나면</li>
<li>Lock을 풀어줘야 한다.</li>
</ul>
<p>조금 더 복잡하지만 대신 기능이 더 많다.</p>
<p>예를 들어:</p>
<ul>
<li>일정 시간만 기다렸다가 포기하기</li>
<li>먼저 기다린 스레드부터 처리하기(Fairness)</li>
<li>Lock 획득 실패 시 다른 작업 수행하기</li>
</ul>
<p>같은 고급 기능들을 지원한다.</p>
<p>Reentrant는 &#39;같은 스레드가 이미 가진 Lock을 다시 획득할 수 있다&#39;는 뜻이다.</p>
<p>쉽게 말하면</p>
<ul>
<li>내가 이미 회의실 열쇠를 가지고 있는데</li>
<li>잠깐 다시 문을 열어도</li>
<li>“너 이미 사용 중이니까 괜찮아”</li>
</ul>
<p>라고 허용해주는 개념이다.</p>
<p>내부적으로는 &#39;이 스레드가 몇 번 Lock을 걸었는지&#39;를 숫자로 관리한다.</p>
<p>그리고 마지막까지 unlock 해야 완전히 해제된다.</p>
<p>지금까지 Lock 기반 기법을 살펴보았다. 이번엔 Lock을 사용하지 않는 방식을 알아보자.</p>
<h3 id="동기화-lock-free기반-기법">동기화 Lock-Free기반 기법</h3>
<ol>
<li>Atomic(원자적)
동시성 문제를 CPU 명령 자체를 원자적으로 처리하는 기법이다.<pre><code>AtomicInteger count = new AtomicInteger();
count.incrementAndGet();</code></pre>의 형식으로 사용된다.</li>
</ol>
<p>Atomic은 <strong><em>CAS(Compare And Swap)</em></strong>을 통해 이루어진다.
CAS는 현재 값이 내가 예상한 값이면 변경하는 형태로 동작한다.
<img src="https://velog.velcdn.com/images/venyclxx__d/post/2c701a46-7a12-406d-b800-3e629d53cbf7/image.png" alt="">
처음 들었던 예시로 보자면 아래와 같다.</p>
<pre><code>1. A가 재고 확인
2. B가 재고 확인
3. A가 -1 연산
4. B가 -1 연산
5. A가 결과값을 예상 값과 비교 (맞아서 저장)
6. B가 결과값을 예상 값과 비교 (틀려서 다시 시도)
7. B가 재고 재확인
8. B가 -1 재연산
9. B가 결과값을 예상 값과 비교 (맞아서 저장)</code></pre><p>예시만 보아도 알겠지만 CAS를 사용하는 Atomic은 복잡한 작업에서는 사용하기 어려워진다. 여러 연산을 하나의 원자적 작업으로 묶기 어렵기 때문이다.</p>
<p>대신 Lock이 없고, Context Switching이 적으며, 빠르다는 장점을 가진다. </p>
<ul>
<li>Lock방식의 경우 대기상태와 컨텍스트 스위칭/스케쥴링이 계속해서 발생하고, CAS방식은 블로킹 없이 재시도하기 때문에 문맥교환 비용이 없어 빠르다.</li>
</ul>
<h3 id="마무리">마무리</h3>
<p>결국 동시성 문제는 멀티 스레드 환경에서 공유 자원을 안전하게 관리하기 위한 문제이며 이를 해결하기 위해서는 Lock 기반 또는 Lock Free 기반의 다양한 동기화 기법이 사용된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리팩토링 프로젝트]]></title>
            <link>https://velog.io/@venyclxx__d/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@venyclxx__d/%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Mon, 18 May 2026 05:36:57 GMT</pubDate>
            <description><![CDATA[<p>요즘은 조금 바쁜 날을 보내고 있다.
덕분에 개인적인 고민도 조금 생기는 것 같다.</p>
<p>요즘 하고 있는 것은</p>
<ol>
<li>정처기 딸 준비 / 면접 준비 겸해서 CS개념 복습</li>
<li>Re:View 프로젝트 리팩토링</li>
<li>Cosider 프로젝트 진행(설계 및 구현)</li>
<li>개인적인 운동
이정도이다.
1,2에서 각각 하루에 2<del>3시간정도를 사용하고 3,4에서 각각 하루 1</del>2시간정도를 사용하는데 정말 하루가 눈코뜰새 없이 바쁘다.</li>
</ol>
<p>본론으로 돌아와서 오늘은 내가 진행중인 리팩토링에 대해 간단하게 이야기해보고자 한다.</p>
<h3 id="개요">개요</h3>
<p>Re:View프로젝트는 사용자 후기를 중심으로한 쇼핑 플랫폼이다. 멀티캠퍼스 부트캠프에서 최종 팀프로젝트로 했던 것이다. </p>
<p>개인적으로 가장 시간을 많이 들인 프로젝트인데 아쉬움이 많이 남고 문제점도 많아서 리팩토링을 하고자 했다.</p>
<p>리팩토링 단계를 여러 개로 나누어서 진행중이고 진행 예상 기간은 5월초~6월초 정도로 약 한 달의 시간을 잡았다.</p>
<p>내가 잡은 리팩토링 단계는 3단계이다. </p>
<pre><code>1. 안정화 단계
2. 최적화 단계
3. 문서화 단계</code></pre><p>현재는 안정화 단계를 끝내고 최적화 단계로 진입한 상태이다.
아마 최적화 단계도 이번 주에서 다음주 안으로 끝나지 않을까 싶다.</p>
<p>문서화 단계가 끝나고 나서 할 일이 딱히 없다면 아마 확장성을 조금 더 챙기거나 기존에 도입하려 했지만 시간적인 압박으로 하지 못했던 것들을 구현하는 방향으로 리팩토링을 진행하지 않을까 싶다.</p>
<h3 id="안정화">안정화</h3>
<p>Re:View프로젝트는 상당히 불안정한 상태의 플랫폼이었다.
내가 팀장을 맡으면서 빠뜨린 부분이 많게 된 것 같다.
주먹구구식으로 2달 정도의 시간동안 처음보는 언어와 체계로 진행을 하다보니 아쉬운 점이 많이 남았다.</p>
<p>안정화 부분에서 아쉬운 점은 아래와 같다.</p>
<pre><code>1. 환경 변수 값들이 여기저기 흩어져있다.
2. 예외 처리 응답이 엉망이다.
3. Spring security와 관련된 보안적 측면 또한 많이 아쉽게 되어있었다.</code></pre><p>이러한 점들을 개선하기 위해서 지난 2주동안 프로젝트를 다시 파악하고 세가지 부분을 보완했다.</p>
<h3 id="최적화">최적화</h3>
<p>기본적으로 Re:View프로젝트는 테스트가 이루어지지 못한 프로젝트이다. 프로젝트를 진행하면서 잠깐잠깐 콘솔과 API Dog정도로 간략한 테스트만 했었기에 서비스의 성능 자체가 좋지 못할 것 같다는 생각이 들어서 이 단계를 채택했다.</p>
<p>최적화 단계에서 진행할 것은 아래과 같다.</p>
<pre><code>1. 주요 API의 현재 성능 측정
2. 데이터 규모와 상태에 따른 성능 변화 측정
3. 실측 결과 기반 이미지, 페이징, 검색등의 부하 분리
4. 병목점 파악 후 개선</code></pre><p>현재는 성능 측정을 위해 도구를 선택하고 기본적인 성능 측정을 기입하기 위한 문서를 만들어놓은 상태이다.
해당 내용은 필자의 Github(Re-view-personal)에서 확인할 수 있다.</p>
<h3 id="마무리">마무리</h3>
<p>아마 최적화 단계가 끝나고 나면 문서화를 통해 포트폴리오를 조금 더 강화시키게 될 것 같다. 추후에 Cosider프로젝트까지 끝이 나게된다면 내 포트폴리오와 이력서도 공개하면서 피드백을 받아보고 싶다.
피드백에서 신랄하게 비판하거나 지적할 부분이 많을 것 같아 조금 두렵긴 하다.
학생 신분을 가졌을 때 너무 느긋하게 살지 않았나 싶기도 하다...
물론 학생때에 공부와 알바를 병행하느라 내 나름대로는 바쁘게 살긴 했다만 사실 알바보다는 공부에 더 비중을 두는게 맞지 않았나 싶기도 하다.
그러나 다시 그때로 돌아간다고 해서 내가 알바보다 공부를 더 중하게 생각하진 않았을 것 같다. 
결국 그때의 난 자취를 하기 위해서 목표를 잡았고 그 목표를 향해서는 달려가고 있었기 때문이다. 그리고 백앤드 개발자라는 직업에 진정으로 관심을 가지기까지는 꽤나 오랜 시간이 걸렸기 때문이다. 
그래서 그때의 선택을 엄청나게 후회하진 않는다. 그저 아쉬움이 조금 남았을 뿐이지... ㅠ
오늘은 여기까지 하고 앞으로는 리팩토링과 관련된 내용도 간략하게 올려보겠다.
시간이 날 때 올릴 것 같은데. 자주 쓴다고 장담하진 못할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[API명세서 작성 방법]]></title>
            <link>https://velog.io/@venyclxx__d/API%EB%AA%85%EC%84%B8%EC%84%9C-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@venyclxx__d/API%EB%AA%85%EC%84%B8%EC%84%9C-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 16 May 2026 02:51:25 GMT</pubDate>
            <description><![CDATA[<p>오늘은 기능 요구사항과 예외 사항 정책서, ERD를 기반으로 API 명세서를 작성하는 방법에 대해 설명해보겠다.
(오늘 내용은 개인적인 견해와 방식이다.)</p>
<p>컨트롤러를 끊는 방식은 크게 4가지로 나뉜다.</p>
<ol>
<li>자원 중심(URL의 명사)</li>
<li>행위 중심(사용자의 행위)</li>
<li>화면 중심(프론트 페이지)</li>
<li>CRUD 통합(없음)</li>
</ol>
<h3 id="자원-중심">자원 중심</h3>
<pre><code>/workspaces        → WorkspacesController
/workspaces/members → WorkspaceMembersController
/tasks             → TasksController</code></pre><p>URL의 명사를 기준으로 자른다.
Rest원칙이 가장 가까우면서, API의 태그 분류가 명확해진다. 도메인이 많을 때 적합하다.
그러나 컨트롤러의 수가 많아진다.</p>
<h3 id="행위-중심">행위 중심</h3>
<pre><code>LoginController    → 로그인, 로그아웃, 토큰 갱신
InviteController   → 멤버 초대, 수락, 취소
AssignController   → 이슈 담당자 지정, 변경</code></pre><p>사용자의 행동을 기준으로 자른다.
요구사항 문서와 1:1 대응에 용이하다. 이는 기획자와의 소통이 쉽다는 장점을 가질 수 있겠다.
그러나 자원이 여러 컨트롤러에 분산되어 유지보수가 어렵고, URL 설계가 Rest답지 않을 수 있다.</p>
<h3 id="화면-중심">화면 중심</h3>
<pre><code>DashboardController   → 대시보드 화면에 필요한 모든 데이터
ProjectDetailController → 프로젝트 상세 화면용 API 묶음</code></pre><p>FE를 위한 BE방식이라고 보면 된다. 페이지 단위를 기준으로 자른다.
FE 개발자가 한 컨트롤러만 보면 되어서 협업이 쉽다.
그러나 화면이 변경되면 BE도 변경될 수 있고, 로직의 중복이 생긴다.</p>
<h3 id="crud-통합-중심">CRUD 통합 중심</h3>
<pre><code>AuthController → login, logout, signup, withdraw, oauth, refresh 전부</code></pre><p>작은 프로젝트나 초기 프르토 타입에서 용이하다.
그러나 파일이 커지면서 수정할 때 어디를 건드려야할지 파악이 어려워지고 Guard 선언이 메서드마다 달라진다.</p>
<ul>
<li>Guard: NestJS에서 요청 통과를 결정하는 관문이다. </li>
</ul>
<h3 id="실제-작업-순서">실제 작업 순서</h3>
<pre><code>① ERD 보고 테이블군 파악
        ↓
② FK 방향 + 라이프사이클로 모듈 결정
        ↓
③ 자원/Guard/변경이유 기준으로 컨트롤러 분리
        ↓
④ 컨트롤러에 엔드포인트 배치
        ↓
⑤ 각 엔드포인트에 API 명세 작성</code></pre><p>필자는 위와 같은 작업 순서로 먼저 큰 모듈을 정리하고 컨트롤러에 엔드포인트를 배치하는 형식을 사용했다.</p>
<p>쉽게 이야기하면 기능요구사항을 참고하여 각 기능과 사용 자원에 따라 모듈을 정리하고 해당 모듈에 컨트롤러들을 배치하는 형식이다.</p>
<p>이러한 방식은 한 번에 큰 단위의 초기작업을 진행하다보니 초기 작업 속도가 느려진다. 
하지만 큰 틀이 잡혀 후속 작업이 금방금방 진행될 수 있다. </p>
<p>일반적으로 필자는 위와같이 큰 틀을 잡아놓고 후속 작업을 진행하는 탑바텀 방식을 선호한다. 큰 그림을 먼저 그리고 세부적인 디테일을 잡아가는게 필자의 스타일이기 때문이다. 
그러나 카카오톡과 같은 서비스를 제공한다고 하면 너무너무 큰 대용량 작업이기 때문에 큰 틀을 잡는 것 자체가 너무 비효율적이어진다.
(카카오톡은 단순 메신저라고 생각할 수도 있지만 실제로 우리가 사용하는 카카오톡의 기능은 너무나도 많다. 예를들면 최근 화제가 되었던 인스타와 같은 피드 기능, 숏츠 기능, 선물 기능 등의 부가 기능이 정말 많다.)</p>
<p>그러한 경우에는 먼저 핵심적인 흐름을 잡아내어 작업을 하는 것이 편할 것 같다.</p>
<h3 id="마무리">마무리</h3>
<p>이상으로 필자가 사용하는 방식의 API 명세서 작성 방법에 대해 알아보았다.
항상 느끼는 바이지만 이 세상에는 완벽한 방법, 완벽한 무언가라는건 존재하지 않는 것 같다. 그래서 언제나 체크하고 의심하며 살아가는게 참 중요한 것 같다. 
지금 내가 사용하는 방식이 과연 지금 상황에 맞는 방식인지. 이 방식이 최선인지를 생각하는게 완벽에 가장 가까워질 수 있는 방법인 것 같다.</p>
<p>오늘은 여기까지.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 진행 사항]]></title>
            <link>https://velog.io/@venyclxx__d/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A7%84%ED%96%89-%EC%82%AC%ED%95%AD</link>
            <guid>https://velog.io/@venyclxx__d/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A7%84%ED%96%89-%EC%82%AC%ED%95%AD</guid>
            <pubDate>Wed, 13 May 2026 04:28:11 GMT</pubDate>
            <description><![CDATA[<h3 id="개요">개요</h3>
<p>이번에 진행하는 프로젝트는 NestJS와 Nuxt를 이용한 프로젝트이다. TypsScript 기반 프로젝트라고 이해하면 편하겠다.</p>
<p>프로젝트 명은 Cosider로 프로젝트 가이드 방식의 협업툴이다. 현재 내가 활동중인 Croffledev팀에서 진행중이다. 
서비스 자체가 비즈니스로 전환될 가능성이 높다고 생각하여 Private으로 설정해놓고 프로젝트를 진행중이다.</p>
<p>프로젝트를 Private으로 진행하는 만큼 따로 기록을 남겨놓는게 더욱 중요하다고 생각하여 앞으로 프로젝트에 대한 글을 쓸 예정이다.</p>
<p>앞으로 글의 개요는 <code>프로젝트의 전반적인 진행 상황</code>, <code>프로젝트에서 내가 한 것</code>, <code>비고</code>의 형식으로 이루어질 것이다.</p>
<p>추가로 Croffledev에서는 매년마다 팀원 각자 아이디어를 구상하여 발표를 하고 회의를 통해 각 아이디어를 구현하고 있다고 한다. 난 올해들어 처음 들어왔고 들어온지 이제 3~4개월정도 밖에 되지 않았다. </p>
<h3 id="현황">현황</h3>
<p>아이디어 발표 이후 2개월 정도가 지났는데, 그동안은 아이디어에 대한 구현 우선순위를 정하고 올해 첫 프로젝트에 대한 기획과 설계를 진행했다.</p>
<p>진행이 늦어진 것은 아이디어를 구상한 팀장의 개인적인 이슈로 한 달간 탈주하다시피 했기 때문에 어쩔 수 없이 늦어진 감이 없다고 생각한다.</p>
<p>이번 프로젝트는 사용자 요구사항 정의부터 시작되었다.
사용자 요구사항 정의란 이 프로젝트가 완성되었을 때 사용자가 무엇을 요구하는지에 대해 간략하게 정리해보는 것이다.</p>
<pre><code>사용자 A: 30세, 비개발자, 개발에 대한 관심을 가지고 있으나 개발적 지식이 거의 없어 제품 개발(프로젝트 진행)에 어려움을 겪음.
- 개발 가이드 제시</code></pre><p>위와 같은 요구사항 정의를 통해 MVP에 대한 개요를 짰다.</p>
<ul>
<li>MVP(Minimum Viable Product)란 최소한의 기능을 가진 제품이라는 뜻이다.</li>
</ul>
<p><code>사용자가 ~~하기위해, ~~를 도입 / 구현</code>
요구사항 정의 이후에는 요구분석이라는 틀을 통해 위와 같이 한 번 더 정제해주었다.
그리고 요구분석을 하며 어떤 식으로 구현할 것인가에 대해 정리해보는 절차를 가졌다.</p>
<p>이후 기술 스택을 정하고 기능 요구사항 및 예외 정책서를 작성하였다.
각 기능을 기준으로 요구사항들을 정리하고 요구사항이나 기능에 대한 예외를 정리하는 절차이다. </p>
<ul>
<li>일반적으로 기능 요구사항을 먼저 정리하고 예외 정책의 경우 API 명세서와 함께 작성하는 것으로 알고 있다.</li>
</ul>
<p>기능 요규사항과 예외 정책서를 바탕으로 페이지 구성리스트와 ERD를 먼저 작성하게 되었다.</p>
<ul>
<li>&#39;API 명세서는 미리 API Endpoint를 파악하고 Convention(경로 형태)를 일관성 있게 해야할 것 같다.&#39;라는 팀장의 말로 API명세서의 우선순위가 변경.</li>
</ul>
<p>이후 페이지 구성리스트 작성과 함께 ERD 작성을 하고
현재는 API명세서 작성을 진행중이다.</p>
<p>아마 금주나 차주 내에 API 명세서와 DataFlow 및 Sequence설계, UI 디자인등이 완료될 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU Scheduling 그리고 동기와 블로킹]]></title>
            <link>https://velog.io/@venyclxx__d/CPU-Scheduling-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B8%94%EB%A1%9C%ED%82%B9</link>
            <guid>https://velog.io/@venyclxx__d/CPU-Scheduling-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B8%94%EB%A1%9C%ED%82%B9</guid>
            <pubDate>Mon, 11 May 2026 10:26:52 GMT</pubDate>
            <description><![CDATA[<p>오늘은 어제 말했던 대로 CPU Scheduling, 그리고 그와 연결되는 동기와 블로킹에 대해 이야기해보겠다.</p>
<h2 id="목차">목차</h2>
<ul>
<li><a href="#Summary">Summary</a></li>
<li><a href="#CPU-Scheduling">CPU Scheduling</a></li>
<li><a href="#Scheduling-%EB%91%90%EA%B0%80%EC%A7%80-%EB%B2%94%EC%9C%84">Scheduling 두가지 범위</a></li>
<li><a href="#%EB%8F%99%EA%B8%B0/%EB%B9%84%EB%8F%99%EA%B8%B0(Synchronous/Asynchronous-Sync/Async)">동기/비동기(Synchronous/Asynchronous - Sync/Async)</a></li>
<li><a href="#%EB%B8%94%EB%A1%9C%ED%82%B9/%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9(Blocking/non-Blocking)">블로킹/논블로킹(Blocking/non-Blocking)</a></li>
<li><a href="#%EB%8F%99%EA%B8%B0/%EB%B8%94%EB%A1%9C%ED%82%B9&amp;%EB%B9%84%EB%8F%99%EA%B8%B0/%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9">동기/블로킹&amp;비동기/논블로킹</a></li>
<li><a href="#%EB%A7%88%EB%AC%B4%EB%A6%AC">마무리</a></li>
</ul>
<hr>
<p>그 전에 저번 시간에 이야기했던 CPU에서 Thread까지의 내용을 되짚어보자</p>
<h3 id="summary">Summary</h3>
<ol>
<li>CPU는 기계어의 명령어를 실행하는 컴퓨터의 연산장치이다.</li>
<li>프로그램은 기계어의 명령어와 그 외의 것들로 구성된다.</li>
<li>프로세스는 Code, Data, Heap, Stack으로 이루어져있으며 메모리에서 실행되는 프로그램의 독립적인 실행 단위이다.</li>
<li>스레드는 프로세스의 구성에서 Stack을 제외한 나머지 자원을 공유하는 프로그램의 최소 실행 단위이다.</li>
<li>CPU는 프로세스 단위로 프로그램을 메모리에 올려놓고 실행하는데 기존 작업이 끝났을 때 PCB를 확인하여 문맥교환을 한다.</li>
</ol>
<p>저번 시간에 이야기했던 내용을 간략하게 줄이면 이정도가 되겠다.
그럼 CPU는 어떤 기준으로 프로세스의 스케쥴을 짤까?</p>
<h3 id="cpu-scheduling">CPU Scheduling</h3>
<p>여기서 중요한건 CPU는 직접 프로세스의 스케쥴을 짜지 않는다.
CPU는 단순히 작업 공간이라고 이해하면 된다. 우리가 일터에 갔을 때 일터 자체가 스케쥴을 짜진 않지 않는가? 이와 같이 CPU는 &#39;작업 공간&#39; 그 자체이다.</p>
<p>그렇다면 누가 프로세스의 스케쥴을 짤까?</p>
<p>그건 바로 운영체제라고 부르는 Operating System(OS)이다. </p>
<p>어제도 얼굴을 비추었던 OS는 여러가지 일을 하는데 그 중 하나가 바로 CPU Scheduling이다. </p>
<p>왜 OS는 프로세스의 스케쥴을 짤까?</p>
<p>이유는 아래와 같이 여러가지로 구성된다.</p>
<p><code>CPU를 가만히 있도록 내비두기 싫어서.</code>
<code>CPU의 능률을 올려주기 위해서.</code>
<code>작업의 대기 시간을 줄이기 위해서.</code>
<code>특정 작업만 돌아가게 하지 않기 위해서.</code></p>
<p>위와 같은 이유들은 우리가 사장님이라고 생각해보면 바로 느낄 수 있다.
만약 내가 돈을 주고 고용한 직원이 오늘 해야할 일을 모른 채로 가만히 있는다면 어떻겠는가? 또 직원이 잘 안되는 일만 막 붙잡고 계속 가만히 있으면? 또는 컴퓨터로 5분걸리는 작업량을 가진 직원과 3시간걸리는 작업량을 가진 직원중 3시간 걸리는 직원이 사내에 한 대 있는 컴퓨터를 쓰고있는다고 한다면? </p>
<p>생각만해도 비효율적이고, 화가 난다.</p>
<p>이처럼 OS는 효율을 위해서 CPU의 스케쥴을 짠다.</p>
<h3 id="scheduling-두가지-범위">Scheduling 두가지 범위</h3>
<p>Scheduling은 크게 선점과 비선점 두가지의 범위를 가진다.
이름에서 알 수 있듯 
<strong><em>비선점 스케쥴링(non-preemptive scheduling)</em></strong>은 프로세스가 종료되거나 스스로 자리를 양보하기 전에는 다른 프로세스가 그 자리를 뺏았지 못한다.
<strong><em>선점 스케쥴링(Preemptive scheduling)</em></strong>은 비선점과 반대로 OS가 강제로 CPU를 강탈한다.</p>
<p>그로 인해 구현이나 문맥교환에 대한 비용이 낮아진다거나 CPU의 응답률이 올라간다거나 하는 각각의 특징들을 갖는다.</p>
<p>스케쥴링의 종류는 여러가지가 있다.
그중에 우리는 대표적인 5가지에 대해 알아보고자 한다.</p>
<p><strong><em>FCFS</em></strong>
&#39;First Come First Served&#39;라고도 불리는 FCFS는 들어온 순서대로 먼저 처리하는 순차적인 실행 상태를 가진다. 가장 단순하며, 긴 작업이 발생할 때에는 다른 일이 모두 지연되는 호위효과(Convoy Effect)가 발생할 수 있다.</p>
<p><strong><em>SJF</em></strong>
&#39;Shortest Job First&#39;라고 불리는 SJF는 이름에서 알 수 있듯 실행시간이 짧은 것부터 먼저 실행한다. 그 대신 실행시간을 매번 파악해야하고, 긴 작업이 계속 밀려나는 기아상태(Starvation)이 발생할 수 있다.</p>
<p><strong><em>Round Robin</em></strong>
&#39;RR&#39;이라고도 불리는 Round Robin은 프로세스가 일정 시간(Time Quantum)만큼 CPU를 사용할 수 있게 한다. 그로 인해 보편적으로 응답성이 향상된다. 그러나 문맥교환이 잦아지고 FCFS와 비슷하게 동작할 수도 있다.</p>
<p><strong><em>Priority Schduling</em></strong>
우선순위 스케쥴링은 우선순위가 높은 것부터 실행하는 방식이다. SJF와 동일하게 Starvation이 일어날 수 있다. 그러나 프로세스의 기다림에 따라 우선순위가 상승하는 Aging이라는 절차를 통해 이를 어느정도 해소시키기도 한다.</p>
<p><strong><em>SRTF</em></strong>
Shortest Remaing Time First라고 불리는 SRTF는 SJF의 선점 버전이라고 봐도 무방하다. 남은 실행 시간이 적은 프로세스를 먼저 실행시키며 더 짧은 프로세스가 오면 CPU를 강탈당한다.</p>
<p>위와 같은 스케쥴링을 통해 한 번에 하나만 실행하는 CPU는 대기 작업을 다시 실행 가능한 상태로 바꿔가며 처리한다. 이때 블로킹/논블로킹, 동기/비동기에 따라 기다림과 실행 방식, 그리고 스케줄링과 CPU 활용이 달라진다.</p>
<h3 id="동기비동기synchronousasynchronous---syncasync">동기/비동기(Synchronous/Asynchronous - Sync/Async)</h3>
<ul>
<li>tmi 여기서 말하는 동기와 &#39;동기화를 한다고 할 때&#39;의 동기화는 데이터적 관점에서의 개념이고 &#39;동기/비동기&#39;의 동기는 제어 흐름 관점에서의 개념으로 이해하는 게 좋다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/venyclxx__d/post/b5085058-a68c-44c8-92e0-5d36c803e26a/image.png" alt=""></p>
<p>동기는 작업완료 전까지 대기를 했다가 순차적으로 실행해 나가는 것을 이야기한다.
비동기는 작업 완료를 기다리지 않고 다른 작업을 이어가며, 완료되면 결과를 처리하는 방식이다</p>
<p>우리가 라면을 할 때를 생각해보자.</p>
<ol>
<li>물을 끓인다.</li>
<li>면과 스프를 넣는다. </li>
<li>라면을 먹는다.
이런 세가지 절차를 가만히 서서 기다리며 한다면 우리는 동기라고 이야기한다.</li>
</ol>
<p>그러나
우리는 라면을 끓일 때 보통 가만히 있지 않는다. 최소한 나는 그렇다.</p>
<ol>
<li>물을 끓인다. - &#39;물이 끓는 동안 대파를 썰고 김치를 꺼내온다.&#39;</li>
<li>면과 스프를 넣는다. - &#39;면이 익는 동안 계란을 풀어서 준비해놓고 테이블을 닦는다.&#39;</li>
<li>라면을 먹는다. - &#39;영화를 본다&#39;</li>
</ol>
<p>이와 같이 무언가 하나의 일만 하지 않고 계속해서 다른 일을 병행하고 있다고 보면 된다. 이것을 우리는 비동기라고 이야기하는 것이다.</p>
<h3 id="블로킹논블로킹blockingnon-blocking">블로킹/논블로킹(Blocking/non-Blocking)</h3>
<p>동기와 비동기가 결과를 어떻게 처리할 것인지에 대한 내용이라면, 
블로킹과 논블로킹은 실행 흐름에 대한 내용이다.</p>
<p><img src="https://velog.velcdn.com/images/venyclxx__d/post/68f9afe8-4779-478c-af18-22e36f453aed/image.png" alt=""></p>
<p>블로킹은 실행 흐름을 끊고 기다리는 것이고,
논블로킹은 기다리는 것 자체를 하지 않고 실행 흐름을 지속하는 것이다.</p>
<h3 id="동기블로킹비동기논블로킹">동기/블로킹&amp;비동기/논블로킹</h3>
<p>앞에서 간단하게 동기와 비동기, 블로킹과 논블로킹에 대해 알아보았다.</p>
<p>여기서 필자는 <strong>*&quot;동기와 블로킹은 같고 비동기와 논블로킹은 같은게 아닌가?
왜 이걸 굳이 둘로 나눈거지?&quot;*</strong>라는 개인적인 의문이 들었다.</p>
<p>그 이유는 “기다림” 개념에는 실행 흐름 문제와 결과 처리 구조 문제가 섞여 있어서, 이를 분리해야 시스템을 정확하게 설계하고 최적화할 수 있었기 때문이다.</p>
<p>그래서 동기와 비동기는 결과 처리 구조를, 블로킹과 논블로킹은 실행 흐름을 다루는 개념이라고 앞서 설명한 것이다.</p>
<p>그래서 블로킹/논블로킹은 현재 실행 흐름이 멈추는지 여부를 기준으로 하고, 동기/비동기는 결과를 현재 제어 흐름에서 기다려 처리할지 또는 분리된 방식으로 처리할지를 기준으로 한다.</p>
<p>그래서 이러한 동기와 블로킹, 비동기와 논블로킹으로 아래와 같은 조합을 만들어낼 수 있다.
<img src="https://velog.velcdn.com/images/venyclxx__d/post/a387b1f6-d378-4f9a-9d7e-63ac50c2d591/image.png" alt=""></p>
<h3 id="마무리">마무리</h3>
<p>오늘은 CPU 스케줄링부터 시작해서 동기/비동기, 블로킹/논블로킹까지 꽤 긴 여정을 달려왔다.
사실 처음에는 &quot;그냥 기다리면 동기고 안 기다리면 비동기 아니야?&quot;라고 생각했는데, 파고들수록 실행 흐름이냐 결과 처리 구조냐로 개념이 갈린다는 게 꽤 흥미롭지 않았는가?
그렇다면 여기서 한 가지 질문을 던져보겠다.</p>
<p>**&quot;여러 스레드가 같은 자원에 동시에 접근하면 어떤 일이 벌어질까?&quot;
**
다음 시간에는 바로 이 지점에서 시작한다. 동시성 문제가 왜 발생하는지, 그리고 이를 해결하기 위한 동기화 기법에는 어떤 것들이 있는지 알아볼 예정이다. 스포일러를 조금 하자면, 우리가 오늘 배운 블로킹 개념이 거기서도 아주 중요하게 등장한다.
댓글로 위 질문에 대한 생각을 남겨줘도 좋다. 틀려도 괜찮으니 한번 생각해보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU부터 Thread까지: 운영체제가 프로그램을 실행하는 방식]]></title>
            <link>https://velog.io/@venyclxx__d/CPU%EB%B6%80%ED%84%B0-Thread%EA%B9%8C%EC%A7%80-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@venyclxx__d/CPU%EB%B6%80%ED%84%B0-Thread%EA%B9%8C%EC%A7%80-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Sun, 10 May 2026 14:44:29 GMT</pubDate>
            <description><![CDATA[<p>당신은 컴퓨터에서 사용하는 CPU에 대해 알고있는가?</p>
<p>오늘은 CPU를 중심으로, 실제 운영체제 안에서 어떤 일이 벌어지는지를 이야기해보겠다.</p>
<h2 id="목차">목차</h2>
<ul>
<li><a href="#cpu%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%84-%ED%95%98%EB%8A%94%EA%B0%80">CPU는 무엇을 하는가</a></li>
<li><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EB%93%B1%EC%9E%A5">프로세스의 등장</a></li>
<li><a href="#os%EA%B0%80-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%A5%BC-%EA%B8%B0%EC%96%B5%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95">OS가 프로세스를 기억하는 방법</a></li>
<li><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EB%93%B1%EC%9E%A5">스레드의 등장</a></li>
<li><a href="#%EB%A7%88%EB%AC%B4%EB%A6%AC">마무리</a></li>
</ul>
<hr>
<h3 id="cpu는-무엇을-하는가">CPU는 무엇을 하는가</h3>
<p>CPU는 &#39;기계어의 명령어를 하나씩 순서대로 처리하는 연산 장치&#39;이다.
 우리가 계산기에서 <code>1+1</code>을 입력하고 실행하면 2라는 결과가 나오는 것처럼 프로그램을 실행하게 한다.</p>
<p> 위 문장을 통해서 우리는 프로그램이란 <strong>*&quot;기계어의 명령어로 이루어져있거나 기계어의 명령어 그 자체이겠구나&quot;*</strong> 라는 사실을 유추할 수 있다.</p>
<p> 여기서 우리는 궁금증이 들 수 있다.
 계산기는 <code>1+1</code> 또는 <code>2x2+3</code> 정도로 한 번에 하나의 실행을 가진다. 그러나 컴퓨터는 동시에 여러 개의 프로그램을 돌려도 사용이 가능한 것처럼 보인다.</p>
<p> <img src="https://velog.velcdn.com/images/venyclxx__d/post/522dfa74-7721-433b-820e-0c76a9eb3c06/image.png" alt=""> 
 사실 컴퓨터에 있는 CPU는 하나의 작업만 처리할 수 있다. 그러나 운영체제는 CPU를 &quot;너 잠깐 썼다가 쟤 줘.&quot;라고 하며 아주 빠르게 여러 프로그램에게 번갈아가면서 나눠준다. </p>
<p>그래서 우리는 마치 여러 프로그램이 동시에 실행되는 것처럼 느낄 수 있는 것이다.</p>
<p>그렇다면 운영체제. 즉, OS는 &quot;어떻게 CPU에게 프로그램을 나눠줄까?&quot;</p>
<hr>
<h3 id="프로세스의-등장">프로세스의 등장</h3>
<p> OS는 실행 중인 프로그램 하나하나를 <strong><em>프로세스(Process)</em></strong>라는 단위로 관리한다.</p>
<p> 프로세스는 단순히 하나의 프로그램이 아니라, 실행을 위해 운영체제가 할당한 자원을 포함한 각각 독립된 실행 환경이다.
 예를 들자면, 프로그램은 요리책. 프로세스는 재료 손질, 재료 볶기 등의 요리책을 보고 실행하는 것이라고 보면 된다.</p>
<p><img src="https://velog.velcdn.com/images/venyclxx__d/post/9bc14ed8-e326-4c10-9866-ee44e98615ce/image.png" alt=""></p>
<p> 가상 메모리 관점에서의 프로세스는 위와 같이 코드 / 데이터 / 힙 / 스택으로 나뉜다.
 코드: 프로그램의 명령어
 데이터: 정적 변수
 힙: 동적 변수
 스택: 함수 호출 스택</p>
<ul>
<li>tmi. 왜 하필 스택일까? 함수의 동작을 생각해보면 답이 나온다. <pre><code class="language-우리는">만약 바깥에 있는 함수의 답을 내려고 하는데 안에 있는 함수가 답이 안나와있으면 어떻게할까?
바깥에 있는 함수도 답이 당연히 나오지 않을 것이다.
그래서 나중에 들어간 게 먼저 끝나는 LIFO(Last In First Out)구조를 가진 스택을 사용하게 된다.
스택에 대해선 추후 알고리즘 시간에 자세히 다뤄보도록 하겠다.</code></pre>
</li>
</ul>
<hr>
<h3 id="os가-프로세스를-기억하는-방법">OS가 프로세스를 기억하는 방법</h3>
<p> 하지만 CPU는 계속 다른 프로세스를 ADHD마냥 왔다갔다 거리기 때문에, &quot;내가 아까 어디까지 했더라...?&quot;를 기억하고 있어야한다.</p>
<p> 그래서 OS는 각 프로세스마다 하나의 메모장을 만들어둔다.
우리는 그걸 <strong><em>PCB(Process Control Block)</em></strong>이라고 부른다.</p>
<p><img src="https://velog.velcdn.com/images/venyclxx__d/post/af1f27c8-3253-4893-b895-51841459d1f1/image.png" alt="">
 PCB에는 CPU의 레지스터 상태, 프로세스 상태, 메모리 정보, 파일이나 입출력 정보, 현재 실행 위치같이 <strong><em>&#39;내가 어디서 무슨 일을 어떻게 이어나가야하는지&#39;</em></strong> 에 대한 정보가 정리되어있다.</p>
<p>그덕분에 프로세스를 기억하고 CPU는 왔다갔다 거리면서 멀티태스킹을 조질 수 있는거다.</p>
<p>CPU가 프로세스 A을 실행하다가 B로 넘어가는 순간에 OS는 
<img src="https://velog.velcdn.com/images/venyclxx__d/post/1e8d9a56-b3f1-4596-bae2-ad625e343a8c/image.png" alt=""></p>
<pre><code>1. A의 현재 상태를 PCB에 저장하고
2. B의 PCB를 꺼내서 확인하고
3. B의 상태를 CPU에 복원하고
4. B를 실행한다.</code></pre><p>우리는 이 과정을 <strong><em>Context Switching(문맥교환)</em></strong> 이라고 한다.</p>
<p>여기서 문제가 생긴다.</p>
<p> 운영체제에 있는 프로세스는 하나만 존재하지 않고 동시에 여러 개로 존재한다. 이를 <strong><em>멀티 프로세스</em></strong>라고 이야기한다. 
 이러한 멀티 프로세스 구조는 마치 각자 독립된 방을 쓰는 것과 같아서, 방 자체가 많아질수록 공간을 많이 차지하고, 방을 옮길 때마다 짐을 싸고 새 방으로 이동하는 시간이 필요하다는 단점을 가진다.</p>
<p>그래서 사람들은 <strong><em>스레드</em></strong>라는 개념을 창안해냈다.</p>
<hr>
<h3 id="스레드의-등장">스레드의 등장</h3>
<p>스레드는 &#39;CPU가 실제로 실행하는 최소 단위&#39;이다.</p>
<p><img src="https://velog.velcdn.com/images/venyclxx__d/post/6c06c3b8-86ed-40fe-9c5a-4ddb536d1e60/image.png" alt="">
 스레드는 프로세스 내부에서 힙과 코드, 데이터를 공유하며 각자의 스택을 가진다. 즉 각자 어디서 일하고 있었는지를 나눠 가진다는 것이다.</p>
<p> <img src="https://velog.velcdn.com/images/venyclxx__d/post/82921f1d-385d-469f-a720-1c669a0466c8/image.png" alt=""></p>
<p> 이를 통해 힙과 코드를 공유하는 스레드는 바로바로 필요한 자원에 접근이 가능해졌고, 공간을 변경할 필요 없이 스택만 변경하면 되게 되었다. 또한 다른 스레드에서 새로운 힙, 코드, 데이터를 생성하지 않아도 되기에 저장 공간역시 확보가 되었다.</p>
<p> 앞서 언급되었던 멀티 프로세스와 동일하게 <strong><em>멀티스레드</em></strong>라는 개념이 확립이 되었따.</p>
<hr>
<h3 id="마무리">마무리</h3>
<p> 오늘은 이렇게 CPU부터 스레드까지에 대한 개념을 가볍게 알아보았다. 다음에는 여러 프로세스와 스레드가 CPU에게 어떻게 선택되는지에 대해 알아보는 시간을 가질 것이다.</p>
<p> 가기 전에 개인적으로 생각해보면 좋을 간단한 질문을 던져보겠다.</p>
<ol>
<li>멀티 프로세스와 멀티 스레드의 장단점은 무엇일까?</li>
<li>멀티 프로세스와 멀티스레드 두 개념은 언제 사용하는게 좋을까? </li>
<li>스레드가 많아질 때 오히려 느려지는 경우가 생기는데 이러한 경우는 왜 생기는걸까?</li>
</ol>
<p>그럼 오늘은 여기까지.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[첫 시작]]></title>
            <link>https://velog.io/@venyclxx__d/FirstWriting</link>
            <guid>https://velog.io/@venyclxx__d/FirstWriting</guid>
            <pubDate>Sat, 09 May 2026 15:10:28 GMT</pubDate>
            <description><![CDATA[<p>안녕하신가들?</p>
<p>기존에 네이버 블로그를 사용했었는데
이번에 어찌저찌 기회가 되어서 이리로 넘어오게 되었다.</p>
<p>아마 나 혼자 보는 블로그가 될 것 같다.</p>
<p>흠 뭐부터 이야기하는게 좋을까?</p>
<p>일단 간단한 내 소개부터 하자면,
26세 백앤드 개발자를 지향하고 있는 쉬었음 청년이다.
졸업한지는 대략 3개월차가 되고 있다. </p>
<p> 아직 쉬었음 청년이라고 하기엔 애매한가 싶긴 한데 부모님은 나에게 숨고르기 청년이라는 별명을 벌써 붙여주셨기 때문에 당당하게 쉬었음 청년이라고 이야기하겠다.</p>
<p> 요즘은 기존에 했던 프로젝트 리팩토링을 진행중이다.
기존에 했던 프로젝트가 마음에 들지 않는 부분이 상당히 많이 있고, 
시간적으로 압박을 좀 많이 받았던 프로젝트라 여차저차 수정을 좀 해 나아가고 있다.</p>
<p> 리팩토링 진행사항을 앞으로 이 곳에 쓰면서 다시 한 번 복습할 CS도 이 곳에 정리하고자 한다. </p>
<p>원래는 글 쓸 때 이렇게 짜임새 없이 무지성을 쓰진 않는데 첫 글이고 좀 자유롭게 쓸 글이다보니 이래저래 되어버린 느낌이다.</p>
<p>일단 이번 글은 여기서 마치겠다.</p>
]]></description>
        </item>
    </channel>
</rss>