<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>_thist._.log</title>
        <link>https://velog.io/</link>
        <description>하고 싶은 개발을 지향하는 삶을 추구합니다:D</description>
        <lastBuildDate>Tue, 27 May 2025 15:12:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>_thist._.log</title>
            <url>https://velog.velcdn.com/images/_thist_/profile/a310ea4e-4402-4f32-9da7-4c474b663af2/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. _thist._.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_thist_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[ 프로그래밍 기초 ] 매크로 함수 vs 인라인 함수]]></title>
            <link>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%95%A8%EC%88%98-vs-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%95%A8%EC%88%98-vs-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 27 May 2025 15:12:35 GMT</pubDate>
            <description><![CDATA[<p>이번에는 아주 간단하게 <strong>매크로 함수</strong>, <strong>인라인 함수</strong>이 둘의 차이점에 대해서 알아보도록 하겠다.</p>
<h2 id="매크로-함수">매크로 함수</h2>
<p>매크로 함수는 전처리기 단계에서 처리되는 코드이다. 예를 들어 </p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#define SQUARE(x) ((x) * (x))

int main(void) 
{
    std::cout &lt;&lt; SQUARE(5) &lt;&lt; std::endl;
    return 0;
}</code></pre>
<p>위의 코드는 컴파일 전, 전처리 과정을 거치면 다음과 같이 변경된다.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

int main(void) 
{
    std::cout &lt;&lt; ((3) * (3)) &lt;&lt; std::endl;
    return 0;</code></pre>
<p>-&gt; 이처럼 함수의 몸체부분이 함수호출 문장을 완전히 대체했을 경우, <strong>&quot;함수가 인라인화 되었다&quot;</strong>라고 표현한다.</p>
<p>생긴 것은, 함수같지만 실제로는 함수가 아닌 문자열 치환이기 때문에 
우리가 일반적으로 작성하는 함수보다 빠른 속도를 가진다는 이점이 있다. 
하지만, 이에 따라 한계도 분명 존재하는데...</p>
<blockquote>
<p><strong>1. 디버깅이 불편하다. (문자열 치환이기때문에 양날의 검)</strong>
<strong>2. 괄호 누락 등으로 오류 발생 가능성 (한 줄에 다 작성해야 함)</strong>
<strong>3. 복잡한 함수를 정의하는데 한계</strong></p>
</blockquote>
<p>이에, 복잡하고 정의하기 까다로운 매크로 함수 대신, 일반 함수처럼 정의가 가능한 inline함수가 C++에 존재한다.</p>
<h2 id="인라인-함수">인라인 함수</h2>
<p>인라인 함수는 inline 키워드를 사용해 함수의 내용을 함수 호출부에 복사하도록 한다.</p>
<pre><code class="language-cpp">inline int square(int x) {
    return x * x;
}</code></pre>
<p>컴파일러는 이 함수를 호출하는 곳에 실제로 x * x 코드를 붙여넣는다.
→ 마치 매크로 함수처럼 보이지만, 타입 안정성과 디버깅이 매크로함수보다 사용하기 편해보인다.</p>
<p>하지만 이 인라인 함수도 마냥 좋은점만 있는 것은 아니다.
inline은 <strong>요청</strong>일 뿐, 컴파일러가 반드시 인라인화시켜준다는 보장이 없다.</p>
<blockquote>
<p>매크로를 이용한 함수의 인라인화는 전처리기에 의해서 처리되지만,
inline 키워드를 통한 인라인화는 컴파일러에 의해서 처리가 된다. 따라서 컴파일러는 함수의 인라인화가 오히려 성능에 해가 된다고 판단할 경우, 키워드 자체를 무시해버리기도 한다.</p>
</blockquote>
<h2 id="그래서-함수보다-느린건가">그래서 함수보다 느린건가?</h2>
<p>함수는 매 호출 시 다음 과정을 거치게 되는데</p>
<blockquote>
<p><strong>함수 호출 ▶ 인자 복사 (또는 참조) ▶ 스택 프레임 생성 ▶ 리턴</strong></p>
</blockquote>
<p>이러한 오버헤드가 생기기 때문에, 매우 자주 호출되는 짧은 함수라면 인라인 함수에 비해 상대적으로 느릴 수 있다.</p>
<p>하지만 요즘 컴파일러는 최적화를 매우 잘 하기 때문에, 경우에 따라 큰 차이가 없기도 하다.</p>
<h2 id="벤치마킹">벤치마킹</h2>
<p>이제 매크로 함수, 인라인 함수, 일반 함수 이 셋의 성능을 비교해보도록 하자.</p>
<blockquote>
<p>테스트 내용: 제곱 연산을 10억 번 반복해 걸리는 시간 측정</p>
</blockquote>
<p>Code</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;chrono&gt;

// 매크로 함수
#define SQUARE_MACRO(x) ((x) * (x))

// 인라인 함수
inline int square_inline(int x) {
    return x * x;
}

// 일반 함수
int square_normal(int x) {
    return x * x;
}

int main() {
    const int loop_count = 1000000000;
    volatile int result = 0; // 최적화 방지용

    // 매크로 함수
    auto start_macro = std::chrono::high_resolution_clock::now();
    for (int i = 0; i &lt; loop_count; ++i)
        result = SQUARE_MACRO(i);
    auto end_macro = std::chrono::high_resolution_clock::now();

    // 인라인 함수
    auto start_inline = std::chrono::high_resolution_clock::now();
    for (int i = 0; i &lt; loop_count; ++i)
        result = square_inline(i);
    auto end_inline = std::chrono::high_resolution_clock::now();

    // 일반 함수
    auto start_normal = std::chrono::high_resolution_clock::now();
    for (int i = 0; i &lt; loop_count; ++i)
        result = square_normal(i);
    auto end_normal = std::chrono::high_resolution_clock::now();

    // 출력
    auto duration_macro  = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_macro - start_macro).count();
    auto duration_inline = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_inline - start_inline).count();
    auto duration_normal = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_normal - start_normal).count();

    std::cout &lt;&lt; &quot; Macro function time: &quot; &lt;&lt; duration_macro &lt;&lt; &quot; ms\n&quot;;
    std::cout &lt;&lt; &quot; Inline function time: &quot; &lt;&lt; duration_inline &lt;&lt; &quot; ms\n&quot;;
    std::cout &lt;&lt; &quot; Normal function time: &quot; &lt;&lt; duration_normal &lt;&lt; &quot; ms\n&quot;;

    return 0;
}</code></pre>
<p><strong>결과</strong>
<img src="https://velog.velcdn.com/images/_thist_/post/cbc0703f-789e-4f68-96c2-b09e8767d326/image.png" alt=""></p>
<p>결과를 보면 우선,</p>
<blockquote>
<p><strong>매크로 함수</strong>: 전처리 단계에서 치환되기 때문에 함수 호출 자체가 없어서 제일 빠른 성능을 보여주고 있다.
<strong>인라인 함수</strong>: inline 요청에 따라 컴파일러가 함수 호출 없이 코드를 치환시켜줌. 하지만 매크로를 못따라감.
<strong>일반 함수</strong>: 매 호출마다 스택 프레임 생성 후 리턴 과정 때문에 오버헤드가 큰듯.. </p>
</blockquote>
<p>하지만, 인라인 함수랑 일반 함수랑 별로 큰 차이가 없어 보이는데, 그냥 매크로 함수를 쓰던지, 일반 함수를 쓰는게 더 나아 보인다....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 프로그래밍 기초 ] Const키워드]]></title>
            <link>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-Const%ED%82%A4%EC%9B%8C%EB%93%9C</link>
            <guid>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-Const%ED%82%A4%EC%9B%8C%EB%93%9C</guid>
            <pubDate>Sun, 25 May 2025 06:24:33 GMT</pubDate>
            <description><![CDATA[<p>C나 C++을 배우면서 가장 자주 보게 되는 키워드 중 하나가 <strong>&#39;const&#39;</strong>이다.
처음엔 단순히 <strong>&quot;변하지 않는 변수&quot;</strong> 정도로 알고 시작하지만, 
포인터와 함께 쓰이기 시작하면 헷갈리기 딱 좋은 것 같다.</p>
<p>이 글에서는 <strong>&#39;const&#39;</strong>의 기본 개념부터,
포인터와 함께 쓰일 때의 다양한 의미들을 알아보도록 하겠다.</p>
<h2 id="기본-개념---const란">기본 개념 - const란?</h2>
<p>말그대로 <strong>&#39;const&#39;</strong>는 <strong>변하지 않는&#39;</strong>이라는 의미를 가지고 있다.
즉, 선언된 이후에는 값을 바꿀 수 없도록 만드는 역할을 한다.
이게 왜 필요한걸까?</p>
<h2 id="const가-필요한-이유">const가 필요한 이유</h2>
<p>개발자라면 모두들 아시다싶이, 혼자서만 개발하는것이 아니다. 누군가의 코드를 수정해야할 때가 있을것이고, 건드리면 안되는 코드부분도 존재한다. 이를 위해 const키워드는 다음과 같은 역할을
수행한다.</p>
<p><strong>1. 의도하지 않은 수정 방지 (실수 예방)</strong></p>
<pre><code class="language-cpp">void printName(char* name) {
    name[0] = &#39;X&#39;; // 실수로 값 변경할 수도 있음.</code></pre>
<p>만약 A라는 개발자가 printName이라는 함수를 만들었는데, 매개변수 name은 절대 바꾸면 안된다고 했을 때... 위의 코드에서는 name이 변경이 가능하다. 하지만, 아래코드에서는 컴파일 에러가 발생한다.</p>
<pre><code class="language-cpp">void printName(const char* name) {
    // 이제 name을 절대 수정할 수 없음.
    name[0] = &#39;X&#39;; // 컴파일 에러 발생!</code></pre>
<p><strong>2. 코드의 &quot;의도&quot;를 명확하게 표현</strong></p>
<pre><code class="language-cpp">int sum(const int a, const int b);</code></pre>
<p>-&gt; 이 함수는 a,b값을 읽기만 한다는 의도가 분명해보임.
-&gt; 코드를 처음 보는 사람도, &quot;아 이건 절대 바뀌지 않는 값이구나&quot;를 인지하고, 개발고려사항에 착수 할 수 있음. (수정할 때 건들지 않도록)</p>
<p><strong>3. 인터페이스 설계에서 신뢰성 확보</strong></p>
<pre><code class="language-cpp">class Vector {
    public:
        double getLength() const; // 객체 상태 안 바꿈
};</code></pre>
<p>-&gt; 멤버 함수 뒤에 const를 붙이면, 이 함수는 멤버 변수(상태)를 절대 수정하지 않는다는 보장을 컴파일러가 해준다.</p>
<p><strong>4. 최적화에도 도움</strong>
컴파일러 입장에서도 <strong>const</strong>키워드는
<strong>&quot;이 친구는 안바뀌니까 캐시해도 되고, 레지스터에 넣어도 되고, 다른 코드랑 엮어도 안전.&quot;</strong>
결국, 성능 최적화에 도움을 줄 수 있음.</p>
<p>따라서 <strong>const</strong>키워드는 <strong>&quot;절대 바뀌면 안 되는 값&quot;</strong>을 <strong>컴파일러 수준에서 강제하는 일종의 방어막인 셈이다.</strong></p>
<p>**&gt; - 버그를 막고</p>
<blockquote>
<ul>
<li>의도를 분명하게 전할 수 있고</li>
<li>코드의 신뢰도를 높일 수 있다.**</li>
</ul>
</blockquote>
<h2 id="기본-개념---const">기본 개념 - const</h2>
<p>아까 위에서도 상술했듯이, 변하지 않는다는것을 의미하기에, 
즉, 선언된 이후에는 값을 바꿀 수 없도록 만들어준다.</p>
<pre><code class="language-cpp">const int num = 10;
num = 20; // 컴파일 에러</code></pre>
<h2 id="다양한-키워드-const의-의미들">다양한 키워드 const의 의미들</h2>
<p>포인터와 const를 결합해서 쓰기 시작하면, 다양한 의미로도 해석이 가능해진다.
(좀 더 유연한 설계가 가능)</p>
<p><strong>1. const int num = 10;</strong>
-&gt; num의 값을 바꿀 수 없게 고정.</p>
<p><strong>2. int* const ptr</strong>
-&gt; ptr의 주소는 고정, 값은 바꿀 수 있음</p>
<pre><code class="language-cpp">int* const ptr = &amp;val1;
*ptr = 20; // 변경 가능
ptr = &amp;val2; // 변경 불가</code></pre>
<p><strong>3. const int* ptr</strong>
-&gt; ptr의 주소는 바꿀 수 있으나, 값은 고정</p>
<pre><code class="language-cpp">const int* ptr = &amp;val1;
ptr = &amp;val2; // 주소 변경 가능
*ptr = 30; // 컴파일 에러</code></pre>
<p><strong>4. const int* const ptr</strong>
-&gt; ptr의 주소도, 값도 바꿀 수 없음</p>
<pre><code class="language-cpp">const int* const ptr = &amp;val1;
*ptr = 20; // 컴파일 에러
ptr = &amp;val1; // 컴파일 에러</code></pre>
<p><strong>const는 오른쪽이 고정된다.</strong></p>
<pre><code class="language-cpp">const int* p -&gt; *p고정 (값 못 바꿈)
int* const p -&gt; p고정 (주소 못 바꿈)
const int* const p -&gt; 둘 다 못 바꿈</code></pre>
<p><strong>const를 기준으로 &quot;오른쪽을 고정하는 것&quot;이라고 이해하면 편함.</strong></p>
<blockquote>
<p><strong>&#39;const&#39;</strong>키워드를 적극적으로 사용하면,
내 코드에서 <strong>&quot;이 값은 실수로라도 바뀌지 않는다&quot;</strong>라는 것을 컴파일러가 보장해준다.</p>
</blockquote>
<blockquote>
<p>특히 헤더 파일이나 라이브러리 API를 만들 때,
매개변수에 &#39;const&#39;를 명시해주면 <strong>함수의 의도</strong>가 명확해지고,
사용자에게 <strong>불변성</strong>을 강하게 전달해줄 수 있다.</p>
</blockquote>
<p>C/C++ 개발자라면 반드시 알고는 있어야 하는 개념인듯</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 프로그래밍 기초 ] 포인터]]></title>
            <link>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%ED%8F%AC%EC%9D%B8%ED%84%B0</link>
            <guid>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%ED%8F%AC%EC%9D%B8%ED%84%B0</guid>
            <pubDate>Fri, 16 May 2025 17:01:31 GMT</pubDate>
            <description><![CDATA[<h3 id="포인터">포인터</h3>
<h4 id="포인터의-개념">포인터의 개념</h4>
<p><strong>포인터(pointer)</strong>는 메모리 주소를 저장하는 변수이다. 쉽게 말해, 주소를 가리키는 변수이다.</p>
<p>이게 뭔 소리일까? </p>
<h4 id="걍-이거다">걍 이거다.</h4>
<p><img src="https://velog.velcdn.com/images/_thist_/post/390072b5-101e-4d1e-99df-2aacc6450ea4/image.png" alt="">
그렇다..... </p>
<p>프로그래밍 관점에서 그냥 가리키는 그 행위 자체를 <strong>포인터(Pointer)</strong>라고 말해주고 싶다.</p>
<p>우리에게 집이 있듯이 그 집으로 가기 위해서는 주소가 필요하다. </p>
<p>그 주소가 바로 <strong>포인터(Pointer)</strong>라고 볼 수 있다. </p>
<p>그리고 프로그래밍 관점에서 집 그 자체를 우리는 값이라 볼 수 있다.</p>
<p>지금 손으로 아무 사물이나 가르켜보자.</p>
<p>지금 가리키고 있는 손은 <strong>포인터(Pointer)</strong>가 될것이고, </p>
<p>가리키고 있는 대상 그 자체는 <strong>값(Value)</strong>이 되는것이다.</p>
<p>&nbsp;
일반적인 변수는 값을 저장하는 반면, 포인터 변수는 값을 저장하는 변수의 메모리 주소만을 저장한다.</p>
<h3 id="메모리와-변수">메모리와 변수</h3>
<p>먼저 메모리에 대해 간단하게 이해해보자.</p>
<p>프로그램이 실행될 때, CPU는 메모리에서 데이터를 읽고 처리한다.</p>
<p>예를 들어, int a = 10; 이라는 코드가 있을 때, a는 그림과 같이 특정 위치에 10이라는 값을 저장하게 된다. 그리고 이러한 메모리의 각 위치는 고유한 주소를 가지고 있게 된다.
<img src="https://velog.velcdn.com/images/_thist_/post/ed74890e-f48e-4e47-9fd3-b507d3e54151/image.png" alt=""></p>
<p>이 때 a는 값인 10을 저장하는 변수이고, 그 값이 저장된 메모리 주소를 포인터라고 한다.
 <img src="https://velog.velcdn.com/images/_thist_/post/3037c6b8-b205-4e2b-b371-59f67599dc15/image.png" alt=""></p>
<blockquote>
<h3 id="포인터의-역할">포인터의 역할</h3>
<p>포인터의 역할은 결국 ‘<strong>주소를 가리키는 것</strong>’이다. 포인터를 통해 변수의 메모리 주소를 알 수 있으며, 이 주소를 이용하여 간접적으로 변수의 값을 다룰 수 있게 된다.</p>
</blockquote>
<blockquote>
<h3 id="포인터의-기본-구성"><strong>포인터의 기본 구성</strong></h3>
<p><em><strong>1. 포인터 변수 선언</strong></em>
포인터 변수를 선언할 때는 타입 뒤에 *를 붙여서 선언한다. 이 때 *는 포인터 변수임을 나타내는 키워드이다.</p>
</blockquote>
<pre><code class="language-cpp">int* ptr; // int형 포인터</code></pre>
<p><em><strong>2. 주소 연산자</strong></em>
&amp;는 주소 연산자로, 변수의 메모리 주소를 구할 때 사용한다.</p>
<pre><code class="language-cpp">int a= 10;
int* ptr = &amp;a;</code></pre>
<p><em><strong>3. 역참조 연산자</strong></em>
*는 역참조 연산자로, 포인터가 가리키는 주소에 저장된 값을 가져오거나 변경할 때 사용한다.</p>
<pre><code class="language-cpp">int a=10;
int* ptr = &amp;a;
std:cout &lt;&lt; *ptr &lt;&lt; std::endl;</code></pre>
<h3 id="포인터를-이용한-값-수정">포인터를 이용한 값 수정</h3>
<p>포인터를 이용하여 변수의 값을 간접적으로 변경할 수 있다.</p>
<pre><code class="language-cpp">int a = 10;
int* ptr = &amp;a;  
*ptr = 20;  
std::cout &lt;&lt; *ptr &lt;&lt; std::endl;  </code></pre>
<h3 id="문제-결과값은-어떻게-나올까">문제. 결과값은 어떻게 나올까?</h3>
<pre><code class="language-cpp">#include&lt;iostream&gt;

int main(void) {
    int num = 10;
    int* ptr = &amp;num;

    std::cout &lt;&lt; *ptr &lt;&lt; std::endl;
    std::cout &lt;&lt; &amp;ptr &lt;&lt; std::endl;
    std::cout &lt;&lt; ptr &lt;&lt; std::endl;

    return 0;</code></pre>
<p>대략적으로 뭐가 출력되는지만 알면 된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 데이터베이스 ] Key와 관계 연산]]></title>
            <link>https://velog.io/@_thist_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-Key%EC%99%80-%EA%B4%80%EA%B3%84-%EC%97%B0%EC%82%B0</link>
            <guid>https://velog.io/@_thist_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-Key%EC%99%80-%EA%B4%80%EA%B3%84-%EC%97%B0%EC%82%B0</guid>
            <pubDate>Wed, 11 Sep 2024 17:01:56 GMT</pubDate>
            <description><![CDATA[<h3 id="관계relation과-테이블table">관계(Relation)과 테이블(Table)</h3>
<blockquote>
<ul>
<li>관계형 데이터베이스는 데이터를 테이블 형식으로 저장한다. 각 테이블은 <strong>행(Tuple, Record)</strong>과 <strong>열(Attribute, Field)</strong>로 구성된다.
<img src="https://velog.velcdn.com/images/_thist_/post/7d7f4436-5abb-477b-a1b3-d093ae46abaf/image.png" alt=""></li>
</ul>
</blockquote>
<h3 id="도메인-domain">도메인 (Domain)</h3>
<p>정의: 그 속성(Attribute)가 가질 수 있는 값의 범위를 의미한다.</p>
<blockquote>
<p>Ex. 학년 속성의 도메인은 1 ~ 4까지의 정수만 올 수 있다.</p>
</blockquote>
<h4 id="원자적-속성-값-atomic-attribute-value">원자적 속성 값 (Atomic Attribute Value)</h4>
<ul>
<li>속성 값은 원자적이어야 하며, 이는 값을 더 이상 나눌 수 없는 단일한 값을 가진다.<blockquote>
<p>Ex. 전화번호가 (010) 1234-5678 로 저장될 때, 이를 (지역번호) 번호로 나누지 않고 하나의 전체 값으로 저장해야 한다.</p>
</blockquote>
</li>
</ul>
<h4 id="null값-null-value">Null값 (Null Value)</h4>
<ul>
<li>&#39;Null&#39;은 값을 &#39;알 수 없음&#39; 또는 &#39;존재하지 않음&#39;을 의미한다.<blockquote>
<p>Ex. 학생의 전화번호가 아직 등록되지 않은 경우, 해당 필드는 Null값이 될 수 있다.</p>
</blockquote>
</li>
</ul>
<h4 id="relation-schema-and-instance">Relation schema and instance</h4>
<ul>
<li><strong>스키마(Schema)</strong>: 테이블의 구조를 나타내는 정의이다. R(A1, A2, ..., An) 형식으로 표현되며, 여기서 R은 테이블 이름을, A1, A2, ..., An은 속성들을 나타낸다.<blockquote>
<p>instructor(ID, name, dept_name, salary)는 instructor라는 테이블의 스키마를 정의한 것이다.</p>
</blockquote>
</li>
<li><strong>Relation Instance:</strong> 스키마에 따라 실제로 저장된 데이터(행의 집합)를 말한다. 즉, 현재 테이블에 저장된 값들을 의미한다.
<img src="https://velog.velcdn.com/images/_thist_/post/0f63b7de-0f8c-4122-8af0-de20192a6eff/image.png" alt=""></li>
<li>Relation은 정렬되어 저장되지 않는다.</li>
</ul>
<h2 id="키key">키(Key)</h2>
<blockquote>
<p>키(key)는 데이터베이스에서 조건을 만족하는 특정 튜플을 찾거나 다른 튜플들과 구별할 수 있는 유일한 기준이 되는 Attribute(속성)이다.</p>
</blockquote>
<h3 id="슈퍼키superkey">슈퍼키(Superkey)</h3>
<p><strong>* 테이블 내에서 튜플을 고유하게 식별할 수 있는 하나 이상의 속성들의 집합.</strong></p>
<blockquote>
<p>Ex. 학생 테이블에서 ID, ID + 이름, ID + 전화번호 등 여러 조합이 슈퍼키가 될 수 있다.</p>
</blockquote>
<ul>
<li>특징: 중복을 허용하지 않으며, 모든 튜플을 유일하게 식별할 수 있다.</li>
</ul>
<h3 id="후보키candidate-key">후보키(Candidate Key)</h3>
<ul>
<li><strong>슈퍼키 중에서 최소성을 만족하는 키로, 다른 속성들을 포함하지 않는키.</strong><blockquote>
<p>ID가 유일하고 중복되지 않는다면 후보키가 될 수 있다.</p>
</blockquote>
</li>
<li>특징: 중복되지 않으며, 테이블의 모든 튜플을 고유하게 식별할 수 있다. 또한, 여러 개의 후보키가 존재할 수 있다.</li>
</ul>
<h3 id="기본키primary-key">기본키(Primary Key)</h3>
<ul>
<li><strong>후보키 중에서 테이터베이스 설계자가 선택한 주요 키로, 테이블에서 각 튜플을 고유하게 식별함.</strong><blockquote>
<p>학생 테이블에서 ID가 기본키로 설정될 수 있다.</p>
</blockquote>
</li>
<li>특징: NULL 값을 가질 수 없으며, 값이 거의 변경되지 않는다. 테이블에서 오직 하나의 기본키만 존재할 수 있다. 또한, Primary Key는 무조건 밑줄을 그어준다.
<img src="https://velog.velcdn.com/images/_thist_/post/2b4f0e57-06db-4311-95b4-965bd7f515dd/image.png" alt=""></li>
</ul>
<h3 id="대체키alternate-key">대체키(Alternate Key)</h3>
<ul>
<li><strong>후보키 중에서 기본키로 선택되지 않은 나머지 키
다른 테이블의 기본키를 참조하는 키</strong><blockquote>
<p>ID가 기본키로 설정되면, 학번이 대체키가 될 수 있다.</p>
</blockquote>
</li>
<li>특징: 기본키와 동일한 특성을 가지지만, 기본키로 선택되지 못한 키들이다.</li>
</ul>
<h3 id="외래키foreign-key">외래키(Foreign Key)</h3>
<ul>
<li><strong>후보키 중에서 기본키로 선택되지 않은 나머지 키,
다른 테이블의 기본키를 참조하는 키</strong><blockquote>
<p>수강 테이블에서 학생_ID는 학생 테이블의 기본키 ID를 참조한다.</p>
</blockquote>
</li>
<li>특징: 참조 무결성(Referential integrity constraint)을 유지하기 위해 사용되며, 외래키가 가리키는 값은 참조하는 테이블의 기본키 값 중 하나여야 한다.</li>
</ul>
<h3 id="복합키composite-key">복합키(Composite Key)</h3>
<p><strong>* 두 개 이상의 속성을 조합하여 고유성을 보장하는 키</strong></p>
<blockquote>
<p>강의 테이블에서 강의코드 + 학기 조합이 복합키가 될 수 있다.</p>
</blockquote>
<ul>
<li>특징: 개별 속성으로는 고유성을 보장할 순 없지만, 이를 조합하여 고유성을 만들 수 있다.
<img src="https://velog.velcdn.com/images/_thist_/post/a1516765-9244-41ba-9585-d85edd7331b3/image.png" alt=""></li>
</ul>
<h3 id="관계-연산relational-operations">관계 연산(Relational Operations)</h3>
<ul>
<li>관계 연산(Relational Operations)은 관계형 데이터베이스에서 테이블(관계) 간의 데이터를 조작하고 검색하는 데 사용되는 연산</li>
</ul>
<h3 id="select-σ-시그마---행-선택-연산"><strong>Select (σ, 시그마) - 행 선택 연산</strong></h3>
<ul>
<li>정의: 조건을 만족하는 튜플(행)들을 선택하는 연산.<blockquote>
<p>Ex. A와B가 같고 D가 5이상인 행만 선택.
<img src="https://velog.velcdn.com/images/_thist_/post/43ece416-dd84-499b-91b1-0279e44b2ec4/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="project-π-파이---열-선택-연산"><strong>Project (π, 파이) - 열 선택 연산</strong></h3>
<ul>
<li>정의: 특정 속성(열)만 선택하여 결과를 반환하는 연산.<blockquote>
<p>Ex. A,C만 추출.
<img src="https://velog.velcdn.com/images/_thist_/post/c42df43a-ea19-4acc-bd18-127ff4b7c7ba/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="union-∪---합집합-연산"><strong>Union (∪) - 합집합 연산</strong></h3>
<ul>
<li>정의: 두 개의 테이블을 합쳐서 하나의 테이블로 만드는 연산으로, 두 테이블은 같은 속성을 가져야 한다.<blockquote>
<p>Ex. 테이블 R과 S를 Union시킴.
<img src="https://velog.velcdn.com/images/_thist_/post/c4484fda-bde4-4429-a6e8-c51c3f9cad2d/image.png" alt=""></p>
<ol>
<li>두 Table의 Attribute의 개수가 같아야 하며, 의미 또한 같아야 한다. (Union Compatibility)</li>
</ol>
</blockquote>
</li>
</ul>
<h3 id="difference-----차집합-연산"><strong>Difference (-) - 차집합 연산</strong></h3>
<ul>
<li>정의: 한 테이블에 존재하고 다른 테이블에 없는 행들을 반환하는 연산<blockquote>
<p>테이블 R에서 S를 뺌
<img src="https://velog.velcdn.com/images/_thist_/post/76297a67-42b2-4348-a94d-91cc582232f8/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="intersection-∩---교집합-연산"><strong>Intersection (∩) - 교집합 연산</strong></h3>
<ul>
<li>정의: 두 테이블에 모두 존재하는 행들을 반환하는 연산<blockquote>
<p>테이블 R과 S에 공통으로 존재하는 행을 반환
<img src="https://velog.velcdn.com/images/_thist_/post/1fc38f44-5451-405b-95fd-9f5d45859da9/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="cartesian-product-×---카티션-곱-연산"><strong>Cartesian Product (×) - 카티션 곱 연산</strong></h3>
<ul>
<li>정의: 두 테이블의 모든 가능한 행 조합을 생성하는 연산<blockquote>
<p>테이블 R과 S를 카티션 곱
<img src="https://velog.velcdn.com/images/_thist_/post/96dd8814-1474-4656-b364-7057312f75f1/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<p><strong>Cartesian Product (×) - 카티션 곱 연산 Naming Issue</strong></p>
<blockquote>
<p>Cartesian Product 수행 후, 테이블 r과 s 모두 A라는 동일한 속성(열)을 가지고 있을 때, 어떤 테이블의 A인지 구별하기 위해 r.A s.A로 속성을 구분.
<img src="https://velog.velcdn.com/images/_thist_/post/366bd8a0-a7c2-4429-bdea-2c166c76787e/image.png" alt=""></p>
</blockquote>
<h3 id="rename-ρ---이름-변경-연산"><strong>Rename (ρ) - 이름 변경 연산</strong></h3>
<ul>
<li>정의: 테이블의 속성 이름을 변경하는 연산.<blockquote>
<p> 테이블 R을 s라는 이름으로 변경하여 반환하는 연산
<img src="https://velog.velcdn.com/images/_thist_/post/7f187b22-a136-4312-83ff-b3c0f6275b16/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="join-⋈---조인-연산-natural-join"><strong>Join (⋈) - 조인 연산 (Natural Join)</strong></h3>
<ul>
<li>정의: 두 테이블을 특정 조건에 따라 결합하여 새로운 테이블을 만드는 연산.<blockquote>
<p>테이블 r과 테이블 s의 공통속성 A를 기준으로 묶어 r.A = s.A라면, 각 테이블 튜플끼리 결합하여 새로운 테이블을 만듬.
<img src="https://velog.velcdn.com/images/_thist_/post/86fb3621-fc40-4f72-943c-866ea1b6a7c3/image.png" alt="">
연산 식으로 표현하면 다음과 같다. <img src="https://velog.velcdn.com/images/_thist_/post/1758fedb-fc4f-4172-ae7d-4341f0414f08/image.png" alt=""></p>
<ol>
<li><strong>r × s: 테이블 r과 s의 카티션 곱을 수행하여 모든 가능한 튜플 조합을 생성.</strong></li>
<li><strong>σ_{r.A=s.A}: 생성된 조합 중에서 r.A와 s.A의 값이 같은 튜플만 선택.</strong></li>
<li><strong>Π_{A,B,D,E}: 선택된 튜플에서 필요한 속성(A, B, D, E)만을 남겨 최종 결과 테이블을 생성.</strong></li>
</ol>
</blockquote>
</li>
</ul>
<h3 id="join-⋈---조인-연산-theta-join"><strong>Join (⋈) - 조인 연산 (Theta Join)</strong></h3>
<blockquote>
<p>연산식은 다음과 같다. <img src="https://velog.velcdn.com/images/_thist_/post/a95f90da-4e6d-428b-981c-2251c7ff37ca/image.png" alt="">
r과 s는 각각 두 개의 테이블이며, θ는 조인 조건을 의미한다.
조인 조건 θ는 두 테이블의 속성 간의 관계를 정의하며, 조건이 맞는 튜플들만 결합한다. </p>
</blockquote>
<h3 id="natural-join과-theta-join의-차이점">Natural Join과 Theta Join의 차이점</h3>
<h4 id="조인-조건의-설정-방식">조인 조건의 설정 방식</h4>
<h4 id="natural-join">Natural Join:</h4>
<ul>
<li><p>조건 자동 설정: 공통 속성(열)들을 기준으로 자동으로 조인 조건이 설정된다. 
즉, 동일한 이름의 속성을 가진 두 테이블의 값이 동일한 경우에만 튜플이 결합.</p>
</li>
<li><p>사용자 정의 조건 불가능: Natural Join에서는 특정 조건을 직접 설정할 수 없다.
속성 중복 제거: 조인 후 중복된 공통 속성은 하나로 묶인다.</p>
</li>
</ul>
<h4 id="theta-join">Theta Join:</h4>
<ul>
<li><p>조건 수동 설정: 사용자가 지정한 임의의 조건(예: =, &lt;, &gt;, != 등)에 따라 두 테이블을 결합한다.</p>
</li>
<li><p>다양한 조건 사용 가능: 두 테이블 간의 속성 비교 조건을 자유롭게 설정할 수 있다.</p>
</li>
<li><p>속성 중복 허용: Theta Join은 단순히 조건에 맞는 튜플을 결합하기 때문에, 결과에서 중복된 속성이 그대로 유지가 된다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 자료구조 ] 원형큐(Circular Queue)]]></title>
            <link>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%9B%90%ED%98%95%ED%81%90Circular-Queue</link>
            <guid>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%9B%90%ED%98%95%ED%81%90Circular-Queue</guid>
            <pubDate>Sun, 08 Sep 2024 13:17:34 GMT</pubDate>
            <description><![CDATA[<p>앞전에, <strong>큐(Queue)</strong>에 대해서 포스팅을 진행했었다.
내가 마지막에 코드를 작성하고, 마지막줄에 이 코드는 메모리 효율성이 굉장히 떨어진다고, 비추하는 코드라고 작성했었던 기억이 있다. </p>
<p>처음 해보는 사람들이라면 &quot;이게 무슨말이지?&quot; 할 수도 있어서 그림으로 간단하게 보여주겠다. 
<img src="https://velog.velcdn.com/images/_thist_/post/bf7851d8-b839-45f8-9c9b-8ee2e02d0c95/image.png" alt=""></p>
<blockquote>
<p>앞선, Queue에서는 원소삭제시 단순히 Front를 앞으로 이동시키고 있기 때문에, 이전에 사용했던 원소들은 Front의 앞쪽에 고스란히 남아있게 된다. 
즉, 이 공간은 사용하지 않는 쓰레기 공간이라는 것이다. 
이러한 구조를 <strong>선형큐라고 (Non-Circular Queue)</strong>라고 한다.
그렇다면 어떻게 앞에 공간들을 알뜰하게 이용할 수 있을까? 
그래서 나온것이 바로 <strong>원형큐라고 (Circular Queue)</strong>라고 한다. </p>
</blockquote>
<p>구조는 굉장히 단순하다. 
<img src="https://velog.velcdn.com/images/_thist_/post/b702b692-0a5f-46ca-af2d-f556617282a7/image.png" alt="">
나머지 연산자(%)를 통해서 큐를 마치 원형처럼 사용하는 것이다. </p>
<p>잘 이해가 되지 않는가? 다음을 보자</p>
<p>배열의 길이가 총 5인 Arr라고 하는 배열이 있다 가정했을 때, 
Point라고 배열의 인덱스를 가리키는 변수가 있다고 가정해보자.</p>
<p>이 때, 
Point가 0일 때, Point%5 = 0 ---&gt; Arr[0]
Point가 1일 때, Point%5 = 1 ---&gt; Arr[1]
Point가 2일 때, Point%5 = 2 ---&gt; Arr[2]
Point가 3일 때, Point%5 = 3 ---&gt; Arr[3]
Point가 4일 때, Point%5 = 4 ---&gt; Arr[4]
<strong>Point가 5일 때, Point%5 = 0 ---&gt; Arr[0]</strong>
즉, 다시 첫 지점으로 돌아온다.</p>
<p>이러한 점을 이용하여, Rear이 끝까지 다 찼을경우, 다시 배열의 앞부분에 원소를 넣을 수 있는 공간이 있다면 이용하는 것이다.</p>
<p>그림으로 만나보자.</p>
<hr>
<p>최초의 원형큐 상태이다. 여기서, 값을 넣으면 어떻게 될까?
<img src="https://velog.velcdn.com/images/_thist_/post/be2f89ed-93d1-4cda-abcf-01d994411534/image.png" alt="">
<img src="https://velog.velcdn.com/images/_thist_/post/dd536112-33af-4009-925d-f7155b401124/image.png" alt="">
이전 Queue강좌에서 동일하게 Rear 0번지에 원소가 들어가게 된다.</p>
<p>다음 70을 넣으면, 똑같이 Rear이 증가하면서 원소가 넣어지고 있는것을 확인해볼 수가 있다.
<img src="https://velog.velcdn.com/images/_thist_/post/d06755f2-6ea1-483c-9ada-102af3dde3e4/image.png" alt="">
100 Insert.
<img src="https://velog.velcdn.com/images/_thist_/post/eb2b1f1f-6fca-4167-9591-f9568ab5122e/image.png" alt="">
60 Insert.
<img src="https://velog.velcdn.com/images/_thist_/post/f65ba30f-42d4-4a5a-8057-e4f36bc07798/image.png" alt=""></p>
<p>이번엔, 삭제를 해보자.
<img src="https://velog.velcdn.com/images/_thist_/post/6486cbac-4c78-48ba-b115-17dbb1b8ac72/image.png" alt="">
보다싶이, Front가 1증가하면서 앞의 원소를 삭제시켜주며 40이 삭제되었다.</p>
<p>한번 더, 삭제시켜 보겠다.
<img src="https://velog.velcdn.com/images/_thist_/post/8dc5f896-5782-4214-bbd7-5c4c8d2eb79d/image.png" alt="">
이번에도 똑같이, Front가 삭제되면서 앞으로 이동한 것을 볼 수 있다.
이제 다시 값을 넣어보자.
<img src="https://velog.velcdn.com/images/_thist_/post/1695a481-fc67-4eeb-9711-b58e0f1554f2/image.png" alt="">
Rear이 원소의 마지막에 도달했다. </p>
<p>만약, 이상태에서 값을 넣으면 어떻게 될까?
<img src="https://velog.velcdn.com/images/_thist_/post/4af74f3e-25a9-4fce-96f4-69a17d09ea0e/image.png" alt="">
Rear이 다시 0번지를 가르키며 값이 들어간 것을 확인할 수 있다.</p>
<p>이렇게, 공간을 아끼면서 넣을 수 있다는 것이 원형큐의 장점이다.</p>
<h3 id="code">Code</h3>
<hr>
<pre><code class="language-c">#define _CRT_SECURE_NO_WARNINGS
#include&lt;stdio.h&gt;
#include&lt;string.h&gt;
#define N 5  // 큐의 최대 크기를 정의

// 함수 선언
void Insert();
void Delete();
void Queue_Empty();
void Queue_Full();
void Print_Queue();

// 전역 변수 선언
int arr[N];  // 큐 배열
int Front, Rear;  // 큐의 Front와 Rear 인덱스
int cnt;

int main(void) {

    memset(arr, -1, N * sizeof(int));  // 여기서 arr은 배열, -1은 설정 값, N * sizeof(int)는 설정할 메모리 크기

    int Sel = 0;
    printf(&quot;------Circular Queue Version.------\n&quot;);
    // 메뉴를 출력하고 사용자의 선택을 처리하는 반복문
    do {
        printf(&quot; --------------------\n&quot;);
        printf(&quot; |    1.Insert      |\n&quot;);
        printf(&quot; |    2.Delete      |\n&quot;);
        printf(&quot; |    3.Is_Empty?   |\n&quot;);
        printf(&quot; |    4.Is_Full?    |\n&quot;);
        printf(&quot; |    5.Print       |\n&quot;);
        printf(&quot; --------------------\n&quot;);

        printf(&quot;Select Mode:&quot;);
        scanf(&quot;%d&quot;, &amp;Sel);  // 사용자로부터 선택을 입력받음

        // 사용자가 선택한 옵션에 따라 함수 호출
        switch (Sel) {
        case 1: {
            Insert();  // 값 삽입
            break;
        }
        case 2: {
            Delete();  // 값 삭제
            break;
        }
        case 3: {
            Queue_Empty();  // 큐가 비었는지 확인
            break;
        }
        case 4: {
            Queue_Full();  // 큐가 꽉 찼는지 확인
            break;
        }
        case 5: {
            Print_Queue();  // 큐에 있는 값을 출력
            break;
            }
        }
    } while (Sel != -1);  // 사용자가 -1을 입력할 때까지 반복

    return 0;
}

void Insert() {
    int S;
    printf(&quot;Input:&quot;);
    scanf(&quot;%d&quot;, &amp;S);  // 사용자로부터 삽입할 값을 입력받음

    // 만약 이미 해당 위치에 원소가 있다면 Queue에는 값을 더 이상 넣을 수가 없다.

    if (arr[ Rear ] != -1) printf(&quot;Queue is already full!!\n&quot;);

    else { // 만약 그렇지 않다면
        arr[Rear] = S;
        Rear = (Rear + 1) % N; // Queue에는 아직 공간이 남아 있다. Rear의 다음 인덱스 지정.
        cnt++;
    }

    return;

}

void Delete() {
    // 만약 Front의 위치가 -1이라면 값이 없다는 것이므로
    if (arr[Front] == -1) printf(&quot;Queue is already empty!!\n&quot;);

    else {
            arr[Front] = -1; // 해당 요소의 Index 삭제.
            Front = (Front + 1) % N;
            cnt--;
    }

    return;
}

void Queue_Empty() {
    // 만약 Queue가 최초의 상태에서 delete를 시킬경우엔
    if (arr[Front] == -1)  printf(&quot;Queue is already empty!!\n&quot;);
    else printf(&quot;Queue is not empty!!\n&quot;);

    return;
}

void Queue_Full() {
    // 만약 이미 Rear의 다음인덱스에 원소가 있다면
    if (arr[Rear] != -1) printf(&quot;Queue is already full!!\n&quot;); // Queue에는 값을 더 이상 넣을 수가 없다.    
    else printf(&quot;Queue is not full!!\n&quot;);

    return;
}

void Print_Queue() {
    int K;
    K = Front;
    for (int i = 0; i &lt; cnt; i++) printf(&quot;%d &quot;, arr[K++ % N]);

    printf(&quot;\n&quot;);

    return;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 컴퓨터 네트워크 ] 컴퓨터 네트워크 기초]]></title>
            <link>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Fri, 06 Sep 2024 02:56:38 GMT</pubDate>
            <description><![CDATA[<p>네트워크의 정의
컴퓨터 네트워크 (Computer Network) 또는 간단하게 네트워크(Network)라고 부른다.
    다른 하드웨어 장치들간의 상호연결, 물리적이거나 논리적으로 연결되어 서로 소통하고 자원과 정보를 공유할 수 있도록 하는 시스템을 일컫는다.
    이러한 네트워크는 특수한 하드웨어와 소프트웨어를 통해 구성되며, 데이터 교환과 효율적인 자원 활용을 가능하게 해준다.</p>
<pre><code>Node와 Node를 서로 연결해 주는 것을 &#39;링크(Link)&#39; 라고 하며, bits가 지나가는 통로이다.</code></pre><p>Direct Link</p>
<pre><code>Point-To-Point link (점대점 링크): 두 노드(컴퓨터 또는 호스트)간에 직접 연결된 링크이다. 이 연결을 통해 두 컴퓨터가 데이터를 주고 받을 수 있다.
Multiple-access link (다중 접속 링크): 여러 노드가 하나의 링크를 공유하는 구조로, 여러 컴퓨터가 하나의 통신 회선을 통해 데이터를 주고 받을 수 있다.
이러한 노드(Host)들은 응용 프로그램을 실행하며, 서로에게 ‘패킷(Packet)’이라고 불리는 데이터 블록을 전송한다.</code></pre><p>Indirect Link</p>
<pre><code>간접 링크(Indirect Links): 여러 노드가 직접 연결되지 않고, 스위치(Switch)라는 장비를 통해 연결된다. 각 노드는 스위치를 통해 데이터를 다른 노드로 전송하며, 스위치는 데이터를 저장하고 전달하는 역할을 한다.
스위치 네트워크(Switched Network): 스위치(Switch)장치는 패킷을 저장하고 전달한다. 즉, 스위치는 네트워크상의 데이터를 받아 적절한 목적지로 보내는 중요한 역할을 수행한다.</code></pre><p>패킷(Packet)</p>
<pre><code>패킷(Packet): 네트워크에서 데이터를 전송할 때 사용하는 ‘데이터 조각의 단위’이다. 데이터를 작은 단위로 나누어 ‘패킷(Packet)’이라는 형식으로 전송하며, 이를 통해 더 효율적인 전송과 오류 검사가 가능하다.
웹페이지, 이미지, 비디오 등과 같은 다양한 데이터는 바이트 스트림 데이터(Byte stream data)로 변환되어 네트워크를 통해 전송된다. 이러한 데이터는 일정한 크기로 나뉘어 패킷으로 전송되게 된다.</code></pre><p>패킷(Packet)의 구성요소
네트워크 패킷은 헤더(Header), 페이로드(Payload), 트레일러(Trailer) 세 부분으로 크게 구성된다.</p>
<ol>
<li>헤더(Header):
 패킷의 제어 정보가 들어있는 부분으로, 전송 경로를 설정하는 데 필수적인 정보를 포함한다.
 출발지 및 목적지 주소: 패킷이 어디서 왔고, 어디로 가야 하는지를 나타낸다.
 프로토콜 정보: 어떤 프로토콜을 사용하는지에 대한 정보(IP, TCP등)
 순서 번호: 패킷이 순서대로 다시 조립될 수 있도록 각 패킷에 대한 번호
 오류 검사 코드: 데이터가 손상되었는지 확인하는 코드</li>
<li>페이로드(Payload):
실제로 전송하려는 데이터가 담긴 부분이다. 패킷은 데이터가 많을 때 여러 개로 나뉘어 각각 페이로드에 데이터를 담아 전송한다.</li>
<li>트레일러(Trailer):
일부 네트워크 프로토콜에서는 패킷의 끝에 트레일러가 추가되며, 오류검사를 위한 정보가 포함된다.
패킷의 동작 원리
 데이터가 전송될 때, 송신 장치(예:컴퓨터)는 데이터를 여러 패킷으로 쪼개고 각 패킷에 헤더와 오류 검사 정보를 추가한다.
 이러한 패킷은 네트워크를 통해 독립적으로 전송되며, 서로 다른 경로로 전달될 수 있다.
 패킷이 목적지에 도착하면, 수신 장치는 패킷을 다시 조립하여 원래의 데이터로 복원한다.
 손실된 패킷이 있을 경우, 송신 장치에서 해당 패킷을 다시 요청할 수 있다.</li>
</ol>
<p>패킷의 장점</p>
<ol>
<li>효율성: 대용량 데이터를 한꺼번에 전송하지 않고 여러 작은 패킷으로 나누어 전송함으로써, 네트워크 대역폭을 효율적으로 사용할 수 있게 된다.</li>
<li>안정성: 네트워크에서 오류가 발생하더라도 손상된 패킷만 다시 전송하면 되므로, 전체 데이터의 손실을 방지할 수 있다.</li>
<li>병렬 처리: 패킷은 서로 다른 경로를 통해 독립적으로 전송될 수 있으므로, 네트워크 혼잡을 줄이고 더 빠른 전송을 가능하게 한다.
인터네트워크(Inter-network 또는 인터넷)
 서로 다른 네트워크들의 연결망을 의미한다. 즉, 여러 개의 작은 네트워크가 모여서 더 큰 네트워크를 형성한 것이 ‘인터넷(Internet’)이다.
 이러한 작은 네트워크들은 라우터(Router) 또는 게이트웨이(Gateway)를 통해 서로 상호 연결된다.
라우터(Router)와 라우팅(Routing)
라우터(Router):
 라우터(Router)는 서로 다른 네트워크를 연결하는 장비이다. 네트워크와 인터넷 간의 연결을 관리하는 역할을 수행한다.
 또한, 라우터는 패킷을 목적지로 전달하는 역할을 하며, 각 패킷이 올바른 경로로 이동할 수 있도록 중간에서 경로를 설정해 준다.
라우팅(Routing):
 라우팅(Routing)은 출발지에서 목적지까지 최적의 경로를 찾아 패킷을 전달하는 과정이다. 이 작업은 라우터가 수행하며, 네트워크의 효율적인 통신을 위해 필수적인 과정이다.
 이러한 라우터(Router)는 패킷을 전달할 경로를 찾기 위해 여러 알고리즘을 사용하여 패킷이 가장 빠르고 안정적인 경로로 전달되도록 도와준다.
Any-to-any connectivity
Any-to-Any Connectivity는 네트워크 상에서 모든 노드(컴퓨터, 장치 등)들이 다른 모든 노드들과 연결될 수 있는 상태를 의미한다. 즉, 네트워크에 연결된 어떤 장치도 다른 장치와 데이터를 주고받을 수 있는 상태를 말한다. 이는 현대 네트워크에서 중요한 개념이며, 네트워크 인프라의 공유를 통해 실현된다. 이러한 ‘Any-to-any Connectivity’는 분명 이상적인 기술이지만, 많은 데이터가 동시에 전송되면 네트워크 혼잡(Network Congestion)이 발생할 수 있다. 그래서 나온 기술이 ‘Multiplexing(다중화)’이다. Multiplexing은 여러 데이터를 하나의 통로로 묶어 보내고, 반대편에서 다시 분리해 각 장치로 전달하는 방식으로, 네트워크 자원을 효율적으로 사용하면서도 Any-to-any 연결의 장점을 최대한 살리는 역할을 한다.</li>
</ol>
<p>Multiplexing(다중화)에는 크게 TDM(Time Division Multiplexing)과 FDM(Frequency Division Multiplexing)이 있다.
TDM (Time Division Multiplexing): 시간 단위로 자원을 나누어 각 사용자에게 할당해준다.
FDM (Frequency Division Multiplexing): 주파수 단위로 자원을 나누어 각 사용자에게 할당해준다.
프로토콜(Protocol)
네트워크에서 데이터를 주고받기 위해서는 일정한 규칙과 절차가 필요하다. 이 규칙과 절차를 프로토콜(Protocol)이라고 한다. 간단히 말해, 프로토콜은 ‘컴퓨터 간의 통신 규칙’을 의미한다. 이러한 프로토콜이 없다면, 각 컴퓨터가 서로 다른 방식으로 데이터를 주고받으려고 할 것이고, 그로 인해 데이터 통신이 불가능하게 된다. 프로토콜은 이러한 혼란을 방지하고, 모든 장치가 정해진 규칙에 따라 데이터를 주고받을 수 있도록 하는 역할을 수행한다.
프로토콜의 계층 구조 (OSI 모델)
프로토콜은 서로 협력하여 작동하며, 이를 계층 구조를 통해 설명할 수 있다.
가장 대표적인 계층 구조는 OSI 7계층 모델이다. </p>
<ol>
<li><p>물리 계층: 데이터를 전기 신호나 빛의 형태로 변환하여 실제로 전송하는 계층
(예시: 이더넷 케이블, 광섬유 케이블, 네트워크 카드(NIC) 및 허브(Hub) 등)</p>
</li>
<li><p>데이터 링크 계층: 물리 계층에서 전송된 데이터를 오류 없이 상위 계층으로 전달
하는 역할을 하며, 데이터 전송 시 발생할 수 있는 프레임 단위의 오류 검출 및
수정을 담당한다. MAC 주소를 사용하여 물리적 주소를 관리한다.
(예시: MAC주소, 스위치, 이더넷 등)</p>
</li>
<li><p>네트워크 계층: 데이터를 목적지까지 전달하기 위해 경로를 설정하고, 라우팅(Routing)을 통해 패킷을 전송한다. 또한 IP 주소를 사용하여 데이터 패킷을 목적지 네트워크로 전달하는 역할을 수행한다. (예시: IP주소, 라우팅 등)</p>
</li>
<li><p>전송 계층: 종단 간 통신을 제공하고, 데이터 전송의 신뢰성을 보장한다. 패킷을 세그먼트(Segment)로 나누고, 흐름 제어, 오류 복구 등을 수행한다. TCP와 UDP프로토콜이 사용된다. (예시: TCP, UDP 등)</p>
</li>
<li><p>세션 계층: 네트워크 통신 세션을 설정, 관리, 종료하는 역할을 한다. 여기서 ‘세션(Session)’이란, 네트워크 통신에서 두 장치 간의 연결 상태 또는 통신이 이루어지는 일련의 상호작용을 의미한다. 세션(Session)은 네트워크에서 데이터를 주고받는 동안의 논리적인 연결을 유지하고, 그 연결을 관리하는 것을 뜻한다. (예시: RPC, NetBIOS 등)</p>
</li>
<li><p>표현 계층: 데이터를 사용자가 이해할 수 있는 형식으로 변환하는 계층이다. 데이터의 압축, 암호화, 인코딩 및 변환을 처리한다. 
(예시: JPEG, TLS, MPEG 등)</p>
</li>
<li><p>응용 계층: 사용자가 직접적으로 접하는 계층으로, 네트워크 서비스와 애플리케이션이 상호 작용하는 부분이다. 이메일, 웹 브라우징, 파일 전송 등이 이 계층에서 이루어진다. (예시: HTTP/HTTPS, FTP, SMTP, DNS 등)</p>
</li>
</ol>
<p>MAC주소</p>
<p>네트워크 장치의 고유한 하드웨어 주소로, 일반적인 네트워크 카드(Network Interface Card, NIC)에 할당된다. 각 네트워크 장치가 네트워크상에서 식별될 수 있도록 하는 역할을 한다. 이 주소는 전 세계적으로 고유하며, 제조업체에 의해 장치에 할당된다. MAC 주소는 48비트로 구성되어 있으며, 16진수(0-9,A-F)로 표현된다. 
IP주소
IP 주소는 네트워크 상에서 장치를 식별하는 데 사용되는 고유한 숫자 식별자이다. 네트워크 상에서 데이터를 주고받을 때, IP주소는 송신지와 수신지의 위치를 지정하여 데이터를 목적지까지 전달할 수 있도록 해준다.</p>
<p>IP 주소의 특징
• 32비트 주소: IPv4(Internet Protocol Version 4)에서는 IP주소가 32비트로 구성된다. 이는 총 2^32개의 고유한 IP 주소를 만들 수 있음을 의미하며, 약 43억 개의 주소를 지원한다.<br>• 글로벌 주소: IP 주소는 전 세계적으로 고유하며, 인터넷을 통해 통신할 때 장치가 서로 식별하기 위해 사용된다.
• 표기법: IP 주소는 보통 점으로 구분된 10진수 형식으로 표기된다. 예를 들어 169.34.11.56이라는 주소는 4개의 8비트 숫자로 구성된 IP 주소로 169와 34, 11, 56은 각각 8비트 숫자(바이트)를 나타낸다.<br>IP 주소의 분류
    공인 IP 주소 (Public IP Address):
    인터넷에서 전 세계적으로 고유한 주소이다. 공인 IP 주소는 인터넷 서비스 제공업체(ISP)에 의해 할당되며, 인터넷에 직접 연결된 장치에 부여된다.
    사설 IP 주소 (Private IP Address):
    내부 네트워크(예: 가정 또는 회사)에서 사용되는 주소이다. 공인 IP 주소 없이도 내부 네트워크 내에서 장치 간의 통신을 가능하게 한다. 라우터는 이 사설 IP 주소를 통해 내부 장치 간 통신을 관리한다. 사설 IP 주소는 외부 인터넷에서는 사용되지 않으며, NAT(Network Address Translation)을 통해 공인 IP로 변환되어 외부와 통신한다.
    예시: 192.168.x.x, 10.x.x.x
IPv4와 IPv6
    IPv4 (Internet Protocol version 4): 현재 가장 널리 사용되는 인터넷 프로토콜 버전으로, 32비트 주소 체계를 사용한다. 그러나 사용 가능한 주소 공간이 거의 소진되어, 새로운 프로토콜인 IPv6가 도입되었다.
    IPv6: 128비트 주소 체계를 사용하여 더 많은 주소를 제공한다. IPv6는 IP 주소 부족 문제를 해결하기 위해 도입되었으며, 현재는 IPv4와 함께 사용되고 있다.
IP 주소의 중요한 개념
    서브넷 마스크(Subnet Mask): IP 주소를 네트워크 ID와 호스트 ID로 구분하는 데 사용된다. 서브넷 마스크는 네트워크가 크기별로 나뉘어 관리되도록 돕는 역할을 수행한다.
    DHCP (Dynamic Host Configuration Protocol): 네트워크 장치에 자동으로 IP 주소를 할당하는 프로토콜이다. DHCP는 수동으로 IP 주소를 설정하는 대신, 네트워크에 연결될 때마다 동적으로 IP 주소를 할당한다.
IP 주소의 구조
IPv4 주소는 두 가지 주요 부분으로 나뉜다.
    네트워크 부분 (Network ID): 네트워크가 속해 있는 구역을 나타낸다. 같은 네트워크 ID를 가진 장치는 동일한 네트워크에 속한다.
    호스트 부분 (Host ID): 해당 네트워크 내에서 특정 장치를 식별하는 데 사용된다. 각 네트워크 내의 장치(컴퓨터, 프린터 등)마다 고유한 호스트 ID를 가진다.
회선 교환(Circuit Switching)과 패킷 교환(Packet Switching)
데이터를 두 장치 간에 전달할 때 사용하는 방식에는 크게 회선 교환(Circuit Switching)과 패킷 교환(Packet Switching) 두 가지 주요 방법이 있다. 이 두 방식은 통신에서 데이터가 전송되는 방법에 따라 다르게 작동하며, 각각의 방식은 통신의 목적에 따라 선택되게 된다.</p>
<ol>
<li>회선 교환 (Circuit Switching)
회선 교환(Circuit Switching)은 두 장치가 데이터를 주고받기 전에 고정된 통신 경로(회선)를 설정하는 방식이다.이 방식은 전통적인 전화 통신에서 많이 사용되어 왔다.
작동 방식
 연결 설정: 통신을 시작하기 전에, 송신자와 수신자 사이에 하나의 고정된 경로(회선)가 설정된다. 이 경로는 통신이 끝날 때까지 독점적으로 사용된다.
 데이터 전송: 연결이 설정되면, 그 경로를 통해 데이터가 연속적으로 전송된다. 데이터는 연결된 경로를 따라 연속적으로 흐르며, 중간에 경로가 변경되지 않는다.
 연결 해제: 데이터 전송이 끝나면, 통신 회선이 해제되고 다른 사용자가 그 회선을 사용할 수 있게 된다.
특징
 지속적인 연결: 한 번 경로가 설정되면 통신이 끝날 때까지 연속적으로 데이터를 보낼 수 있다.
 고정된 대역폭: 회선 교환 방식은 송신자와 수신자 사이에 고정된 대역폭을 제공한다. 그 대역폭은 통신이 끝날 때까지 독점적으로 사용되며, 다른 사용자는 해당 경로를 사용할 수 없다.
 비효율적 자원 사용: 사용하지 않는 동안에도 회선은 통신 양측 간에 독점적으로 남아 있기 때문에, 자원 낭비가 발생할 수 있다.</li>
</ol>
<p>•  Propagation Delay (전파 지연):
    Caller와 Boston Switch 사이에 발생하는 지연이다. 전파 지연은 데이터가 네트워크를 통해 물리적으로 이동하는 데 걸리는 시간이다. 이는 통신 거리에 따라 다르며, 거리(보스턴에서 LA까지)가 길수록 지연 시간이 증가한다.
•  Processing Delay at Switch (스위치에서의 처리 지연):
    데이터가 스위치를 통과할 때 발생하는 지연이다. 스위치에서 데이터를 처리하고 다음 목적지로 전달하는 데 걸리는 시간이다. 스위치가 데이터를 처리하는 속도에 따라 처리 지연이 발생할 수 있다.
(1) 설정 단계: 통신을 시작하기 위해 회선 설정이 이루어지는 단계이다. 통신이 시작되기 전에 Caller와 Callee 간의 고정 경로가 설정된다.
(2) 데이터 전송 단계: 회선이 설정된 후 데이터(음성 또는 정보)가 양방향으로 전달된다. 이 단계에서 통화 내용이 전송된다.
(3) 종료 단계: 통신이 완료되면 회선이 해제되고, 그 회선은 다른 통신에 사용할 수 있게 된다.
예시
    전화 통신: 전화 통신은 회선 교환 방식을 대표적으로 사용한다. 전화를 걸 때, 송신자와 수신자 간에 하나의 회선이 설정되고, 그 회선은 통화가 끝날 때까지 유지된다.
    장점
    지연 시간 없음: 회선이 한 번 설정되면, 데이터를 연속적으로 전송할 수 있으므로 지연 없이 빠르게 통신할 수 있다.
    단점
    비효율적인 대역폭 사용: 통화 중 대화가 없는 시간에도 회선이 유지되므로, 자원 사용이 비효율적이다.
    설정 시간 필요: 통신 전에 고정된 경로를 설정해야 하므로 초기 설정 시간이 소요된다.</p>
<ol start="2">
<li>패킷 교환 (Packet Switching)
패킷 교환(Packet Switching)은 데이터를 작은 패킷으로 나누어, 각각의 패킷이 독립적으로 전송되는 방식. 이는 주로 인터넷에서 사용되는 방식으로, 데이터를 빠르고 효율적으로 전송할 수 있다.
작동 방식
 데이터 패킷화: 송신자는 데이터를 작은 패킷으로 나눈다. 각 패킷은 출발지 주소와 목적지 주소를 포함하여 독립적으로 전송된다.
 효율적인 경로 탐색: 패킷은 네트워크 상에서 다양한 경로를 통해 가장 효율적인 경로를 찾으면서 목적지로 이동한다. 각 패킷은 서로 다른 경로를 선택할 수 있으며, 네트워크 혼잡에 따라 경로가 달라질 수 있다.
 재조립: 수신자가 패킷을 받으면, 그 패킷들을 다시 원래의 데이터로 재조립한다.
특징
 유동적인 경로: 각 패킷은 독립적인 경로를 통해 목적지로 전송되며, 중간 경로에서 혼잡을 피하거나 가장 빠른 경로를 선택할 수 있다.
 효율적인 대역폭 사용: 패킷 교환 방식은 네트워크 자원을 공유하며, 여러 사용자가 동일한 대역폭을 효율적으로 사용할 수 있다. 이는 회선 교환과 달리 ‘경로가 사전에 예약되지 않음’을 의미한다.
 에러 처리: 패킷이 손실되거나 손상되었을 경우, 손실된 패킷만 다시 요청하여 전송할 수 있다.
라우터에서의 패킷 처리
 패킷이 라우터에 도착하면 다음 두 가지 Condition에 의해서 처리된다.
( i ) 출력 링크가 사용 가능한 경우, 라우터는 패킷을 다음 라우터로 전달한다.
( ii ) 출력 링크가 바쁘면(혼잡 상태), 패킷은 라우터 버퍼에서 대기한다. 
패킷 교환: 저장-전달(Store-and-Forward)</li>
</ol>
<p>저장-전달 방식이란?</p>
<p>저장-전달(Store-and-Forward)방식은 패킷이 라우터에 도착하면, 전송되기전에 패킷 전체가 도착해야 한다는 원칙을 따른다. 즉, 라우터는 패킷의 전체 데이터가 도착한 후, 다음 라우터로 전달되며, 이 과정에서 패킷이 완전히 버퍼링될 때까지 기다려야 한다.
지연 시간
    패킷을 전송할 때는 L비트의 패킷이 네트워크 링크에서 전송 속도 Rbps로 전송되므로, 패킷을 전송하는 데 걸리는 시간을 L/R초이다.
    여러 라우터를 거쳐 목적지까지 도달하는 경우, 각 홉에서 발생하는 전송 지연을 계산할 수 있다.</p>
<p>지연 계산 예시:
    L = 7.5Mbits, R = 1.5Mbps일 때, 한 홉의 전송 지연은 약 5초이다.
    이는 패킷이 하나의 라우터에서 다음 라우터로 전달되기까지 걸리는 시간을 의미한다.
큐잉 지연(Queueing Delay)</p>
<pre><code>큐잉 지연의 원인:
네트워크의 출력 링크로 데이터를 전송할 때, 입력되는 패킷의 속도(R)가 출력 링크의 전송 속도보다 높을 경우 패킷은 대기 상태에 놓이게 된다.
예를 들어, 그림에서는 A에서 패킷이 10Mb/s로 전송되지만, 출력 링크는 1.5Mb/s의 속도를 가지고 있다. 이로 인해 출력 링크의 처리 속도가 부족해지면 패킷은 큐(queue)에 저장되며, 처리되기까지 대기한다.
대기열 발생:
패킷이 출력 링크로 즉시 전송되지 못하면, 패킷은 라우터의 버퍼(buffer)에 쌓인다. 버퍼는 대기 중인 패킷을 저장하는 공간으로, 패킷들이 순서대로 출력 링크로 전송되기를 기다린다.
이 대기 상태를 큐잉(Queueing)이라고 하며, 패킷은 큐에 들어가 전송될 차례를 기다리는 동안 지연이 발생한다.
지연 시간:
큐잉 지연은 네트워크가 혼잡할 때 더 많이 발생하며, 대기열이 길어질수록 지연 시간이 길어진다. 이는 패킷 교환 방식의 단점 중 하나로, 네트워크 트래픽이 많을 때 패킷 전송 속도가 느려질 수 있다.</code></pre><p>패킷 손실(Packet Loss)
    패킷 손실의 원인:
    라우터 또는 스위치의 버퍼 용량은 한정되어 있다. 따라서, 대기열이 가득 차면 새로운 패킷을 수용할 공간이 없기 때문에 더 이상 패킷을 받아들일 수 없다.
    이때 발생하는 현상이 패킷 손실이다. 새로운 패킷은 버퍼에서 제거되거나 폐기된다.
    손실된 패킷의 처리:
    손실된 패킷은 네트워크 상에서 복구될 수 없는 상태가 된다. 하지만 TCP와 같은 신뢰성 있는 프로토콜을 사용할 경우, 손실된 패킷은 다시 전송 요청이 되어 재전송될 수 있다.
    반면, UDP와 같은 프로토콜을 사용할 경우, 패킷 손실이 발생하면 해당 데이터는 재전송되지 않고 손실된 채로 남을 수 있다.
큐잉 지연과 패킷 손실의 해결 방법
    네트워크 자원 확장:
    네트워크의 출력 링크 속도를 증가시켜 더 많은 패킷을 동시에 처리할 수 있도록 해야 한다. 이는 큐잉 지연을 줄이는 데 도움이 될 수 있다.
    버퍼 크기 조정:
    라우터나 스위치의 버퍼 크기를 늘려, 더 많은 패킷을 대기시킬 수 있다. 하지만, 버퍼 크기가 너무 커지면 지연 시간이 길어질 수 있기 때문에 적절한 크기 조정이 필요하다.
    혼잡 제어 및 관리:
    혼잡 제어(congestion control) 메커니즘을 통해 네트워크 트래픽을 관리할 수 있다. TCP 프로토콜은 이러한 혼잡 제어를 제공하며, 네트워크 상태를 감지하여 패킷 전송 속도를 조절할 수 있다.
예시
    인터넷: 인터넷 통신은 패킷 교환 방식을 사용한다. 웹 페이지를 요청할 때, 그 요청은 여러 개의 패킷으로 나뉘어 전송되며, 각각의 패킷은 목적지로 가는 가장 빠르고 효율적인 경로를 선택한다.
    장점
    효율성: 여러 사용자가 동일한 네트워크 자원을 효율적으로 사용할 수 있어, 네트워크 대역폭을 절약할 수 있다.
    확장성: 패킷 교환 방식은 대규모 네트워크에서 더 효과적이다. 네트워크가 확장되어도 패킷은 독립적으로 처리되므로 유연하게 대응할 수 있다.
    단점
    지연 발생 가능성: 패킷이 서로 다른 경로를 통해 전송되기 때문에, 일부 패킷이 늦게 도착할 수 있다. 이로 인해 지연(latency)이 발생할 수 있다.
    재조립 필요: 각 패킷을 수신자가 다시 원래의 데이터로 조립해야 하므로, 복잡성이 높아진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 프로그래밍 기초 ] C/C++ 화살표(->) 와 도트(.)의 차이]]></title>
            <link>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-CC-%ED%99%94%EC%82%B4%ED%91%9C-%EC%99%80-%EB%8F%84%ED%8A%B8.%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-CC-%ED%99%94%EC%82%B4%ED%91%9C-%EC%99%80-%EB%8F%84%ED%8A%B8.%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 05 Sep 2024 13:12:09 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/_thist_/post/0175afcb-2a3d-4e02-843e-a21510267be4/image.png" alt=""></p>
