<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>invisible_thorn</title>
        <link>https://velog.io/</link>
        <description>해위</description>
        <lastBuildDate>Wed, 13 May 2026 08:04:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>invisible_thorn</title>
            <url>https://velog.velcdn.com/images/invisible_thorn/profile/e1f3663a-5412-475d-abf0-483232b82105/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. invisible_thorn. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/invisible_thorn" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[소켓 프로젝트 준비하기(1)]]></title>
            <link>https://velog.io/@invisible_thorn/%EC%86%8C%EC%BC%93-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B01</link>
            <guid>https://velog.io/@invisible_thorn/%EC%86%8C%EC%BC%93-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B01</guid>
            <pubDate>Wed, 13 May 2026 08:04:34 GMT</pubDate>
            <description><![CDATA[<p>서버를 만들기 전에...
기본적인 클라이언트를 구성하고 그 위에 얹어보려고 한다
이미 플레이어가 움직이고 인벤토리가 추가되게 하는 로직을 imgui로 띄우는 것까지 해두었는데, 정리가 필요해서 코드 짠 것도 수정하고 끄적여 보는 시간을 가져야 겠다</p>
<pre><code class="language-cpp">#include &lt;vector&gt;

class Inventory
{
public:
    Inventory(int cap = 10) :capacity(cap) {}
    //~Inventory()
    //{
    //    for (Item* item : items)
    //    {
    //        delete item;
    //    }
    //}

    // bool addItem(Item* newItem);
    bool addItem(std::unique_ptr&lt;Item&gt; newItem);
    void showList();
    void useItem();

    int getSize() const { return items.size(); } // 현재 들어있는 아이템 개수
    int getCapacity() const { return capacity; } // 최대 칸 수 (10)

private:
    //std::vector&lt;Item*&gt; items;
    std::vector&lt;std::unique_ptr&lt;Item&gt;&gt; items;
    int capacity;
};</code></pre>
<p>나는 스마트 포인터의 장점과 사용법을 몰랐기 때문에 그냥 아는 대로만 구현을 했었다
근데 관련해서 공부를 하다보니 스마트 포인터를 쓰면 그냥 포인터를 섰을 때 혹시 모를 메모리 누수를 방지할 수 있어 적극적으로 쓰는 것을 권장한다는 말을 듣고 코드를 수정하기로 했다.</p>
<p>우선</p>
<pre><code class="language-cpp">std::vector&lt;Item*&gt; items;</code></pre>
<p>로 추상 클래스(부모 클래스인) Item 벡터를 포인터로 담아 여러 가지 아이템(자식 클래스들)을 담게 하였다</p>
<p>그리고 main.cpp에서</p>
<pre><code class="language-cpp">if (ImGui::Button(&quot;장검 추가&quot;)) {
    //인자를 new Weapon(&quot;Sword&quot;,10)에서 수정
    if (myInven.addItem(std::make_unique&lt;Weapon&gt;(&quot;Sword&quot;, 10))) {
        std::cout &lt;&lt; &quot;장검을 가방에 넣었습니다.&quot; &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; &quot;가방이 가득 찼습니다!&quot; &lt;&lt; std::endl;
    }
}</code></pre>
<p>근데 여기서 왜 포인터로 담았냐하면
우선 Item은 추상 클래스이기 때문에 자식 클래스에서 구현을 해줘야만 해서</p>
<pre><code class="language-cpp">class Item
{
    std::string name;
}

class Weapon : public Item
{
    std::string name; // 부모(Item)에게 물려받음
    int damage;    // Weapon이 가진 고유 특성    
}</code></pre>
<p>요런 식으로 구현이 되는데</p>
<p>메모리를 박스로 표현하면:</p>
<pre><code>  Item 박스:
  ┌──────────┐
  │   name  │
  └──────────┘

  Weapon 박스:
  ┌──────────┬──────────┐
  │   name  │  damage │
  └──────────┴──────────┘</code></pre><p>따라서 vector<Item>으로 vector에 담게 되면 Item 타입만 담게 돼서 damage 정보는 버려지는 객체 슬라이싱 이슈가 발생하기 때문이다
근데 포인터를 넣게 되면 객체 원본이 아니라 주소값을 저장하니까 해당 타입이 갖고 있는 정보를 다 가져올 수 있게 된다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[언리얼 관찰일기(1)]]></title>
            <link>https://velog.io/@invisible_thorn/%EC%96%B8%EB%A6%AC%EC%96%BC-%EA%B4%80%EC%B0%B0%EC%9D%BC%EA%B8%B01</link>
            <guid>https://velog.io/@invisible_thorn/%EC%96%B8%EB%A6%AC%EC%96%BC-%EA%B4%80%EC%B0%B0%EC%9D%BC%EA%B8%B01</guid>
            <pubDate>Fri, 16 Jan 2026 06:37:24 GMT</pubDate>
            <description><![CDATA[<p>열심히 강의 듣는데 첫번째 챕터부터 막히는 부분이 있었다.</p>
<p>Actor를 하나 만들고 Material을 입히려는데 외않되?
<img src="https://velog.velcdn.com/images/invisible_thorn/post/cbfe488e-d74f-4c91-b739-0b8514d8df78/image.png" alt=""></p>
<pre><code class="language-cpp">
#include &quot;Item.h&quot;

AItem::AItem()
{
    SceneRoot = CreateDefaultSubobject&lt;USceneComponent&gt;(TEXT(&quot;SceneRoot&quot;));
    SetRootComponent(SceneRoot);

    StaticMeshComp = CreateDefaultSubobject&lt;UStaticMeshComponent&gt;(TEXT(&quot;StaticMeshComp&quot;));
    StaticMeshComp-&gt;SetupAttachment(SceneRoot);

    static ConstructorHelpers::FObjectFinder&lt;UStaticMesh&gt; MeshAsset(TEXT(&quot;/Game/Resources/Props/SM_Chair.SM_Chair&quot;));
    if (MeshAsset.Succeeded())
    {
        StaticMeshComp-&gt;SetStaticMesh(MeshAsset.Object);
    }

    ///Script/Engine.MaterialInstanceConstant&#39;/Game/Resources/Materials/M_Armor_B.M_Armor_B&#39;
    static ConstructorHelpers::FObjectFinder&lt;UMaterial&gt; MaterialAsset(TEXT(&quot;/Game/Resources/Materials/M_Armor_B.M_Armor_B&quot;));
    if (MaterialAsset.Succeeded())
    {
        StaticMeshComp-&gt;SetMaterial(0, MaterialAsset.Object);
    }
}</code></pre>
<p>이렇게 작성하고 보니까 암만봐도 틀린게 없어보인다... 멀까했음
나으 힘으로는 찾기 힘들 것 같아서 재미나이를 사용했더니</p>
<p>경로에</p>
<p>/Script/Engine.<strong>MaterialInstanceConstant</strong>&#39;/Game/Resources/Materials/M_Armor_B.M_Armor_B&#39;</p>
<p>이게 들어가면 템플릿을 &lt; UMaterialInterface &gt;로 변경해야 하나보더라
<img src="https://velog.velcdn.com/images/invisible_thorn/post/79a58304-a9b2-410c-a7d4-e0629e558702/image.png" alt="">
빛 때문에 잘 안보이지만 색이 바뀌었음 따단
아니면 아예 경로가 <strong>Engine.Material</strong>인 Material을 찾고 템플릿을 그대로 사용하는 방법도 있다</p>
<p>근데 보니까 템플릿이
&lt; UMaterial &gt;
&lt; UMaterialInstance &gt;
&lt; UMaterialInterface &gt;
이렇게 있는데 그러면 UMaterialInstance를 사용해도 되지 않을까? 했다
근데 왜 UMaterialInstance를 사용하지 않고 UMaterialInterface를 사용했는지를 찾아보아따
우선 UMaterialInterface는 UMaterialInstance와 UMaterial의 부모 클래스이다.
만약 에셋이 Instance가 아닌 일반 Material로 변경이 되면 유지보수 하는데 있어 상위 클래스가 유리하기 때문에 UMaterialInterface를 사용한다고 한다!
업캐스팅을 또 이렇게 사용하는구나 싶다.</p>
<p>언리얼 까다로웡</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C++로 언리얼과 환승연애하기]]></title>
            <link>https://velog.io/@invisible_thorn/C-%EB%A6%AC%EB%A7%88%EC%9D%B8%EB%93%9C1</link>
            <guid>https://velog.io/@invisible_thorn/C-%EB%A6%AC%EB%A7%88%EC%9D%B8%EB%93%9C1</guid>
            <pubDate>Wed, 10 Dec 2025 10:42:36 GMT</pubDate>
            <description><![CDATA[<p>초심자의 마음으로 C++ 씹어먹기를 리트라이 하겠습니다.
여러 강의와 레퍼런스를 들춰보고 있는데,
무슨 무슨 강의를 따라서 하루 들은 것들을 정리하는 시간을 가져볼 생각입니다.</p>
<hr>
<p>게임 개발을 할 때는 빠른 속도가 생명인데, 그렇기 때문에 C++을 선호합니다.
다른 언어랑 다르게 O.S에 직접적으로 연결하여 사용할 수 있기 때문인데요, 요즘 대두되는 JAVA와 C#과의 차이점이라고 볼 수 있습니다.
위 언어들은 대신 메모리를 관리해주는 중간관리자가 있는 반면, C++는 당연히 없습니다.(앞서 말했듯 O.S와 직접 연결되기 때문이죠.)
결론은 내가 관리를 해야하는 거죠.
굉장히 귀찮겠지만, 그 대신 내가 이 메모리를 직접 컨트롤 할 수 있다는 엄청난 장점도 있습니다.
양날의 검이라고 볼 수 있겠네요.
이 언어 굉장히 신경쓰이는 친구입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개노답 삼형제]]></title>
            <link>https://velog.io/@invisible_thorn/%EA%B0%9C%EB%85%B8%EB%8B%B5-%EC%82%BC%ED%98%95%EC%A0%9C-ngevnlc6</link>
            <guid>https://velog.io/@invisible_thorn/%EA%B0%9C%EB%85%B8%EB%8B%B5-%EC%82%BC%ED%98%95%EC%A0%9C-ngevnlc6</guid>
            <pubDate>Wed, 14 May 2025 09:32:31 GMT</pubDate>
            <description><![CDATA[<p>맨날 헷갈리는 개노답 삼형제 모셨습니다.
static, extern, const 차례로 박살 내보죠.
는 내가 부숴질 예정</p>
<p>static의 개념은 전역변수의 특징을 조금 가지고 있는데요,
전역변수의 특징에는 무엇이 있을까요?</p>
<p>*<em>1. data 영역에 적재된다. *</em>
*<em>2. 따라서 프로그램 시작 시 생성되고 종료 시 해제된다. *</em></p>
<p>정적변수 static도 data 영역을 사용합니다.
그런데 이 static의 위치에 따라 의미가 달라진답니다.</p>
<p>대표적으로 3가지 경우가 있는데,</p>
<ol>
<li>함수 내에 선언된 경우</li>
<li>전역변수로 선언된 경우(분할 구현 시 사용)</li>
<li>클래스 안에 선언된 경우(분할 구현 시 사용)</li>
</ol>
<p>... 하나씩 살펴보도록 하겠습니다.</p>
<h3 id="1-함수-내에-선언된-경우">1. 함수 내에 선언된 경우</h3>
<pre><code class="language-cpp">void A()
{
    static int a = 0;
    ++a;
}

int main()
{
    A();
}</code></pre>
<p>정적으로 선언된 변수는 data 영역에 적재되어 프로그램 종료 시까지 남아있습니다.
그렇다면 전역변수와의 차이는 무엇이냐,
변수가 선언된 함수에서만 접근 가능합니다.
main함수에서는 a라는 변수를 사용할 수 없다는 말입니다.
이렇게 되면 나중에 변수가 무방비하게 변경될 일이 없어지겠죠?
(아 물론 포인터로 주소를 가리키면 가능합니다.)</p>
<p>아, 참고로 여러 번 호출이 되도 static은 한 번만 초기화 됩니다.
따라서 0에서 1,2,3.. 호출되는 수만큼 증가합니다.</p>
<h3 id="2-전역변수로-선언된-경우">2. 전역변수로 선언된 경우</h3>
<pre><code class="language-cpp">test1.cpp

static int a = 0;

test2.cpp

static int a = 0;</code></pre>
<p>선언된 파일을 기준으로 int a = 0;을 사용할 수 있습니다.
두 파일에 static 없이 그냥 int a = 0; 을 사용하면 링크 과정에서 오류가 납니다.
(다른 cpp에 똑같은 이름의 전역변수가 있을 때 - 전역 변수는 이때 오류가 남)
각각 파일의 전역변수로 사용이 된다는 겁니다.</p>
<h3 id="3-클래스-내부에-선언된-경우">3. 클래스 내부에 선언된 경우</h3>
<p>클래스 멤버변수(함수) 앞에 static이 붙은 것을 말합니다.</p>
<pre><code class="language-cpp">class TestClass
{
private:
    static int m_StaticMember;
    int        m_Member;

public:
    TestClass()
        // : m_StaticMember(0) -&gt; 오류 발생함
        : m_Member(0)
    {}
   ~TestClass()
       {}
}</code></pre>
<p>정적멤버는 data 영역을 사용합니다.
그런데 객체를 생성할 때마다 계속 생성되는 걸까요?
아니요. data 영역에 한 개만 존재합니다.
객체가 만들어지기 전에 이미 존재하고 있습니다.
그럼 멤버에서 static을 사용하면 무슨 효과가 있느냐,
위 클래스에서만 사용할 수 있는 static 변수입니다.
보통 우리가 객체를 여러 개 만들면 그 지역변수와 값을 바꿔주게 되는데,
static은 그 클래스의 단 하나의 변수로서 사용이 됩니다.</p>
<p>보통 클래스는 헤더파일에 정의가 되는데,
그럴 때마다 static 변수가 좀 문제가 되지 않을까요?
extern과 같이 전방선언 개념입니다.
따라서 선언부가 어딘가 cpp에 존재해야합니다.</p>
<p>정적 멤버함수는 정적 멤버변수에 접근할 수 있음
으아아ㅏ아</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[걱정마세요]]></title>
            <link>https://velog.io/@invisible_thorn/%EA%B1%B1%EC%A0%95%EB%A7%88%EC%84%B8%EC%9A%94</link>
            <guid>https://velog.io/@invisible_thorn/%EA%B1%B1%EC%A0%95%EB%A7%88%EC%84%B8%EC%9A%94</guid>
            <pubDate>Mon, 28 Apr 2025 14:31:34 GMT</pubDate>
            <description><![CDATA[<p>동적할당을 할 때 c언어에서 malloc이라는 함수를 사용한 것을 기억하시나요?</p>
<pre><code class="language-cpp">int main()
{
    void* pData = malloc(100);

    // 동적할당으로 생성된 메모리 공간을 해제하는 함수
    free(pData);
}</code></pre>
<p>왜 자료형을 void*로 주었느냐,
float이나 int를 넣으면, char형과 같이 1바이트 메모리를 할당하고 싶을 때 메모리 낭비가 생깁니다.</p>
<p>동적할당 함수 malloc는 입력된 크기(바이트 단위)만큼 힙 영역에 메모리를 할당한 후, 그 시작 주소를 반환합니다.</p>
<p><strong>반환 타입은 void*입니다.</strong>
malloc을 호출한 사용자가 해당 공간을 어떤 용도로 사용할지 알 수 없기 때문이지요.</p>
<p><strong>memory leak 발생</strong>
동적할당을 하고, 프로그램이 종료될 때까지 해당 공간을 해제하지 않고 프로그램이 종료된 경우</p>
<p>그런데 우리 c++에서는 동적할당 시 malloc 함수를 사용하지 않습니다.
왜 일까요?</p>
<p>c++에는 생성자와 소멸자를 개념이 추가되었습니다.
객체를 만들었을 때 우리는 생성자가 자동으로 호출되지만, malloc으로 동적할당을 할 시, 생성자를 호출해주지 못합니다.
malloc과 free는 요청된 크기만큼 동적할당하고, 알려준 주소를 메모리 해제시키기 때문에 해당 공간이 어떤 목적으로 사용되고 있는지 알 수 없습니다.
또한 malloc(정수)로 표현이 되는데
어떻게 클래스 객체를 시작 주소로 해서 생성자를 호출해줄 수 있을까요.</p>
<p>이를 해결하기 위해 <strong>new</strong>와 <strong>delete</strong>라는 템플릿 기반 키워드가 등장했습니다.</p>
<pre><code class="language-cpp">MyClass* pNewMy = new MyClass;
delete pNewMy;</code></pre>
<p>malloc과 생성자 호출,
free와 소멸자 호출까지 해주는 템플릿을 통해 c++는 동적할당을 구현할 수 있게 되었습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[연산자 오버로딩]]></title>
            <link>https://velog.io/@invisible_thorn/%EC%97%B0%EC%82%B0%EC%9E%90-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9-rk77w8rj</link>
            <guid>https://velog.io/@invisible_thorn/%EC%97%B0%EC%82%B0%EC%9E%90-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9-rk77w8rj</guid>
            <pubDate>Wed, 16 Apr 2025 03:02:13 GMT</pubDate>
            <description><![CDATA[<p>우리는 이제까지 다양한 연산자를 사용했습니다
+,-,*,/,% ...</p>
<p>그리고 기본 자료형의 변수를 만들고 그들을 연산해주었습니다
그런데 클래스나 구조체 자료형도 그대로 연산이 될까요?
스스로 설계한 자료형은 연산자도 스스로 만들어줘야합니다</p>
<pre><code class="language-cpp">Class TestClass
{
private:
    int m_i;
public:
    TestClass(){}
   ~TestClass(){}
}

int main()
{
    int a = 100, int b = 200;
    int c = a + b; // 300

    TestClass ta;
    TestClass tb;
    TestClass tc = ta + tb; // 오류 발생
}</code></pre>
<p>전역함수와 멤버변수 두 가지 버전으로 한 번 만들어봅시다</p>
<h3 id="1-전역변수-ver">1. 전역변수 ver</h3>
<pre><code class="language-cpp">Class TestClass
{
private:
    int m_i;
public:
    TestClass(){}
   ~TestClass(){}
   // 전역 함수는 클래스 멤버 변수에 접근을 못하므로 get,set함수가 필요
}

// 전역함수로 추가하기
TessClass operator+(TestClass _right, TestClass _left)
{

}

int main()
{
    int a = 100, int b = 200;
    int c = a + b; // 300

    TestClass ta;
    TestClass tb;
    TestClass tc = ta + tb; // operator+(ta,tb)를 이렇게 표현 가능
}</code></pre>
<h3 id="2-멤버함수-ver">2. 멤버함수 ver</h3>
<pre><code class="language-cpp">Class TestClass
{
private:
    int m_i;
public:
    TestClass(){}
   ~TestClass(){}

   int SetData(int _i)
   {
           m_Data = _i;
   }

   // 멤버함수로 추가하기
   // 인자를 하나만 받음
   // 호출자가 this
    TestClass operator+(TestClass _other)
    {
        TestClass data;
        data.m_Data = this-&gt;m_Data + _other-&gt;m_Data;
        return data;
    }
}


int main()
{
    int a = 100, int b = 200;
    int c = a + b; // 300

    TestClass ta;
    ta.SetData(10);

    TestClass tb;
    tb.SetData(100);

    TestClass tc = ta + tb; // ta.operator+(tb)를 이렇게 표현 가능
}</code></pre>
<p>그런데 갑분 생각해보아야 할 점
함수 내부의 지역변수가 return 될 때 왜 사라지지 않고, 호출했을 때 값을 받아올 수 있는 걸까요?
예를 들어봅시다.</p>
<pre><code class="language-cpp">int getInt()
{
    int a = 1;
    return a;
}

int main()
{
    getInt();
}</code></pre>
<p>int a는 지역변수고, 함수가 종료되면 사라질텐데 어떻게 return 할 수 있는 걸까요?
(사실 저도 안궁금해했음 당연한 거라고 생각함)
정답은 a 내부의 값을 레지스터 메모리에 저장시켜놓습니다.</p>
<p>위의 TestClass타입을 반환하는 data도 이런 식으로 리턴되어 값이 사라지지 않고 복사된 값을 받을 수 있게됩니다.</p>
<p>그리고 오퍼레이터는 내가 만든 기호 내부 식으로 연산을 하는 것이기 때문에 정의되어있는 연산자와 의미가 다를 수도 있습니다.
우리가 c++에서 아주 많이 사용하는 cout 객체도 그렇습니다.</p>
<pre><code class="language-cpp">cout.ostream::operator&lt;&lt;(10);</code></pre>
<p>&lt;&lt;는 원래 비트 연산자지만,
입벌리고 있으니 먼가 출력해줄 거 같은 느낌적인 느낌이 드는 겁니다.
그러니 이런 식으로 만들고 사용하게 되었습니다.</p>
<pre><code class="language-cpp">// 멤버함수
void operator &lt;&lt;(int a)
{
    printf(&quot;%d&quot;,a);
}

TestClass ta;
ta.operator&lt;&lt;(10) &lt;&lt; 20; // 컴파일 에러</code></pre>
<p>왜 문제가 될까요?
멤버 함수는 호출 객체가 필요합니다.
ta.operator&lt;&lt;(10)는 this 포인터로 operator 멤버 함수를 호출하여 10을 출력했는데, 그리곤 ta 객체로 돌아오지 못했기 때문입니다!
(대충 this 포인터가 아니라는 뜻)
그럼 다시 리턴 값으로 ta가 돌아오게 만들어봅시다.</p>
<pre><code class="language-cpp">TestClass* operator &lt;&lt;(int a)
{
    printf(&quot;%d&quot;,a);

    return this; // 자기 자신의 주소를 반환
}

*(*(*(ta &lt;&lt; 40))&lt;&lt; 50)&lt;&lt;  60; //... </code></pre>
<p>복사본이 아닌 원본을 참조하기 위해 리턴 받은 this를 참조하고 또 그 리턴 값을 참조 참조... 했는데 너무 불편하지 않을까요?
그래서 이렇게 바꿔보겠습니다.</p>
<pre><code class="language-cpp">
TestClass&amp; operator &lt;&lt;(int a)
// 레퍼런스는 원본을 받아도 주소가 넘어감
{
    printf(&quot;%d&quot;,a);

    return *this; // this는 이미 포인터 타입이므로 *를 붙여줘야 원본 참조
}
 ta &lt;&lt; 10 &lt;&lt; 20 &lt;&lt; 30;</code></pre>
<p> 이렇게 되면 우리가 이제껏 생각한대로 출력할 수 있게 됩니다.</p>
<p> ...
정리할 내용 조금 더 있슴 -&gt; 함수 주소값으로 endl 구현하는 거는 좀 나중에 하겠소</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[생성자가 복사가 된다고]]></title>
            <link>https://velog.io/@invisible_thorn/%EC%83%9D%EC%84%B1%EC%9E%90%EA%B0%80-%EB%B3%B5%EC%82%AC%EA%B0%80-%EB%90%9C%EB%8B%A4%EA%B3%A0-4t82f2xu</link>
            <guid>https://velog.io/@invisible_thorn/%EC%83%9D%EC%84%B1%EC%9E%90%EA%B0%80-%EB%B3%B5%EC%82%AC%EA%B0%80-%EB%90%9C%EB%8B%A4%EA%B3%A0-4t82f2xu</guid>
            <pubDate>Tue, 15 Apr 2025 11:23:53 GMT</pubDate>
            <description><![CDATA[<p>복사 생성자가 뭔지 알려면 우선 생성자가 무엇인지 알아야겠죠?
내친김에 소멸자까지 함께 알아봅시다.</p>
<p>길게 안합니다.</p>
<pre><code class="language-cpp">class TestClass()
{
private:
    int m_i;

public:
    TestClass(){}
   ~TestClass(){}
}

int main()
{
    TestClass tc; // 객체 생성
};</code></pre>
<p>클래스는 보통 이런 형태로 이루어집니다.
멤버변수와 멤버함수
그리고 생소멸자는 멤버함수 그 클래스의 멤버함수 입니다.</p>
<pre><code class="language-cpp">TestClass();</code></pre>
<p>생성자입니다
<strong>객체가 생성</strong>될 때 호출되는 함수입니다.
초기화 함수 등을 따로 만들 필요없이 이곳에 작성하는 것이 효율적입니다.
반환 타입을 적지 않으며, 함수명은 반드시 자료형 이름(클래스 이름)과 동일해야합니다.</p>
<pre><code class="language-cpp">~TestClass();</code></pre>
<p>소멸자입니다
<strong>객체가 소멸</strong>될 때 호출되는 함수입니다
메모리 해제를 하는 함수 등을 이곳에 작성하면 효율적입니다
생성자와 같이 반환 타입을 적지 않고 함수명은 자료형 이름을 따릅니다</p>
<blockquote>
<p>모든 멤버함수에는 보이지 않는 지역변수  *this를 갖는다
주소 변수를 매개변수로 받지 않아도 되는 이유가 이것
해당 멤버함수를 호출시킨 객체의 주소값을 받아온다</p>
</blockquote>
<p>네 그렇습니다 아주 중요한 내용입니다.
기본적인 성질을 알아보았으니, 돈복사 대신 생성자를 복사 해봅시다.</p>
<pre><code class="language-cpp">classs TestClass()
{
private:
    float m_data;

public:
    // 기본 생성자(Default construction)
    TestClass()
        : m_data(0.f)
    {}
    TestClass(float _data)
        : m_data(_data)
    {}
    ~TestClass()
    {}
}

int main()
{
    TestClass tsc;
    TestClass tsc2(10.f); // 오버로딩된 생성자를 가리킴

    // 기본 생성자를 호출할까?
    // Nope
    // 컴파일러는 반환 타입이 TestClass이며 인자가 없는 함수의 전방선언으로 봄
    TestClass tsc2();
    // 따라서  객체 생성이 안됨
    // setData().. 등의 함수를 만들어서 값을 넣어주어야함

};</code></pre>
<p>만약 클래스에 생성자가 정의되어 있지 않으면 기본 생성자를 생성합니다.</p>
<pre><code class="language-cpp">TestClass(){}</code></pre>
<p>이니셜라이즈도 하지 않은 아무 의미를 담지 않은 생성자 일지라도 규칙이라 호출하게 됩니다.</p>
<p>그러나 생성자 오버로딩으로 인자를 가진 생성자가 있다면 기본 생성자를 호출하지 않습니다.</p>
<pre><code class="language-cpp">TestClass(int _data)
    :m_data(_data)
{}

// main
TestClass tsc;</code></pre>
<p>이 코드는 컴파일 오류가 납니다.
왜일까요?</p>
<p>여기서 tsc의 객체는 기본 생성자를 호출하는 객체이기 때문입니다.
생성자에 맞추어 인자를 갖게끔 오버로딩된 객체를 만들어줘야 합니다.</p>
<p>따라서</p>
<pre><code class="language-cpp">TestClass tsc(3.f);</code></pre>
<p>이런 식으로 작성해줘야합니다.
그래야 오버로딩된 생성자를 잘 호출하겠죠?</p>
<p>네 그럼 이제 진짜  복사 생성자를 알아봅시다.</p>
<pre><code class="language-cpp">class TestClass
{
private:
    float m_data;

public:
    void setData(float _data)
    {
        m_data = _data;
    }

public:
    TestClass() 
        : m_data(0.f)
    {}
    TestClass(float _data)
        : m_data(_data)
    {}
    ~TestClass() {}
};

int main()
{
    TestClass tsc;
    tsc.setData(2.f);

    // 디폴트 복사 생성자 
    TestClass tsc2(tsc);
}</code></pre>
<p>디폴트 복사 생성자라는 걸 작성했을 때 컴파일 오류가 나지 않습니다.
그말인 즉 컴파일러가 자동으로 생성해준다는 이야기인데요,
만약 복사 생성자가 구현되어있다면 어떻게 작성 되어있을지 확인해 봅시다.</p>
<pre><code class="language-cpp">// 복사 비용을 줄이기 위해 원본 값을 참조한다.
// 원본을 수정할 수 없게 const 키워드를 추가
// 복사하고자 하는 값과 동일하게 시작하기 위함
TestClass(const TestClass&amp; _Other)
    : m_Data(_Other.m_Data)
{}</code></pre>
<p>복사 생성자가 구현되어있으면?
기본 생성자는 구현되지 않습니다.
그니까 어떤 생성자건 본인이 직접 구현한 생성자가 있다면 기본 생성자는 만들어지지 않습니다!
개헷갈림
깊은 복사와 얕은 복사를 사용할 때 특히 중요합니다.
이 부분은 나중에...</p>
<p>디폴트 복사 생성자가 문제가 되어 금지하는 경우도 있답니다.</p>
<pre><code class="language-cpp">TestClass(const TestClass&amp; _Other) = delete;</code></pre>
<p>이어서 봅시다.</p>
<pre><code class="language-cpp">class MyClass
{
private:
    int m_i;
public:
    void setData(int _a) { m_i = _a;}
}
;

int main()
{
    // 기본 생성자 생성
    MyClass mc1;
    mc1.setData(10);

    // 복사 생성자 생성
    MyClass mc2(mc1);

    // 대입 연산자 -&gt; 디폴트 대입 연산자도 있음
    MyClass mc3;
    mc3 = mc1;

}</code></pre>
<p>디폴트 대입 연산자를 직접 구현하자면</p>
<pre><code class="language-cpp">void operator=(const MyClass&amp; _Other)
{
    m_i = _Other.m_i;
}</code></pre>
<p>mc3이 호출 객체가 되는 연산자 함수입니다.
근데 사실 컴파일러가 만들어주는 디폴트 대입 연산자는 MyClass&amp; 타입을 반환하는 함수여야합니다.
얘는 걍 러프하게 작성해본 거임</p>
<pre><code class="language-cpp">MyClass&amp; operator=(const MyClass&amp; _Other)
{
    m_i = _Other.m_i;
    return *this;
}</code></pre>
<p>이렇게 되어야 주소를 갖는 자기자신을 반환하면서 대입 대입 대입... 이 되어 값이 결정되는 것 입니다.</p>
<pre><code class="language-cpp">int i = 0;
int i1 = 10;
int i2 = 100;

i2= i1 = i;
// i의 0이 i1으로 전달
// i1은 0을 가지고 i2에 전달
// i2는 0을 값으로 가짐</code></pre>
<p>이와 같이</p>
<pre><code class="language-cpp">int main()
{
    // 기본 생성자 생성
    MyClass mc1;
    mc1.setData(10);

    // 복사 생성자 생성
    MyClass mc2(mc1);

    // 대입 연산자 
    MyClass mc3;
    mc3 = mc2 = mc1;

}</code></pre>
<p>대입이 연달아 이어 진행될 수 있도록, operator=의 반환타입은 호출자 자기 자신이 되면 됩니다.</p>
<p>+추가</p>
<pre><code class="language-cpp">MyClass mc4 = mc3;
// 생성자가 호출되기 전에 대입이 일어남
// 복사 생성자로 해석해서 처리함

// -&gt;

MyClass mc4;
mc4 = mc3;
// 생성자 호출 후 대입 연산자 호출됨

MyClass mc4(mc3);
// 복사 생성자 호출!</code></pre>
<p>그러니 굳이 두 줄에 나누어 구현할 필요가 없겠네요. ㅇㅅㅇ
복사 생성자는 여기까쥐</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[학씨]]></title>
            <link>https://velog.io/@invisible_thorn/%ED%95%99%EC%94%A8</link>
            <guid>https://velog.io/@invisible_thorn/%ED%95%99%EC%94%A8</guid>
            <pubDate>Tue, 15 Apr 2025 11:10:02 GMT</pubDate>
            <description><![CDATA[<p>다들 폭삭 속았수다 재밌게 보셨나요
전 광광 우럭슴</p>
<p>어쨌든 그건 그거고
작년 말부터 티스토리에 글 적기 시작했는데...
꾸밀 줄 모르니까 꾸미고 싶다는 생각에 더 스트레스 받음
그래서 그냥 썸네일 고르며 재밌어했던 벨로그로 돌아왔습니다 (대충 박수 갈채)
그리고 머... 또 공부했던 것을 수정수정들 하면서..
다시 겅부하기~ 와~</p>
<p>그러면서 티스토리 일단 링크 남겨놓기
<a href="https://thornpang2.tistory.com/">쏜팡이 티스토리</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[IPC란 무엇인가... ]]></title>
            <link>https://velog.io/@invisible_thorn/IPC%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@invisible_thorn/IPC%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Tue, 10 Dec 2024 11:37:25 GMT</pubDate>
            <description><![CDATA[<p>프로세스 간 통신입니당(Inter Process Communication) 
협력 프로세스들이 데이터를 공유하고 작업을 조율하기 위해 사용하는 다양한 메커니즘을 일컫습니다. </p>
<p>여러가지 방법이 있는데 요것들을 알아보겠슴니다. </p>
<h3 id="1-파이프pipes">1. 파이프(Pipes)</h3>
<p>단방향 통신
부모-자식 프로세스
데니터 스트림 전송 시 사용</p>
<h3 id="2-이름있는-파이프named-pipes">2. 이름있는 파이프(Named Pipes)</h3>
<p>양방향 통신
시스템 내 어떤 프로세스 간에도 사용 가능
파일 시스템 내에 특정 이름을 가진 파일 형태로 존재 - &gt; 이를 통해 데이터 주고받음</p>
<h3 id="3-메세지-큐message-queues">3. 메세지 큐(Message Queues)</h3>
<p>데이터 블럭을 전송하기 위한 메커니즘
비동기적 메세지 송수신
복잡한 데이터 구조 전송
메세지 우선 순위 설정 기능 제공</p>
<h3 id="4-공유-메모리shared-memory">4. 공유 메모리(Shared Memory)</h3>
<p>두 개 이상의 프로세스가 시스템 메모리의 동일한 부분 공유 - &gt; 데이터 접근, 변경
매우 빠른 데이터 접근, 전송 but 동기화 메커니즘 사용해야함</p>
<h3 id="5-세마포어semaphores">5. 세마포어(Semaphores)</h3>
<p>간접적으로 프로세스 간 통신에 사용
공유 자원 제한 접근 - &gt; 데이터의 일관성과 동시성 유지</p>
<h3 id="6-소켓sockets">6. 소켓(Sockets)</h3>
<p>네트워크를 통한 프로세스 통신
TCP/IP와 UDP 프로토콜을 사용하여 같은 시스템 내늬 프로세스 또는 다른 시스템에 있는 프로세스 간에 데이터 주고 받기 가능</p>
<h3 id="7-시그널signals">7. 시그널(Signals)</h3>
<p>프로세스에 특정 이벤트 발생 시 나타나는 메세지
운영체제 또는 다른 프로세스로부터 프로세스에 비동기적으로 알림을 전달하는데 사용됨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데드락(DeadLock)]]></title>
            <link>https://velog.io/@invisible_thorn/%EB%8D%B0%EB%93%9C%EB%9D%BDDeadLock</link>
            <guid>https://velog.io/@invisible_thorn/%EB%8D%B0%EB%93%9C%EB%9D%BDDeadLock</guid>
            <pubDate>Mon, 25 Nov 2024 06:48:30 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요? 
저는 데드락이 게임하고 발로란트 요원 밖에 몰랐는데
&#39;교착 상태&#39;를 의미하는 데드락이 어떤 일을 벌이고 있는지 확인해봅시다. </p>
<h3 id="데드락deadlock">데드락(DeadLock)</h3>
<p>두 개 이상의 프로세스나 스레드가 <strong>서로</strong> 자원을 얻지 못해 다음 처리를 하지 못하는 상태
(무한히 다음 자원을 기다림, 서로 원하는 자원이 상대방에게 할당되어 있어서 두 프로세스가 무한정 wait 상태에 빠짐) </p>
<p>이러한 상태를 말하는 데요, 그렇다면 어떤 상황에서 데드락이 발생할까요? </p>
<h3 id="데드락의-발생-조건">데드락의 발생 조건</h3>
<ol>
<li>상호 배제
: 프로세스가 소유 중인 자원에 다른 프로세스가 접근할 수 없음(자원은 한 번에 한 프로세스만 사용)</li>
<li>점유 대기
: 자원을 최소한 하나 보유한 상태에서 다른 프로세스가 가지고 있는 자원을 요청</li>
<li>비선점
: CPU나 메모리같은 자원을 강제로 뺏어올 권한이 없는 상태(프로세스간 분쟁 사이 개입 못함) </li>
<li>순환 대기
: 프로세스가 서로의 자원을 요청하는 무한 굴레에 빠짐</li>
</ol>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/bd965dda-db63-4d59-811f-64026f548b14/image.png" alt=""></p>
<p>그림을 보면 쉽게 이해가 될 것입니다. 
서로를 계속 요청하는 상태입니다. 손에 손잡고 강강술래</p>
<p>아래와 같이 선형 구조는 헤드와 꼬리를 통해 빠져나올 수 있답니다. -&gt; 데드락은 환형구조여야함
<img src="https://velog.velcdn.com/images/invisible_thorn/post/423d3bb4-f75b-4885-b02c-2c77de0d271e/image.png" alt=""></p>
<blockquote>
<p>[사진 참조] <a href="https://wikidocs.net/217376">https://wikidocs.net/217376</a></p>
</blockquote>
<p>이게 정상적으로 작동하는 상태는 아니기 때문에 해결을 해줘야겠죠? 
해결법에 대해 알아봅시다!</p>
<h3 id="데드락-해소하기">데드락 해소하기</h3>
<p>이에는 3가지 방법을 둔다고 합니다. </p>
<ol>
<li>데드락이 일어나지 않도록 <strong>예방</strong>하거나, </li>
<li>데드락이 일어날 가능성을 염두해두면서 적절히 <strong>회피</strong>하거나, </li>
<li>데드락이 일어났지만 데드락을 <strong>탐지</strong>하여 데드락에서 <strong>회복</strong>하는 법이 있슴니다. </li>
</ol>
<h3 id="1-데드락-예방-deadlock-prevention">1. 데드락 예방 (Deadlock Prevention)</h3>
<p>(1) 상호 배제(Mutual Exclusion) 차단
자원을 공유할 수 있도록 설계합니다.
예: 읽기 전용 자원은 여러 프로세스가 동시에 접근 가능하도록 함.</p>
<p>(2) 점유 대기(Hold and Wait) 차단
프로세스가 자원을 요청할 때 이미 필요한 모든 자원을 한 번에 할당받도록 강제합니다.
문제점:
자원을 비효율적으로 사용하게 됨.
모든 자원을 한꺼번에 기다려야 하므로 지연이 발생할 수 있음.</p>
<p>(3) 비선점(No Preemption) 차단
자원을 점유 중인 프로세스가 요청한 자원을 획득하지 못하면 이미 점유 중인 자원을 강제로 해제하도록 설계합니다.
예: CPU 스케줄링에서 선점형 알고리즘 사용.</p>
<p>(4) 순환 대기(Circular Wait) 차단
자원에 고유한 순서를 부여하고, 각 프로세스가 자원을 요청할 때 반드시 그 순서대로 요청하도록 합니다.
예: 자원 A→B→C 순서로만 요청 가능.</p>
<h3 id="2-데드락-회피-deadlock-avoidance">2. 데드락 회피 (Deadlock Avoidance)</h3>
<p>데드락이 발생할 가능성을 예측하고 안전 상태를 유지하도록 설계하는 방법입니다.</p>
<p><strong>은행원 알고리즘(Banker&#39;s Algorithm)</strong></p>
<p>(1) 은행원 알고리즘
프로세스의 자원 요청을 허용하기 전에 시스템이 &quot;안전 상태(Safe State)&quot;인지 확인합니다.
안전 상태(Safe State): 모든 프로세스가 요구하는 자원을 순차적으로 할당하여 데드락 없이 종료될 수 있는 상태.
시스템이 안전 상태에 있다면 요청을 허용하고, 그렇지 않다면 요청을 거부.</p>
<p>(2) 장단점
장점: 데드락 발생 가능성을 사전에 방지.
단점: 프로세스의 최대 자원 요구량을 미리 알아야 하며, 계산 비용이 증가.</p>
<h3 id="3-데드락-탐지-및-회복-deadlock-detection-and-recovery">3. 데드락 탐지 및 회복 (Deadlock Detection and Recovery)</h3>
<p>데드락이 발생할 가능성을 허용하지만, 발생한 이후 이를 탐지하고 해결합니다.</p>
<p>(1) 데드락 탐지
주기적으로 자원 할당 그래프(Resource Allocation Graph)를 분석하여 순환 대기(Circular Wait)를 찾습니다.
순환 대기가 발견되면 데드락이 발생한 것으로 간주.</p>
<p>(2) 데드락 회복
데드락 상태를 해결하기 위해 다음과 같은 방법을 사용:
프로세스 종료
데드락에 연루된 프로세스를 하나씩 강제 종료하거나, 모든 관련 프로세스를 종료.
단점: 데이터 손실이나 작업 지연 가능성.
자원 선점
자원을 점유한 프로세스에서 자원을 강제로 해제하고 다른 프로세스에 재할당.
단점: 해당 프로세스가 다시 자원을 요청해야 함.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[뮤텍스(Mutex)와 세마포어(Semaphore) ]]></title>
            <link>https://velog.io/@invisible_thorn/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%8F%99%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@invisible_thorn/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%8F%99%EA%B8%B0%ED%99%94</guid>
            <pubDate>Tue, 19 Nov 2024 06:18:41 GMT</pubDate>
            <description><![CDATA[<p>이번 시간엔 뮤텍스와 세마포어에 대해 알아보고자 합니다. 
이를 알기 전엔 <strong>프로세스 동기화</strong>를 알아야합니다. </p>
<h3 id="프로세스-동기화">프로세스 동기화</h3>
<p>여러 개의 프로세스(or 스레드)가 컴퓨터 내에 공유된 리소스에 접근하는 경우에 데이터 일관성을 유지하기 위한 방식을 말한다. 
데이터 일관성이 무엇이냐 하면</p>
<blockquote>
<p>시스템 내의 데이터가 동일한 상태를 유지하고 모순이나 충돌이 없는 상태(= 모두 같은 정보를 보게 만드는 것) </p>
</blockquote>
<p>티켓팅을 하는데 하나의 좌석에 여러 명이 접근하게 되면 이선좌 메세지가 뜨잖아요?
그거랑 비슷한 느낌입니다. 
근데 만약 이선좌가 안뜨고 많은 사람들이 같은 좌석을 선택하면 어떻게 될까요? 
생각만 해도 엄청 큰 문제가 발생할 것이란게 느껴집니다. 
프로세스 관점에서는 이를 동기화 문제가 발생했다고 합니다.
그리고 이 문제를 해결하기 위한 방법이 앞서 언급한 <strong>뮤텍스</strong>와 <strong>세마포어</strong>입니다. </p>
<p>좀 더 자세히 예를 들어보겠습니다. 
지피티가 알맞은 예제를 가져왔네요. </p>
<h4 id="예시-은행-계좌">예시: 은행 계좌</h4>
<h4 id="시나리오">시나리오:</h4>
<p>계좌에 1000원이 있습니다.
두 개의 스레드, 스레드 A와 스레드 B가 이 계좌에서 돈을 인출하려고 합니다. 두 스레드는 동시에 이 계좌에 접근합니다.
스레드 A: 500원을 인출하려고 합니다.
스레드 B: 700원을 인출하려고 합니다.</p>
<p><strong>경쟁 상태 (Race Condition)</strong>
경쟁 상태는 여러 프로세스나 스레드가 동시에 공유 자원에 접근하고, 그 순서나 타이밍에 따라 결과가 달라지는 상황을 말합니다.</p>
<p><strong>동작 순서 (경쟁 상태 발생)</strong>
스레드 A가 계좌의 잔액을 읽고, 현재 잔액이 1000원임을 확인합니다.
스레드 B도 계좌의 잔액을 읽고, 잔액이 1000원임을 확인합니다.
스레드 A는 500원을 인출하려고 하고, 스레드 B도 700원을 인출하려고 합니다.
스레드 A가 500원을 인출하여 계좌 잔액을 500원으로 변경합니다.
그런데, 그 사이 스레드 B도 700원을 인출하려고 하면서, 잔액이 500원인 것을 모르고 인출을 시도합니다.
결국, 스레드 B가 700원을 인출하게 되면, 계좌 잔액은 -200원이 되어 과도한 인출이 발생합니다.</p>
<h4 id="문제">문제:</h4>
<p>위와 같이, 두 스레드가 동시에 공유 자원인 계좌에 접근하면서 일어나는 경쟁 상태로 인해 잘못된 결과가 발생합니다. 계좌에는 1000원이지만, 두 스레드가 동시에 인출을 시도하면서 결과적으로 과도한 인출이 발생하는 문제가 생깁니다.</p>
<p><strong>임계영역 (Critical Section)</strong>
임계영역은 공유 자원에 접근할 때 여러 스레드가 동시에 접근하지 않도록 해야 하는 코드 블록을 의미합니다. 여러 스레드가 동시에 공유 자원에 접근하면 경쟁 상태가 발생할 수 있기 때문에, 이를 해결하려면 임계영역을 보호해야 합니다.</p>
<h4 id="해결책-임계영역-보호">해결책: 임계영역 보호</h4>
<p>임계영역을 보호하기 위해, <strong>뮤텍스(Mutex)</strong> 나 <strong>세마포어(Semaphore)</strong> 를 사용할 수 있습니다.
이를 통해 한 번에 하나의 스레드만 공유 자원(계좌 잔액)에 접근할 수 있도록 동기화할 수 있습니다.</p>
<h4 id="예시-해결">예시 해결:</h4>
<p>뮤텍스를 사용해서 스레드 A와 스레드 B가 동시에 계좌에 접근하지 못하도록 동기화합니다.
스레드 A가 계좌 잔액을 수정할 때는 뮤텍스 잠금을 걸고, 다른 스레드가 계좌에 접근하지 못하게 합니다.
스레드 A가 작업을 끝내고 뮤텍스 잠금 해제를 하면, 그때서야 스레드 B가 계좌에 접근할 수 있습니다.
이렇게 하면 임계영역을 보호하고, 경쟁 상태를 방지할 수 있습니다.</p>
<h4 id="정리">정리:</h4>
<p><strong>경쟁 상태(Race Condition)</strong> 는 여러 스레드가 동시에 공유 자원에 접근하여 예상치 못한 결과를 초래하는 상황입니다. 예시에서는 두 스레드가 동시에 은행 계좌에 접근하면서 잘못된 인출 결과가 발생한 상황입니다.</p>
<p><strong>임계 영역(Critical Section)</strong> 은 공유 자원에 대한 동시 접근을 막아야 하는 코드 부분을 의미합니다. 여러 스레드가 동시에 자원에 접근하면 문제가 생기므로, 임계영역을 보호해야 합니다. 이를 위해 뮤텍스나 세마포어와 같은 동기화 도구를 사용하여 경쟁 상태를 방지합니다.</p>
<p>따라서 한 줄로 요약해보자면, 경쟁 상태를 해결하기 위해 임계 영역 관리의 필요하다는 것이다.
여기까지 이해가 됐다면 뮤텍스와 세마포어를 알아갈 준비가 되었다. </p>
<h3 id="뮤텍스mutex">뮤텍스(Mutex)</h3>
<h3 id="세마포어semaphore">세마포어(Semaphore)</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[게임인재원 6기 나온 썰 푼다]]></title>
            <link>https://velog.io/@invisible_thorn/%EA%B2%8C%EC%9E%84%EC%9D%B8%EC%9E%AC%EC%9B%90-6%EA%B8%B0%EB%A5%BC-%EB%82%98%EC%98%A4%EB%A9%B4%EC%84%9C-lcy0z31v</link>
            <guid>https://velog.io/@invisible_thorn/%EA%B2%8C%EC%9E%84%EC%9D%B8%EC%9E%AC%EC%9B%90-6%EA%B8%B0%EB%A5%BC-%EB%82%98%EC%98%A4%EB%A9%B4%EC%84%9C-lcy0z31v</guid>
            <pubDate>Mon, 11 Nov 2024 02:23:14 GMT</pubDate>
            <description><![CDATA[<p>프리스쿨을 지나 1,2학기 그리고 3학기 중반까지의 회고를 작성해보고자 합니다. 
7기 신청 기간이라고 알고 있는데 도움이 되길 바라며... 
최대한 객관적으로 작성하겠지만 사람인지라 주관성이 포함되는 부분은 알아서 필터링 해주시면 감사하겠습니다:) </p>
<p>저는 인재원 프로그래밍학과를 나왔구요. 
우선 저는 쿼터 전공자(?) 입니다. 
산업경영공학과를 나왔고 4학년 2학기에 부전공으로 컴퓨터 공학 수업을 찍먹한 수준이기 때문에 프로그래밍에 대해 무지한 상태였습니다. 
이전에 빅데이터 솔루션 만드는 회사에서 프론트도 찍먹해보긴 했지만 애매하게 아는 정도로 게임인재원에 운좋게 들어가게 되었습니다. </p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/2e9a0c41-cfd5-4270-a644-265718ff3e43/image.jpg" alt="">
대충 인재원 6기 인증 컷</p>
<h2 id="1학기-2403-2405">1학기 (24.03~ 24.05)</h2>
<p>어쨌든 입학은 저처럼 전공자가 아니어도 할 수 있습니다.
실제로 저보다 관련없는 인문계열 학과를 나온 친구들도 있었구요. 
그런데 적응하느냐의 문제는... 본인에게 달린 것 같습니다. </p>
<p>1학기 수업은 컴퓨터 개론, 자료구조, C언어, 유니티로 배우는 수학, 게임수학 그리고 블렌더 이렇게 진행되었었는데(맞나?) 
모든 걸 상세히 적기는 힘들고 좋았던 점과 힘들었던 점을 위주로 써보자면
컴퓨터 개론 같은 경우는 관련 자료를 잘찾아주셔서 도움이 됐던 것 같고
C언어는 이해가 잘되게 자세히 설명을 해주셨습니다. 
게임 수학과 같은 경우도 예시를 잘 들어주셔서 이해하기 좋았던 것 같고, 학생들이 되게 좋아했던 기억이 나네요. 
자료구조 같은 경우는 제가 C언어도 부족하고 자료구조라는 것 자체가 생소해서 따라가기 제일 어렵지 않았나 싶습니다. 개인적으로는 조금 더 원리를 설명해주셨으면 하는 바람이 있었는데 아무래도 대다수의 학생들은 기초적인 내용이라 넘어가지 않으셨을까 합니다. 
유니티로 배우는 게임수학은... 유니티도 모르고 게임수학도 어려운 상태에서 따라가기 힘들었던 것 같습니다. 유니티하는 법을 조금 더 가르쳐주시면서 했으면 달랐을까 하는 아쉬움도 있습니다. ㅜ.ㅜ
블렌더 같은 경우는 프로그래머인데 왜 배울까? 싶었는데 배우면서 디자이너들의 고충을 많이 알았던 시간이었습니다. 그리고 교수님이 거의 클릭이야부터 가르쳐주셔서 따라가기 좋았습니다.(따봉 아트교수님...)</p>
<p>그리고 인재원 학기 말의 꽃은 모든 학과가 협업하는 단체 프로젝트인데요. 
저희는 상용엔진을 사용하지 않습니다. 
유니티 언리얼 이만 자리로 돌아가줘... 
WinApi를 이용해 자체엔진을 만들어 프로젝트를 진행합니다. 
이게 뭐냐? 싶으시다면 검색 ㄱㄱ 유투브에 어소트락이라고 잘 나와있어요. 
처음에는 왜 취업하면 쓰지도 않는 엔진을 직접 만들어서 날 힘들게 해... 했는데 이 과정에서 게임엔진 구조의 전반적인 흐름을 배울 수 있습니다.
C++ 코드 작성도 많이 해볼 수 있구요. 많이 많이 중요한 시간이었다고 생각합니다. </p>
<p>저는 사실 1학기부터 낯선 환경과 학업들을 핑계로 과제와 공부를 소홀히 했습니다. 
그럼에도 불구하고 그 한 학기동안 배운게 혼자서 공부해보겠다고 마음 먹는 몇 달보다 많았습니다. 
그리고 생각보다 잘하는 친구들의 도움을 받는게 굉장히 큰 도움이 됐습니다. 
사람들은 여러분 생각보다 친절하고 열려있으니 어려운 일이 있다면 반드시 교수님들이나 학생분들에게 도움을 받으세요.
제가 1학기 때 그걸 못하고 프로젝트 할 때서야 하게 된게 제일 후회됩니다.
결론은 1학기라고 얕보지말고 열심히 공부하세요! </p>
<h2 id="2학기-2406-2408">2학기 (24.06~ 24.08)</h2>
<p>대부분의 커리큘럼이 비슷했는데 달라진 점은, 
엔진 만드는 수업이 따로 생겼습니다.
그리고 수업을 담당하는 교수님들의 포지션이 일부 바뀌면서 좀 더 나은 방향으로 수업이 진행된 것 같습니다. 아무래도 저같은 학생들이 있어서 고민을 많이 하신듯
DirectX 2D 라고 들어보셨나요? 
와! D2D! 아시는 구나~
진. 짜. 겁. 나. 어. 렵. 습. 니. 다
사실 3학기 때 얘기를 미리하자면 디투디는 어려운 편이 아닙니다. ㅋ ㅠ
어찌됐든 제일 곤욕이었던 수업이 이 수업인 것 같습니다. 
이걸로 과제도 내고 개인 프로젝트도 하고 팀 프로젝트도 했어야 했으니까요. 
이때는 정말 여러 친구들의 도움을 받아 과제를 완성하고 개인 프로젝트도 (완성이라기엔 부족한)마무리 했던 기억이 납니다. 
자주 10시까지 남아서 과제하고 같이 공부했는데 힘들었지만 역시 그만큼 도움이 됐습니다. 
아쉬운 게 하나 있다면, 과제를 다 제출한 학생에 한해서 팀 프로젝트를 진행했었는데 저는 다하고도 자신이 없어 개인 프로젝트와 추가 공부를 자진했다는 점이 있네요. 
사실 1학기 때도 도움을 많니 받으면서 팀플을 진행했던게 고맙지만 미안한 마음이 더 큰 스트레스로 남아서 그렇게 선택을 했는데...
지나고 보니 그런 경험하는게 많이 있을 일은 아닌데 내가 너무 겁먹었구나 생각이 들긴합니다. </p>
<h2 id="3학기-2409--2410">3학기 (24.09 ~ 24.10)</h2>
<p>3학기 때부턴 난이도가 급격히 증가합니다. 
DirectX 3D로 엔진이 바뀌고, 게임수학 대신 쉐이더 프로그래밍, 거기에 시스템 프로그래밍까지 겹치니 저는 그만 정신을 잃고 말았습니다. 
그때부터 저는 여기서 공부를 하는게 저 스스로에게는 효율이 떨어지는 일이라고 생각이 들기 시작했습니다. 
그래서 게임 회사에 무작정 지원서를 넣고 어디든 가야겠다는 마인드로 불안에 떨고 있었습니다. 
이러면 안되지만... 수업 때는 원서와 자소서를 계속 작성하느라 초반부터 거의 다 놓쳤던 것 같네요. 
그러다 프로그래머는 아니지만, QA 직무로 서류가 합격했던 머기업이 있어서 여기서 일하다 가능하면 직무 이동을 생각해보자.. 라고 엄청 기대를 크게 가졌었습니다. 
그러나 세상은 호락호락하지 않네요. 
사실 너무 안일하게 생각한게 컸습니다. 
모든 질문에 멍충하게 대답을 하고 나서 당연히 떨어졌습니다.:) 데헷
신입을 뽑는다는 대부분의 공고에서 연락이 오지 않으면서 저는 레전드 멘붕에 빠집니다. 
이 상황을 이전에 인턴을 했던 회사 동료 분께 말씀드렸더니 6개월 정도 계약직으로 있을 생각이 없냐는 얘기를 하셨고 어떻게 보면 도망치듯 수락하고 인재원을 나온 것 같네요.
갑작스럽게 결정된 거라 저도 아쉽고 친구들과 같이 공부를 못한다는 사실이 조금 슬프게 느껴졌습니다. 
오래 붙어있다보니 확실히 정이 들어요. ㅇㅅㅇ
하지만 일단 저는 제 상황에서 최선의 선택을 했다고 생각합니다. 
이 회사에서 6개월 간 일하면서 상반기 공채를 노려볼까해요. 
새삼 회고 쓰면서 또 열심히 공부해야겠다는 생각이 드네요.</p>
<p>니 얘기 안궁이고 그냥 인재원 어떤지 세줄 요약해달라구요? 알겠습니다.</p>
<ol>
<li>비전공자 및 무경험자는 정말 열심히 하세요. 이미 잘하는 친구들 많아서 나중에 더 차이나요. </li>
<li>무료로 배우는데 이런 시설에서 이런 퀄리티 수업 받기 힘들다고 생각합니다. 제대로 배우고 싶은데 국비지원이랑 고민이시면 전 인재원 추천드립니다.</li>
<li>개인적인 생각으로 인재원은 대학보다 고등학교 느낌이 강합니다. 전국에서 다양한 성격에 다양한 연령층이 모이지만 다 같은 마음으로 배우러 온 학생들이니까 반 학생들과 잘 지냈으면 좋겠습니다. 평균 연령 20대 중반-후반인데 본인이 잘 행동하면 아무도 배척하지 않아요. 뭐... 당연한 얘기죠? 왜 이야기 하는지는... 여기까지 하겠습니다. </li>
</ol>
<p>아무튼 저는 게임개발을 포기한 게 아니구요. 
현재 게임 개발 동아리도 활동 중이고 혼자 다시 부족한 부분 채우는 시간을 갖고 있습니다.
앞으로 열심히 해서 그때 면접 본 그 회사 문 뿌시고 들어갈 수 있길 빌어주세요. 낄낄
그러니까 발로란트 좀 그만하자... 발로조아 발로재밌어 오늘 네오프런티어 떴어... 
암튼 끗</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[STL로 C++ 레디언트 가즈아]]></title>
            <link>https://velog.io/@invisible_thorn/STL%EB%A1%9C-C-%EB%A0%88%EB%94%94%EC%96%B8%ED%8A%B8-%EA%B0%80%EC%A6%88%EC%95%84-xsq4g93e</link>
            <guid>https://velog.io/@invisible_thorn/STL%EB%A1%9C-C-%EB%A0%88%EB%94%94%EC%96%B8%ED%8A%B8-%EA%B0%80%EC%A6%88%EC%95%84-xsq4g93e</guid>
            <pubDate>Thu, 31 Oct 2024 05:50:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>[출처 / 모두의 코드] <a href="https://modoocode.com/174">https://modoocode.com/174</a></p>
</blockquote>
<p>아이스박스는 사이퍼를 주로하는 저에게 가장 별로인 맵인데요,
그만큼 이해도가 낮은 맵이기도 합니다.
근데 이럴수가 STL 컨테이너에 대한 이해도도 낮은 거예요(깜짝)
그래서 STL 컨테이너를 공부하는 겸사겸사, 아이스박스 컨테이너도 흘겨보자해서 포스팅해봅니다.</p>
<p>절대 공부하기 싫어서 핑계로 맵을 외우려는 판단? 그런거 맞습니다.
아박에서 킬조이 연습해야지 히히</p>
<p>우선 C++ 스킬부터 레디언트 보내야하니, STL 컨테이너 먼저 알아보겠습니다.
다양한 컨테이너가 있지만, 제가 이전까지 코드를 짜면서 가장 많이 보였던 <strong>vector, list, map</strong>을 살펴보도록 할 겁니다.</p>
<h3 id="vector동적-배열">vector(동적 배열)</h3>
<blockquote>
<p>[출처]  <a href="https://hwan-shell.tistory.com/119">https://hwan-shell.tistory.com/119</a></p>
</blockquote>
<p>vector 생성 시 heap에 동적 할당됩니다.
array 배열과 비교했을 때 성능이 떨어지지만 메모리 효율이 좋고 예외처리가 좋다는 장점이 있습니다.</p>
<p>오늘 썼던 코드를 예시로 가져오자면,</p>
<pre><code class="language-cpp">
    vector&lt;string&gt; numWords = {
        &quot;zero&quot;, &quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;,
        &quot;five&quot;, &quot;six&quot;, &quot;seven&quot;, &quot;eight&quot;, &quot;nine&quot;
    };</code></pre>
<p>특정 자료형을 벡터에 담아서</p>
<pre><code class="language-cpp">    for (size_t j = 0; j &lt; numWords.size(); j++)
    {
        // 현재 인덱스에서 영단어가 일치하는지 확인
        if (numWords[j] == s.substr(i, numWords[j].length()))
        {
            numStr += to_string(j);
            i += numWords[j].length(); // 인덱스 이동
            break;
        }
    }</code></pre>
<p>벡터의 사이즈만큼 순회를 도는 구문이었슴니다.</p>
<p>벡터에 대하 할말 개많긴한데 앞으로 코테 계속 풀면서 추가하는게 좋을 것 같습니다.
중요한 것은 벡터는 <strong>가변 길이의 배열</strong>이라는 점!</p>
<h3 id="list링크드-리스트">List(링크드 리스트)</h3>
<blockquote>
<p>[출처] <a href="https://blockdmask.tistory.com/76">https://blockdmask.tistory.com/76</a></p>
</blockquote>
<p>vector와 같이 시퀀스 컨테이너(순서를 유지하는 구조를 가짐)의 하나로 더블 링크드 리스트와 구조가 같습니다.
처음에 인재원에서 시험 보고 후드려 맞은 기억이 아주 잘나는 자료구조이다...ㅋ
vector와는 다르게 노드를 기반으로한 컨테이너로 원소 탐색에 있어서도 다르게 접근해야합니당
예를들면, 중간 노드를 임의로 삭제할 수 없고 양옆 노드를 특정함수를 사용하여 삽입, 삭제하는 방식으로 수정할 수 있습니다.(아닌가)</p>
<p>현재 항해 99에서 하는 1달 챌린지 코테 중인데 앞으로 사용하게 될 때 예시 코드를 다시 가져와보도록 하겠습니다.</p>
<p>아, 여담인데 친구들이 vector가 list를 사용했을 때보다 더 빠르다는 말을 했었는데, 아마 vector는 메모리에 연속적으로 할당되어 있지만 list는 그렇지 않기 때문에 해당 메모리로 찾아가는 시간이 있어 그런 걸 아닐까 생각했던 기억이 나네요.</p>
<h3 id="map연관-컨테이너">map(연관 컨테이너)</h3>
<blockquote>
<p>[출처] <a href="https://life-with-coding.tistory.com/305">https://life-with-coding.tistory.com/305</a></p>
</blockquote>
<p>map역시 노드를 기반으로 한 컨테이너입니다.
근데 이제 key와 value를 곁들인
중복을 허용하지 않는 pair형태로 저장된다고 합니다.</p>
<pre><code class="language-cpp">map&lt;key,value&gt; m;</code></pre>
<p>음.... 직접 코드 짜보면서 추가하기로 합시다... 다시 포인터 봐야지..헤헤..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS님을 아세요? - 5번째]]></title>
            <link>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-%EB%8B%A4%EC%84%AF-%EB%B2%88%EC%A7%B8</link>
            <guid>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-%EB%8B%A4%EC%84%AF-%EB%B2%88%EC%A7%B8</guid>
            <pubDate>Tue, 22 Oct 2024 10:11:26 GMT</pubDate>
            <description><![CDATA[<h2 id="cpu-스케줄링">CPU 스케줄링</h2>
<p>CPU 스케줄링이라는 것에 대해 들어는 봤는데 무엇인지 기억이 안난다.
하나씩 더듬더듬 생각해보자.</p>
<p>모든 프로세스는 실행을 위해 CPU를 필요로 하고 먼저 사용하려고 하는데, 자원은 한정되어 있기 때문에 이 사용에 순서를 정해주어야한다.</p>
<p>이때 운영체제가 프로세스들에게 공정하고 합리적으로 CPU자원을 배분하는 것
이것이 <strong>CPU 스케줄링</strong>이다!</p>
<p>그렇다면 어떤 방식으로 CPU를 먼저 사용하게 하느냐, <strong>우선순위</strong>가 높은 프로세스에게 먼저 할당을 해야한다.
또 그러면 우선순위가 높은 프로세스는 어떻게 정해주느냐,
그거슨 빨리처리해야하는 프로세스를 의미한다고 한다.
예를 들면 입출력 작업이 많은 프로세스가 있는데 이것이 왜 효율적인지를 알려면 프로세스가 어떤 과정을 거치며 실행되는지 알아야한다.</p>
<p>프로세스마다 CPU와 입출력장치를 이용하는 시간이 다르겠죠?
비디오 재생 등 입출력 작업이 많은 프로세스를 <strong>입출력 집중 프로세스</strong>라고 하고,
복잡한 수학연산, 컴파일 등 cpu 작업이 많은 프로세스를 <strong>CPU 집중 프로세스</strong>라고 한다.</p>
<p>더 많이 머물러 있는 상태는,
입출력 집중 프로세스  -&gt; 실행 상태 &lt; <strong>대기 상태</strong>
CPU 집중 프로세스       -&gt; <strong>실행 상태</strong> &gt; 대기 상태
가 된다.</p>
<p>입출력 버스트(실행)에서는 CPU를 많이 사용하지 않기 때문에 빠르게 사용하고 대기상태로 넘겨
CPU 버스트가 되게 만든다고 하는데... 음 정확히 무슨 의미인지는 계속 읽어봐야겠다.</p>
<p>운영체제가 PCB에 순서를 명시해주는데 당연히 우선순위가 높은 프로세스가 많이, 빨리 실행된다.
그렇지만 해당 프로세스를 찾기위해 PCB를 일일이 찾아다니는 건 비효율적이므로 프로세스들을 줄세우는 <strong>스케줄링 큐</strong>를 구현하고 관리한다.</p>
<p>이걸 토대로 앞서 봤던 프로세스 상태 다이어그램을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/9ddb3e08-ba24-4ffd-aa0e-04c4fe4dd726/image.png" alt=""></p>
<p>따단
준비 큐, 대기 큐에 프로세스들이 들어가 순차적으로 실행된다.</p>
<p>그런데 평화로운 이 상황에 CPU를 아주 급하게 써야하는 프로세스가 등장했다고 생각해보자.
선택은 두 가지</p>
<ol>
<li>냉큼 지금 CPU를 사용하고 있는 프로세스에게서 빼앗아서 준다.</li>
<li>실행되고 있는 프로세스가 끝날 때까지 기다리는다.</li>
</ol>
<p>첫 번째 선택은 <strong>선점형 스케줄링</strong>이다.
프로세스마다 정해진 시간만큼 자원을 사용하고 정해진 시간이 지나 타이머 인터럽트가 발생하면 이를 뺏어 다음 프로세스에 할당하는 방식 역시 선점형 스케줄링이다.</p>
<p>두 번째 선택은 <strong>비선점형 스케줄링</strong>이다.
하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되고나 스스로 대기상태에 들어가기 전까지는 다른 프로세스가 끼어들 수 없다. 자원 사용을 독점할 수 있다는 것이다. wow</p>
<p>각각의 장단이 있는데,
선점형 스케줄링은 Context Switching 과정에서 오버헤드가 발생할 문제점이 있다.
문맥교환, 오버헤드는 정확히 뭔지에 대해서는 우리 발표자가 설명해주겠지? 히히</p>
<p>그리고 <strong>스케줄링 알고리즘</strong>에는 일곱가지가 있는데 하나씩 알아보자</p>
<h2 id="스케줄링-알고리즘">스케줄링 알고리즘</h2>
<h3 id="선입-선처리-스케줄링fcfs-스케줄링">선입 선처리 스케줄링(FCFS 스케줄링)</h3>
<p>: 단순히 큐에 삽입된 순서대로 프로세스를 처리하는 비선점형 스케줄링 방식
  공정해보이지만 아주 적은 시간의 CPU를 사용해야하는 프로세스가 너무 오래 대기하는 문제 발생
  -&gt; 호위 효과라고 함</p>
<h3 id="최단-작업-우선-스케줄링sjf-스케줄링">최단 작업 우선 스케줄링(SJF 스케줄링)</h3>
<p>: 호위 효과를 방지하기 위해서는 위의 문제를 바로 해결해줄 수 있다.
 CPU 사용시간이 짧은 프로세스 부터 먼저 실행해주는 것이다.
 (비전섬형 스케줄링)</p>
<h3 id="라운드-로빈-스케줄링">라운드 로빈 스케줄링</h3>
<p>: 선입 선처리 스케줄링 + <strong>타임 슬라이스</strong>
 타임 슬라이스는 프로세스가 CPU 사용 시간이 정해져 있는 것을 말한다.
 (선점형 스케줄링)</p>
<h3 id="최소-잔여-시간-우선-스케줄링srt-스케줄링">최소 잔여 시간 우선 스케줄링(SRT 스케줄링)</h3>
<p>: 최단 작업 우선 스케줄링 + 라운드 로빈
 정해진 타임 슬라이스만큼 CPU를 사용하지만, CPU를 사용할 다음 프로세스는 남아있는 시간이 가장 적은 프로세스가 선택된다.</p>
<h3 id="우선순위-스케줄링">우선순위 스케줄링</h3>
<p>: 우선순위가 높은 것부터 실행, 우선 순위가 낮은 프로세스들은 게속해서 연기될 수 있는 <strong>기아</strong>현상 발생
이를 방지하기 위해 오랫동안 대기한 프로세스의 우선순위를 점차 높이는 <strong>에이징</strong> 기법을 사용</p>
<h3 id="다단계-큐-스케줄링">다단계 큐 스케줄링</h3>
<p>: 우선순위별로 준비 큐를 여러 개 사용하는 스케줄링 방식</p>
<h3 id="다단계-피드백-큐-스케줄링">다단계 피드백 큐 스케줄링</h3>
<p>: 다단계 큐 + 프로세스들이 큐 사이를 이동할 수 있음
 -&gt; 얘 너무 복잡한데 발표자가 잘 설명좀 ㅎㅎ</p>
<p> 대충 이런 알고리즘들을 띄고 있다 ㅇㅅㅇ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS님을 아세요? - 4번째]]></title>
            <link>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-4%EB%B2%88%EC%A7%B8</link>
            <guid>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-4%EB%B2%88%EC%A7%B8</guid>
            <pubDate>Fri, 11 Oct 2024 08:35:06 GMT</pubDate>
            <description><![CDATA[<p>우선 컴퓨터의 구조를 먼저 알아보자.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/f4302cbf-551e-4004-afa8-eccf2ad49d8e/image.png" alt=""></p>
<p><strong>데이터</strong>는 컴퓨터가 이해하는 숫자, 문자, 이미지, 동영상과 같은 정적인 정보를 가리키고,
<strong>명령어</strong>는 데이터를 움직이고 컴퓨터를 작동시키는 정보이다.</p>
<p>그러니까 명령어는 컴퓨터를 작동시키는 정보이고, 데이터는 명령어를 위해 존재하는 재료라고 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/0103b9e8-cec8-45ef-9ebd-b34abb1a2d59/image.png" alt=""></p>
<p>* 주기억장치에는 RAM과 ROM이 있는데 메모리는 보통 RAM을 가리킨다.</p>
<p>이 네 가지 핵심부품을 시각화해보자.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/83fb016f-b3c6-4df6-902f-11229a664451/image.png" alt=""></p>
<p>하나씩 살펴봅시다요.</p>
<h2 id="메모리">메모리</h2>
<p>보통 RAM을 가리킨다.
현재 실행되는 프로그램의 명령어와 데이터를 저장하는 부품
따라서 프로그램이 실행되려면 반드시 메모리에 저장되어 있어야 한다.</p>
<p>메모리에 저장된 명령어와 데이터의 위치는 정돈되어 있어야 하기 때문에,
<strong>주소</strong>라는 개념을 사용한다.
이 주소를 통해 메모리 내 원하는 위치에 접근할 수 있다.</p>
<h2 id="cpu">CPU</h2>
<p>메모리에 저장된 명령어를 읽고 이를 해석하고 실행하는 부품이다.
이 내부에는 또 여러 가지 구성 요소가 있는데,
<strong>산술논리연산장치(ALU), 레지스터, 제어장치</strong>가 가장 중요하다.</p>
<h3 id="alu">ALU</h3>
<p>계산기와 같다. 컴퓨터 내부 대부분의 연산을 수행한다.</p>
<h3 id="레지스터">레지스터</h3>
<p>CPU 내부의 작은 임시 저장 장치이다. 프로그램을 실행하는데 필요한 값을 <strong>임시로</strong> 저장한다.
CPU 안에는 여러 개의 레지스터가 있고 각기 다른 이름과 역할을 가지고 있다.</p>
<h3 id="제어장치">제어장치</h3>
<p><strong>제어 신호</strong>라는 전기 신호를 내보내고 명령어를 해석하는 장치이다.
<strong>제어 신호</strong>는 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호이다.</p>
<ul>
<li>CPU가 메모리에 저장된 값을 읽고 싶으면 메모리에 <strong>메모리 읽기</strong>라는 신호를 보냄</li>
<li>CPU가 메모리에 어떤 값을 저장하고 싶으면 메모리에 <strong>메모리 쓰기</strong>라는 신호를 보냄</li>
</ul>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/b6393145-abb7-48ba-a67b-c65a99870def/image.png" alt=""></p>
<h2 id="보조기억장치">보조기억장치</h2>
<p>메모리는 실행되는 프로그램의 명령어와 데이터를 저장하지만, 가격이 비싸 저장 용량이 적고 전원이 꺼지면 저장된 내용을 잃는다는 단점이 있다.</p>
<p>하드 디스크, SSD, USB메모리 등.. 저장 장치가 보조기억장치의 일종이다.
컴퓨터의 전원이 꺼져도 컴퓨터에 파일이 남아있는 이유가 이것!</p>
<h2 id="입출력장치">입출력장치</h2>
<p>우리가 생각하는 그거티비
마이크, 스피커, 프린터, 키보드 등등</p>
<h2 id="메인보드">메인보드</h2>
<p>앞서 언급한 핵심 부품들은 모두 <strong>메인보드</strong>에 연결된다.
메인보드에 연결된 부품들은 서로 정보를 주고 받을 수 있는데, 메인보드 내부에 <strong>버스</strong>라는 통로가 있기 때문이다. 다양한 종류의 통로(버스)가 있지만 제일 중요한 버스는 <strong>시스템 버스</strong>이다.
시스템 버스는 <strong>주소버스, 데이터 버스, 제어버스</strong>로 나뉜다.</p>
<p>이렇게 핵심 부품들을 알아보았는데 그중에서 더 알아볼 부분은 <strong>레지스터</strong>에 대해 정리해보겠따.
그리고 그와 비슷한 역할을 하는 <strong>캐시</strong>도 함께 알아보자.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/cf3d2fea-2053-4557-8c19-e161222062cb/image.png" alt=""></p>
<p>메모리의 계층 구조는 이렇게 되어 있다.
보이다 싶이 위로 올라갈수록 비싸고, 빠르고, 작고, CPU와 근접해있다.</p>
<p>그럼 둘을 비교 요약해보자.</p>
<table>
<thead>
<tr>
<th><strong>특성</strong></th>
<th><strong>레지스터(Register)</strong></th>
<th><strong>캐시(Cache)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>위치</strong></td>
<td>CPU 내부</td>
<td>CPU 내부 또는 가까운 위치</td>
</tr>
<tr>
<td><strong>속도</strong></td>
<td>가장 빠름</td>
<td>레지스터보다는 느리지만 메모리보다 빠름</td>
</tr>
<tr>
<td><strong>용량</strong></td>
<td>매우 작음 (몇 바이트)</td>
<td>상대적으로 큼 (수십 KB ~ 수 MB)</td>
</tr>
<tr>
<td><strong>주요 역할</strong></td>
<td>CPU 연산에 필요한 데이터 저장</td>
<td>자주 사용되는 데이터나 명령어 저장</td>
</tr>
<tr>
<td><strong>제어</strong></td>
<td>하드웨어에서 직접 제어</td>
<td>CPU와 하드웨어가 자동으로 관리</td>
</tr>
</tbody></table>
<p>+
L1 캐시: CPU 코어 내부에 위치하며, 가장 빠르고 가장 작은 캐시
L2 캐시: L1 캐시보다는 약간 더 느리고 크기가 크며, 여전히 CPU에 매우 가깝다.
L3 캐시: 여러 코어가 공유하는 캐시로, L1, L2 캐시보다 크지만 속도는 더 느리다.</p>
<p>레지스터는 보통 어떠한 연산을 할 때 값을 저장하는 용도로 사용하고,
캐시는 반복되는 데이터를 저장해서 CPU에게 전달하는 용도로 사용되는 것 같다.</p>
<p>어제 스터디에서 스터디원이 <strong>캐시</strong>에 대해 더욱 자세히 설명해줬다.
정리를 더 해보좌</p>
<blockquote>
<p>참고는 여기서 <a href="https://taku7664.tistory.com/">https://taku7664.tistory.com/</a></p>
</blockquote>
<p>우선 캐시를 사용함으로써 얻을 수 있는 이점이 무엇이냐,
매우매우 중요하다.</p>
<p><strong>자주 사용되는 데이터나 명령어를 저장하여 메인 메모리와의 접근 시간을 줄임으로써 병목현상을 낮춰준다고 한다.</strong> WOW</p>
<p>자주 사용되는 데이터가 캐시에 저장되어있으면 CPU가 메모리에 접근할 필요가 없어지기 때문이겠죠?
실제로 CPU에서 데이터가 개빠르게 들어오는데 RAM은 그만큼의 속도처리가 안되기 때문에 딜레이가 걸리고 느려지는 거랍니당</p>
<p>캐시가 어떤 식으로 쓰이는 지 알려면
<strong>캐시 미스</strong>와 <strong>캐시 히트</strong> 개념을 알아야합니다만</p>
<p><strong>캐시 미스(캐시에 데이터 없음)</strong> 발생 시는 캐시에 데이터가 없어 CPU가 RAM에 접근하여 데이터를 가져와 캐시에 저장하여 연산을 수행하고,
<strong>캐시 히트(캐시에 데이터 있음)</strong> 발생 시엔 RAM에 접근하지 않고 캐시에서 바로 데이터를 가져와 사용함니다.</p>
<p>당연히 캐시 히트율(적중률)을 높여야 좋겠져? 생각만 해도 성능 향상이 될 것 같고 도키도키 합니다.</p>
<p>나머지 캐시에 대한 내용은 위 블로그에 잘 기술 되어있으니 확인해보세용</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백트래킹 구조를 쉽게 구현하려면]]></title>
            <link>https://velog.io/@invisible_thorn/%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%89%BD%EA%B2%8C-%EA%B5%AC%ED%98%84%ED%95%98%EB%A0%A4%EB%A9%B4</link>
            <guid>https://velog.io/@invisible_thorn/%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%89%BD%EA%B2%8C-%EA%B5%AC%ED%98%84%ED%95%98%EB%A0%A4%EB%A9%B4</guid>
            <pubDate>Tue, 08 Oct 2024 06:00:38 GMT</pubDate>
            <description><![CDATA[<p>보통 BFS(너비우선탐색)과 비교되어 나오는 DFS에 대해 알아보자.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/b3167b26-ab2f-476e-bc85-5f8c87d1468b/image.png" alt=""></p>
<p>특징은 이렇다고 말하는데 사실 나는 이런 모든 개념들이 완벽하게 와닿지는 않는 것 같다.</p>
<p>어떤 식으로 정점을 방문하고 탐색하는지 그림으로 생각해보면,</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/db84b9f3-6110-46c7-8d5b-606b33a53410/image.gif" alt=""></p>
<blockquote>
<p>출처 <a href="https://ko.wikipedia.org/wiki/%EA%B9%8A%EC%9D%B4_%EC%9A%B0%EC%84%A0_%ED%83%90%EC%83%89">https://ko.wikipedia.org/wiki/%EA%B9%8A%EC%9D%B4_%EC%9A%B0%EC%84%A0_%ED%83%90%EC%83%89</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS님을 아세요? - 3번째]]></title>
            <link>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-3%EB%B2%88%EC%A7%B8-esthw826</link>
            <guid>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-3%EB%B2%88%EC%A7%B8-esthw826</guid>
            <pubDate>Mon, 07 Oct 2024 07:59:27 GMT</pubDate>
            <description><![CDATA[<p>드디어 스레드 스레드란 무엇일까?</p>
<h2 id="스레드란">스레드란?</h2>
<p>스레드란 프로세스를 구성하는 실행의 흐름 단위이다.
하나의 프로세스는 여러 개의 스레드를 가질 수 있다.
스레드를 이용하면 하나의 프로세스에서 여러 부분을 동시에 실행할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/b5316241-9b02-4b94-b469-f31134fe582d/image.png" alt=""></p>
<p>요렇게 여러 스레드가 하나의 프로세스에서 동시에 실행됨</p>
<h2 id="프로세스와-스레드는-무슨-관계">프로세스와 스레드는 무슨 관계?</h2>
<p>우선 위에 언급한 내용과 다르게 전통적 관점에서는 프로세스가 한 번에 하나의 일만 해왔다.
이를 <strong>단일 스레드 프로세스</strong>라고 한다.</p>
<p>이후 하나의 프로세스가 한 번에 여러 일을 동시에 처리할 수 있게 되면서 여러 명령어를 동시에 실행할 수 있게 되었다.
이를 <strong>멀티 스레드 프로세스</strong>라고 한다.</p>
<p>스레드의 구성 요소를 확인해보자.
스레드는 프로세스 내에서 각기 다른 <strong>스레드 ID, 프로그램 카운터 값을 비롯한 레지스터 값, 스택</strong>으로 구성된다.
따라서 스레드마다 각기 다른 코드를 실행할 수 있는 것이다.</p>
<p>프로세스의 스레드들은 실행에 필요한 최소한의 정보(스레드 ID를 뺀 정보)만을 유지한 채 프로세스 자원을 공유하며 실행된다.</p>
<h2 id="자-이제-멀티-프로세스와-멀티-스레드">자 이제 멀티 프로세스와 멀티 스레드</h2>
<p>1 프로세스 - 여러 스레드
여러 프로세스 - 더 여러 프로세스
이거 아님? ㅋ</p>
<p>여러 프로세스를 동시에 실행하는 것을 <strong>멀티 프로세스</strong>라고 하고,
여러 스레드로 프로세스를 동시에 실행하는 것을 <strong>멀티 스레드</strong>라고 한다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/f141b199-f948-42ff-a258-f50d13b664f5/image.png" alt="">
여러 프로세르를 실행하는 것 vs 여러 스레드를 실행하는 것</p>
<p>프로세스끼리는 기본적으로 자원을 공유하지 않지만 스레드끼리는 같은 프로세스 내의 자원을 공유한다.
그니까 프로세스는 fork작업이 일어나면 자원이 복사되어 메모리에 적재된다.</p>
<p>반면, 스레드는 각기 다른 값을 가질 뿐 프로세스 내부의 자원을 공유하므로
<strong>여러 프로세스를 병행 실행하는 것보다 메모리를 더 효율적으로 사용할 수 있다.</strong>
또한 <strong>스레드는 서로 협력과 통신에 유리하다.</strong></p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/6cc72870-4795-476b-9310-fdcb4c482045/image.png" alt=""></p>
<p>이 그림을 보면 조금은 이해가 될랑가</p>
<p>물론 자원을 공유하기 때문에 문제가 생기는 경우도 있다.
자원이 잘못되면 그 자원을 공유받은 모든 스레드가 문제가 생긴다는... 그런 거 하지만 편리했죠?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS님을 아세요? - 2번째]]></title>
            <link>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-2%EB%B2%88%EC%A7%B8-kh0almdv</link>
            <guid>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-2%EB%B2%88%EC%A7%B8-kh0almdv</guid>
            <pubDate>Sun, 06 Oct 2024 08:43:54 GMT</pubDate>
            <description><![CDATA[<h2 id="프로세스가-뭐냐면">프로세스가 뭐냐면</h2>
<p>프로그램이 실행되기 전 : 보조기억장치에 있는 데이터 덩어리
프로그램이 실행된 후 : 프로그램 -&gt; 프로세스 (wow)</p>
<p>프로세스는 프로그램을 보조기억장치에 저장된 프로그램을 메모리에 적재하고 실행하는 순간! 생성된다.</p>
<h3 id="포그라운드-프로세스-vs-백그라운드-프로세스">포그라운드 프로세스 VS 백그라운드 프로세스</h3>
<p>작업 관리자처럼 우리가 볼 수 있는 공간에서 실행되는 프로세스인 <strong>포그라운드 프로세스</strong>가 있고, ps? 명령어? 라는 우리가 볼 수 없는 뒤편에서 실행되는 프로세스인 <strong>백그라운드 프로세스</strong>가 있다.</p>
<p>근데 또 여기서 사용자와 직접 상호작용이 가능한 <strong>백그라운드 프로세스</strong>가 있고, 아닌 것도 있다.
아닌 백그라운드 프로세스를 윈도우 운영체제에서는 <strong>서비스</strong>라고 부른다고 한다.</p>
<h2 id="프로세스-제어-블록pcb은">프로세스 제어 블록(PCB)은?</h2>
<p>특정한 프로세스를 관리할 필요가 있는 정보를 포함하는, 운영체제 커널의 자료구조이다.
PCB는 운영 체제가 프로세스를 표현한 것이라 할 수 있다.</p>
<p>모든 프로세스가 실행을 위해 CPU를 사용해야하지만 그 자원이 한정 되어있기 때문에 프로세스들은 차례로 돌아가며 제한된 시간만큼 이용한다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/9ef6e53a-79bf-4cc9-922a-d772d3905750/image.png" alt=""></p>
<p>타이머 인터럽트가 발생할 때마다 위 과정을 반복한다.</p>
<p>프로세스의 실행 순서를 관리하고 자원을 배분하기 위해 <strong>프로세스 제어 블록</strong>을 이용한다.</p>
<p>이 친구는 프로세스와 관련된 정보를 저장하는 자료구조로, 해당 프로세스를 식별하기 위해 꼭 필요한 정보들이 저장된다.(그리고 얘도 커널 영역에 생성됨)
또한 프로세스 생성 시 만들어지고 실행이 끝나면 폐기된다.</p>
<p>* 새로운 프로세스 생성 = 운영체제가 PCB 생성
* 프로세스 종료 = 운영체제가 PCB 폐기</p>
<p>라고 생각하면 된다.</p>
<p>PCB 안에는 굉장히 많은 정보가 들어간다 ㄷㄷ
프로세스 ID, 레지스터 값, 프로세스 상태, CPU 스케줄링 정보, 메모리 정보 관리, 사용한 파일과 입출력장치 목록 등...</p>
<h2 id="문맥-교환">문맥 교환?</h2>
<p>내가 아는 문맥은 수능 국어 볼 때나 썼던 말인 거 같은데 여기서 나오네 신기방기
Context Switching이라고도 하는 듯 ㅇㅇ</p>
<p>PCB에서 프로세스를 관리하며 타이머 인터럽트가 발생했을 때, 그동안 실행했던 내용들을 백업을 해둬야 다시 차례가 왔을 때 실행을 재개할 수 있겠죠?</p>
<p>이러한 하나의 프로세스 수행을 다시 시작하기 위해 기억해야할 정보를 <strong>문맥</strong>이라고 부른답니다.(PCB에 저장되는 정보들이라고 봐도 됨)</p>
<p><strong>문맥 교환</strong>은 여러 프로세스가 끊임없이 빠르게 번갈아가며 실행되는 원리이기에, 자주 일어나면 우리 눈에는 프로세스가 동시에 실행되는 것처럼 보인다고 한다.</p>
<h2 id="프로세스의-메모리-영역">프로세스의 메모리 영역</h2>
<p>프로세스 생성 시 <em>커널 영역</em>에 PCB가 생성된다.
그렇다면 <em>사용자 영역</em>은 어떨까?</p>
<p>메모리에 크게 <strong>stack, heap, data, code</strong> 영역으로 나뉘어 저장된다.
많이들 아는 내용일테지만 확실하게 다시 정리를 해보자.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/cf2ea9b4-4f98-4595-8d90-dcbe354af6b8/image.png" alt=""></p>
<h3 id="코드-영역">코드 영역</h3>
<p>텍스트 영역이라고도 한다.
데이터가 아닌 CPU가 실행할 기계어로 이루어진 명령어가 저장되므로 쓰기가 금지 되어있다.(읽기 전용 공간임)</p>
<h3 id="데이터-영역">데이터 영역</h3>
<p>잠깐 썼다 없앨 데이터가 아니고!
프로그램이 실행되는 동안 유지할 데이터가 저장되는 영역이다.
<strong>전역 변수</strong>가 대표적임</p>
<p>코드 영역과 데이터 영역은 크기가 변하지 않는다.
그래서 코드, 데이터 영역은 <strong>정적 할당</strong> 영역
힙, 스택 영역은 <strong>동적 할당</strong> 영역이라고 부른다
근데 이제 우리가 생각한 정적 할당과 동적 할당과는 다른...</p>
<h3 id="힙-영역">힙 영역</h3>
<p>프로그램을 만드는 사용자가 직접 할당할 수 있는 저장 공간이다.
여기서는 직접 할당을 했기 때문에 언젠가 메모리 공간을 반환해야한다.
그렇지 않으면 할당된 공간이 메모리 내에 계속 남아 메모리 낭비(메모리 누수)를 초래한다. 꼭 해제해주세요</p>
<h3 id="스택-영역">스택 영역</h3>
<p>데이터를 일시적으로 저장하는 공간으로, 데이터 영역에 담기는 값과는 달리 잠깐 쓰다 말 값이 저장되는 공간이다.
보통 <strong>함수의 실행이 끝나면</strong> 사라지는 <strong>매개 변수, 지역 변수</strong>가 대표적이다.</p>
<p>이렇게 나뉘는 이유는 최대한 데이터를 공유하여 메모리 사용량을 줄여야하기 때문이다.</p>
<h2 id="프로세스-상태와-계층-구조">프로세스 상태와 계층 구조</h2>
<p>프로세스도 부모 자식 관계를 가진다고 합니다.
이게 무슨 소리인지 자세히 알아봅시다.</p>
<h3 id="프로세스-상태라는-것은">프로세스 상태라는 것은?</h3>
<p>운영체제가 프로세스의 상태를 PCB를 통해 인식하고 관리한다.
앞 전에 PCB에 들어간 정보 중에 프로세스 상태라는 게 있었지?</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/a8f62734-2c5c-43de-869d-636e97733626/image.png" alt=""></p>
<p>나야, <strong>프로세스 상태 다이어그램</strong></p>
<p>생성 상태(new): 프로세스를 생성 중인 상태, 준비된 프로세스는 바로 실행이 아니라 <strong>준비 상태</strong>가 되어 CPU 호출 기다림 
준비 상태(ready): 차례가 되지 않아 기다리는 상태, 차례가 되면 CPU를 할당받아 <strong>실행 상태</strong>가 됨 
실행 상태(running): CPU 할당 받고 실행 중인 상태, 할당된 모든 시간 사용 -&gt; <strong>준비 상태</strong>, 입출력장치 작업 끝까지 기다림 -&gt; <strong>대기 상태</strong>
대기 상태(blocked): 입출력장치의 작업을 기다리는 상태, 작업완료 -&gt; <strong>준비 상태</strong>
종료 상태(terminated): 프로세스가 종료된 상태, 운영체제는 PCB와 프로세스가 사용한 메모리를 정리</p>
<h3 id="프로세스-계층-구조">프로세스 계층 구조</h3>
<p>프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있다.
이 때 새 프로세스를 생성한 프로세스를 <strong>부모 프로세스</strong>, 이에 의해 생성된 프로세스를 <strong>자식 프로세스</strong>라고 한다.
(계속해서 트리구조로 나아감)</p>
<h3 id="프로세스-생성-기법">프로세스 생성 기법</h3>
<p>부모 프로세스는 <strong>fork</strong>를 통해 자신의 복사본을 자식 프로세스로 생성하고, 만들어진 복사본(자식 프로세스)는 <strong>exec</strong>를 통해 자신의 메모리 공간을 다른 프로그램으로 교체 한다.</p>
<p>프로세스는 대충 이러한 개념들을... 갖고 있고 이제 곧 스레드에 대해 알아보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS님을 아세요? - 1번째]]></title>
            <link>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-1%EB%B2%88%EC%A7%B8</link>
            <guid>https://velog.io/@invisible_thorn/CS%EB%8B%98%EC%9D%84-%EC%95%84%EC%84%B8%EC%9A%94-1%EB%B2%88%EC%A7%B8</guid>
            <pubDate>Mon, 30 Sep 2024 05:59:08 GMT</pubDate>
            <description><![CDATA[<h2 id="운영체제란-무엇인가">운영체제란 무엇인가?</h2>
<p>우선 우리는 운영체제가 무엇인지부터 정의를 해야합니다.
운영체제란 무엇인가하면,
Operation System의 약자 OS라고도 부르며 말그대로 컴퓨터 전반적인 부분을 운영하는 &#39;시스템 소프트웨어&#39;이다.</p>
<blockquote>
<p><a href="https://www.itbankcyber.com/lcms/1411/contents/01/20811411_%EA%B0%95%EC%9D%98%EB%85%B8%ED%8A%B8_0101.pdf">https://www.itbankcyber.com/lcms/1411/contents/01/20811411_%EA%B0%95%EC%9D%98%EB%85%B8%ED%8A%B8_0101.pdf</a> 참고</p>
</blockquote>
<p><strong>우선 컴퓨터의 전반적인 구조는 이렇다</strong>
<img src="https://velog.velcdn.com/images/invisible_thorn/post/765836b1-46dd-4438-b1f0-8404fbb4a33b/image.png" alt=""></p>
<p>그리고 <strong>소프트웨어</strong>에서
<img src="https://velog.velcdn.com/images/invisible_thorn/post/a7c92478-dc03-4ea0-9c1b-1ee08ab2a8fd/image.png" alt=""></p>
<p>OS는 이렇게 시스템 소프트웨어에 속한다</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/27e3ddbc-44dd-4d7d-92e9-1f9c56a56856/image.png" alt="">
<strong>운영체제</strong>는 컴퓨터 부팅 시 메모리 내 <strong>커널 영역</strong>에 따로 적재되어 실행된다.
(이 부분을 제외한 나머지 영역, 사용자가 이용하는 응용 프로그램이 적재되는 영역은 <strong>사용자 영역</strong>이라고 한다.)</p>
<p>따라서 <strong>운영체제</strong>는 커널 영역에 적재되어 사용자 영역에 적재된 프로그램들에 자원을 할당하고 이들이 올바르게 실행하도록 돕는다. 대충 매우 중요한 역할이라는 거</p>
<p>예를 들면,
<img src="https://velog.velcdn.com/images/invisible_thorn/post/29cc9637-96b4-4896-a77d-bffb133a0675/image.png" alt="">
요런 식으로 운영체제가 응용 프로그램들을 적재해주는 것이다.</p>
<p>또한 응용 프로그램이 실행되려면 CPU가 필요하기 때문에, 하나의 프로그램이 CPU를 독점하지 않도록 하고 동시에 두 개의 프로그램이 하나의 하드웨어를 동시에 사용하지 못하게 막는 역할도 한다.
(프린트 할 때 메모장, 워드 번갈아가면서 출력되지 않즤? 하나 다 끝나고 다음 응용 프로그램이 출력될 거여)</p>
<p>그렇다면 이제 운영체제가 적재되는 공간, 커널에 대해서 알아보좌</p>
<h2 id="커널은-또-무엇인가">커널은 또 무엇인가?</h2>
<p><strong>커널</strong>은 운영체제의 핵심 서비스를 담당하는 부분이다.
그러한 핵심 서비스에는</p>
<ol>
<li>자원에 접근하고 조작하는 기능</li>
<li>프로그램이 올바르고 안전하게 실행되게 하는 기능
..이 있답니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/ace23f90-f356-4d8f-9213-742a78adf961/image.png" alt=""></p>
<p>-- 커널은 운영체제의 핵심부!
그렇다고 커널이 운영체제의 전부냐하면 그건 아니고, <strong>사용자 인터페이스</strong>(윈도우 바탕화면 같은 거)등이 있다.
그리고 그것도 우리가 알고 있는 CLI와 GUI로 나뉜다.</p>
<p>그리고 응용 프로그램이 운영체제에게 어떻게 도움을 받으며 실행되는지를 알아보자.</p>
<h2 id="이중모드-그리고-시스템-호출">이중모드 그리고 시스템 호출</h2>
<p>뭐임? 진짜 처음 들어봄</p>
<p>일단 운영체제는 응용 프로그램이 하드웨어 자원에 직접 접근하는 것을 막고 보호한다. (맘대로 접근하면 자원이 무질서하게 관리될 것임)
오로지 자신을 통해서만 접근하도록! 한다.</p>
<p>따라서 응용 프로그램은 운영체제에 도움을 요청해야하는데, 이때 운영체제가 문지기 하는 게 <strong>이중 모드</strong>이다.
CPU가 명령어를 실행하는 모드를 <strong>사용자 모드</strong>와 <strong>커널 모드</strong>로 구분 하는 방식을 말한다.</p>
<h3 id="사용자-모드-vs-커널-모드">사용자 모드 VS 커널 모드</h3>
<p><strong>사용자 모드</strong>는 운영체제의 서비스를 제공 받을 수 없으며(커널 영역의 코드 실행 못함) 아까 위에서 언급했듯이 하드웨어 자원에 직접 접근이 불가능하다.</p>
<p><strong>커널 모드</strong>는 반대로 운영체제의 서비스를 제공 받을 수 있다.(커널 영역의 코드 실행 가능 ^^!) 또 위에서 말했듯 자원에 접근하여 명령어를 실행할 수 있다.</p>
<p>그러니까, 사용자 모드로 실행되는 프로그램은 자원에 접근하는 운영체제 서비스를 제공받으려면 <strong>[운영체제에 요청 -&gt; 커널 모드 전환]</strong>이 필요하다.
이때의 요청을 <strong>시스템 호출(시스템 콜)</strong>이라고 한다. 아하</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/9a084c2a-3468-41a7-b41f-827fb8cbd764/image.png" alt=""></p>
<p>시스템 호출은 일종의 인터럽트로, <strong>소프트웨어 인터럽트</strong>라고 한다.
(입출력장치에 의해 발생하기도 하지만 특정 명령어에 의해 발생할 때를 일컫음)</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/03bfbe12-07e3-4459-a76c-2ec76a445180/image.png" alt=""></p>
<ol>
<li>운영체제에 서비스를 요청하여 커널 모드로 전환하고</li>
<li>운영체제에서 코드를 실행하여 자원에 접근하여</li>
<li>접근이 끝나면 사용자 모드로 복귀하여 실행됨</li>
</ol>
<p>이 과정을 반복하는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/aa5df97e-6927-48c1-bd72-d44c40bc3b06/image.png" alt=""></p>
<p>그럼 너무 잘 나와있다 그냥 제 블로그 보지말고 혼자공부하는컴퓨터개론 그거 보세요.</p>
<p>위에서 커널을 언급하면서 운영체제가 핵심 서비스를 제공하는 부분이라고 했는데, 이제 그 <strong>핵심 서비스</strong>가 뭔지를 알아보자.</p>
<h2 id="운영체제는-커널-모드에서-핵심-서비스를-제공해">운영체제는 커널 모드에서 핵심 서비스를 제공해</h2>
<p>대표적으로 프로세스 관리, 자원 접근 및 할당, 파일 시스테 관리가 있다.</p>
<h3 id="프로세스">프로세스?</h3>
<p>실행 중인 프로그램을 <strong>프로세스</strong>라고 한다.(윈도우 작업관리자 열어보면 개많음)
프로세스는 레알 개다양해서 운영체제가 잘 관리하고 실행할 수 있어야한다. 이거 다음 블로그에 포스팅 할 거임 ㅇㅇ</p>
<h3 id="자원에-접근하고-할당한다">자원에 접근하고 할당한다</h3>
<p>앞서 계속 얘기한 내용이고, 컴퓨터 4가지 핵심 부품 CPU, 메모리, 보조기억창치, 입출력장치를 어떻게 관리하고 기능하는지는 차차 알아가보자 ㅋ</p>
<h3 id="파일-시스템-관리도-해">파일 시스템 관리도 해</h3>
<p>여러 파일을 묶어 폴더로 관리하는 것조차 운영체제가 서비스 한다는 점~</p>
<p>이번의 키워드, <strong>운영체제</strong>와 그가 적재되는 공간 <strong>커널</strong> 그리고 거기서 무엇을 서비스 하는지 잊지 말고 다음으로 넘어가봅시다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[네모의 꿈 짖밟기]]></title>
            <link>https://velog.io/@invisible_thorn/%EB%84%A4%EB%AA%A8%EC%9D%98-%EA%BF%88-%EC%A7%96%EB%B0%9F%EA%B8%B0</link>
            <guid>https://velog.io/@invisible_thorn/%EB%84%A4%EB%AA%A8%EC%9D%98-%EA%BF%88-%EC%A7%96%EB%B0%9F%EA%B8%B0</guid>
            <pubDate>Fri, 20 Sep 2024 03:06:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/invisible_thorn/post/bbbbe15b-0ea8-45b4-b3f3-1934da89e857/image.gif" alt=""></p>
<p>유니티로 배우는 게임수학 시간에 만든 거
네모 터렛이 적군을 자동 사냥하고 이를 얼마나 버티는 지 타이머로 나타내었다. (a.k.a 네모의 꿈)</p>
<blockquote>
<p>[깃허브] <a href="https://github.com/1thorn1/Unity_Project">https://github.com/1thorn1/Unity_Project</a></p>
</blockquote>
<p>이따가 코드 리뷰도 해야지</p>
]]></description>
        </item>
    </channel>
</rss>