<p>위 둘은 클래스나 구조체에서 멤버변수를 사용할 때 이용하는 연산자들 이다.
즉, 무언가를 접근할 때 사용하는 연산자로 쓰인다.</p>
<h4 id="도트연산자--">도트연산자( . )</h4>
<ul>
<li>포인터가 아닌 객체나 멤버변수에 직접적으로 사용한다.</li>
</ul>
<h4 id="화살표연산자----">화살표연산자 ( -&gt; )</h4>
<ul>
<li>포인터인 객체의 멤버변수에 간저벅으로 접근할 때 사용한다.</li>
</ul>
<p>아래에 예시를 보자.</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;
using namespace std;

class Account {
    public:
        const char* name = &quot;홍길동&quot;;
        const char* Account_Number = &quot;293-685-233-574639&quot;;
        int balance = 9870;
};

struct User {
    public:
        const char* UserName = &quot;돈내놔&quot;;
        const char* Job = &quot;전사&quot;;
        int Level = 58;
};

int main(void) {
    // MyClass 클래스선언
    Account MyClass;

    // .(도트)는 클래스의 맴버에 직접적으로 접근할 수 있다.
    cout &lt;&lt; MyClass.name &lt;&lt; endl;
    cout &lt;&lt; MyClass.Account_Number &lt;&lt; endl;
    cout &lt;&lt; MyClass.balance &lt;&lt; endl;

    // MyUser 구조체선언
    User* MyUser = new User();

    // -&gt;(화살표)는 구조체의 멤버에 간접적으로 접근할 수 있다.
    cout &lt;&lt; MyUser-&gt;UserName &lt;&lt; endl;
    cout &lt;&lt; MyUser-&gt;Job &lt;&lt; endl;
    cout &lt;&lt; MyUser-&gt;Level &lt;&lt; endl;

    delete MyUser;

    return 0;
}</code></pre>
<p>포인터 객체인데, 도트연산자( . )를 사용한다거나, 
포인터객체가 아닌데 화살표 연산자( -&gt; )를 사용하면 에러가 발생한다.</p>
<p>만약 본인이 정말 도트연산자를 사용하고 싶다면</p>
<pre><code>MyUser -&gt; UserName</code></pre><p>다음과 같이 사용하면 된다.</p>
<pre><code>(*MyUser).UserName</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[HCI ( Human - Computer Interaction ) 이란?]]></title>
            <link>https://velog.io/@_thist_/HCI-Human-Computer-Interaction-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@_thist_/HCI-Human-Computer-Interaction-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Thu, 05 Sep 2024 08:21:46 GMT</pubDate>
            <description><![CDATA[<p>시대의 흐름에 따라 우리는 수 많은 기술의 발전을 목격해 왔다. </p>
<p>처음에는 단순한 계산을 하기 위한 기계들이 등장했고, 이후에는 컴퓨터와 소프트웨어, 스마트폰과 같은 혁신적인 기술들이 우리의 일상에 깊숙히 자리 잡았다. </p>
<p>이제 우리는 IT없이 살 수 있을까? </p>
<p>나는 불가능할 것이라고 본다. 그 만큼, IT는 우리의 삶 깊숙하고 다양하게 자리잡고 있다.
<br><br>
그런 의미에서 오늘은 <strong>HCI ( Human - Computer Interaction )</strong>에 대해서 간단하게 알아보도록 하자.</p>
<h3 id="hci란-무엇인가">HCI란 무엇인가?</h3>
<p>우선, Wiki에 검색해 보니, 다음과 같이 정의 하고 있다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/5010ae5f-fd89-4267-acf3-54d14b2a3c8b/image.png" alt="">
출처: <a href="https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction">https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction</a>
글의 내용을 읽어보니 컴퓨터 기술을 연구하고 사람과 컴퓨터간의 인터페이스를 디자인하는것에 
초점이 맞춰져 있는것을 <strong>HCI</strong>라고 Wiki는 말하고 있다.</p>
<blockquote>
<p><strong>HCI ( Human - Computer Interaction )</strong>은 직역하자면, &quot;<strong>인간-컴퓨터 상호작용</strong>&quot;으로 볼 수 있는데, _<strong>이는 기술의 발전에 따라 인간이 컴퓨터와 소통하는 방식을 연구하는 학문</strong>_이라고 볼 수 있다.</p>
</blockquote>
<p>HCI는 1980년대 개인용 컴퓨팅과 함께 등장하였으며, Apple의 맥킨토시, IBM등과 같은 컴퓨터와 말이다. 이 때 당시의 컴퓨터는 단순히 워드프로세서, 게임 장치, 엑셀등과 같이 특정 분야에 대한 제작을 진행했었기 때문에, 디자인에 그렇게 큰 관심이 있지 않았다.</p>
<p>하지만, 그리고 시대가 점점 발전함에 따라 수 많은 가정과 사무실에서 등장하기 시작하였고, 이에 컴퓨터는 더 이상 비싼 도구가 아니게 되었고 이에 따라, 일반 사용자들에게도 쉽게 편리하고 효율적으로 제작해야하는 필요성을 느끼게 되었다. </p>
<p>그래서 만들어진 학문이 <strong>HCI ( Human - Computer Interaction )</strong>인 것이다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/1c294f0d-1968-4e86-8d1d-ca78d73a8bae/image.png" alt=""></p>
<p>HCI는 단순한 기계뿐만 아니라 소프트웨어, 애플리케이션, 웹사이트 등을 포함하고 있으며, HCI는 사용자 인터페이스(UI)와 사용자 경험(UX)을 중심으로, 사용성 및 인간공학을 포함한 다양한 요소들을 통합한다. </p>
<p>이의 주된 목표는, <strong>사용자와 컴퓨터 간의 상호작용을 개선하여 컴퓨터 인터페이스의 사용성을 높이는 것</strong>이다. 
<br>
이는 UI 디자인, 프로토타이핑, 평가, 그리고 인터페이스 구현을 통해 이루어지는데, 
사용성은 <strong>ISO (International Organization for Standardization)</strong>에서 정의하는 바와 같이 사용자가 특정 환경에서 목표를 얼마나 효과적이고 효율적이며 만족스럽게 달성하는지를 평가하는 기준을 의미한다.</p>
<h4 id="사용성-usability의-예시들">사용성 (Usability)의 예시들.</h4>
<ul>
<li><strong>강력함(Robust)</strong>: 시스템이 안정적이고 신뢰할 수 있음.</li>
<li><strong>최소 오류율(Minimal Error Rates)</strong>: 사용자 오류를 최소화하는 디자인.</li>
<li><strong>좋은 피드백(Good Feedback):</strong> 오류 복구를 돕는 명확한 피드백 제공.</li>
<li><strong>발견 가능성(Discoverable)</strong>: 시간이 지나면서 새로운 기능을 쉽게 배울 수 있음.</li>
<li><strong>즐거움과 만족도(Pleasing)</strong>: 사용자가 만족하고 즐겁게 사용할 수 있음.</li>
<li><strong>학습 용이성(Fun and Learnable)</strong>: 사용이 쉽고 반복 사용 시 더 빨라짐.</li>
<li><strong>기억 용이성(Memorable)</strong>: 일관된 경험 제공.</li>
<li><strong>유연성(Flexible)</strong>: 여러 방법으로 작업을 수행할 수 있음.</li>
<li><strong>효율성(Efficient)</strong>: 작업을 빠르게 수행할 수 있음.
<img src="https://velog.velcdn.com/images/_thist_/post/81264cd8-363f-4a95-9d0e-b2d228e54ed0/image.png" alt=""></li>
</ul>
<blockquote>
<p>컴퓨터 과학자, 심리학자인 허버트 사이먼(Herbert Simon)의 말로, <strong>&quot;인간을 제대로 연구하는 것은 디자인의 과학이다&quot;</strong>라는 의미를 담고 있다. </p>
</blockquote>
<p>이는 인간 행동과 상호작용을 이해하기 위해 디자인이 얼마나 중요한지를 강조하는 말이다. </p>
<p>특히 HCI(Human-Computer Interaction) 분야에서, 디자인은 단순히 미적 요소가 아니라 인간의 필요와 행동을 반영하여 기술과 상호작용하는 방식을 형성하는 핵심적인 학문이라는 것을 뜻한다.</p>
<h3 id="ui--ux">UI / UX</h3>
<p><img src="https://velog.velcdn.com/images/_thist_/post/23434a89-48c7-4486-8c5f-73a8969f16dc/image.png" alt=""></p>
<blockquote>
<p><strong>UI/UX (User Interface/User Experience)에서,</strong> 주로 UI는 사용자가 컴퓨터나 애플리케이션과 상호작용할 수 있는 인터페이스를 말하며, UX는 사용자가 이 인터페이스를 사용할 때의 전체적인 경험을 의미한다. </p>
</blockquote>
<p>다시 말해, <strong>UI는 시각적 디자인에 초점</strong>을 맞추고, <strong>UX는 전체적인 사용자 경험을 향상</strong>시키는 것에 중점을 두고 있다.</p>
<p>그리고 이 UI/UX는 HCI의 결과물 중 하나이다.</p>
<h3 id="좋은-ux--ui를-만들기-위해선">좋은 UX / UI를 만들기 위해선?</h3>
<p><strong>1. 사용자 중심 디자인</strong>
    ▶ 사용자의 인지 능력 이해: 지각, 물리적 조작, 기억력, 조직적 직무 능력 등을 고려.
    ▶ 사용자가 지속적으로 참여하도록 유지: 개발자와 사용자가 함께 작업.
    ▶ 사용자 관점에서 세상을 바라보기: 기술 중심이 아닌 사용자 필요에 맞춘 설계.
    <br>
<strong>2. 기술이 아닌 사용자 우선</strong>
    ▶ 기술 중심이나 기능 주도적 접근이 아닌, 사용자의 필요와 경험을 우선시하는 디자인 철학을 채택.</p>
<h2 id="사례">사례</h2>
<p>대표적인 예로 우리가 흔히 아는 &#39;Apple&#39;이 있다. 
<img src="https://velog.velcdn.com/images/_thist_/post/0b43b513-b80a-47fa-86a7-b10f64bdd49c/image.png" alt=""></p>
<p>애플은 디자인 철학으로 세 가지 주요 원칙을 강조하고 있는것을 확인 할 수 있는데,</p>
<p><strong>1. Clarity (선명하게):</strong> 모든 텍스트는 크기와 상관없이 명확하게 읽을 수 있어야 하며, 아이콘은 정밀하고 깨끗하게 디자인되어야 한다.</p>
<p><strong>2. Deference (컨텐츠를 최우선으로):</strong> 최소한의 장식 요소를 사용해 인터페이스를 가볍게 유지하고, 컨텐츠를 강조한다.</p>
<p><strong>3. Depth (깊이 활용 다양한 콘텐츠 접근):</strong> 터치와 탐색 가능성을 통해 기능성과 추가 콘텐츠에 접근하면서 맥락을 잃지 않도록 설계한다.</p>
<h3 id="hci의-중요성--business-aspect-">HCI의 중요성 ( Business aspect )</h3>
<p>현재 전세계 기업의 시가총액 순위는 1위가 애플, 2위가 마이크로소프트이다. 
그럼 어떻게, 애플은 시총 1위의 마이크로소프트를 뛰어 넘게 되었을까?</p>
<p>그 이유들은 다음과 같다.</p>
<blockquote>
<p><strong>1. 사용성에 대한 집착:</strong> Apple은 뛰어난 사용자 경험과 사용성에 집착하는 접근을 유지하였다.
<strong>2. 열광적인 고객 기반:</strong> 강력한 브랜드 충성도와 매니아층을 형성하였다.
<strong>3. 핵심 역량 집중:</strong> 소프트웨어와 하드웨어 디자인에 집중하며, 하드웨어 제조는 아웃소싱하였다.
<strong>4. 제품 및 앱스토어 통제:</strong> 전체 생태계를 통제하여 품질을 유지하였다.
<strong>5. 기술 패러다임 전환 포착:</strong> iPod, iPhone, iPad를 통해 새로운 기술 시대를 선도하였다.</p>
</blockquote>
<h3 id="hci의-관련-분야">HCI의 관련 분야</h3>
<p>HCI는 크게, <strong>인간분야</strong>, <strong>컴퓨터분야</strong>, <strong>사용자분야</strong> 3가지 파트로 나누어 볼 수 있다.</p>
<p><strong>인간 이해</strong></p>
<ul>
<li>심리학, 인지과학, 사회과학, 인류학: 인간 정보 처리와 사회 문제 연구.</li>
<li>심리학, 인지과학: 인간이 현상을 어떻게 받아들이는지 이해.</li>
<li>사회과학, 인류학: 컴퓨터 시스템이 사회에 미치는 영향 연구.</li>
</ul>
<p><strong>컴퓨터 이해</strong></p>
<ul>
<li>컴퓨터 과학, 전기공학, 산업공학: 상호작용 방식 구현, 새로운 장치와 센서 개발.</li>
<li>컴퓨터 과학: 상호작용 방법 구현.</li>
<li>전기공학: 새로운 장치 및 센서 개발.</li>
<li>산업공학: 인간의 작업 분석.</li>
</ul>
<p><strong>사용성 이해</strong></p>
<ul>
<li>인지공학, 인간공학: 인간의 인지적, 신체적 활동 지원 연구.</li>
<li>디자인: 제품, 웹, UX 디자인 및 정보 시각화.</li>
<li>최근 동향: 사물 디자인에서 상호작용과 환경 디자인으로 변화.</li>
</ul>
<p>이렇듯, HCI는 어느 한 분야에서만 연구하는것이 아닌, 다방면으로 분석하고 연구하는 <strong>다학제 학문</strong>임을 알 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 데이터베이스 ] DBMS와 FileSystem]]></title>
            <link>https://velog.io/@_thist_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-DBMS%EC%99%80-FileSystem</link>
            <guid>https://velog.io/@_thist_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-DBMS%EC%99%80-FileSystem</guid>
            <pubDate>Tue, 03 Sep 2024 14:20:47 GMT</pubDate>
            <description><![CDATA[<h1 id="database-system">DataBase System</h1>
<h3 id="database-management-system">Database Management System</h3>
<p>정의: 데이터베이스를 관리하고 운영하는 소프트웨어.</p>
<p>*<em>DBMS의 특징 *</em></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 상호연관 되어 있는 데이터들에 접근할 수 있는 프로그램들의 집합이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 편리하고 효율적으로 사용할 수 있는 환경을 제공해준다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 데이터베이스는 매우 클 수 있다. (많은 사용자들을 저장해야하기 때문에.) </p>
<p>*<em>일상속의 DataBase 응용분야 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 은행업, 항공사, 대학교, 판매, 제조업, 인사 관리등</p>
<p>*<em>대학교에서의 DataBase System *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 예시1) 새로운 학생, 교수, 강좌 추가하기. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 예시2) 강의에 학생들 추가 및 수업 제작. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 예시3) 학생들에게 성적을 부여하고 GPA 계산 </p>
<p>초기에는, 이러한 시스템들은 ‘파일시스템’위에 구축되었다. </p>
<h3 id="파일시스템-filesystem">파일시스템 (FileSystem)</h3>
<p><img src="https://velog.velcdn.com/images/_thist_/post/90df22d7-a74f-43d6-a616-1f51a805e05f/image.png" alt=""></p>
<p>정의: 말 그대로 파일들을 이용하여 System을 구축한 것. </p>
<p><strong>파일시스템의 단점 **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. **데이터 중복과 불일치</strong> -  각 파일에 Data가 중복해서 발생할 수 있음.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. <strong>데이터 접근의 어려움</strong>  - 새로운 작업을 수행하기 위해 새로운 Program개발이 요구될 수 있음. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. <strong>데이터 고립</strong> - 데이터가 여러 파일들과 다양한 형식으로 저장되어 있어서, 가져오기 번거로움. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. <strong>무결성 문제</strong> - 새로운 조건을 추가하거나 기존 조건들을 변경하는 것이 어렵다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. <strong>원자성(Atomicity) 문제</strong> - 업데이트 중 장애가 발생하면, 데이터베이스 중 일부만 업데이트된 불일치 상태가 될 수 있음. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6. <strong>다중 사용자 동시 접근</strong> - 성능 향상을 위해 동시성 제어가 필요할 수 있음. - 통제되지 않는 동시성 제어는 데이터 불일치성을 야기할 수 있음. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7. <strong>보안문제</strong> - 일부 데이터만 특정 사용자에게 보여주는 것이 어려움. </p>
<h3 id="스키마와-인스턴스-schemas-and-instances-">*<em>스키마와 인스턴스 (Schemas and Instances) *</em></h3>
<h4 id="스키마-schema"><strong>스키마 (Schema)</strong></h4>
<p><strong>정의: 스키마는 데이터베이스의 구조를 정의하는 틀.</strong>
테이블, 열, 데이터 타입, 제약 조건 등을 포함해 데이터베이스의 전체적인 설계도 역할을 수행한다.</p>
<p><strong>특징</strong>
&nbsp;&nbsp;&nbsp;◼일반적으로 데이터베이스를 처음 설계할 때 설정되며, 잘 변경되지 않는다.
&nbsp;&nbsp;&nbsp;◼데이터베이스에 저장될 데이터의 형태와 구조를 정의한다.
&nbsp;&nbsp;&nbsp;◼데이터베이스의 메타데이터라고도 할 수 있다.</p>
<p><strong>예시</strong>
&nbsp;&nbsp;&nbsp;학교 데이터베이스 스키마에서는 학생 테이블에 이름, 학번, 학과 열이 있다고 정의할 수 있다.</p>
<h4 id="인스턴스-instance"><strong>인스턴스 (Instance)</strong></h4>
<p><strong>정의: 인스턴스는 특정 시점에 데이터베이스에 저장된 데이터의 실제 상태.</strong></p>
<p><strong>특징</strong>
&nbsp;&nbsp;&nbsp;◼데이터는 시간에 따라 변동될 수 있으므로 인스턴스는 시점마다 달라질 수 있다.
&nbsp;&nbsp;&nbsp;◼특정 시점에서의 데이터 상태를 나타내며, 데이터가 추가되거나 수정되면 인스턴스도 변한다.</p>
<p><strong>예시</strong>
&nbsp;&nbsp;&nbsp;학생 데이터베이스 인스턴스는 학생 테이블에 현재 등록된 모든 학생의 실제 데이터를 포함한다. 오늘과 내일의 인스턴스는 학생들의 등록 현황에 따라 변경될 수 있다.</p>
<h3 id="스키마schema의-종류"><strong>스키마(Schema)의 종류</strong></h3>
<p>*<em>⚫ 개념적 스키마 (Conceptual Schema) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;◼ 데이터베이스의 전체 구조와 관계를 정의. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;◼ 사용자나 애플리케이션이 보는 데이터의 통합된 개념적 구조 설계.</p>
<p>*<em>⚫ 논리적 스키마 (Logical Schema) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;◼ 데이터베이스의 전체 구조. (= 설계도) 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;◼ 어떠한 데이터가 들어갈지 설계하는 단계.</p>
<p>*<em>⚫ 물리적 스키마 (Physical Schema) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;◼ 데이터베이스가 실제로 어떻게 저장되는지에 대한 물리적 구조.</p>
<p>이러한 스키마들은 서로 독립적이며, 물리적 스키마를 변경하여도 논리적 스키마에 영향을 미치지 않는 것을 ‘<strong>물리적 데이터 독립성 (Physical data Independence)</strong>’라고 한다. </p>
<h3 id="데이터-모델-data-model-">*<em>데이터 모델 (Data Model) *</em></h3>
<p>정의: 데이터를 설명하기 위한 도구들의 모음으로서, 데이터 관계, 데이터의 의미, 데이터 제약조건들을 정의하는데 사용함. </p>
<p><strong>데이터 모델의 종류 **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong>1. 관계형 모델 (Realational Model) **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터를 테이블 형식으로 구성하여 <strong>행(row)과 열(column)</strong>로 관리. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ SQL을 통해 데이터를 처리하며, 가장 널리 사용되는 데이터 모델. 
<img src="https://velog.velcdn.com/images/_thist_/post/7588f5bb-dc1e-4769-b5ee-711b9670a466/image.png" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 행(Row)는 <strong>Tuple</strong> 또는 <strong>Record</strong>라고도 부른다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 열(Column)은 <strong>Field</strong> 또는 <strong>Attribute</strong>라고도 부른다. </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<em>2. 엔티티 – 관계 모델 (Entity – Relationship Model, ER모델) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터베이스 설계를 위해 주로 사용되며, 엔티티(객체)와 그들 간의 관계를 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;시각적으로 표현함. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ ER 다이어그램을 사용하여 데이터 구조를 쉽게 이해할 수 있게 해줌. 
<img src="https://velog.velcdn.com/images/_thist_/post/7d93a1a6-de93-411d-8113-37094823cb0a/image.png" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<em>3. 객체 기반 데이터 모델 (Object-Based Model) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 객체 지향 모델: 객체와 클래스를 사용하여 데이터를 표현하는 모델. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 객체 – 관계형 모델: 관계형 모델과 객체 지향 모델의 특징들을 결합하여 설계된 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;데이터베이스 *<em>(Relation Model + Object Oriented Model) *</em></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<em>4. 반구조화 데이터 모델 (Semi-structured Data Model) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 마크업 언어를 사용하여 데이터를 표현. ( 예: XML ) </p>
<h3 id="xml--extensible-markup-language-"><strong>XML ( Extensible Markup Language )</strong></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• ‘W3C(월드 와이드 웹 컨소시엄)’에 의해 정의된 언어이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 원래는 문서 마크업 언어로 설계되었으며, 데이터베이스 언어가 아니었다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 새로운 태그를 정의하고 중첩된 태그 구조를 만들 수 있는 기능 덕분에 데이터 교환의 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;훌륭한 수단으로 자리 잡게 되었다.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• XML은 차세대 데이터 교환 형식의 기본이 되었다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• XML 문서와 데이터를 파싱, 탐색, 질의할 수 있는 다양한 도구들이 널리 사용되고 있다. </p>
<p><strong>특징 및 장점 **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. **유연한 구조</strong>: 사용자가 필요한 태그를 직접 정의할 수 있어, 다양한 형태의 데이터를 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;표현하고 교환하는 데 적합하다.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. <strong>데이터 교환 표준</strong>: 플랫폼에 상관없이 데이터를 주고받을 수 있어, 웹 서비스와 같은 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;시스템 통합에 광범위하게 사용된다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. <strong>도구의 풍부함</strong>: XML을 파싱하거나 탐색하는 도구들이 많이 개발되어 있어 데이터를 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;다루는 작업이 용이하다. </p>
<p>기타 오래된 모델들 </p>
<ol>
<li><strong>계층형 모델(Hierarchical Model)</strong> : 데이터를 트리 구조로 저장하여 데이터를 표현. </li>
<li><strong>네트워크 모델(Network Model)</strong> : 데이터를 그래프 형태로 표현하여 관계를 표현. </li>
</ol>
<p>*<em>DDL (Data Definition Language - 데이터 정의 언어) *</em>
<img src="https://velog.velcdn.com/images/_thist_/post/0270d34e-4220-4cd3-91b2-c1679a2ef604/image.png" width=300, height=400 >
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ DDL은 데이터베이스 스키마를 정의하기 위한 명세 표기법이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ DDL 컴파일러는 데이터 딕셔너리 (Data Dictionary)에 저장되는 테이블 템플릿 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;세트를 생성. </p>
<h3 id="데이터-딕셔너리-data-dictionary-">*<em>데이터 딕셔너리 (Data Dictionary) *</em></h3>
<p>*<em>1. 데이터베이스 스키마 정의 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 테이블, 열, 데이터 타입, 인덱스, 뷰, 제약 조건 등의 구조적인 정보를 저장한다.</p>
<p>*<em>2. 무결성 제약 조건 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 예를 들어, 기본 키(Primary Key), 외래 키(Foreign Key), 고유 제약(Unique Constraint) 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;등의 규칙을 정의하고 저장한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터의 일관성과 정확성을 유지하기 위한 제약 조건이 포함된다. </p>
<p>*<em>3. 권한과 접근 제어 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터베이스 내에서 누가 어떤 데이터에 접근할 수 있는지에 대한 권한 정보를 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;관리한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 사용자와 역할(role)에 대한 정보, 그리고 각 사용자에게 허용된 권한이 포함된다. </p>
<p>*<em>4. 데이터 관계 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 테이블 간의 관계(예: 일대다, 다대다)를 정의하여 데이터 간의 연결성을 설명한다. </p>
<p>*<em>5. 기타 메타데이터 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 트리거(Trigger), 저장 프로시저(Stored Procedure), 기본값(Default Value) 등의 정보도 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;포함할 수 있다. </p>
<p><strong>데이터 딕셔너리의 중요성 **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• **데이터베이스 관리</strong>: 데이터베이스의 구조와 규칙을 명확하게 정의하고 저장하여 관리를 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;용이하게 해준다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• <strong>데이터 무결성 유지</strong>: 정의된 제약 조건을 통해 데이터의 무결성을 유지할 수 있게 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;해준다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• <strong>보안 강화</strong>: 사용자 권한을 명확하게 관리함으로써 보안을 강화할 수 있다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• <strong>문서화 및 유지 보수</strong>: 데이터베이스 구조를 문서화하여 시스템의 이해도를 높이고, 유지 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;보수를 쉽게 할 수 있도록 돕는다. </p>
<p>*<em>DML (Data Manipulation Language – 데이터 조작 언어) *</em>
<img src="https://velog.velcdn.com/images/_thist_/post/83c2aae6-67ee-414a-a2be-fc837b3d590d/image.png" width=500, height=400>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ DML은 데이터를 접근하고 조작하기 위한 언어이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ DML은 ‘쿼리 언어(Query Language)’라고도 불린다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 또한, DML은 ‘선언형 언어(Declarative)언어’로서, 데이터를 어떻게 가져오는지 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;명시하지 않고 어떤 데이터를 가져올지를 지정한다.</p>
<h3 id="sql-structured-query-language--구조적-질의-언어-">*<em>SQL (Structured Query Language – 구조적 질의 언어) *</em></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ SQL은 데이터베이스 관리 시스템(DBMS)에서 데이터를 정의하고 관리하기 위해 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;설계된 특수 목적의 프로그래밍 언어이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 상업적으로 가장 널리 사용되는 언어이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⚫ 응용 프로그램은 임베디드 SQL이나 ODBC(JDBC)와 같은 인터페이스를 통해 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQL쿼리를 데이터베이스에 저장할 수 있다. </p>
<h3 id="database-design-">*<em>DataBase Design *</em></h3>
<p>*<em>➢ 개념적 설계 (Conceptual Design) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 사용자의 요구사항을 바탕으로 데이터베이스의 전체적인 구조를 개념적으로 정의. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 주로 ER 다이어그램을 사용하여 엔티티, 속성, 관계를 시각적으로 표현함. </p>
<p>*<em>➢ 논리적 설계 (Logical Design) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 개념적 설계를 바탕으로 데이터베이스 관리 시스템(DBMS)에 맞는 논리적 모델을 구축. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 주로 관계형 모델을 사용하여 테이블, 열, 관계를 정의. </p>
<p>*<em>➢ 물리적 설계 (Physical Design) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 논리적 설계를 실제 데이터베이스 시스템에 구현. </p>
<h3 id="스토리지-매니저-storage-manager"><strong>스토리지 매니저 (Storage Manager)</strong></h3>
<p>스토리지 매니저는 데이터베이스 시스템의 저수준 데이터와 응용 프로그램 및 쿼리 간의 인터페이스 역할을 하는 프로그램 모듈이다. 
스토리지 매니저는 데이터베이스의 저장 및 접근 효율성을 높이는 데 중요한 역할을 한다. </p>
<p><strong>주요 역할 및 책임</strong>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 효율적인 데이터 저장, 검색 및 업데이트 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터를 효율적으로 저장하고 필요할 때 빠르게 검색하며, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;데이터를 수정할 때도 신속하게 반영되도록 한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 운영 체제의 파일 관리자와의 상호작용 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 운영 체제의 파일 시스템과 협력하여 데이터의 물리적 저장 및 관리를 수행한다. </p>
<p>*<em>1. 스토리지 접근 (Storage Access) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터를 빠르고 효율적으로 접근할 수 있도록 접근 방식(예: 순차 접근, 랜덤 접근 등)을 관리함. </p>
<p>*<em>2. 파일 조직 (File Organization) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 데이터를 저장할 때 파일의 구조를 어떻게 구성할 것인지 결정해준다. 예를 들어, 데이터를 연속적으로 저장할지, 블록 단위로 나눌지 등을 결정한다.</p>
<p>*<em>3. 인덱싱 및 해싱 (Indexing and Hashing) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 인덱스나 해시 테이블을 사용하여 데이터를 빠르게 검색할 수 있도록 한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 인덱싱은 검색 속도를 높이는 데 중요한 역할을 하며, 해싱은 데이터의 분산 저장을 통해 효율성을 높여준다. </p>
<h3 id="쿼리-프로세서query-processor-">*<em>쿼리 프로세서(Query Processor) *</em></h3>
<p>정의: 쿼리 프로세서는 데이터베이스 시스템에서 사용자가 입력한 쿼리를 처리하고 실행하는 역할을 
담당하며, 쿼리 처리 과정은 크게 세 단계로 나뉘게 된다.
<img src="https://velog.velcdn.com/images/_thist_/post/7c45f438-05a1-4ce4-b76e-c8cfb66fe289/image.png" alt=""></p>
<p><strong>1. 파싱 및 번역 (Parsing and Translation) **
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 쿼리 프로세서는 입력된 쿼리를 분석하여 구문 오류를 체크하고, 이를 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong>관계 대수 표현(Relational-Algebra Expression)<strong>으로 변환한다. 
&nbsp;&nbsp;&nbsp;&nbsp;➢ **파서(Parser)</strong>와 <strong>번역기(Translator)</strong>가 이 과정을 수행하며, 쿼리의 논리적 구조를 파악하고 시스템이 이해할 수 있는 형태로 변환한다.</p>
<p>*<em>2. 최적화 (Optimization) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 변환된 관계 대수 표현을 최적화하여 효율적인 실행 계획을 수립한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 최적화기는 여러 가지 실행 계획 중에서 비용이 가장 적게 드는 계획을 선택한다. 이는 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;데이터 통계와 시스템의 상태 등을 바탕으로 결정되게 된다. </p>
<p>*<em>3. 평가 (Evaluation) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 최적화된 실행 계획을 실제로 실행하여 결과를 생성한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 평가 엔진(Evaluation Engine)이 실행 계획을 따라 데이터를 처리하고, 최종적으로 쿼리의 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;결과를 사용자에게 제공한다. </p>
<p>*<em>쿼리 처리 과정의 흐름 *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 사용자가 쿼리를 입력하면 파서와 번역기가 이를 관계 대수 표현으로 변환하고, 이후 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;최적화기가 최적의 실행 계획을 생성한다. 마지막으로, 평가 엔진이 이 실행 계획에 따라 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;데이터를 처리하여 쿼리 결과를 반환한다. </p>
<h3 id="쿼리query의-대안적-평가-방법-">*<em>쿼리(Query)의 대안적 평가 방법 *</em></h3>
<p>*<em>1. 동등한 표현식 (Equivalent Expressions) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 동일한 결과를 제공하는 여러 형태의 쿼리 표현이 있을 수 있는데, 이러한 동등한 표현식은 쿼리의 성능을 개선할 수 있는 가능성을 제공한다. </p>
<p>*<em>2. 각 작업에 대한 다양한 알고리즘 (Different Algorithms for Each Operation) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 쿼리의 각 작업(예: 조인, 정렬, 집합 연산)에 대해 다양한 알고리즘이 존재한다. 예를 들어, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;조인을 수행할 때는 중첩 루프 조인, 해시 조인, 정렬 병합 조인 등 여러 알고리즘을 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;사용할 수 있기에, 이러한 알고리즘들은 상황에 따라 성능 차이가 크게 날 수 있다. </p>
<p>*<em>3. 작업 비용 추정 (Estimation of the Cost of Operations) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 각 쿼리 연산의 비용을 추정하여, 가장 적은 비용으로 수행할 수 있는 계획을 선택한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;비용은 주로 CPU 사용량, I/O 접근 횟수, 메모리 사용량 등을 기반으로 계산되게 된다. </p>
<p>*<em>4. 평가 방법 간의 비용 차이 (Cost Difference) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 쿼리를 잘못 평가할 경우, 최적화된 방법에 비해 매우 높은 비용이 발생할 수 있다.  </p>
<p>*<em>5. 통계 정보 의존성 (Dependency on Statistical Information) *</em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 쿼리 최적화는 데이터베이스가 유지하는 관계에 대한 통계 정보에 크게 의존한다. 이 정보에는 테이블 크기, 인덱스의 유용성, 데이터 분포 등이 포함되게 된다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;➢ 중간 결과에 대한 통계치를 추정하여 복잡한 표현식의 총 비용을 계산하는 데 필요하다. </p>
<h3 id="transaction-트랜잭션-">*<em>Transaction (트랜잭션) *</em></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;• 트랜잭션은 데이터베이스에서 수행되는 하나의 논리적 작업 단위로, 데이터베이스의 일관성을 유지하는 것이 핵심이다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 트랜잭션은 데이터베이스의 상태를 변경할 수 있으며, 모든 작업이 성공적으로 완료되거나 모두 취소되어야 한다. 이를 ‘원자성(Atomicity)’이라 부른다. </p>
<h3 id="transaction-manager-트랜잭션-관리자-">*<em>Transaction Manager (트랜잭션 관리자) *</em></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 트랜잭션 관리자는 데이터베이스 내에서 트랜잭션을 조정하고 관리한다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 주요 역할은 트랜잭션이 성공적으로 완료될 때까지 모든 변경 사항을 추적하며, 실패 시에는 변경 사항을 롤백 하여 데이터베이스를 원래 상태로 되돌리는 역할을 수행한다. </p>
<h3 id="concurrency-control-manager-동시성-제어-관리자-">*<em>Concurrency-Control Manager (동시성 제어 관리자) *</em></h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 동시성 제어 관리자는 여러 트랜잭션이 동시에 실행될 때 데이터의 일관성을 유지하기 위해 관리해준다. 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;• 트랜잭션 간의 충돌을 방지하고, 데이터의 무결성을 보장하기 위한 다양한 동시성 제어 기법 (예: 잠금, 타임스탬프)을 사용한다. </p>
<h3 id="데이터베이스-시스템의-역사-">*<em>데이터베이스 시스템의 역사 *</em></h3>
<ol>
<li>1950 ~ 1960년 : 자기 테이프를 이용한 저장방식. (펀치를 이용하여 입력함) </li>
<li>1960 ~ 1970년 : 하드디스크를 이용한 데이터의 접근이 가능해짐. Edgar F.Codd가 관계형 
데이터 모델 (ER Model)을 정의함. 또한, IBM에서는 R언어를 발표. </li>
<li>1980년 : ORACLE이 등장하고, SQL이 산업의 표준이 되었음. </li>
<li>1990년 : 대규모로 확장되었으며, 전자상거래가 발달하였음. </li>
<li>2000년 : XML 및 XQuery가 표준화 되었고, 데이터베이스의 관리가 자동화되었다. </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 자료구조 ] 큐(Queue)]]></title>
            <link>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%ED%81%90-Queue</link>
            <guid>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%ED%81%90-Queue</guid>
            <pubDate>Thu, 29 Aug 2024 09:44:14 GMT</pubDate>
            <description><![CDATA[<p>이번 글에서는 자료구조 중 하나인 큐(Queue)에 대해 알아보도록 하자.
큐는 컴퓨터 과학에서 자주 사용되는 기본적인 자료구조로, 데이터를 선입선출(FIFO, First In First Out) 방식으로 관리된다. 
먼저 들어온 데이터가 먼저 처리되는 구조로, 여러 가지 상황에서 매우 유용하게 사용되고 있다.</p>
<h2>큐(Queue)의 기본 개념</h2>
큐는 First In, First Out(FIFO) 구조를 따르는 선형 자료구조이다.
이는 줄을 서서 기다리는 상황과 유사하게, 먼저 들어온 데이터가 가장 먼저 나가는 것을 의미한다. 

<img src= "https://velog.velcdn.com/images/_thist_/post/4a885689-d6ec-4652-9f4a-be8a4a77cb1b/image.png" width=800 height=100>
<br>
큐에서 사용되는 연산들은 다음과 같다.
<br>

<ul>
<li><strong>삽입(Enqueue):</strong> 큐의 끝(Rear)에 새로운 Data를 추가한다.</li>
<li><strong>삭제(Dequeue):</strong> 큐의 앞(Front)에 Data를 제거하고 반환한다.</li>
<li><strong>큐가 가득 찼는지 확인(Queue_full):</strong> 큐가 더 이상 Data를 추가할 수 없는 상태인지 확인한다.</li>
<li><strong>큐가 비어 있는지 확인(Queue_Empty):</strong> 큐에 Data가 없는 상태인지 확인한다.<br>
<h4>위의 네 가지 경우에 대해 그림으로 보도록 하자.</h4>
<br>

</li>
</ul>
<h3>1. 최초의 큐(Queue)상태</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/8636599f-198b-4d76-903e-b2ce9023df51/image.png" width=800 height=100>현재 Queue내에는 아무런 Data가 존재하지 않음으로, Front와 Rear를 -1로 초기화 <br>(배열은 0번부터 시작하기 때문에)
<br><br>

<h3>2. 'Apple' Data 삽입(Enqueue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/b46727f4-3e22-4928-8345-c1986a82a77b/image.png" width=800 height=100>최초의 Data가 Queue에 들어오게 된다면 Front와 Rear를 0으로 초기화.
<br><br>

<h3>3. 'Melon' Data 삽입(Enqueue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/b00c9089-1791-4f68-867b-e7a002f7f73b/image.png" width=800 height=100>Data가 삽입되었으므로 Rear를 1증가.
<br><br>

<h3>4. 'Cake' Data 삽입(Enqueue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/c2c66d11-bde4-4be8-9179-641f0da15c71/image.png" width=800 height=100>Data가 삽입되었으므로 Rear를 1증가.
<br><br>

<h3>5. 'Apple' Data 삭제(Dequeue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/5d0d2df3-679e-4af5-8401-51ab5e739d1c/image.png" width=800 height=100>Data가 삭제되었으므로 Front를 1증가.
<br><br>

<h3>6. 'Phone' Data 삽입(Enqueue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/f54fe22e-2a94-49c8-b6a1-d4ba9d120143/image.png" width=800 height=100>Data가 삽입되었으므로 Rear를 1증가.
<br><br>

<h3>7. 'Melon' Data 삭제(Dequeue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/6611c55d-9bac-4a4c-99d3-d418b713b790/image.png" width=800 height=100>Data가 삭제되었으므로 Front를 1증가.
<br><br>

<h3>8. 'Cake' Data 삭제(Dequeue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/c2aa8c72-844d-4a0c-831f-96abacdb6762/image.png" width=800 height=100>Data가 삭제되었으므로 Front를 1증가.<br>(Front와 Rear의 위치가 같아졌다. 이로써 Data가 하나만 남음을 의미.)
<br><br>

<h3>9. 'Phone' Data 삭제(Dequeue)</h3>
<img src="https://velog.velcdn.com/images/_thist_/post/b4976c18-45d9-4d46-aeae-7db57e27c2f1/image.png" width=800 height=100>Data가 삭제되었으므로 Front를 1증가.<br>(Front가 Rear값을 초과하였다. 이로써, Queue는 값이 비었음을 의미.)
<br><br>

<p>이렇듯 큐는 무조건 순차적으로 따르는것인가? 라고 생각할 수 있지만, Queue에는 종류가 많다. 
이러한 Queue를 응용하여 <strong>선형큐(Circular Queue)</strong>와 <strong>우선순위큐(Priority Queue)</strong>등이 존재한다. </p>
<p>그리고 방금처럼 순환되지 않는 큐를 우리는 <strong>비순환 큐(Non-Circular Queue)</strong>라고 표현한다.</p>
<p>이러한 비순환 큐를 구현하는 가장 기본적이고 쉬운 방법은 1차원 배열을 사용하는 것이다.</p>
<p>큐는 이렇듯FIFO 구조를 가지며 다양한 상황에서 데이터를 효율적으로 관리하는 데 사용되게 된다.
하지만, 비순환 배열 기반 큐는 간단하지만 메모리 낭비가 발생할 수 있는 단점이 존재한다.</p>
<h4 id="code">Code</h4>
<hr>
<pre><code class="language-c">#define _CRT_SECURE_NO_WARNINGS
#include&lt;stdio.h&gt;
#define M 10000  // 큐의 최대 크기를 정의

// 함수 선언
void Insert();
void Delete();
void Queue_Empty();
void Queue_Full();
void Print_Queue();

// 전역 변수 선언
int arr[M];  // 큐 배열
int Front, Rear;  // 큐의 Front와 Rear 인덱스

int main(void) {
    int Sel = 0;

    // 메뉴를 출력하고 사용자의 선택을 처리하는 반복문
    do {
        printf(&quot; --------------------\n&quot;);
        printf(&quot; |    1.Insert      |\n&quot;);
        printf(&quot; |    2.Delete      |\n&quot;);
        printf(&quot; |    3.Is_Empty?   |\n&quot;);
        printf(&quot; |    4.Is_Full?    |\n&quot;);
        printf(&quot; |    5.Print       |\n&quot;);
        printf(&quot; --------------------\n&quot;);

        printf(&quot;Select Mode:&quot;);
        scanf(&quot;%d&quot;, &amp;Sel);  // 사용자로부터 선택을 입력받음

        // 사용자가 선택한 옵션에 따라 함수 호출
        switch (Sel) {
        case 1: {
            Insert();  // 값 삽입
            break;
        }
        case 2: {
            Delete();  // 값 삭제
            break;
        }
        case 3: {
            Queue_Empty();  // 큐가 비었는지 확인
            break;
        }
        case 4: {
            Queue_Full();  // 큐가 꽉 찼는지 확인
            break;
        }
        case 5: {
            Print_Queue();  // 큐에 있는 값을 출력
            break;
        }
        }
    } while (Sel != -1);  // 사용자가 -1을 입력할 때까지 반복

    return 0;
}

// 큐에 값을 삽입하는 함수
void Insert() {
    int S;
    printf(&quot;Input:&quot;);
    scanf(&quot;%d&quot;, &amp;S);  // 사용자로부터 삽입할 값을 입력받음

    if (Rear &lt; M) {  // Rear 값이 M보다 작다면 (큐에 공간이 남아있다면)
        arr[Rear++] = S;  // Rear 인덱스에 값을 삽입하고 Rear를 1 증가
        printf(&quot;Value is successfully Inserted!\n&quot;);
    }
    else {
        printf(&quot;Queue is Full!!\n&quot;);  // 큐가 꽉 찬 경우
    }

    return;
}

// 큐에서 값을 삭제하는 함수
void Delete() {
    if (Front &gt;= 0 &amp;&amp; Front &lt; Rear) {  // Front가 0 이상이고 Rear보다 작다면 (삭제할 값이 있다면)
        Front++;  // Front를 1 증가시켜 다음 요소를 가리키게 함
        printf(&quot;Value is successfully deleted!!\n&quot;);
    }
    else {
        printf(&quot;Queue is already empty!!\n&quot;);  // 큐가 비어있는 경우
    }

    return;
}

// 큐가 비어있는지 확인하는 함수
void Queue_Empty() {
    if (Front == Rear) {  // Front와 Rear가 같다면 큐가 비어있는 상태
        printf(&quot;Queue is Empty!!\n&quot;);
    }
    else {
        printf(&quot;Queue is not Empty!!\n&quot;);  // 큐에 요소가 있는 경우
    }
    return;
}

// 큐가 꽉 찼는지 확인하는 함수
void Queue_Full() {
    if (Front == 0 &amp;&amp; Rear == M) {  // Rear가 큐의 최대 크기 M에 도달했다면 큐가 꽉 찬 상태
        printf(&quot;Queue is Full!!\n&quot;);
    }
    else {
        printf(&quot;Queue is not Full!!\n&quot;);  // 큐에 여유 공간이 있는 경우
    }
    return;
}

// 큐의 현재 상태를 출력하는 함수
void Print_Queue() {
    // Front부터 Rear까지의 모든 요소를 출력
    for (int i = Front; i &lt; Rear; i++) {
        printf(&quot;%d &quot;, arr[i]);
    }
    printf(&quot;\n&quot;);

    return;
}
</code></pre>
<p>Front를 단순히 앞으로만 당기고 있어,  메모리 낭비가 정말 심한 코드이다. 
따라서 별로 추천하고 싶지 않은 코드이다..ㅎ</p>
<p>이에 대한 해결방법으로는 Circular-Queue(원형큐)나 STL Vector를 사용하는것이 좋은 방안이 될 수 있다.</p>
<p><strong>Circular-Queue(원형큐)</strong>나 <strong>STL Vector</strong>에 대해서는 조만간 올리도록 하겠다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 프로그래밍 기초 ] 값에 의한 참조 (Call by Value), 주소에 의한 참조 (Call by Reference)]]></title>
            <link>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%EA%B0%92%EC%97%90-%EC%9D%98%ED%95%9C-%EC%B0%B8%EC%A1%B0-Call-by-Value-%EC%A3%BC%EC%86%8C%EC%97%90-%EC%9D%98%ED%95%9C-%EC%B0%B8%EC%A1%B0-Call-by-Reference</link>
            <guid>https://velog.io/@_thist_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B8%B0%EC%B4%88-%EA%B0%92%EC%97%90-%EC%9D%98%ED%95%9C-%EC%B0%B8%EC%A1%B0-Call-by-Value-%EC%A3%BC%EC%86%8C%EC%97%90-%EC%9D%98%ED%95%9C-%EC%B0%B8%EC%A1%B0-Call-by-Reference</guid>
            <pubDate>Wed, 17 Jul 2024 18:47:17 GMT</pubDate>
            <description><![CDATA[<p>오늘은 프로그래밍을 배우는 분들이라면 꼭 알아두어야 할 중요한 개념인 
&quot;<em><strong>Call by Value(값에 의한 호출)</strong></em>&quot;와 &quot;<strong><em>Call by Reference(참조에 의한 호출)</em></strong>&quot;에 대해 설명해 보고자 한다.</p>
<p>이 두 개념은 함수나 메서드 호출 시 인수(argument)가 어떻게 전달되는지를 이해하는 데 매우 중요한 역할을 하기에, 꼭 짚고 넘어가보자.</p>
<p>이전에 C언어 공부를 했던 사람이라면 들어봤을법한 내용이다.</p>
<ul>
<li><strong>Call by Value</strong></li>
<li>*<em>Call by Reference *</em></li>
</ul>
<p>혹시 두 함수의 호출방식에 대해서 기억하고 있는가?</p>
<p>_<strong>Call by Value(값에 의한 호출)</strong>_은 <strong>값을 인자로 전달하는 함수 호출방식</strong>이며,
_<strong>Call by Reference(주소에 의한 호출)</strong>_은 <strong>주소를 인자로 전달하는 함수 호출방식</strong>이다.</p>
<p>이 차이를 알기 위해, 단순히 Swap하는 예제를 통해 알아보도록 하자.</p>
<p><strong>사용언어: C++</strong></p>
<pre><code class="language-cpp">// 값에 의한 참조 ( Call by Value )

int main(void) {
    int num1 = 10;
    int num2 = 20;

    cout &lt;&lt; &quot; 변경 전 결과: &quot; &lt;&lt; num1 &lt;&lt; &#39; &#39; &lt;&lt; num2 &lt;&lt; endl;
    Swap(num1, num2);
    cout &lt;&lt; &quot; 변경 후 결과: &quot; &lt;&lt; num1 &lt;&lt; &#39; &#39; &lt;&lt; num2 &lt;&lt; endl;

    return 0;
}

void Swap(int Val1, int Val2) {
    int Temp;

    Temp = Val1;
    Val1 = Temp;
    Temp = Val2;

    return;
}</code></pre>
<p>num1에 10을, num2에 20을 넣고 Swap함수를 통해 인자 두개를 전달한 다음, Print했을 때, 
결과가 어떻게 나올까?
<img src="https://velog.velcdn.com/images/_thist_/post/53f7e5e8-14c5-4f6e-a1b9-2b8e29fd61f6/image.png" alt=""></p>
<p>값이 바뀌지 않았다. </p>
<p>왜 그럴까?
<img src="https://velog.velcdn.com/images/_thist_/post/6dcb298d-6a9d-4640-bf4a-452e7921f1bb/image.png" width='60%'></p>
<p>이는 Swap함수에서 매개변수들이 num1과 num2의 인자값들만 받았기 때문이다.</p>
<p>따라서 매개변수 Val1과 Val2는 함수외부에 선언된 변수의 접근이 불가능하다.</p>
<p>결국, 다음과 같이 함수를 정의하면 Swap을 할 수 없게된다.</p>
<p>그러면 어떻게 하면 함수외부에 있는 값들에 대해 접근할 수 있을까?</p>
<p>바로 주소를 전달해서 바꾸는 방법이다.</p>
<p>그것이 곧 <strong><em>Call by Reference(주소에 의한 참조)</em></strong>이다.</p>
<p>※ 이 내용은 <strong>포인터(Pointer)</strong>에 대한 선행을 필요로 합니다.</p>
<pre><code class="language-cpp">// 주소에 의한 참조 ( Call by Reference )

int main(void) {
    int num1 = 10;
    int num2 = 20;

    cout &lt;&lt; &quot; 변경 전 결과: &quot; &lt;&lt; num1 &lt;&lt; &#39; &#39; &lt;&lt; num2 &lt;&lt; endl;
    Swap(&amp;num1, &amp;num2);
    cout &lt;&lt; &quot; 변경 후 결과: &quot; &lt;&lt; num1 &lt;&lt; &#39; &#39; &lt;&lt; num2 &lt;&lt; endl;

    return 0;
}

void Swap(int* Val1, int* Val2) {
    int temp;

    temp = *Val1;
    *Val1 = *Val2;
    *Val2 = temp;

    return;
}</code></pre>
<p>실행결과는 다음과 같다.
<img src="https://velog.velcdn.com/images/_thist_/post/c897c3b7-3313-46c4-9c40-8867812f83bf/image.png" alt="">
방금 전 예제와 달리, 값이 바뀌었다는 것을 우리눈으로 확인할 수가 있다.</p>
<p>이는, 
<img src="https://velog.velcdn.com/images/_thist_/post/8112f949-7fb3-4d5f-b8d5-6d9fb247f636/image.png" width='60%'>
포인터 변수 Val1과 Val2에 num1과 num2의 주소값을 받았기 때문이다.</p>
<p>그리고, 임시변수 temp를 활용해 주소에 <strong>&quot;참조된 값만 바꾸는 형태&quot;</strong>로 Swap이 진행되었다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/64b060c0-c9c3-4a96-b390-cceb2132fcb6/image.png" alt=""></p>
<p>※ <strong>값만 바뀌었을 뿐, 둘의 주소는 바뀌지 않았다!</strong> <em>( 매우 중요! )</em>
<br>
정리하자면 다음과 같다.</p>
<p><strong>값에 의한 호출 (Call-by-value)</strong></p>
<ul>
<li>인자의 값이 함수에 전달된다.</li>
<li>함수 내부에서 인자를 변경해도 원래 변수에는 영향을 미치지 않는다.</li>
</ul>
<p><strong>참조에 의한 호출 (Call-by-reference)</strong></p>
<ul>
<li>인자의 값이 들어있는 주소가 함수에 전달된다.</li>
<li>함수 내부에서 인자를 변경하면 원래 변수도 변경된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 컴퓨터구조 ] 2. Memory]]></title>
            <link>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-2.-Memory</link>
            <guid>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-2.-Memory</guid>
            <pubDate>Mon, 15 Jul 2024 11:00:49 GMT</pubDate>
            <description><![CDATA[<p>저번시간에 우린 컴퓨터의 간단한 구조 및 개요를 살펴보았다.</p>
<p>이번 시간에는 Memory에 대해서 강의를 시작해보려고 한다.</p>
<h3 id="21-memory란">2.1 Memory란?</h3>
<p><img src="https://velog.velcdn.com/images/_thist_/post/cbfe91f7-ec76-4b16-8482-3f6b21064964/image.png" alt=""></p>
<p>메모리는 크게 다음과 같은 특징을 지니고 있다.</p>
<ol>
<li><p>메모리에는 프로그램이 실행될 때 (실행 중인 프로그램을 프로세스라고 함) 프로그램이 포함되어 있으며, 실행되지 않는 프로그램은 일반적으로 하드디스크에 저장되게 된다.</p>
</li>
<li><p>실행 중인 프로그램 또는 프로세스는 변수, 파일 및 기타 리소스와 같은 다양한 유형의 데이터에 액세스해야 한다.
이러한 데이터는 일반적으로 RAM에 저장되어 CPU가 프로그램 실행 중에 빠르게 액세스할 수 있도록 해준다.</p>
</li>
<li><p>PC 메모리는 일반적으로 DRAM (Dynamic Random Access Memory) 칩으로 구성되게 된다. </p>
</li>
</ol>
<p>개인 컴퓨터(PC) 메모리인 RAM과 같은 것들은 일반적으로 DRAM(Dynamic Random Access Memory) 칩을 사용하여 구성되게 된다.</p>
<p>DRAM은 휘발성 메모리 유형으로, 빠른 읽기 및 쓰기 액세스를 가능하게 하므로 CPU가 빠르게 액세스해야 하는 데이터 및 프로그램을 저장하는 데 적합합니다.</p>
<p>랜덤 액세스(Random Access)?</p>
<ul>
<li>말 그대로 Random하게 접근한다는 의미로, 물리적으로 위치한 곳과 상관없이 메모리의 어떤 위치든지 거의 동일한 시간에 액세스할 수 있다는 것을 의미한다.</li>
</ul>
<p>반대로 하드 디스크는 순차 액세스(Sequential Access)이다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/1507d51a-ab2d-46df-80e7-e17f2d9bb263/image.png" alt=""></p>
<p>하드 디스크는 일반적으로 데이터를 읽거나 쓰려면 데이터가 물리적으로 저장된 위치로 읽기/쓰기 헤드를 이동해야 하며, 데이터의 물리적 위치에 따라 다양한 시간이 걸릴 수 있게 된다.</p>
<h3 id="22-컴퓨터-메모리의-종류-types-of-computer-memory">2.2 컴퓨터 메모리의 종류 (Types of Computer Memory)</h3>
<p>빠르고 강력한 중앙 처리 장치(CPU)는 성능을 극대화하기 위해 대용량 데이터를 빠르고 쉬운 엑세스를 필요로 한다.</p>
<p>CPU가 필요한 데이터에 액세스할 수 없으면 말 그대로 멈추고 기다려야 한다.
현대 CPU는 약 1 기가헤르츠의 속도로 동작하며, 초당 수십 억 바이트의 대량 데이터를 처리할 수 있다. </p>
<p>이런 메모리를 대량으로 사용하는 것은 대부분의 사람들이 감당할 수 없을 정도로 많은 비용이 들게 된다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/eb2c11b4-18fe-4c52-961f-9029acc7c921/image.png" alt=""></p>
<p>그래서, 컴퓨터 디자이너들은 이 비용 문제를 <strong>&quot;계층 구조화 메모리&quot;</strong>를 사용하여 해결을 하였다. </p>
<p>즉 소량의 비싼 메모리를 사용하고 더 저렴한 메모리의 대량 사용으로 보완하는 방법이다.</p>
<p>그림을 보면 피라미드형 구조를 볼 수 있는데, 이는 각각의 트레이드오프관계를 계층화 시킨것이다. </p>
<p>비용, 속도, 용량순으로 비교를 해보자.</p>
<p>*<em>비용: 보조기억장치(HDD) &lt; 주기억장치(RAM) &lt; 캐시(Cache) &lt; 레지스터(Register)
속도: 보조기억장치(HDD) &lt; 주기억장치(RAM) &lt; 캐시(Cache) &lt; 레지스터(Register)
용량: 보조기억장치(HDD) &gt; 주기억장치(RAM) &gt; 캐시(Cache) &gt; 레지스터(Register)
*</em></p>
<p>이제 각각 뭐하는 놈들인지 알아보도록 하자.</p>
<p><strong>1. 레지스터 (Registers)</strong></p>
<p>레지스터는 CPU 내부에 내장된 가장 빠른 메모리로, 매우 소량의 데이터를 저장한다. 
또한, 레지스터는 CPU의 핵심 부분 중 하나로, 프로세서가 즉시 접근할 수 있는 데이터와 명령어를 저장한다.</p>
<pre><code>역할: 레지스터는 CPU가 현재 수행 중인 연산에 필요한 데이터를 임시로 저장한다.
속도: 매우 빠르며, CPU의 클럭 속도와 일치하여 최상의 성능을 제공해준다.
용량: 매우 적은 용량을 가지며, 일반적으로 몇 바이트에서 수십 바이트 수준이다.</code></pre><p><strong>2. 캐시 (Cache)</strong></p>
<p>캐시 메모리는 CPU와 주기억장치(RAM) 사이에 위치하여, 자주 사용되는 데이터를 저장함으로써 데이터 접근 시간을 줄여준다. 캐시는 여러 레벨(L1, L2, L3)로 나뉘며, </p>
<p>각 레벨은 CPU에 대한 접근 속도와 용량에 따라 차이가 존재한다.</p>
<pre><code>L1 캐시
CPU 내부에 위치하며, 가장 빠른 메모리이다.
용량은 일반적으로 2KB ~ 64KB 사이
CPU가 가장 빈번하게 사용하는 데이터를 저장하여 성능을 향상시켜준다.

L2 캐시
L1 캐시의 상위 계층으로, CPU 근처에 위치한다.
용량은 일반적으로 256KB ~ 2MB 사이이다.
L1 캐시에 비해 약간 느리지만, 더 많은 데이터를 저장할 수 있다.

L3 캐시
여러 CPU 코어가 공유하는 캐시이다.
용량은 수 MB에서 수십 MB에 달한다.
L1, L2 캐시보다 느리지만, 주기억장치보다 빠르다.</code></pre><p><strong>3. 주기억장치 (Main Memory)</strong></p>
<p>주기억장치, 흔히 RAM(Random Access Memory)으로 불리는 이 메모리는 실행 중인 프로그램과 데이터를 저장한다.</p>
<pre><code>역할: 현재 실행 중인 프로그램과 그 프로그램이 처리하는 데이터를 저장하여 CPU가 빠르게 접근할 수 있도록 한다.
속도: 캐시보다 느리지만, 보조기억장치보다 빠르다.
용량: 일반적으로 수 GB에서 수십 GB에 달한다.
특징: 전원이 꺼지면 데이터가 사라지는 휘발성 메모리이다.</code></pre><br>

<p><strong>4. 보조기억장치 (Secondary Storage)</strong></p>
<p>보조기억장치는 데이터를 영구적으로 저장하는 데 사용됩니다. 하드디스크(HDD)와 솔리드 스테이트 드라이브(SSD)가 대표적인 예이다.
<img src="https://velog.velcdn.com/images/_thist_/post/d34470f9-474a-4cfd-a1d0-688204a2f361/image.png" alt=""></p>
<p><strong>하드디스크 (Hard Disk Drive, HDD)</strong></p>
<ul>
<li>자기 플래터와 기계적 암을 사용하여 데이터를 읽고 쓴다.</li>
<li>용량이 크고 가격이 저렴하지만, 속도가 느리다.</li>
<li>데이터는 트랙과 섹터로 나뉘어 저장된다.</li>
</ul>
<p><strong>솔리드 스테이트 드라이브 (Solid State Drive, SSD)</strong></p>
<ul>
<li>플래시 메모리 칩을 사용하여 데이터를 저장한다.</li>
<li>HDD보다 빠르며, 기계적 부품이 없어 충격에 강하다.</li>
<li>용량은 일반적으로 수백 GB에서 수 TB에 달한다.</li>
</ul>
<br>

<h3 id="23-데이터-보관-방법-a-safe-place-for-data">2.3 데이터 보관 방법 (A Safe Place for Data)</h3>
<p><strong>1. Volatile Main Memory (휘발성 주 메모리)</strong></p>
<ul>
<li>주 메모리는 컴퓨터의 RAM(Random Access Memory)을 가리킨다.</li>
<li>이 메모리는 전원이 꺼지거나 컴퓨터가 재부팅되면 저장된 데이터와 명령을 잃어버린다.</li>
<li>주로 프로그램이 실행될 때 데이터를 일시적으로 저장하는 데 사용되며, 빠른 액세스를 제공해준다.</li>
</ul>
<p><strong>2. Non-volatile Secondary Memory (비휘발성 보조 메모리)</strong></p>
<ul>
<li>비휘발성 보조 메모리는 주 메모리와 달리 데이터를 전원이 꺼져도 보존하는 메모리를 가리킨다.</li>
<li>주로 데이터를 장기 저장 및 백업 용도로 사용되게 된다.</li>
<li>주요 비휘발성 보조 메모리 유형으로는 magnetic disk(자석 디스크), flash memory(플래시 메모리), optical disk(CD-ROM, DVD) 등이 있다.</li>
</ul>
<p><strong>3. Magnetic Disk (자석 디스크)</strong></p>
<ul>
<li>자석 디스크는 회전하는 디스크 표면에 자료를 자석으로 기록하는 기술을 사용한다.</li>
<li>이 디스크는 컴퓨터의 하드 디스크로 사용되며, 데이터를 비휘발성으로 저장한다.</li>
<li>대용량 데이터 저장 및 빠른 액세스를 위해 주로 사용된다.</li>
</ul>
<p><strong>4. Flash Memory (플래시 메모리)</strong></p>
<ul>
<li>플래시 메모리는 반도체 기술을 사용하여 데이터를 저장하는 메모리이다.</li>
<li>주로 USB 드라이브, SSD(Solid State Drive) 등의 형태로 사용되며, 전원이 꺼져도 데이터를 보존해준다.</li>
<li>빠른 데이터 액세스 및 내구성이 특징이다.</li>
</ul>
<p><strong>5. Optical Disk (광학 디스크 - CD-ROM, DVD)</strong></p>
<ul>
<li>광학 디스크는 레이저 빛을 사용하여 데이터를 읽고 쓰는 디스크이다.</li>
<li>CD-ROM, DVD 등이 있으며, 주로 데이터 및 미디어 파일을 저장하는 데 사용된다.</li>
<li>데이터의 안전한 보관과 고용량 저장이 가능하다.</li>
</ul>
<br>

<h3 id="24-컴퓨터의-데이터-처리-과정">2.4 컴퓨터의 데이터 처리 과정</h3>
<p><strong>1. 코드 실행 단계</strong></p>
<ul>
<li><p>프로그램 코드는 하드 디스크나 다른 저장 장치에서 읽혀서 RAM(Random Access Memory)으로 적재되게 된다.</p>
</li>
<li><p>코드가 RAM에 적재되면 CPU는 이 코드를 실행한다.
   CPU는 코드와 데이터를 연산기(예: 중앙 처리 장치, CPU)까지 가져와야 한다.</p>
</li>
</ul>
<p><strong>2. 캐시 메모리 사용</strong></p>
<ul>
<li>코드나 데이터가 처음으로 CPU에 필요할 때, RAM에서 읽어오는 것보다 캐시에서 읽어오는 것이 빠르다. </li>
</ul>
<p><strong>3. 레지스터로의 전달</strong></p>
<ul>
<li><p>CPU의 레지스터(Register)는 CPU 내부에 있는 작고 빠른 메모리 셀입니다. 레지스터는 CPU가 직접 액세스할 수 있으며, 레지스터를 통해 CPU는 연산을 수행하고 결과를 저장한다.</p>
</li>
<li><p>캐시에서 데이터나 코드가 필요할 때, CPU는 해당 데이터를 레지스터로 가져와 연산을 수행한다.</p>
</li>
</ul>
<p><strong>4. ALU(산술 논리 장치)에서 연산</strong></p>
<ul>
<li><p>ALU는 CPU의 핵심 부분 중 하나로, 산술 및 논리 연산을 수행한다. CPU는 ALU를 사용하여 코드나 데이터를 연산하고 원하는 결과를 생성한다.</p>
</li>
<li><p>ALU는 주로 레지스터의 데이터에 직접 접근하여 연산을 수행한다. 이렇게 하면 데이터의 빠른 처리와 연산 결과의 빠른 반환이 가능하다.</p>
</li>
</ul>
<p>여기서 모르는 단어 및 용어는 차차 강의하면서 배워보도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 컴퓨터구조 ] 1. 컴퓨터 구조 개요]]></title>
            <link>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-1.-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@_thist_/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-1.-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Mon, 15 Jul 2024 09:47:33 GMT</pubDate>
            <description><![CDATA[<p>오늘은 컴퓨터의 심장부라고 할 수 있는 컴퓨터 구조론에 대해 이야기해보고자 한다.</p>
<h3 id="11-컴퓨터-개요">1.1 컴퓨터 개요</h3>
<p>우리가 매일 사용하는 스마트폰, 태블릿, PC 등 다양한 디지털 기기들은 모두 복잡한 컴퓨터 구조를 바탕으로 작동한다.</p>
<p>이 구조를 이해하는 것은 단순히 기계적인 작동 원리를 아는 것을 넘어서, 소프트웨어 개발, 시스템 성능 최적화, 문제 해결 능력 향상에 큰 도움이 된다.</p>
<p>컴퓨터 구조는 CPU, 메모리, 입출력 장치와 같은 하드웨어 구성 요소들이 어떻게 상호작용하는지, </p>
<p>그리고 이러한 상호작용을 통해 어떻게 효율적인 컴퓨팅이 이루어지는지를 다룰 예정이다.</p>
<p>컴퓨터 기술은 지난 몇십 년간 비약적으로 발전되어왔다.</p>
<p>이러한 발전을 설명할 때 사용하는 법칙이 바로 <strong>무어의 법칙(Moore&#39;s Law)</strong>이다.
<img src="https://velog.velcdn.com/images/_thist_/post/63b0b1c7-ea9e-46cf-a98e-8935d663865e/image.png" height="70%" width="70%"></p>
<p>&#39;<strong>무어의 법칙(Moore&#39;s Law)이란</strong>&#39; 컴퓨터의 처리 능력은 18 ~ 24개월마다 두 배로 증가한다는 이론이다. </p>
<p>실제로, 지난 20년 동안 컴퓨터 용량은 약 16,000배 증가하였다.</p>
<p>이러한 컴퓨터 혁명은 제 1차 산업혁명, 제 2차 산업혁명에 이은 <strong>세 번째 혁명</strong>이라고 불리고 있으며, 미래에서만 보던 SF는 더이상 단순히 상상이 아니라는것을 보여주고 있다.</p>
<h3 id="12-컴퓨터의-종류">1.2 컴퓨터의 종류</h3>
<p>컴퓨터는 용도에 따라 크게 <strong>데스크탑(Desktop)</strong>, <strong>서버(Server)</strong>, <strong>데이터센터(Internet DataCenter)</strong>, <strong>임베디드 컴퓨터(Embedded Computer)</strong> 네 가지로 나뉘게 된다.</p>
<p>먼저 <strong>데스크탑 컴퓨터 (Desktop Computer)</strong>이다.
이 컴퓨터는 주로 개인용 컴퓨터로, 다양한 응용 프로그램을 실행하고,
사용자의 다양한 요구를 충족하기 위해 사용된다.</p>
<p>이러한 컴퓨터는 사용자에게 높은 유연성과 다양한 작업 옵션등을 제공해준다.</p>
<p>다음은 <strong>서버 컴퓨터 (Server Computer)이다</strong>.
서버 컴퓨터는 주로 데이터센터에 배치되는 컴퓨터로, 데이터 및 서비스를 관리한다.
이러한 컴퓨터는 일반 데스크탑 컴퓨터와 유사한 작업을 수행하지만, 
높은 신뢰성과 안정성이 필요하다. </p>
<p>갑작스러운 프로그램 다운은 개인용 컴퓨터보다 큰 손실을 야기하기 때문이다.</p>
<p>만약, 지금 당장 은행의 서버가 불에타서 내 계좌에 돈이 사라지면 어떻게 되겠는가? 상상만 해도 끔찍하지 않겠는가? 
이러한 상황을 방지하기 위해 은행 및 다양한 기업들은 백업용 서버를 따로 분산 배치하여 예방하고 있다.</p>
<p>또한, 이러한 서버는 상시 서버가 계속해서 운용되어야 되기 때문에 데이터 보존 및 전력공급에 특별한 주의가 필요하다.</p>
<p>다음은 <strong>인터넷 데이터센터 (Internet Datacenter)</strong>이다.
인터넷 데이터센터는 대용량 클러스터를 위한 컴퓨터로, 수백 대 또는 수천 대의 컴퓨터가 동시에 사용된다. 
이러한 데이터센터는 서버 컴퓨터보다 훨씬 높은 계산 능력을 제공해준다.</p>
<p>마지막으로, <strong>임베디드 컴퓨터 (Imbedded Computer)</strong>이다.
임베디드 컴퓨터는 매우 작은 사이즈의 컴퓨터로, 마이크로프로세서(MicroProcessor)가 포함된다. 
이러한 컴퓨터는 장치나 시스템 내에 숨겨져 있으며, 예를 들어 자동차나 비행기와 같은 여러 장소에 사용되고 있다.</p>
<p>이러한 임베디드는 전력 소비가 낮아야 하며, 정확한 연산을 정해진 시간 내에 수행해야 한다.</p>
<h3 id="14-컴퓨터의-구성요소">1.4 컴퓨터의 구성요소</h3>
<p>컴퓨터의 구성요소는 크게 5가지로 구성된다.
<img src="https://velog.velcdn.com/images/_thist_/post/4a4f5e55-e927-481d-9495-3b704707dbab/image.png" alt="">
컴퓨터는 크게 <strong>입력(Input)</strong>, <strong>출력(Output)</strong>, <strong>메모리(Memory)</strong>, <strong>데이터 패스 및 제어(Data Path &amp; Control)</strong>로 구성된다.</p>
<p><strong>1. 입력(Input):</strong> 입력은 컴퓨터에 데이터나 명령을 제공하는 과정을 나타낸다.
사용자가 컴퓨터와 상호 작용하거나 다른 기기에서 데이터를 전송하는 경우 입력이 이루어지게 된다.</p>
<p><strong>2. 출력(Output):</strong> 출력은 컴퓨터가 처리한 결과를 사용자에게 제공하는 과정이다. 이것은 모니터 화면에 정보를 표시하거나 프린터로 출력하는 것과 같이 다양한 형태로 나타나게 된다.</p>
<p><strong>3. 메모리(Memory):</strong> 메모리는 컴퓨터가 데이터를 저장하고 처리하는 공간이다. 프로그램과 데이터는 주기억장치(RAM)에 저장되며, 영구적인 데이터는 보조 저장장치(하드 디스크, CD/DVD, 플래시 드라이브 등)에 저장되게 된다.</p>
<p><strong>4. 데이터 패스(Data Path) 및 제어(Control)</strong>: 데이터 패스는 컴퓨터의 중앙 처리 장치(CPU)에서 연산이 수행되는 곳이다. 이곳에서 데이터의 산술 연산, 논리 연산 및 다른 계산이 이루어지게 된다. 제어는 명령어의 실행을 관리하고 컴퓨터 시스템을 제어하는 역할을 수행하게 된다.</p>
<p>이러한 네 가지 구성 요소를 통해 컴퓨터는 데이터를 처리하고 사용자의 요구를 충족시키며 다양한 작업을 수행하게 된다.</p>
<p>컴퓨터 시스템의 구조를 보면 다음과 같은데, 
<img src="https://velog.velcdn.com/images/_thist_/post/5186e36f-e2ef-49bf-8a32-2966970e794b/image.png" alt="">
하나 이상의 CPU와 장치 컨트롤러들이 <strong>시스템 버스(System BUS)</strong>를 통해 연결되고 공유 메모리가 접근하게 된다.</p>
<p>여기서, CPU와 여러장치들은 메모리 사이클을 경쟁적으로 사용하며 동시에 실행되게 된다.</p>
<p><strong>System BUS란?</strong>
<img src="https://velog.velcdn.com/images/_thist_/post/4363228f-45ef-4264-b5f8-37e5aa25ca4e/image.png" alt="">
CPU, 메모리, 디스크 컨트롤러, USB 컨트롤러, 그래픽 어댑터 등 모든 구성 요소들을 연결하는 통로이다.</p>
<br>

<h3 id="15-컴퓨터-아키텍처란">1.5 컴퓨터 아키텍처란?</h3>
<p><img src="https://velog.velcdn.com/images/_thist_/post/c75576a4-0cdb-4845-bba8-ccbe7b13ef10/image.png" alt="">
<strong>컴퓨터 아키텍처(Computer Architecture)</strong>는 컴퓨터 시스템의 구조와 동작을 정의하고 설계하는 분야이다. </p>
<p>컴퓨터 아키텍처는 다음과 같은 주요 측면에 대해서 다루고 있다.</p>
<p><strong>1. 하드웨어 설계:</strong> 아키텍트는 중앙 처리 장치(CPU), 메모리, 입력 및 출력 장치, 버스 시스템, 저장 장치 등과 같은 컴퓨터의 하드웨어 구성 요소를 설계한다.
이러한 구성 요소는 컴퓨터의 성능, 확장성, 에너지 효율성 등을 결정하는 중요한 역할을 한다.</p>
<p><strong>2. 명령 집합 아키텍처(ISA):</strong> 컴퓨터 아키텍처는 <strong>명령 집합 아키텍처(ISA)</strong>를 정의한다.
<img src="https://velog.velcdn.com/images/_thist_/post/46bd7c6a-d6bd-403c-9f97-a41b3a8a2523/image.png" alt="">
<strong>ISA(Instruction Set Architecture)</strong>는 컴퓨터가 수행할 수 있는 명령어 집합과 명령어의 동작 방식을 정의하는데, 
이는 소프트웨어와 하드웨어 간의 효율적인 상호 작용을 지원한다.</p>
<p><strong>3. 성능 최적화:</strong> 컴퓨터 시스템의 성능을 최적화하기 위해 다양한 설계 트레이드오프를 고려합니다. 이는 처리 속도, 메모리 용량, 에너지 효율성 등을 고려한 결정을 포함한다.</p>
<p><strong>4. 비용 관리:</strong> 아키텍트는 하드웨어 및 소프트웨어 설계에서 비용 효율성을 고려한다. </p>
<p><strong>5. 확장성:</strong> 아키텍트는 시스템의 확장성을 고려하여 미래의 요구 사항을 충족할 수 있도록 설계한다.</p>
<p><br><br>
오늘은 컴퓨터의 심장부라고 할 수 있는 컴퓨터 구조론의 기본 개념에 대해 알아보았다.</p>
<p>다음 시간에는 컴퓨터 시스템에서 중요한 역할을 하는 메모리(Memory)에 대해 자세히 알아보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 운영체제 ] 1. 운영체제의 개요]]></title>
            <link>https://velog.io/@_thist_/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80</link>
            <guid>https://velog.io/@_thist_/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80</guid>
            <pubDate>Sun, 14 Jul 2024 18:13:23 GMT</pubDate>
            <description><![CDATA[<h4 id="1-1-운영체제란-무엇인가-what-is-an-operating-system">1-1. 운영체제란 무엇인가? (What is an Operating System)</h4>
<p>세상에는 다양한 OS들이 존재한다.
<img src="https://velog.velcdn.com/images/_thist_/post/22008c75-defd-4e9f-b041-821644b4cb68/image.png" height="100%" width="60%"><br></p>
<p>가까이 있는것부터 비교해보면, 크게 Windows와 Mac이 있을것이다. </p>
<p>그리고 휴대폰에 Android, iOS 이것들 또한 OS이다.</p>
<p>평소에, 주변에서 &quot;운영체제&quot;라는 단어는 많이 들었어도, 그게 정확히 어떠한 용어인지 아는 사람은 많지 않은 것 같아 보인다.</p>
<p>운영체제 OS(Operating System)은 크게 두 Part로 나눌 수 있다고 본다.</p>
<p><strong>Operating</strong>  그리고   <strong>System.</strong></p>
<p><strong>Operating</strong>이란 본래, 운영이라는 뜻으로, 다양한 기계나 장비들을 작동하는것을 의미한다.</p>
<p><strong>System</strong>이란, 여러가지 <strong>Part</strong>들이 모여 하나의 <strong>Set</strong>을 구성하는것을 의미한다.</p>
<p>즉, 이 두 단어를 합쳐보면 &quot;여러가지 Part들이 모여 하나의 Set을 구성하고, 이러한 Set을 통해 다양한 기계 혹은 장비들을 운영한다&quot; 정도로 해석될 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/de5bf4c3-5b00-412d-9a60-2caecf994ca0/image.png" alt="">
이 그림을 보면 OS(Operating System)이 하드웨어와 Program사이에 있는것을 볼 수 있는데, 왜 그런지 다음과 같은 시나리오들을 살펴보도록 해보자.</p>
<br>

<p><strong>1. 개발자들의 특정 장치에 맞는 애플리케이션 개발</strong></p>
<ul>
<li>문제점: 각 장치의 하드웨어 및 소프트웨어 환경이 다르기 때문에 애플리케이션을 개발하는 데 어려움이 있을 수 있다.</li>
</ul>
<br>

<p><strong>2. 유저들의 다른 장치에서 동일한 애플리케이션 사용</strong></p>
<ul>
<li>문제점: 장치마다 다른 하드웨어와 운영체제 환경이 존재할 수 있다.</li>
</ul>
<br>

<p><strong>3. 유저들의 여러 애플리케이션 실행</strong></p>
<ul>
<li>문제점: 여러 애플리케이션이 동시에 실행될 때, CPU, 메모리, 디스크 등의 자원을 효율적으로 관리해주어야 한다.</li>
</ul>
<br>

<p><strong>4. 여러 사용자가 동일한 애플리케이션 실행</strong></p>
<ul>
<li>문제점: 다수의 사용자가 동일한 애플리케이션을 사용할 때, 한정된 자원을 차지하기 위해 충돌이 발생할 수 있다.</li>
</ul>
<br>

<p>다양한 계층에서 다양한 문제들이 발생하는것을 우리는 볼 수 있다.</p>
<br>

<p>운영체제는 이러한 문제들이 발생하지 않도록, 사전에 다음과 같은 일을 수행하고 있다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/7e321828-6286-4918-a517-4e3a7cae1462/image.png" alt=""></p>
<p>이렇듯, OS는 Hardware와 Software 딱 그 중간사이에 위치해서 우리가 더 편히 일을 할 수 있도록, 다양한 기능들을 제공해 준다.</p>
<h4 id="1-2-운영체제의-주요-역할과-기능-major-roles-and-functions-of-operating-systems">1-2. 운영체제의 주요 역할과 기능 (Major Roles and Functions of Operating Systems)</h4>
<ol>
<li><strong>하드웨어 관리(Manages a Computer&#39;s Hardware)</strong></li>
</ol>
<p>--&gt; 하드웨어의 자원 (CPU, 메모리, 디스크, 입출력 장치)등을 관리한다.</p>
<ol start="2">
<li><strong>응용 프로그램 지원(Provides Basis for Application Programs)</strong></li>
</ol>
<p>--&gt; 응용 프로그램들이 하드웨어와 상호작용할 수 있도록 기본적인 환경을 제공한다.</p>
<ol start="3">
<li><strong>사용자 프로그램과 하드웨어 간의 상호작용(Interaction between User Programs and Hardware)</strong></li>
</ol>
<p>--&gt; 소프트웨어와 컴퓨터 하드웨어간의 중재자 역할을 수행해준다.</p>
<p>이를 통해, </p>
<p>사용자가 프로그램을 실행하고, 컴퓨터를 쉽게 이용할 수 있게 해주며,</p>
<p>한눈에 보기 쉽도록 다양한 인터페이스 및 기능을 제공해준다.</p>
<p>또한, 이러한 보다 빠르고 편리한 기능을 위해 한정된 자원들을 최대한 효율적으로 사용하여 성능을 최적화 시켜준다.</p>
<p>마지막으로 User Interface에 대해서 알아보도록 하자.</p>
<p>User Operating System Interface는 사용자가 컴퓨터와 어떻게 서로 의사소통할지 만들어진 하나의 매개체이다. </p>
<p>사람들끼리 의사소통할 때, 주로 대화나 펜을 이용해서 서로 대화를 주고 받지 않는가?</p>
<p>컴퓨터에는 크게 
<strong>CLI(Command Line Interface)</strong>와 
<strong>GUI(Graphic User Interface)</strong> 두가지로 나뉜다.</p>
<p><img src="https://velog.velcdn.com/images/_thist_/post/902c64ee-3c37-4c71-828c-b9522c99969a/image.png" alt=""></p>
<p>CLI에서는 주로 &#39;<strong>Shell</strong>&#39;이라고 불리는 것을 사용하여 컴퓨터와 의사소통한다.</p>
<p>영화나 드라마를 보면 해커가 검은창을 띄워놓지 않는가? </p>
<p>그것이 바로 <strong>&#39;Shell&#39;</strong>이라고 하는 인터페이스이다.</p>
<p>반대로, <strong>GUI</strong>에서는 우리가 주로 사용하는 사용자 친화적 인터페이스로, 한눈에 알아보기 쉽고 접근하기가 쉽다는 것이 가장 큰 장점이다.</p>
<br>

<p>이번 시간을 통해, 우리는 OS가 무엇이며 대충 어떠한일을 수행하는지에 대해 추상적으로 배워보는 시간을 가졌다.</p>
<br>

<p>우리는 이제 이러한 일을 어떻게 OS가 수행하는지 보다 자세하게 다뤄볼 예정이다.</p>
<p><br><br>
<strong>1. 운영체제의 개요</strong></p>
<ul>
    <li> 1-1. 운영체제란 무엇인가? (What is an Operating System?)</li>
    <li> 1-2. 운영체제의 주요 역할과 기능 (Major Roles and Functions of Operating Systems)</li>
</ul>

<p><strong>2. 운영체제의 구성 요소 (Components of Operating Systems)</strong></p>
<ul>
    <li>2-1. 커널 (Kernel)</li>
    <li>2-2. 파일 시스템 (File System)</li>
    <li>2-3. 장치 드라이버 (Device Drivers)</li>
    <li>2-4. 사용자 인터페이스 (User Interface)</li>
</ul>

<p><strong>3. 프로세스 관리 (Process Management)</strong></p>
<ul>
    <li>3-1. 프로세스와 스레드 (Processes and Threads)</li>
    <li>3-2. 프로세스 스케줄링 (Process Scheduling)</li>
    <li>3-3. 동기화와 통신 (Synchronization and Communication)</li>
</ul>

<p><strong>4. 메모리 관리 (Memory Management)</strong></p>
<ul>
    <li>4-1. 물리적 메모리와 가상 메모리 (Physical Memory and Virtual Memory)</li>
    <li>4-2. 메모리 할당 기법 (Memory Allocation Techniques)</li>
    <li>4-3. 페이지 교체 알고리즘 (Page Replacement Algorithms)</li>
</ul>

<p><strong>5. 파일 시스템 관리 (File System Management)</strong></p>
<ul>
    <li>5-1. 파일 시스템 구조 (File System Structure)</li>
    <li>5-2. 파일 할당 방법 (File Allocation Methods)</li>
    <li>5-3. 디렉터리 구조와 관리 (Directory Structure and Management)</li>
</ul>

<p><strong>6. 입출력 시스템 (Input/Output Systems)</strong></p>
<ul>
    <li>6-1. 입출력 하드웨어 (I/O Hardware)</li>
    <li>6-2. 입출력 소프트웨어 (I/O Software)</li>
    <li>6-3. 입출력 버퍼링과 스풀링 (I/O Buffering and Spooling)</li>
</ul>

<p><strong>7. 보안과 보호 (Security and Protection)</strong></p>
<ul>
    <li>7-1. 운영체제 보안 기법 (Operating System Security Techniques)</li>
    <li>7-2. 사용자 인증과 권한 관리 (User Authentication and Authorization)</li>
    <li>7-3. 데이터 보호와 암호화 (Data Protection and Encryption)</li>
</ul>

<p><strong>8. 가상화 (Virtualization)</strong></p>
<ul>
    <li>8-1. 가상화의 개념과 필요성 (Concept and Necessity of Virtualization)</li>
    <li>8-2. 가상 머신과 하이퍼바이저 (Virtual Machines and Hypervisors)</li>
    <li>8-3. 컨테이너 기술 (Container Technology)</li>
</ul>

<p><strong>9. 미래의 운영체제 (Future of Operating Systems)</strong></p>
<ul>
    <li>9-1. 클라우드 운영체제 (Cloud Operating Systems)</li>
    <li>9-2. 사물인터넷(IoT) 운영체제 (Internet of Things Operating Systems)</li>
    <li>9-3. 분산 운영체제 (Distributed Operating Systems)</li>
</ul>]]></description>
        </item>
        <item>
            <title><![CDATA[넥슨 [라이브본부] 면접 후기]]></title>
            <link>https://velog.io/@_thist_/%EB%84%A5%EC%8A%A8-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%B3%B8%EB%B6%80-%EB%A9%B4%EC%A0%91-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@_thist_/%EB%84%A5%EC%8A%A8-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%B3%B8%EB%B6%80-%EB%A9%B4%EC%A0%91-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Fri, 12 Jul 2024 15:49:14 GMT</pubDate>
            <description><![CDATA[<p><em>저번주, 넥슨 라이브본부에서 게임프로그래머 채용공고에서 1차 합격을 했었다.</em>
<img src="https://velog.velcdn.com/images/_thist_/post/1b10761a-3a19-4f51-878d-4ffedfb08e1b/image.png" alt=""></p>
<p>그래서 약 일주일동안 면접을 준비하면서 좌절도 많이 하고, 자신감도 얻고 뭐... 혼자서 난리를 피웠던 일주일 이었던 것 같다.</p>
<p>나에 대해서 좀 더 객관적으로 바라볼 수 있는 소중한 시간이었고, 내가 어떠한 점이 부족한지, 앞으로 어떤 공부를 해서 어떻게 나아가야할지 방향성이 보이기 시작했다.</p>
<p>사실, 그냥 아무 중소기업에나 들어가서 일이나 하면서 사는게 내 인생이겠거니 하고 있었는데, 이렇게 좋은 기회를 만들어준 넥슨에 정말 감사하다고 전하고 싶다.</p>
<p>면접은 다대다로 봤었고, 지원자 넷에 면접관 5분이 계셨다.</p>
<p>면접 난이도는 주로 자기소개서 위주와 기술면접 위주로 돌아가면서 질문을 받았던 것 같다.</p>
<p>그런데, 기술질문에서 꽤 깊게 들어와서 당황했었던 것 같다.</p>
<p>평소에 생각안해보고 가볍게 넘어갔었던 문제들에 대해 질문이 들어왔었다.</p>
<p>지금 생각해보니까, 차근차근 생각했다면 풀었을 질문이었는데, 그 땐 횡설수설하면서 엉망으로 대답했었던 것 같다.</p>
<p>결론적으로, 면접은 잘 못봤지만 그래도 정말 훌륭하신 면접관님들과 같이 면접을 봤던 지원자분들을 보면서, 왠지 모르게 소속감도 느끼고 뿌듯했던 시간이었던 것 같다.</p>
<p>난 정말 이 기회를 잡기 위해서 정말 열심히 공부하고 또 준비했다.</p>
<p>근데, 준비할수록 더 모르는것 투성이었다.</p>
<p>진작에 이렇게 공부해놓을걸...이제 내 손을 떠났고, 그 상황에선 나로선 최선을 다하고 하고싶은말도 다 했기 때문에</p>
<p>결과는 하늘에 맡겨보려고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 자료구조 ] 스택(Stack)]]></title>
            <link>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9DStack</link>
            <guid>https://velog.io/@_thist_/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9DStack</guid>
            <pubDate>Thu, 20 Jun 2024 17:54:39 GMT</pubDate>
            <description><![CDATA[<p>자료구조란 무엇인가? 개발자가 되려면 꼭 해야하나?</p>
<p>정답은 <strong>&#39;Yes&#39;</strong>이다. 자료구조는 컴퓨터 과학의 핵심 개념으로, 
데이터가 어떻게 저장되고 어떻게 사용되고, 어떻게 관리되는지 알아야 컴퓨터 전체의 복잡한 시스템의 구조를 이해할 수 있다. ( 되게 복잡한데 차근차근 가보자 )</p>
<p>그 첫번째 단계로 우선 <strong>Stack</strong>에 대해서 설명하려고 한다.</p>
<p>Stack이란 선입후출 <strong>FILO(First In, Last Out)</strong>구조를 지닌, 자료구조 이다. 즉, 먼저 삽입된 데이터가 마지막에 제거되는 구조를 의미한다.</p>
<p>또한, Stack에는 <strong>&#39;Top&#39;</strong>이라는 개념이 존재하는데, 
스택의 맨 위에 있는 요소를 가리킨다. 이 <strong>&#39;Top&#39;</strong>에서는 데이터가 <strong>추가(Push)</strong> 되거나, <strong>삭제(Pop)</strong>되는 위치이다.</p>
<p>이를 통해 Stack은 다음과 같은 특징은 지닌다.
<br>
<strong>1. Push 연산:</strong></p>
<p>   데이터를 Stack의 맨 위에 추가하는 작업이다. ( 데이터 삽입 )</p>
<p>   예를 들어, &quot;Apple&quot;이란 Data가 있을 때, Push를 하면 다음과 같다.
<img src="https://velog.velcdn.com/images/_thist_/post/a8c974df-ec41-45eb-abbf-1582c1b60d43/image.png" width="500px" height="300px" align="center"></p>
<p>   다음으로, &quot;Banana&quot;란 Data를 Push해보자.
<img src="https://velog.velcdn.com/images/_thist_/post/823d6f15-c28a-49df-b1a1-fb332044bcdc/image.png" width="500px" height="300px" align="center"></p>
<p>   마지막으로, &quot;Melon&quot;이란 Data를 Push해보자.
<img src="https://velog.velcdn.com/images/_thist_/post/d82abe6c-ca3c-4a24-80d8-58b9207022c2/image.png" width="500px" height="300px" align="center"></p>
<p>이렇게 Data를 넣을 때마다, Top이 위로 올라가는것을 볼 수 있다. 
마치, 우리가 원형 주스잔에 공을 하나씩 넣었을 때, 가장 마지막으로 넣은게 가장 위쪽에 있는 공인것 처럼 말이다.</p>
<p>이제 데이터를 하나씩 지워볼까?</p>
<p>데이터를 지우기 위해 Pop을 해보겠다.
<br><br>
<strong>2. Pop 연산:</strong></p>
<p>   Stack의 Top에 존재하는 Data를 삭제한다. ( 데이터 삭제 )</p>
<p>   <img src="https://velog.velcdn.com/images/_thist_/post/d035feb9-2fdf-42f9-ac6a-34489eec401a/image.png
" width="500px" height="300px" align="center"></p>
<p>현재 Stack의 Top에 존재하는 데이터인 &quot;Melon&quot;이 삭제된다. </p>
<p>   <img src="https://velog.velcdn.com/images/_thist_/post/07aaf7eb-6c3e-4159-871e-2a238a17185e/image.png
" width="500px" height="300px" align="center"></p>
<p>다음으로, &quot;Banana&quot;를 삭제해보자.</p>
<p>   <img src="https://velog.velcdn.com/images/_thist_/post/bd3cdf8d-a290-4f89-96a4-cded1b21601e/image.png
" width="500px" height="300px" align="center">
   <img src="https://velog.velcdn.com/images/_thist_/post/93829e51-f6a9-424a-9d9b-1a06da03f10a/image.png
" width="500px" height="300px" align="center">
마지막으로, &quot;Apple&quot;을 삭제해보자.</p>
<p>   <img src="https://velog.velcdn.com/images/_thist_/post/1834c577-9cbb-4341-a2d2-9ad18dd659c1/image.png
" width="500px" height="300px" align="center">
   <img src="https://velog.velcdn.com/images/_thist_/post/9919cd2d-9f50-4f33-9673-e09c79e744c9/image.png
" width="500px" height="300px" align="center">
마지막까지 남은 데이터 &quot;Apple&quot;까지 삭제하니 텅텅 비어져 버렸다.</p>
<p>이렇듯, 데이터가 쌓이고 삭제되는 과정을 통해 Stack 자료구조의 기본 원리를 이해할 수 있다. </p>
<p>Stack은 단순한 구조이지만, 여러 가지 중요한 프로그래밍 문제를 해결하는 데 유용하게 사용된다. 
<br><br></p>
<h4 id="code">Code</h4>
<hr>
<pre><code class="language-c">#define _CRT_SECURE_NO_WARNINGS
#include&lt;stdio.h&gt;
#define M 10  // 스택의 최대 크기 정의

// 전역 변수 선언
int arr[M];  // 스택을 저장할 배열
int front;   // 스택의 top을 가리키는 변수

// 함수 선언
void Push();
void Pop();
void Stack_Empty();
void Stack_Full();
void Print_Stack();

int main(void) {
    int Sel = 0;

    // 메뉴를 출력하고 사용자의 선택을 처리하는 반복문
    do {
        printf(&quot; --------------------\n&quot;);
        printf(&quot; |    1.Push        |\n&quot;);
        printf(&quot; |    2.Pop         |\n&quot;);
        printf(&quot; |    3.Is_Empty?   |\n&quot;);
        printf(&quot; |    4.Is_Full?    |\n&quot;);
        printf(&quot; |    5.Print       |\n&quot;);
        printf(&quot; --------------------\n&quot;);
        printf(&quot;Select Mode:&quot;);

        scanf(&quot;%d&quot;, &amp;Sel);  // 사용자로부터 선택을 입력받음

        // 사용자가 선택한 옵션에 따라 함수 호출
        switch (Sel) {
        case 1: {
            Push();  // 스택에 값을 삽입
            break;
        }
        case 2: {
            Pop();   // 스택에서 값을 삭제
            break;
        }
        case 3: {
            Stack_Empty();  // 스택이 비어있는지 확인
            break;
        }
        case 4: {
            Stack_Full();   // 스택이 꽉 찼는지 확인
            break;
        }
        case 5: {
            Print_Stack();  // 스택의 모든 요소를 출력
            break;
        }
        }

    } while (Sel != -1);  // 사용자가 -1을 입력할 때까지 반복

    return 0;
}

// 스택에 값을 삽입하는 함수
void Push() {
    int S;
    printf(&quot;Input:&quot;);
    scanf(&quot;%d&quot;, &amp;S);  // 사용자로부터 삽입할 값을 입력받음

    if (front &lt; M) {  // 스택의 현재 위치가 최대 크기보다 작으면
        arr[front++] = S;  // 현재 위치에 값을 삽입하고 top을 증가
        printf(&quot;Value Inserted Successfully!\n&quot;);
    }
    else {
        printf(&quot;Stack is full!!!\n&quot;);  // 스택이 꽉 찬 경우
    }

    printf(&quot;\n\n&quot;);
    return;
}

// 스택에서 값을 삭제하는 함수
void Pop() {
    if (front &gt; 0) {  // 스택에 값이 하나 이상 있을 경우
        printf(&quot;Value deleted Successfully!\n&quot;);
        front--;  // top을 감소시켜 가장 최근에 삽입된 값을 제거
    }
    else {
        printf(&quot;Stack is already empty!!\n&quot;);  // 스택이 비어있는 경우
    }

    printf(&quot;\n\n&quot;);
    return;
}

// 스택이 비어있는지 확인하는 함수
void Stack_Empty() {
    if (front == 0)  // top이 0일 경우 스택이 비어있는 상태
        printf(&quot;Stack is Empty!!\n&quot;);
    else
        printf(&quot;Stack is Not Empty!!\n&quot;);  // 스택에 값이 있는 경우

    printf(&quot;\n\n&quot;);
    return;
}

// 스택이 꽉 찼는지 확인하는 함수
void Stack_Full() {
    if (front == M)  // top이 최대 크기와 같을 경우 스택이 꽉 찬 상태
        printf(&quot;Stack is Full!!\n&quot;);
    else
        printf(&quot;Stack is Not Full!!\n&quot;);  // 스택에 여유 공간이 있는 경우

    printf(&quot;\n\n&quot;);
    return;
}

// 스택의 현재 상태를 출력하는 함수
void Print_Stack() {
    printf(&quot;Print Stack: &quot;);
    for (int i = 0; i &lt; front; i++)  // top까지의 모든 값을 출력
        printf(&quot;%d &quot;, arr[i]);

    printf(&quot;\n\n&quot;);
    return;
}


다음에는 큐(Queue)에 대해서 알아보도록 하자.




















</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[자기소개...]]></title>
            <link>https://velog.io/@_thist_/%EC%9E%90%EA%B8%B0%EC%86%8C%EA%B0%9C</link>
            <guid>https://velog.io/@_thist_/%EC%9E%90%EA%B8%B0%EC%86%8C%EA%B0%9C</guid>
            <pubDate>Wed, 19 Jun 2024 18:10:16 GMT</pubDate>
            <description><![CDATA[<p>안녕,
오늘은 내 첫 게시글을 쓰는 날이다. 
뭘 쓸까 하다가 그냥 내 얘기나 쓰면서 시작해 보려고 한다.</p>
<img src="https://mblogthumb-phinf.pstatic.net/MjAyMTAyMTNfMjIx/MDAxNjEzMTQ2NjIyMTg4.YSztPWgiQu65mfs2C_EKqKBdioPoMkrYFGVfAbjQ-dEg.H0qd5GtqDt6npms6zvw1uJ1ExKgyupAtETxKCgkokNog.JPEG.psb011004/IMG_4396.JPG?type=w800" height="100px" width="300px" align="center">

<p>나는 26살(만으로는 24살)이고, 가천대학교 학생이다. </p>
<p>소프트웨어학과 재학 중이고 현재 4학년이다.</p>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR493-eAJHMLU5VvhsESB_dMB2-3yeZbJwE7g&s" height="100px" width="300px" align="center">

<p>곧 졸업인데 뭘 할지 고민하다가, 이전부터 공부해왔던 게 있고 
또 하고 싶은 공부도 있어서 여기에 공부 겸 복습 겸 정리 겸 겸사겸사 하려고 한다.</p>
<p>내가 개발자가 되려고 했던 이유? </p>
<p>사실은 화이트해커가 되려고 시작한건데 지금은 개발자로 꿈이 바뀌었다..</p>
<p>왜냐하면, 나는 게임을 너무 너무 좋아했기 때문이다.. </p>
<p>유치원 때 처음으로 스타크래프트를 했으니까... 물론 지금도 하고 있다..(뼛속까지 테란)</p>
<p>초등학교 4학년 때였나? 그때, 스타크래프트 유즈맵을 엄청나게 좋아해서 친구랑 얘기 나누다가 친구가 유즈맵 같이 만들어보자고 했었다. </p>
<p>그래서 처음으로 에디터를 써봤는데, 진짜 너무 재밌어서 몇 날 며칠을 유즈맵 만들면서 혼자 놀았던 것 같다. </p>
<p>그리고 유즈맵을 다 만들면 다른 유저랑 같이 플레이하고, &quot;이거 내가 만들었다&quot;면서 자랑도 좀 하고. 사실 그러면 사람들이 되게 놀라고 칭찬해주더라. </p>
<p>나는 그게 너무 너무 좋았었다. </p>
<p>그래서 그 때 부터 윤성우님의 &quot;열혈강의 C 프로그래밍&quot; 책을 사서 독학하면서 공부를 시작했었고, 고등학교를 거쳐.. 현재는 대학생 끝물이다..</p>
<p>어쨋든, 열심히 해보려고 한다.</p>
]]></description>
        </item>
    </channel>
</rss>