<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>asiatic_ricecake.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 18 Jun 2026 09:00:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>asiatic_ricecake.log</title>
            <url>https://velog.velcdn.com/images/asiatic_ricecake/profile/d4b2978a-a647-4376-bcb7-5683421da248/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. asiatic_ricecake.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/asiatic_ricecake" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[C#] 트리 심화(Trie, 트라이)]]></title>
            <link>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%AC-%EC%8B%AC%ED%99%94Trie-%ED%8A%B8%EB%9D%BC%EC%9D%B4</link>
            <guid>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%AC-%EC%8B%AC%ED%99%94Trie-%ED%8A%B8%EB%9D%BC%EC%9D%B4</guid>
            <pubDate>Thu, 18 Jun 2026 09:00:11 GMT</pubDate>
            <description><![CDATA[<p>저번에는 트리 기반 자료구조 중 <a href="https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%AC-%EC%8B%AC%ED%99%94">Heap</a>을 살펴봤습니다.
오늘은 트라이에 대해서 알아봅시다.</p>
<h1 id="📖-1-trie트라이">📖 1. Trie(트라이)</h1>
<blockquote>
<p>트라이는 문자열을 저장하고 탐색하는 데 특화된 트리 구조입니다.</p>
</blockquote>
<p>여기 문자열 배열이 있습니다.</p>
<pre><code class="language-csharp">string[] words = { &quot;apple&quot;, &quot;app&quot;, &quot;application&quot;, &quot;banana&quot; };</code></pre>
<p>배열에서 &quot;app&quot;으로 시작하는 단어를 찾으려면 전부 다 비교를 해야 합니다.
즉, 시간 복잡도가 <code>O(n)</code>이 되는 겁니다.</p>
<p>이를 해결하기 할 수 있는 트리기반 자료구조입니다.</p>
<hr>
<h2 id="🔖-1-1-트라이-구조">🔖 1-1. 트라이 구조</h2>
<p>Trie는 문자 하나를 Node로 저장하는 구조를 가졌습니다.
각 노드가 문자 하나를 담고, 자식 노드들이 다음 문자를 담는 구조입니다</p>
<p>&quot;app&quot;, &quot;apple&quot;, &quot;banana&quot;를 저장한다고 가정해볼까요?</p>
<pre><code>root
├── a
│   └── p
│       └── p (여기서 &quot;app&quot; 완성)
│           └── l
│               └── e (여기서 &quot;apple&quot; 완성)
└── b
    └── a
        └── n
            └── a
                └── n
                    └── a (여기서 &quot;banana&quot; 완성)</code></pre><p>기본적으로 이런 식으로 저장이 되는 겁니다
<br/></p>
<p>그렇다면 같은 구조를 가진 문자열이 있다면 어떻게 될까요?
&quot;cat&quot;, &quot;car&quot;, &quot;dog&quot;로 예를 들어볼게요</p>
<pre><code>Root
├── c
│   └── a
│       ├── t (&quot;cat&quot;)
│       └── r (&quot;car&quot;)
│
└── d
    └── o
        └── g (&quot;dog&quot;)</code></pre><p>공통 접두사(prefix)를 공유해서 저장합니다</p>
<p>트라이를 응용한다면 <span style = "color:slateblue">아이템 검색창</span>, <span style = "color:yellowgreen">자동완성</span> 이런 부분을 구현할 수 있습니다!</p>
<hr>
<h2 id="🔖-1-2-트라이-구현">🔖 1-2. 트라이 구현</h2>
<pre><code class="language-csharp">class TrieNode
{
    public Dictionary&lt;char, TrieNode&gt; Children = new Dictionary&lt;char, TrieNode&gt;();
    public bool IsEnd = false; // 단어가 끝나는지 표시
}


class Trie
{
    private TrieNode root = new TrieNode();

    // 삽입
    public void Insert(string word)
    {
        TrieNode node = root;
        foreach (char c in word)
        {
            if (!node.Children.ContainsKey(c))
                node.Children[c] = new TrieNode();
            node = node.Children[c];
        }
        node.IsEnd = true; // 단어 끝 표시
    }

    // 탐색
    public bool Search(string word)
    {
        TrieNode node = root;
        foreach (char c in word)
        {
            if (!node.Children.ContainsKey(c)) return false;
            node = node.Children[c];
        }
        return node.IsEnd;
    }

    // 접두사 탐색 (Prefix Search)
    public bool StartsWith(string prefix)
    {
        TrieNode node = root;
        foreach (char c in prefix)
        {
            if (!node.Children.ContainsKey(c)) return false;
            node = node.Children[c];
        }
        return true; // IsEnd 상관없이 경로만 있으면 됨
    }
}</code></pre>
<p>문자열을 저장하면 노드들이 Dictionary로 연결됩니다.</p>
<pre><code class="language-csharp">Trie trie = new Trie();
trie.Insert(&quot;app&quot;);
trie.Insert(&quot;apple&quot;);

trie.Search(&quot;app&quot;);       // true  → &quot;app&quot; 단어가 존재
trie.Search(&quot;appl&quot;);      // false → &quot;appl&quot; 단어는 없음
trie.StartsWith(&quot;appl&quot;);  // true  → &quot;appl&quot;로 시작하는 단어는 있음</code></pre>
<h3 id="🤔-1-2-1-여기서-isend는-왜-있을까요">🤔 1-2-1. 여기서 IsEnd는 왜 있을까요?</h3>
<p>만약 단어의 끝을 알려주는 bool이 없다고 가정해봅시다</p>
<p>Trie에 <code>card</code>를 추가한다고 생각해볼게요</p>
<pre><code>Root
└── c
    └── a
        └── r
            └── d</code></pre><p>그러면 이런 식으로 저장이 되겠죠?</p>
<p>자 여기서 <code>car</code> 검색한다고 해봅시다
<code>c -&gt; a -&gt; r</code></p>
<p>여기서 문제가 됩니다.</p>
<p><code>r</code>이 단어 끝인지 확인할 길이 없기 때문에
<code>car</code>라는 단어를 저장하지 않아도 검색하면 단어가 있다고 나와버리는 현상이 생깁니다</p>
<pre><code>저장된 단어 : card

검색 : car

결과 : 존재함 -&gt; 잘못됨 🙅‍♂️</code></pre><p>그래서 <code>r 노드가 단어 끝인가?</code>를 꼭 확인할 수 있도록 <code>bool IsEnd</code>로 꼭 확인하는 겁니다!</p>
<hr>
<h2 id="⏰-1-3-시간복잡도">⏰ 1-3. 시간복잡도</h2>
<table>
<thead>
<tr>
<th align="center">연산</th>
<th align="center">시간복잡도</th>
</tr>
</thead>
<tbody><tr>
<td align="center">삽입</td>
<td align="center">O(L) - L은 문자열 길이</td>
</tr>
<tr>
<td align="center">탐색</td>
<td align="center">O(L)</td>
</tr>
<tr>
<td align="center">접두사 탐색</td>
<td align="center">O(L)</td>
</tr>
</tbody></table>
<p>단어 개수(n)에 상관없이 문자열 길이에만 비례해서 단어가 100만 개여도 &quot;apple&quot; 찾는 건 5번만 이동합니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C#] 트리 심화(Heap)]]></title>
            <link>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%AC-%EC%8B%AC%ED%99%94</link>
            <guid>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%AC-%EC%8B%AC%ED%99%94</guid>
            <pubDate>Thu, 18 Jun 2026 08:06:11 GMT</pubDate>
            <description><![CDATA[<p>앞에서 <a href="https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%ACTree">자료구조 트리</a>에 대한 기본적인 이론을 살펴본 적이 있습니다.</p>
<p>이러한 트리 구조를 기반으로 발전한 다양한 응용 트리 자료구조를 살펴보려고 합니다. 
Heap, Trie, AVL Tree, Red-Black Tree, B-Tree 그리고 게임 AI에서 활용되는 Behavior Tree까지 순차적으로 학습하며 각각이 어떤 문제를 해결하기 위해 등장했는지 알아보겠습니다.</p>
<p>이번 글에서는 Heap을 살펴보겠습니다</p>
<h1 id="🌲-1-heap">🌲 1. Heap</h1>
<p>힙은 <span style = "color:slateblue">가장 우선순위가 높은 값</span>을 빠르게 꺼내기 위한 트리 구조입니다.</p>
<p>여기서 우선순위가 가장 높다는 건 꺼낼 때마다 항상 최댓값(또는 최솟값)이 나오도록 설계된 트리라는 뜻입니다</p>
<p><code>BST</code>는 왼쪽 &lt; 나 &lt; 오른쪽 규칙이었다면, Heap은 대표적으오 2가지 규칙을 가집니다</p>
<h2 id="🔖-1-1-max-heap">🔖 1-1. Max Heap</h2>
<blockquote>
<p>부모가 자식보다 크거나 같은 트리</p>
</blockquote>
<h2 id=""><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/179df772-6163-4236-8e9e-65a84eb4af04/image.png" alt=""></h2>
<p>해당 트리를 보시면 Root인 90이 가장 큰 것을 알 수 있습니다</p>
<h2 id="🔖-1-2-min-heap">🔖 1-2 Min Heap</h2>
<blockquote>
<p>부모가 자식보다 작거나 같은 트리</p>
</blockquote>
<h2 id="-1"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/c1a5aaf3-dfb6-4549-adc6-f5ba305dbe98/image.png" alt=""></h2>
<p>Min Heap은 반대로 Root인 10이 가장 작은 값입니다.</p>
<h2 id="🔖-1-3-삽입insert">🔖 1-3. 삽입(Insert)</h2>
<blockquote>
<h3 id="🗃️-삽입-과정">🗃️ <strong>삽입 과정</strong></h3>
<p>1️⃣ 새 값을 맨 마지막에 추가
2️⃣ 부모와 비교해서 크면 교환 → 이 과정을  <span style = "color:slateblue"><strong>Heapify Up</strong></span> 또는 <span style = "color:slateblue"><strong>Bubble Up</strong></span> 이라고 합니다
3️⃣ 부모보다 작거나 루트에 도달하면 멈춤</p>
</blockquote>
<br/>


<p>글로만 보면 이해를 할 수는 없으니 해당 힙으로 삽입 과정을 알아봅시다.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/179df772-6163-4236-8e9e-65a84eb4af04/image.png" alt="">
-
배열로 나타낸다면 아래와 같습니다.</p>
<pre><code class="language-csharp">[90, 70, 50, 30, 40]</code></pre>
<br/>
여기에 100을 추가한다고 할 때 삽입 과정입니다.

<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/c6798f6f-b741-478d-a7b1-1f03e256eaa1/image.png" alt=""></p>
<h2 id="🔖-1-4-삭제delete">🔖 1-4. 삭제(Delete)</h2>
<p>Heap에서 삭제는 항상 <strong>루트(최댓값)</strong>만 삭제해. &quot;지금 당장 가장 큰 값을 꺼내줘&quot;가 Heap의 존재 이유거든.</p>
<blockquote>
<h3 id="❌-삭제-과정">❌ <strong>삭제 과정</strong></h3>
<p>1️⃣ 루트 제거
2️⃣ 마지막 노드를 루트 자리로 이동
3️⃣ 자식 중 더 큰 값과 비교해서 작으면 교환 → 이 과정을  <span style = "color:slateblue"><strong>Heapify down</strong></span> 또는 <span style = "color:slateblue"><strong>Bubble down</strong></span> 이라고 합니다
4️⃣ 자식보다 크거나 리프에 도달하면 멈춤</p>
</blockquote>
<p>마찬가지로 글로만 보면 이해를 할 수는 없으니 해당 힙으로 삭제 과정을 알아봅시다.</p>
<h2 id="-2"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/9bcde01f-b959-410b-8363-3094f7864c99/image.png" alt=""></h2>
<p>배열로 나타낸다면</p>
<pre><code class="language-csharp">[100, 70, 90, 30, 40, 50]</code></pre>
<br/>
여기서 100을 삭제한다고 했을 때 삭제 과정입니다

<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/f81af57f-b660-4ab8-9f77-abf6a91d26a5/image.png" alt=""></p>
<h2 id="🔖-1-5-시간복잡도">🔖 1-5. 시간복잡도</h2>
<p>루트만 보면 되니까 조회는 O(1), 삽입, 삭제는 트리 높이만큼만 이동하니까 O(log n)가 됩니다.</p>
<table>
<thead>
<tr>
<th align="center">연산</th>
<th align="center">시간 복잡도</th>
</tr>
</thead>
<tbody><tr>
<td align="center">삽입</td>
<td align="center">O(log n)</td>
</tr>
<tr>
<td align="center">삭제</td>
<td align="center">O(log n)</td>
</tr>
<tr>
<td align="center">최댓값/최솟값 조회</td>
<td align="center">O(1)</td>
</tr>
</tbody></table>
<h2 id="🔖-1-6-heap이-완전-이진-트리인-이유-2가지">🔖 1-6. Heap이 완전 이진 트리인 이유 2가지</h2>
<h3 id="✔️-1-6-1-높이를-낮게logn-유지">✔️ 1-6-1. 높이를 낮게(logN) 유지</h3>
<p>Heap에서 중요한 연산은 삽입과 삭제입니다.
둘 다 연산 시 부모 방향으로 이동하거나 자식 방향으로 반복해서 이동합니다
따라서 성능은 트리 높이에 비례할 수 밖에 없습니다.</p>
<h4 id="🆚-완전-이진-트리-vs-편향-트리-비교">🆚 완전 이진 트리 vs 편향 트리 비교</h4>
<p>노드가 같은 7개라고 했을 때</p>
<p><strong>완전 이진 트리의 경우</strong></p>
<h2 id="-3"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a6e60436-6699-4da4-a33e-3daa42486034/image.png" alt=""></h2>
<p>높이가 3이 되기 때문에 삽입/삭제 시 최대 3번까지 이동합니다.
<br/><br/></p>
<p><strong>편향 트리의 경우</strong>
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/0bb82277-6d64-4c50-acd9-45b392492352/image.png" alt="">
-
높이가 7이 되기 때문에 삽입/삭제 시 최대 7번까지 이동합니다.
<br/></p>
<blockquote>
<p>즉, 완전 이진 트리면 O(logN), 편향 트리의 경우 O(N)가 되는 거고 높이를 낮게 유지하는 게 곧 속도이기 때문에 Heap에 완전 이진 트리를 사용하는 겁니다</p>
</blockquote>
<h3 id="✔️-1-6-2-배열로-구현하기-위해">✔️ 1-6-2. 배열로 구현하기 위해</h3>
<p>완전 이진 트리는 위에서 아래, 왼쪽에서 오른쪽 순서로 노드를 채우기 때문에 배열로 쉽게 구현이 가능합니다.</p>
<pre><code>레벨 0:        90          → 인덱스 0
레벨 1:      70  50        → 인덱스 1, 2
레벨 2:    30  40  10      → 인덱스 3, 4, 5</code></pre><h2 id="-4"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/ea6517aa-3d67-419f-a7ae-6235c41f23cc/image.png" alt=""></h2>
<p>해당 트리를 배열로 나타낸다면 아래와 같이 나타낼 수 있습니다</p>
<pre><code class="language-csharp">[90, 70, 50, 30, 40, 10]</code></pre>
<p>그렇게 된다면 부모, 자식을 해당 계산으로 찾을 수 있습니다!</p>
<pre><code>left  = index * 2 + 1;
right = index * 2 + 2;
parent = (index - 1) / 2;</code></pre><br/>

<blockquote>
<p>계산식만 봤을 때는 이해하기 힘드니 예를 들어볼까요?</p>
</blockquote>
<pre><code class="language-csharp">heap[0] = 90</code></pre>
<blockquote>
<blockquote>
<p>이 친구의 왼쪽 자식은 <code>index * 2 + 1</code>를  적용하여 <code>0 * 2 + 1 = 1</code>로 계산한다면</p>
</blockquote>
</blockquote>
<pre><code class="language-csharp">heap[1] = 70</code></pre>
<p>으로 나오는 것을 알 수 있습니다.
<br/></p>
<blockquote>
<blockquote>
<p>오른쪽 자식을 계산해보면 <code>index * 2 + 2</code>를 적용하여 <code>0 * 2 + 2 = 2</code>로 계산한다면</p>
</blockquote>
</blockquote>
<pre><code class="language-csharp">heap[2] = 50</code></pre>
<p>으로 나오는 것을 알 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C#] 트리(Tree)]]></title>
            <link>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%ACTree</link>
            <guid>https://velog.io/@asiatic_ricecake/C-%ED%8A%B8%EB%A6%ACTree</guid>
            <pubDate>Mon, 15 Jun 2026 08:55:10 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-1-트리">📖 1. 트리</h1>
<blockquote>
<p>트리는 노드(Node)들이 부모-자식 관계로 연결된 비선형 계층 구조 자료구조</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/f0b72cd2-ac43-490c-953d-005767677cf2/image.png" alt=""></p>
<h2 id="🔖-1-1-노드node">🔖 1-1. 노드(node)</h2>
<p>먼저 트리를 이해하기 위해서는 노드의 개념을 알고 있어야 합니다.</p>
<blockquote>
<p>노드는 데이터를 담고 있으면서 다른 노드와 연결될 수 있는 객체</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/cc7ca3c5-e5d3-4de7-8ff2-cf2d4b0b7952/image.png" alt=""></p>
<pre><code class="language-csharp">class Node
{
    public int Data;   // 값을 저장하는 변수
    public Node Left;  // 다른 Node를 가리키는 변수
    public Node Right; // 다른 Node를 가리키는 변수
}</code></pre>
<p>핵심은 <span style = "color:red">Left, Right</span> 변수입니다.</p>
<p>이 둘은 <code>Node 타입의 변수</code>인데, 여기에 담기는 값이 또 다른 Node 객체의 참조(주소)가 되는 것입니다.</p>
<pre><code class="language-csharp">Node root = new Node { Data = 10 };
Node left = new Node { Data = 20 };
Node right = new Node { Data = 30 };

root.Left = left;   // root의 Left 변수에 left 객체의 주소를 저장
root.Right = right;</code></pre>
<pre><code>   10 (root)
     /  \
   20    30
 (Left) (Right)</code></pre><p><code>root.Left.Data</code>로 20에 접근 가능한 것입니다.</p>
<h2 id="🖥️-1-2-트리를-쉽게-이해하기-위한-코드">🖥️ 1-2. 트리를 쉽게 이해하기 위한 코드</h2>
<p>트리를 이해하기 위한 코드를 살펴봅시다</p>
<pre><code class="language-csharp">public class TreeNode
{
    public int Value;

    public TreeNode Left;
    public TreeNode Right;

    public TreeNode(int value)
    {
        Value = value;
    }
}</code></pre>
<p>이 코드를 예시를 들어봅시다</p>
<pre><code class="language-csharp">TreeNode root = new TreeNode(10);

root.Left = new TreeNode(20);
root.Right = new TreeNode(30);</code></pre>
<p>이렇게 인스턴스를 생성했다고 가정합니다</p>
<pre><code class="language-csharp">Console.WriteLine(root.Value);
Console.WriteLine(root.Left.Value);
Console.WriteLine(root.Right.Value);</code></pre>
<pre><code>10
20
30</code></pre><p>콘솔로 실행하면 이런 결과물이 나올 겁니다.
<br/>
콘솔로 보면 이해가 되지 않아 그림으로 나타낸다면...</p>
<pre><code>    10
   /  \
 20    30</code></pre><p>이 상태로 연결된다는 것으로 이해하시면 됩니다.</p>
<p>그럼 여기서 노드를 추가해볼까요?</p>
<pre><code class="language-csharp">TreeNode root = new TreeNode(10);

root.Left = new TreeNode(20);
root.Right = new TreeNode(30);

root.Left.Left = new TreeNode(40);
root.Left.Right = new TreeNode(50);</code></pre>
<pre><code class="language-csharp">Console.WriteLine(root.Left.Left.Value);
Console.WriteLine(root.Left.Right.Value);</code></pre>
<pre><code>40
50</code></pre><p>일반 콘솔로 실행한다면 이런 값이 나오겠지만...</p>
<p>이 부분을 그림으로 나타낸다면</p>
<pre><code>          10
         /  \
       20    30
      /  \
    40    50</code></pre><p>이렇게 노드가 연결되는 것입니다.</p>
<hr>
<h1 id="📖-2-트리-순회traversal">📖 2. 트리 순회(Traversal)</h1>
<p>자 위에서 트리에 대한 기본 개념을 설명드렸습니다
위의 코드 예시를 보면 노드가 증가할 수록 계속 참조를 하고 있습니다.</p>
<pre><code class="language-csharp">Console.WriteLine(root.Value);
Console.WriteLine(root.Left.Value);
Console.WriteLine(root.Right.Value);</code></pre>
<p>근데 여기서 만약 노드가 1000개라면? <code>root.Left.Right.Left.Right....</code> 
하루종일 이것만 적을 겁니다</p>
<p>여기서 추가로 배워볼 개념이 <code>트리 순회</code>입니다!</p>
<h2 id="🔖-2-1-트리-순회-개념">🔖 2-1. 트리 순회 개념</h2>
<blockquote>
<p>트리에 있는 모든 노드를 한 번씩 방문하는 것</p>
</blockquote>
<p>왼쪽 노드와 오른쪽 노드를 모두 방문하기 위해서 <code>재귀</code> 개념을 사용합니다</p>
<pre><code>      10
     /  \
   20    30
  /  \
40   50</code></pre><p>이 트리를 순회한다고 가정할게요</p>
<pre><code class="language-csharp">void Traverse(Node node)
{
    if (node == null) return; // 종료 조건 (자식이 없으면 멈춤)

    Console.WriteLine(node.Data); // 방문
    Traverse(node.Left);          // 왼쪽 -&gt; 재귀로 끝까지 방문
    Traverse(node.Right);         // 오른쪽 -&gt; 재귀로 끝까지 방문
}</code></pre>
<p>왼쪽 노드부터 방문하고 오른쪽 노드를 출력하니까
<code>10 → 20 → 40 → 50 → 30</code> 가 결과로 나올 것입니다.</p>
<h2 id="🔖-2-2-순회의-3가지-방식">🔖 2-2. 순회의 3가지 방식</h2>
<p>순회의 방식은 대표적으로 3가지가 있습니다.</p>
<pre><code>          10
         /  \
       20    30
      /      / \
    40     50  60</code></pre><p>이런 트리구조를 가지고 있다고 가정하고 설명하겠습니다.</p>
<h3 id="2-2-1-✔️-전위-순회preorder">2-2-1. ✔️ 전위 순회(Preorder)</h3>
<p>전위 순회는 <code>나 -&gt; 왼쪽 -&gt; 오른쪽</code> 순서로 순회하는 방식입니다</p>
<pre><code class="language-csharp">static void PreOrder(TreeNode node)
{
    if (node == null)
        return;

    Console.WriteLine(node.Value);

    PreOrder(node.Left);
    PreOrder(node.Right);
}</code></pre>
<pre><code>10
20
40
30
50
60</code></pre><h3 id="2-2-2-✔️-중위-순회inorder">2-2-2. ✔️ 중위 순회(InOrder)</h3>
<p>중위 순회는 <code>왼쪽 -&gt; 나 -&gt; 오른쪽</code> 순서로 순회하는 방식입니다</p>
<pre><code class="language-csharp">static void InOrder(TreeNode node)
{
    if (node == null)
        return;

    InOrder(node.Left);

    Console.WriteLine(node.Value);

    InOrder(node.Right);
}</code></pre>
<pre><code>40
20
10
50
30
60</code></pre><h3 id="2-2-3-✔️-후위-순회postorder">2-2-3. ✔️ 후위 순회(PostOrder)</h3>
<p>후위 순회는 <code>왼쪽 -&gt; 오른쪽 -&gt; 나</code> 순서로 순회하는 방식입니다</p>
<pre><code class="language-csharp">static void PostOrder(TreeNode node)
{
    if (node == null)
        return;

    PostOrder(node.Left);
    PostOrder(node.Right);

    Console.WriteLine(node.Value);
}</code></pre>
<pre><code>40
20
50
60
30
10</code></pre><hr>
<h1 id="📖-3-이진-트리binary-tree">📖 3. 이진 트리(Binary Tree)</h1>
<p>이진 트리는 모든 노드가 자식을 <strong><span style = "color:red">최대 2개</span>까지만 가질 수 있는 트리</strong>입니다.</p>
<pre><code class="language-csharp">class Node
{
    public int Data;
    public Node Left;
    public Node Right;
}</code></pre>
<p>위에서 트리를 설명하기 위해 보여준 예시들이 <code>이진 트리</code>라고 생각하시면 됩니다</p>
<h2 id="🔖-3-1-이진-트리-종류">🔖 3-1. 이진 트리 종류</h2>
<h3 id="✔️-3-1-1-정-이진-트리full-binary-tree">✔️ 3-1-1. 정 이진 트리(Full Binary Tree)</h3>
<p>모든 노드가 자식이 0개 또는 2개만 가지는 트리입니다. 즉 1개인 노드가 없습니다.</p>
<pre><code>      1
     / \
    2   3
   / \
  4   5</code></pre></br>

<h3 id="✔️-3-1-2-포화-이진-트리perfect-binary-tree">✔️ 3-1-2. 포화 이진 트리(Perfect Binary Tree)</h3>
<p>모든 레벨이 완전히 채워진 트리이고 리프 노드들이 모두 같은 깊이에 있습니다.
위의 특징으로 모든 노드가 자식 2개를 가집니다.</p>
<pre><code>        1
      /   \
     2     3
    / \   / \
   4  5  6  7</code></pre></br>

<h4 id="⭐-노드-수-공식참고">⭐ 노드 수 공식(참고)</h4>
<p>$$
\text{노드 수} = 2^h - 1
$$</p>
<ul>
<li>h : 트리의 레벨(Level)</li>
<li>레벨 1 → 1개</li>
<li>레벨 2 → 2개</li>
<li>레벨 3 → 4개</li>
<li>레벨 4 → 8개</li>
</ul>
<p>각 레벨의 노드 수는 2배씩 증가하여 등비수열 합 공식으로 노드 수가 나옵니다.</p>
<p>$$
1 + 2 + 4 + ... + 2^{h-1}
=
2^h - 1
$$</p>
</br>

<h3 id="✔️-3-1-3-완전-이진-트리complete-binary-tree">✔️ 3-1-3. 완전 이진 트리(Complete Binary Tree)</h3>
<p>마지막 레벨을 제외한 모든 레벨이 채워져 있고, <span style = "color:red">마지막 레벨은 왼쪽</span>부터 채워지는 트리입니다.</p>
<pre><code>        1
      /   \
     2     3
    / \   /
   4  5  6</code></pre><pre><code>        1
      /   \
     2     3
    /
   4</code></pre><p>왼쪽부터 채워야 하기 때문에 오른쪽부터 채워진 밑에 트리는 성립할 수 없습니다.</p>
<pre><code>        1
      /   \
     2     3
      \     
       5</code></pre></br>

<h3 id="✔️-3-1-4-편향-이진-트리skewed-binary-tree">✔️ 3-1-4. 편향 이진 트리(Skewed Binary Tree)</h3>
<p>모든 노드가 한쪽 자식만 가져서 한쪽으로 쏠리는 모양이 됩니다.</p>
<pre><code>1                    1
 \                  /
  2                2
   \              /
    3            3
     \          /
      4        4
(오른쪽 편향)    (왼쪽 편향)</code></pre><p>사실상 Linked List와 동일한 모양이 됩니다.</p>
<hr>
<h1 id="📖-4-bst-binary-search-tree-이진-탐색-트리">📖 4. BST (Binary Search Tree, 이진 탐색 트리)</h1>
<p>BST는 이진 트리에 순서 규칙을 추가한 것입니다.</p>
<p>각 노드를 기준으로 숫자 크기에 따라 정렬을 하는 건데 일단 수를 나열해봤을 때 Root가 가장 가운데 값을 가집니다. 왼쪽 자식 Root보다 작게 오른쪽 자식은 Root보다 더 크게 정렬합니다</p>
<pre><code>        50
       /   \
     30      70
    /  \    /  \
   20  40  60  80</code></pre><p>보시면 왼쪽은 50보다 전부 작고 오른쪽은 50보다 전부 크죠? 이런 특징을 가진 트리가 BST입니다.</p>
<h2 id="🤔-4-1-왜-이런-식으로-정렬할까요">🤔 4-1 왜 이런 식으로 정렬할까요?</h2>
<p>가장 큰 이유는 빠르게 탐색(Search)하기 위해서입니다.</p>
<p>예를 들어 80 찾는다고 했을 때 전부 순회해서 찾는 것보다 Root 값을 기준으로 그 값이 크면 오른쪽만 탐색하면 되기 때문에 효율적입니다!</p>
<pre><code class="language-csharp">public Node Search(Node node, int target)
{
    if (node == null) return null;          // 못 찾음
    if (node.Data == target) return node;   // 찾음

    if (target &lt; node.Data)
        return Search(node.Left, target);   // 왼쪽으로
    else
        return Search(node.Right, target);  // 오른쪽으로
}</code></pre>
<p>매번 비교해서 절반씩 줄여나가는 게 이진 탐색과 똑같은 원리입니다!</p>
<h2 id="🤔-4-2-삽입insert은">🤔 4-2. 삽입(Insert)은?</h2>
<p>앞에서는 탐색을 살펴봤다면 삽입하는 건 어떨까요?</p>
<pre><code class="language-csharp">public Node Insert(Node node, int value)
{
    if (node == null) return new Node { Data = value }; // 빈 자리에 삽입

    if (value &lt; node.Data)
        node.Left = Insert(node.Left, value);
    else
        node.Right = Insert(node.Right, value);

    return node;
}</code></pre>
<p>마찬가지로 삽입 위치를 찾는 비교 횟수가 확 줄어들기 때문에 빠릅니다.</p>
<h2 id="🚨-4-3-최악의-경우편향-이진-트리">🚨 4-3. 최악의 경우(편향 이진 트리)</h2>
<p>편향 이진 트리의 경우 한쪽으로만 연결 되어있는 구조라고 앞에서 언급했습니다.</p>
<pre><code>1
 \
  2
   \
    3
     \
      4
       \
        5</code></pre><p>결국 이건 Linked list와 같은 구조로 되어버립니다.
여기서 탐색의 시간복잡도가 <code>O(n)</code>이 됩니다.</p>
<p>이 부분을 해결하기 위해서 <code>AVL, Red-Black Tree 같은 균형 BST</code>가 있습니다.</p>
<h2 id="📊-4-4-시간-복잡도-정리">📊 4-4. 시간 복잡도 정리</h2>
<table>
<thead>
<tr>
<th>자료구조</th>
<th>검색(Search)</th>
<th>삽입(Insert)</th>
<th>삭제(Delete)</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>배열</td>
<td>O(n)</td>
<td>O(n)</td>
<td>O(n)</td>
<td>중간 삽입/삭제 시 밀기 발생</td>
</tr>
<tr>
<td>Linked List</td>
<td>O(n)</td>
<td>O(1)*</td>
<td>O(1)*</td>
<td>위치를 이미 알고 있을 때</td>
</tr>
<tr>
<td>BST (평균)</td>
<td>O(log n)</td>
<td>O(log n)</td>
<td>O(log n)</td>
<td>트리가 균형 잡힌 경우</td>
</tr>
<tr>
<td>BST (최악)</td>
<td>O(n)</td>
<td>O(n)</td>
<td>O(n)</td>
<td>편향 트리 발생</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] MCP 세팅(with Coplay, Claude)]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-MCP-%EC%84%B8%ED%8C%85with-Coplay-Claude</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-MCP-%EC%84%B8%ED%8C%85with-Coplay-Claude</guid>
            <pubDate>Sun, 14 Jun 2026 02:46:31 GMT</pubDate>
            <description><![CDATA[<h1 id="⚙️-1-시작하기-전">⚙️ 1. 시작하기 전</h1>
<p>사실  Coplay에서 친절하게 가이드를 전부 제공을 한 상태이기 때문에 참고하시면 됩니다.</p>
<h2 id="🐻❄️-1-1-coplay-github">🐻‍❄️ 1-1. Coplay Github</h2>
<p><a href="https://github.com/CoplayDev/unity-mcp">Coplay Github</a></p>
<h2 id="📄-1-2-coplay-공식-기술문서">📄 1-2. Coplay 공식 기술문서</h2>
<p><a href="https://docs.coplay.dev/coplay-mcp/claude-code-guide">Coplay 기술문서</a></p>
<hr>
<h2 id="📥-1-3-필수-설치-목록">📥 1-3. 필수 설치 목록</h2>
<h3 id="✔️-1-3-1-unity-20213-lts">✔️ 1-3-1. Unity 2021.3 LTS+</h3>
<p>해당 버전 이상으로 설치해주시고 무조건 LTS로 설치하셔야 합니다.</p>
<h3 id="✔️-1-3-2-python-310-and-uv">✔️ 1-3-2. Python 3.10+ and uv</h3>
<h4 id="📥-1-3-2-1-파이썬--설치">📥 1-3-2-1. 파이썬  설치</h4>
<p><a href="https://www.python.org/downloads/windows/">파이썬 설치</a></p>
<h4 id="📥-1-3-2-2-uv-설치">📥 1-3-2-2. UV 설치</h4>
<p>UV는 터미널에서 사용할 수 있도록 해주는 파이썬 패키지 입니
<a href="https://docs.astral.sh/uv/getting-started/installation/">UV 공식 가이드</a>를 참고하시면서 설치하주시면 됩니다</p>
<p>1️⃣ <strong>터미널에서 UV 설치</strong>
터미널 열어서 해당 명령키를 입력하여 설치합니다.</p>
<p>① <strong><span style = "color:yellow">PowerShell을 사용하는 경우</span></strong>
윈도우 사용자는 PowerShell를 사용하시면 됩니다.</p>
<pre><code class="language-powershell">powershell -ExecutionPolicy ByPass -c &quot;irm https://astral.sh/uv/install.ps1 | iex&quot;</code></pre>
<p>② <strong><span style = "color:yellow">Git Bash를 사용하는 경우</span></strong>
Powershell이 명령키가 잘 안 먹힐  때가 있어서 그 때는 Git을 설치하여 Git Bash에서 Linux 계열 명령어를 입력해주시면 됩니다.</p>
<pre><code class="language-bash">curl -LsSf https://astral.sh/uv/install.sh | sh</code></pre>
<p>2️⃣ <strong>설치됐는지 확인</strong>
재시작해서 해당 명령키를 넣어서 확인하시면 됩니다.      </p>
<pre><code class="language-powershell">uv --version
uvx --version</code></pre>
<p>Powershell이나 Git Bash 아무 터미널 괜찮습니다!
저 명령어를 입력했을 때 버전이 나오면 설치가 완료된겁니다.</p>
<h4 id="📥-1-3-2-3-an-mcp-client">📥 1-3-2-3. An MCP Client</h4>
<p>Claude Desktop, Claude Code, Cursor, VS code Copilot, Antigravity 등 원하시는 걸로 설치하시면 됩니다</p>
<p>저는 Claude Code를 사용할 예정입니다</p>
<hr>
<h1 id="⚙️-2-unity에-패키지-설치">⚙️ 2. Unity에 패키지 설치</h1>
<h2 id="📥-2-1-unity-mcp-설치">📥 2-1. Unity MCP 설치</h2>
<p>Unity 프로젝트를 먼저 생성하고 PackageManager에서 URL로 패키지를 추가합니다</p>
<p><code>Window &gt; Package Manager &gt; Add package from git URL...</code>
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/6115e0d5-f1a3-493f-ae3b-65d6e9abf49f/image.png" alt=""></p>
<pre><code>https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main</code></pre><p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/db83e548-ffeb-49ac-bdb9-f6794afa6c66/image.png" alt=""></p>
<p>유니티에서 <code>Window &gt; MCP For Unity</code>가 나와있으면 설치 된 겁니다.</p>
<h2 id="📥-2-2-coplay-설치">📥 2-2. Coplay 설치</h2>
<p><code>Window &gt; Package Manager &gt; Add package from git URL...</code></p>
<p>로 가셔서 해당 링크 복사해서 설치하시면 됩니다. </p>
<pre><code>https://github.com/CoplayDev/coplay-unity-plugin.git#beta</code></pre><h3 id="🚨-2-2-1-unity-6인-경우-오류">🚨 2-2-1. Unity 6인 경우 오류</h3>
<p>Unity 6에서는 해당 오류가 나오면서 툴바에 Coplay 버튼이 안 보일 겁니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/48eb8103-bbdd-4bab-8b79-819302d6aac4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/63a58283-af4a-421d-8f1e-2f907f702be9/image.png" alt=""></p>
<pre><code class="language-csharp">We have detected that your project includes custom elements added to the Unity Editor&#39;s main toolbar using unsupported methods. This approach is not supported and will lead to issues in future versions. Refer to the official &lt;a href=&quot;https://docs.unity3d.com/6000.3/Documentation/ScriptReference/Toolbars.MainToolbar.html&quot;&gt;API documentation&lt;/a&gt; for adding custom elements to the main toolbar.

Your custom toolbar elements can be unhidden via the context menu (right-click the main toolbar -&gt; &lt;i&gt;Unsupported User Elements&lt;/i&gt;).
UnityEngine.UIElements.VisualElement:Add (UnityEngine.UIElements.VisualElement)
Coplay.Coplay/&lt;&gt;c:&lt;CoplayToolbarButton&gt;b__30_0 ()
UnityEditor.EditorApplication:Internal_CallDelayFunctions ()</code></pre>
<p><strong>Coplay 플러그인</strong>이 <strong>Unity 6의 새로운 툴바 API를 아직 완전히 지원 못해서</strong> 나오는 경고입니다. </p>
<p>사용할 수 없는 건 아니니 걱정 안 하셔도 됩니다.</p>
<p>저기 경고 메시지대로 <strong><code>우클릭 → Unsupported User Elements</code></strong> 에서 다시 표시할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a42b7c26-a173-4ad8-9c4a-6ebf507a1047/image.png" alt=""></p>
<p>이렇게 <code>Coplay AI</code>가 나오면 잘 된 겁니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/ebe23cd9-5cac-4ef8-98f5-683560e7cd7d/image.png" alt=""></p>
<hr>
<h1 id="⚙️-3-claude-설치">⚙️ 3. Claude 설치</h1>
<p>Claude로 Unity MCP를 사용하려면 무조건 <strong>Pro 요금제를</strong> 사용하고 있어야 합니다!</p>
<p>그리고 Claude Desktop과 Claude Code 중 하나만 설치하시면 됩니다.</p>
<h2 id="📥-3-1-claude-desktop-설치">📥 3-1. Claude Desktop 설치</h2>
<p><a href="https://claude.com/ko-kr/download">Claude 공식 사이트</a> 가셔서 앱 다운 받으시면 됩니다</p>
<h2 id="📥-3-2-claude-code-설치">📥 3-2. Claude Code 설치</h2>
<p>해당 작업은 PowerShell보다는 <strong>Git Bash</strong>로 설치하시는 걸 권장합니다.</p>
<h3 id="✔️-3-2-1-nodejs와-npm-설치">✔️ 3-2-1. Node.js와 npm 설치</h3>
<p><a href="https://nodejs.org/">https://nodejs.org</a> 에서 <strong>LTS 버전</strong> 다운로드 후 설치</p>
<p>1️⃣ <strong>설치 확인 (Git Bash)</strong>
둘 다 버전 숫자가 뜨면 설치 완료된 겁니다</p>
<pre><code class="language-powershell">node --version
npm --version</code></pre>
<p>이 때 PowerShell을 사용하여 npm이 안 먹는 경우가  있습니다.</p>
<p>PowerShell은 기본적으로 외부 스크립트 실행을 막는 보안 정책이 있어서, npm 같은 명령어가 차단될 수 있습니다.</p>
<p><strong>⭐ 해결방법</strong></p>
<p>PowerShell을 <strong>관리자 권한</strong>으로 열고 아래 명령어 실행합니다</p>
<p>시작 메뉴에서 <code>PowerShell</code> 검색 → 우클릭 → <strong>&quot;관리자 권한으로 실행&quot;</strong></p>
<pre><code class="language-powershell">Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned</code></pre>
<p><code>Y</code> 입력 후 터미널 <strong>완전히 닫고 재시작</strong>하면 npm 정상 작동합니다.</p>
<h3 id="✔️-3-2-2-claude-code-cli-설치">✔️ 3-2-2. Claude Code CLI 설치</h3>
<p>터미널을 열고 다음 명령어를 누르시면 됩니다.</p>
<pre><code class="language-bash">npm install -g @anthropic-ai/claude-code</code></pre>
<p><strong>1️⃣ 설치 확인 (Git Bash)</strong>
마찬가지로 버전 숫자가 뜨면 설치 완료됨</p>
<pre><code class="language-bash">claude --version</code></pre>
<hr>
<h1 id="🔗-4-unity-mcp-연결">🔗 4. Unity MCP 연결</h1>
<p>지금까지는 MCP 연결을 위해 필요한 것을 설치했다면 이제는 MCP 연결을 진행할 겁니다. </p>
<p>둘 다 Claude지만 Desktop과 Code 각각 연결하는 방법이 조금 다릅니다.</p>
<h2 id="🔖-4-1-claude-code">🔖 4-1. Claude Code</h2>
<h3 id="✔️-4-1-1-coplay-mcp-서버-추가">✔️ 4-1-1. Coplay MCP 서버 추가</h3>
<p>터미널(Git Bash)에 해당 명령어를 넣어 Claude Code에 서버를 추가합니다.</p>
<pre><code class="language-bash">claude mcp add --scope user --transport stdio coplay-mcp --env MCP_TOOL_TIMEOUT=720000 -- uvx --python &quot;&gt;=3.11&quot; coplay-mcp-server@latest</code></pre>
<p>해당 부분이 나오면 정상적으로 등록된 겁니다.</p>
<pre><code class="language-bash">Added stdio MCP server coplay-mcp with command: uvx --python &gt;=3.11 coplay-mcp-server@latest to user config</code></pre>
<h3 id="✔️-4-1-2-claude-code-실행-후-서버가-등록되었는지-확인">✔️ 4-1-2. Claude Code 실행 후 서버가 등록되었는지 확인</h3>
<p>Git Bash에 해당 명령어를 입력하시면 Claude Code가 실행됩니다.</p>
<pre><code class="language-bash">claude</code></pre>
<p>다음으로 <code>/mcp</code>를 입력하여 Unity MCP 서버가 있는지 확인합니다</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/95ba1669-93bd-4c71-aa72-9899d8b68a78/image.png" alt=""></p>
<p>여기서 coplay-mcp가 보인다면 정상적으로 연결된겁니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/2af411c4-34c1-490e-a758-1906cd37050e/image.png" alt=""></p>
<h2 id="🔖-4-2-claude-desktop">🔖 4-2. Claude Desktop</h2>
<h3 id="✔️-4-2-1-claude-desktop-실행">✔️ 4-2-1. Claude Desktop 실행</h3>
<h3 id="✔️-4-2-2-설정--개발자--구성-편집">✔️ 4-2-2. 설정 &gt; 개발자 &gt; 구성 편집</h3>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/75e254ce-6b88-4298-bbef-92117eee427a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/c363869e-df7c-4527-a6b5-5ce5a06f920d/image.png" alt=""></p>
<h3 id="✔️-4-2-3-claude_desktop_configjson-json-파일을-열어서-해당-부분-추가">✔️ 4-2-3. claude_desktop_config.json JSON 파일을 열어서 해당 부분 추가</h3>
<pre><code class="language-json">    {
      &quot;mcpServers&quot;: {
        &quot;coplay-mcp&quot;: {
          &quot;command&quot;: &quot;uvx&quot;,
          &quot;args&quot;: [
            &quot;--python&quot;,
            &quot;&gt;=3.11&quot;,
            &quot;coplay-mcp-server@latest&quot;
          ],
          &quot;env&quot;: {
            &quot;MCP_TOOL_TIMEOUT&quot;: &quot;720000&quot;
          }
        }
      }
    }</code></pre>
<h3 id="✔️-4-2-4-mcp-서버가-등록-잘-되었는지-확인">✔️ 4-2-4. MCP 서버가 등록 잘 되었는지 확인</h3>
<p>Claude 설정에 개발자에 들어가셔서 Coplay MCP 서버가 연결되어 있으면 완료한겁니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/2c2b5e00-39ef-403a-adb3-ed223def6db6/image.png" alt=""></p>
<hr>
<h1 id="🤖-5-테스트">🤖 5. 테스트</h1>
<p>연결까지 완료했다면 테스트를 한번 해봅시다</p>
<p>유니티에서 <code>Window &gt; MCP For Unity &gt; Toggle MCP Window</code> 에 들어가주세요.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a84e3dcd-c217-4323-9b8a-b58d70798965/image.png" alt=""></p>
<p>일단 사용할 AI가 register 되어있는지 확인합니다</p>
<p>지금 이미지처럼 되어있으면 된 겁니다.(전 Claude Code로 테스트 중)</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/b5e6a372-fa28-457c-87c5-4737d977f1e0/image.png" alt=""></p>
<p>유니티에 테스트 명목으로 한번 시켜보고 정상 작동하는지 확인합니다.</p>
<pre><code class="language-bash">지금 MCP 세팅 전부 완료했는데 기능이 동작하는지 테스트 한번 해줄 수 있을까?</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 벡터]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EB%B2%A1%ED%84%B0</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EB%B2%A1%ED%84%B0</guid>
            <pubDate>Sat, 13 Jun 2026 11:14:39 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-1-벡터-개념">📖 1. 벡터 개념</h1>
<p>벡터는 &quot;방향(Direction) + 크기(Magnitude)&quot; 개념이 있는 물리량입니다.</p>
<p>밑에 그림을 참고하면 더 쉽게 이해하실 수 있습니다
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/fb6c7563-bddf-4c4d-81da-7bde17849491/image.png" alt=""></p>
<pre><code class="language-csharp">Vector3 vector = new Vector3(3,0,0)</code></pre>
<p>유니티에서는 벡터를 이렇게 나타내는데 &quot;<span style = "color:red">오른쪽 방향으로 3만큼</span>&quot;의 의미가 있습니다</p>
<hr>
<h1 id="📖-2-벡터의-덧셈">📖 2. 벡터의 덧셈</h1>
<h2 id="🔖-2-1-벡터의-덧셈">🔖 2-1. 벡터의 덧셈</h2>
<p>현재 플레이어의 위치가 여기있다고 가정할게요</p>
<pre><code class="language-csharp">Vector3 pos = new Vector3(5,0,0)</code></pre>
<p>여기서 오른쪽으로 2칸 이동하고 싶다고 했을때</p>
<pre><code class="language-csharp">Vector3 move = new Vector3(2, 0, 0);</code></pre>
<p>이런 식으로 더해서 이동할 수 있겠죠</p>
<pre><code class="language-csharp">pos = pos + move</code></pre>
<h2 id="🔖-2-2-unity에서-활용">🔖 2-2. Unity에서 활용</h2>
<p>게임 개발할 때 밑의 예시처럼 사용하는 경우는 별로 없습니다</p>
<pre><code class="language-csharp">transform.position += Vector3.forward;</code></pre>
<p><code>Vector3.forward</code>이건 앞으로 이동 즉 Z축 +로 이동하는 겁니다
기본값은 <code>(0,0,1)</code>로 고정되어있습니다.</p>
<p>그래서 이동을 구현할 때 <code>speed</code>라는 변수를 선언해서 곱해서 사용하는 겁니다(여기서 <strong>벡터의 곱</strong>이 사용되는 겁니다)</p>
<pre><code class="language-csharp">public float speed = 5f;

transform.position += Vector3.forward * speed;</code></pre>
<h3 id="🤔-2-2-1-이동-구현-시-소수점으로-표현하는-이유">🤔 2-2-1. 이동 구현 시 소수점으로 표현하는 이유?</h3>
<p>이동 구현할 때 float(부동소수점)를 사용하는 이유를 생각해볼까요?</p>
<p>int를 사용하면 정수이기 때문에 소수점이 잘려서 움직임이 끊기거나 아예 움직이지 않을 수도 있습니다</p>
<p>프레임이 60FPS라고 가정하면 <code>Time.deltaTime</code>이 <code>0.016</code>인데</p>
<pre><code class="language-csharp">int move = (int)(5 * Time.deltaTime);</code></pre>
<pre><code class="language-csharp">(int)0.08</code></pre>
<p>이렇게 되면 <code>0</code>으로 나와서 움직이지 않다가 계속 계산되면서 갑자기 움직이고 그런 식으로 끊기게 됩니다.</p>
<p>그래서 float을 사용하여 소수점 단위 위치 표현해야 부드러운 이동 가능하도록 만드는 것입니다.</p>
<hr>
<h1 id="📖-3-벡터의-뺄셈">📖 3. 벡터의 뺄셈</h1>
<p>벡터의 뺄셈은 정말 중요한 개념입니다.
게임에 정말 많이 응용되는 개념이라 무조건 알고 계셔야 합니다</p>
<p>한 오브젝트에서 다른 오브젝트까지의 거리와 방향을 구하고자 할 때 사용되는 계산 방식입니다.</p>
<h2 id="🔖-3-1-벡터의-뺄셈">🔖 3-1. 벡터의 뺄셈</h2>
<p>내 위치를 <code>(2,0,0)</code>라고 하고 적 위치를 <code>(8,0,0)</code>라고 한다면 나 기준으로 오른쪽 6만큼 가면 적이 있다는 의미가 됩니다.</p>
<p>유니티에서 코드로 표현한다면 대략 이런 코드로 되겠네요</p>
<pre><code class="language-csharp">Vector3 direction = target.position - transform.position;</code></pre>
<p>이 부분을 응용하면 AI 추적, 유도 미사일, 카메라 추적, 플레이어 따라오기 등 정말 많은 기능을 구현할 수 있습니다</p>
<p>물론 유니티에서는 굳이 코드로 구현을 안해도 시네머신, NevMesh등 으로 카메라 추적이나 AI 추적 구현은 가능하긴 한데 기본적인 원리는 <span style = "color:red">벡터의 뺄셈</span>을 통해 한 오브젝트에서 다른 오브젝트까지의 거리와 방향을 계산하여 만드는 겁니다.</p>
<hr>
<h1 id="📖-4-unity의-벡터-타입">📖 4. Unity의 벡터 타입</h1>
<p>위에서도 잠시 예시 코드로 보여줬지만 게임에서 많이 사용하는 Vector 타입은 <code>Vector2</code>, <code>Vector3</code>입니다.</p>
<p><code>Vector4</code>도 있긴 한데 거의 사용하지 않습니다.</p>
<table>
<thead>
<tr>
<th>타입</th>
<th>의미</th>
<th>사용처</th>
</tr>
</thead>
<tbody><tr>
<td>Vector2</td>
<td>x, y</td>
<td>2D 게임, UI</td>
</tr>
<tr>
<td>Vector3</td>
<td>x, y, z</td>
<td>3D 게임</td>
</tr>
<tr>
<td>Vector4</td>
<td>x, y, z, w</td>
<td>쉐이더, 특수 계산</td>
</tr>
</tbody></table>
<h2 id="🔖-4-1-vector2">🔖 4-1. Vector2</h2>
<p>2차원 좌표입니다. x = 좌우, y = 상하로 구분하고 있습니다
당연히 2D로 사용하는 부분에서 해당 벡터가 사용이 되겠죠?</p>
<pre><code class="language-csharp">Vector2 pos = new Vector2(10, 5);</code></pre>
<h2 id="🔖-4-2-vector3">🔖 4-2. Vector3</h2>
<p>3차원 좌표입니다. x = 좌우, y = 위아래, z = 앞뒤로 구분합니다
Vector3는 이미 위에서 많이 설명을 드린 개념이고 Unity에 Vector 관련된 문법 대부분이 Vector3라고 생각하시면 됩니다</p>
<pre><code class="language-csharp">transform.position

transform.forward

transform.right</code></pre>
<pre><code class="language-csharp">Vector3 pos = new Vector3(1, 2, 3);</code></pre>
<h2 id="🔖-4-3-vector2int--vector3int">🔖 4-3. Vector2Int / Vector3Int</h2>
<p>벡터 뒤에 Int가 있는 타입도 있습니다.
Vector2 / Vector3의 경우 float 기반 벡터라 소수점 표현 가능해서 위치, 이동, 속도 등에 사용하기에 적합하지만 타일, 슬롯, 격자 등 소수형이 맞지 않는 경우가 있습니다. 그래서 int 기반 벡터를 지원합니다</p>
<pre><code class="language-csharp">Vector2Int tilePos = new Vector2Int(3, 5);</code></pre>
<p>타일맵, 그리드, 인벤토리 칸 좌표 등 좌표가 칸 단위로 정확히 떨어져야 할 때 사용하는 개념입니다.</p>
<hr>
<h1 id="📖-5-벡터의-크기magnitude">📖 5. 벡터의 크기(magnitude)</h1>
<p>지금까지 벡터의 기본에 대하여 알이봤는데 조금 세부적으로 이해를 할 필요가 있습니다</p>
<p>magnitude는 벡터의 크기(길이)입니다.</p>
<pre><code class="language-csharp">Vector3 v = new Vector3(5, 0, 0);</code></pre>
<p>여기서 해당 코드 의미는 <code>오른쪽 방향 + 길이 5</code>이며, 5가 magnitude가 되는 것입니다</p>
<h2 id="🔖-5-1-distance">🔖 5-1. Distance()</h2>
<p>추가로 알 필요가 있는 문법이 <code>Distance()</code>입니다.
해당 위치의 거리를 구할 수 있는 메서드입니다</p>
<pre><code class="language-csharp">float distance = Vector3.Distance(transform.position,target.position);</code></pre>
<hr>
<h1 id="📖-6-normalized단위-벡터">📖 6. normalized(단위 벡터)</h1>
<p>단위 벡터 개념 정말 중요하고 많이 쓰입니다</p>
<blockquote>
<p>벡터의 방향은 유지하고 길이(magnitude)를 1로 만드는 것</p>
</blockquote>
<pre><code class="language-csharp">Vector3 dir = new Vector3(10, 0, 0);</code></pre>
<p>이 벡터는 <code>오른쪽 방향 + 길이 10</code>을 의미합니다</p>
<p>여기서 정규화를 진행한다면</p>
<pre><code class="language-csharp">Vector3 result = dir.normalized;

(1, 0, 0)</code></pre>
<p>방향은 그대로 유지하고 길이를 10 → 1로 변경하는 겁니다</p>
<h2 id="🔖-6-1-왜-굳이-길이를-1로-만들까요">🔖 6-1. 왜 굳이 길이를 1로 만들까요</h2>
<p>추격 시스템을 만든다고 가정해볼게요.</p>
<h3 id="✔️-6-1-1-현재-위치">✔️ 6-1-1. 현재 위치</h3>
<p>플레이어<code>(10,0,0)</code>
몬스터 <code>(0,0,0)</code></p>
<h3 id="✔️-6-1-2-방향-구하기">✔️ 6-1-2. 방향 구하기</h3>
<pre><code class="language-csharp">Vector3 dir = player.position - monster.position;</code></pre>
<pre><code class="language-csharp">(10,0,0)</code></pre>
<p>이 상태로 이동해버린다면</p>
<pre><code>transform.position += dir;</code></pre><p>한 프레임에 10칸 이동해버리는 이상한 현상이 나타납니다.</p>
<p>direction의 크기가 거리 자체이기 때문에 플레이어가 멀수록 direction의 크기가 커져서 빠르게 이동하는 겁니다</p>
<p>그래서 normalized 사용하여 길이를 1로 만드는 것입니다</p>
<pre><code class="language-csharp">Vector3 dir = (player.position - monster.position).normalized;</code></pre>
<p>플레이어가 <span style = "color:red">10m 떨어져 있든 100m 떨어져 있든</span> 속도가 동일해야 하는 것이 핵심입니다.</p>
<hr>
<h1 id="📖-7-dot-product내적">📖 7. Dot Product(내적)</h1>
<p>두 벡터가 얼마나 같은 방향을 보고 있는가를 나타내는 개념으로 시야각 만들 때 사용합니다
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/8c2e411f-a3bd-4de9-9388-e2b8ae57c93b/image.png" alt=""></p>
<p>몬스터가 보는 방향과 플레이어 방향이 거의 비슷하면 발견하는 겁니다.
길이는 무시하고 방향만 비교하기 위해 normalized를 사용합니다.</p>
<hr>
<h1 id="📖-8-cross-product외적">📖 8. Cross Product(외적)</h1>
<p>내적이 &quot;얼마나 같은 방향인가&quot;를 숫자 하나로 표현하는거면, 외적은 두 벡터에 수직인 새 벡터를 만드는 개념입니다</p>
<blockquote>
<p><code>|A×B| = |A| × |B| × sin(θ)</code></p>
</blockquote>
<h2 id="🔖-8-1-평행0°180°이면-sin0-→-외적--0">🔖 8-1. 평행(0°/180°)이면 sin=0 → 외적 = 0</h2>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/3839bd9f-bceb-4da9-ab7d-875f40aa7f2c/image.png" alt="외적 수평"></p>
<h2 id="🔖-8-2-수직90°이면-sin1-→-외적-최대">🔖 8-2. 수직(90°)이면 sin=1 → 외적 최대</h2>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/d90b4ff0-c04f-4f2e-9383-80fbde55b762/image.png" alt="외작 수직"></p>
<p>기하학적으로는 두 벡터가 만드는 평행사변형 넓이라고 이해하시면 됩니다</p>
<h2 id="🔖-8-3-게임에서-활용">🔖 8-3. 게임에서 활용</h2>
<p>앞에서 외적은 현재 방향에서 다른 방향의 벡터를 새로 만드는 개념이라고 했잖아요?</p>
<p>플레이어가 앞을 보고 있을 때 오른쪽 방향을 추가로 구한다고 생각해봅시다</p>
<p><code>transform.forward</code>를 알고 있지만 <code>transform.right</code>는 모르는 상황입니다</p>
<pre><code class="language-csharp">Vector3 right = Vector3.Cross(transform.up,transform.forward);</code></pre>
<p>이런 식으로 외적 계산하여 오른쪽 방향을 알 수 있습니다</p>
<p>가장 많이 사용되는 건 조명, 그림자, 반사 계산입니다.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/b5afe912-fbb5-475f-be7f-ce8bc1591aaa/image.png" alt=""></p>
<h3 id="✔️-8-3-1-삼각형-두-변edge을-구한다">✔️ 8-3-1. 삼각형 두 변(edge)을 구한다</h3>
<p>3D Mesh는 삼각형으로 이루어져 있습니다. 꼭짓점 A, B, C가 있으면</p>
<pre><code class="language-csharp">Vector3 edge1 = B - A;  // A에서 B로 가는 벡터
Vector3 edge2 = C - A;  // A에서 C로 가는 벡터</code></pre>
<h3 id="✔️-8-3-2-두-변을-외적해서-법선을-구한다">✔️ 8-3-2. 두 변을 외적해서 법선을 구한다</h3>
<p>이 두 변을 외적하면 이 삼각형 면이 바라보는 방향이 나오는데 이게 법선(Normal)입니다. 삼각형 위에 딱 수직으로 솟아있는 벡터가 나오는 거죠</p>
<pre><code class="language-csharp">Vector3 normal = Vector3.Cross(edge1, edge2).normalized;</code></pre>
<h3 id="✔️-8-3-3-법선과-빛-방향을-내적해서-밝기를-구합니다">✔️ 8-3-3. 법선과 빛 방향을 내적해서 밝기를 구합니다</h3>
<pre><code class="language-csharp">float brightness = Vector3.Dot(normal, lightDir);
// 1.0  → 빛이 면을 정면으로 비춤 → 가장 밝음
// 0.0  → 빛이 면과 평행 → 경계선
// -1.0 → 면이 빛을 등짐 → 어두움</code></pre>
<p><strong>외적은 &quot;이 면이 어느 방향을 보고 있냐&quot;를 알아내는 데 쓰이고</strong>, 그걸 구한 다음에 내적으로 빛을 구하는 겁니다. 외적 없이는 법선을 못 구하니까 조명 계산 자체가 불가능합니다
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/8eee516e-c454-4f73-8c2d-b65d673e5fbe/image.png" alt=""></p>
<p>상당히 복잡한데 다행히 실제 개발할 때 외적을 직접 사용하여 게임을 구현하는 경우는 많지 않습니다. 그런 상황이 있다고 해도 Unity 자체에서 계산(빛, 그림자 계산)해주는 기능이 많아서 코드에 직접 사용하는 경우는 정말 드뭅니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C#] 변수]]></title>
            <link>https://velog.io/@asiatic_ricecake/C-%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@asiatic_ricecake/C-%EB%B3%80%EC%88%98</guid>
            <pubDate>Fri, 05 Jun 2026 06:07:17 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-1-변수">📖 1. 변수</h1>
<p>변수는 <strong>값을 저장하기 위해 메모리에 만든 공간</strong>입니다.<br>흔히 <strong>&quot;상자&quot;</strong> 에 비유하는데, 상자에 이름을 붙이고 물건(데이터)을 넣는 것과 같습니다.</p>
<pre><code class="language-csharp">int speed;      // 정수를 저장할 공간(상자) 생성
speed = 1;      // 그 공간에 1을 저장
Console.WriteLine(speed); // 출력: 1</code></pre>
<p>변수는 언제든지 값을 바꿀 수 있습니다.</p>
<pre><code class="language-csharp">int speed = 1;
speed = 4;
Console.WriteLine(speed); // 출력: 4</code></pre>
<h2 id="🔖-1-1-왜-변수가-필요할까">🔖 1-1. 왜 변수가 필요할까?</h2>
<p>아래 코드를 보면 변수가 왜 필요한지 바로 느껴집니다.</p>
<pre><code class="language-csharp">int hp = 100;
hp = hp - 10;
// 1. hp가 100이라는 값을 기억하고
// 2. hp - 10 을 계산하고
// 3. 결과를 다시 hp에 저장
// → 이 모든 과정에서 &quot;값을 보관할 공간&quot;이 필요합니다</code></pre>
<p>즉, 변수는 <strong>값을 잠시 보관해두는 상자</strong> 역할을 합니다.</p>
<hr>
<h1 id="📖-2-상수const">📖 2. 상수(const)</h1>
<p>상수는 <strong>한 번 값을 정하면 변경할 수 없는</strong> 변수입니다.</p>
<pre><code class="language-csharp">const int MAX_PLAYER_COUNT = 4;
MAX_PLAYER_COUNT = 8; // ❌ 컴파일 오류 발생!</code></pre>
<p>변하면 안 되는 값(중력, 최대 레벨, 화면 크기 등)에 사용합니다.</p>
<hr>
<h1 id="📖-3-자료형data-types">📖 3. 자료형(Data Types)</h1>
<p>변수를 만들 때는 <strong>어떤 종류의 데이터를 담을지</strong> 먼저 지정해야 합니다.</p>
<pre><code class="language-csharp">int    playerScore = 100;       // 정수
float  moveSpeed   = 3.5f;      // 실수 (소수점)
string playerName  = &quot;홍길동&quot;;   // 문자열
bool   isAlive     = true;      // 참/거짓
char   grade       = &#39;A&#39;;      // 문자 하나</code></pre>
<h2 id="🔖-3-1-정수형">🔖 3-1. 정수형</h2>
<table>
<thead>
<tr>
<th>타입</th>
<th>크기</th>
<th>범위</th>
<th>용도</th>
</tr>
</thead>
<tbody><tr>
<td><code>byte</code></td>
<td>1바이트</td>
<td>0 ~ 255</td>
<td>작은 양수</td>
</tr>
<tr>
<td><code>short</code></td>
<td>2바이트</td>
<td>-32,768 ~ 32,767</td>
<td>작은 정수</td>
</tr>
<tr>
<td><code>int</code></td>
<td>4바이트</td>
<td>약 ±21억</td>
<td><strong>가장 많이 사용</strong></td>
</tr>
<tr>
<td><code>long</code></td>
<td>8바이트</td>
<td>약 ±920경</td>
<td>매우 큰 정수</td>
</tr>
</tbody></table>
<h2 id="🔖-3-2-실수형">🔖 3-2. 실수형</h2>
<table>
<thead>
<tr>
<th>타입</th>
<th>크기</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><code>float</code></td>
<td>4바이트</td>
<td>Unity에서 주로 사용. 뒤에 <code>f</code> 붙임</td>
</tr>
<tr>
<td><code>double</code></td>
<td>8바이트</td>
<td>C# 실수 기본값. 더 정밀</td>
</tr>
<tr>
<td><code>decimal</code></td>
<td>16바이트</td>
<td>금융 계산용. 오차 최소화</td>
</tr>
</tbody></table>
<blockquote>
<p>💡 Unity 개발에서는 <code>float</code>을 기본으로 씁니다.<br><code>double</code>보다 정밀도는 낮지만 성능이 좋고, Unity API 자체가 <code>float</code> 기준으로 설계돼 있습니다.</p>
</blockquote>
<h2 id="🔖-3-3-문자문자열논리형">🔖 3-3. 문자/문자열/논리형</h2>
<table>
<thead>
<tr>
<th>타입</th>
<th>크기</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>char</code></td>
<td>2바이트</td>
<td><code>&#39;A&#39;</code>, <code>&#39;가&#39;</code></td>
</tr>
<tr>
<td><code>string</code></td>
<td>가변</td>
<td><code>&quot;Hello&quot;</code>, <code>&quot;길동&quot;</code></td>
</tr>
<tr>
<td><code>bool</code></td>
<td>1바이트</td>
<td><code>true</code>, <code>false</code></td>
</tr>
</tbody></table>
<blockquote>
<p><code>char</code>는 작은따옴표(<code>&#39;</code>), <code>string</code>은 큰따옴표(<code>&quot;</code>)를 씁니다. 헷갈리기 쉬우니 주의!</p>
</blockquote>
<pre><code class="language-csharp">// 실제로 메모리 크기를 출력해볼 수 있습니다
Console.WriteLine($&quot;int:    {sizeof(int)} 바이트&quot;);    // 4
Console.WriteLine($&quot;float:  {sizeof(float)} 바이트&quot;);  // 4
Console.WriteLine($&quot;double: {sizeof(double)} 바이트&quot;); // 8
Console.WriteLine($&quot;char:   {sizeof(char)} 바이트&quot;);   // 2
Console.WriteLine($&quot;bool:   {sizeof(bool)} 바이트&quot;);   // 1</code></pre>
<hr>
<h1 id="📖-4-네이밍-컨벤션-명명-규칙">📖 4. 네이밍 컨벤션 (명명 규칙)</h1>
<p>코드는 혼자 짜는 게 아닙니다. 팀원이 봤을 때 <strong>바로 이해할 수 있는 이름</strong>을 짓는 것이 중요합니다.</p>
<h2 id="🔖-4-2-케이스-규칙-4가지">🔖 4-2. 케이스 규칙 4가지</h2>
<table>
<thead>
<tr>
<th>방식</th>
<th>형태</th>
<th>사용처</th>
</tr>
</thead>
<tbody><tr>
<td>camelCase</td>
<td><code>playerScore</code></td>
<td>지역 변수, private 필드</td>
</tr>
<tr>
<td>PascalCase</td>
<td><code>PlayerScore</code></td>
<td>클래스명, 메서드명, public 멤버</td>
</tr>
<tr>
<td>snake_case</td>
<td><code>player_score</code></td>
<td>Python 문화권 (C#에선 잘 안 씀)</td>
</tr>
<tr>
<td>UPPER_SNAKE_CASE</td>
<td><code>MAX_HEALTH</code></td>
<td>상수(const)</td>
</tr>
</tbody></table>
<h2 id="🔖-4-3-c--unity에서의-실제-적용-예시">🔖 4-3. C# / Unity에서의 실제 적용 예시</h2>
<pre><code class="language-csharp">public class PlayerController : MonoBehaviour
{
    // public 변수 → PascalCase
    public int MaxHealth = 100;

    // private 필드 → camelCase (또는 _언더스코어 접두사)
    private int currentHealth;
    private float _moveSpeed;

    // 상수 → UPPER_SNAKE_CASE
    private const int MAX_LEVEL = 99;

    // 메서드 → PascalCase, 매개변수 → camelCase
    public void TakeDamage(int damage)
    {
        // 지역 변수 → camelCase
        int actualDamage = damage - 5;
        currentHealth -= actualDamage;
    }
}</code></pre>
<h3 id="좋은-변수명-짓는-팁">좋은 변수명 짓는 팁</h3>
<table>
<thead>
<tr>
<th>❌ 나쁜 예</th>
<th>✅ 좋은 예</th>
<th>이유</th>
</tr>
</thead>
<tbody><tr>
<td><code>a</code></td>
<td><code>playerScore</code></td>
<td>의미가 있어야 함</td>
</tr>
<tr>
<td><code>theCurrentPlayerHealthPoint</code></td>
<td><code>currentHealth</code></td>
<td>너무 길면 오히려 불편</td>
</tr>
<tr>
<td><code>hp</code></td>
<td><code>health</code></td>
<td>약어보다 명확한 단어가 낫다</td>
</tr>
<tr>
<td><code>data123</code></td>
<td><code>itemList</code></td>
<td>숫자 붙이기보단 역할을 표현</td>
</tr>
</tbody></table>
<hr>
<h1 id="⚠️-5-변수-선언-시-주의사항">⚠️ 5. 변수 선언 시 주의사항</h1>
<h2 id="5-1-변수명-규칙">5-1. 변수명 규칙</h2>
<pre><code class="language-csharp">int 1carSpeed;  // ❌ 숫자로 시작 불가
int car speed;  // ❌ 공백 포함 불가
int int;        // ❌ 예약어 사용 불가
int 속도;       // ⚠️ 가능은 하지만 권장하지 않음 (한글 비권장)

int carSpeed;   // ✅ 올바른 선언</code></pre>
<ul>
<li>첫 글자는 <strong>문자</strong> 또는 <code>_</code>로 시작</li>
<li>공백 포함 불가, 길이 255자 이하</li>
<li>C# 예약어(<code>int</code>, <code>class</code>, <code>void</code> 등) 사용 불가</li>
<li>한글 사용은 기술적으로 가능하지만 <strong>권장하지 않음</strong></li>
</ul>
<blockquote>
<p>예약어 전체 목록: <a href="https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/">Microsoft 공식 문서</a></p>
</blockquote>
<h2 id="5-2-초기화하지-않은-변수는-사용-불가">5-2. 초기화하지 않은 변수는 사용 불가</h2>
<pre><code class="language-csharp">int hp;
Console.WriteLine(hp); // ❌ 컴파일 오류: 할당되지 않은 변수 사용</code></pre>
<p>C#은 <strong>사용 전에 반드시 값을 초기화</strong>해야 합니다.<br>초기화하지 않으면 메모리에 이전에 남아있던 쓰레기 값이 그대로 있을 수 있어 위험하기 때문입니다.</p>
<pre><code class="language-csharp">int hp = 100;           // ✅ 선언과 동시에 초기화
int hp;
hp = 100;               // ✅ 이렇게 나눠도 가능 (사용 전에만 초기화되면 됨)</code></pre>
<h2 id="5-3-같은-타입-여러-개-한-번에-선언">5-3. 같은 타입 여러 개 한 번에 선언</h2>
<pre><code class="language-csharp">int number1, number2, number3;
number1 = 1;
number2 = 2;
number3 = 3;

Console.WriteLine(&quot;{0}, {1}, {2}&quot;, number1, number2, number3);
// 출력: 1, 2, 3</code></pre>
<hr>
<h1 id="🖥️-6-전체-예제-코드">🖥️ 6. 전체 예제 코드</h1>
<pre><code class="language-csharp">static void Main(string[] args)
{
    int playerScore    = 100;
    float moveSpeed    = 3.5f;
    string playerName  = &quot;길동&quot;;
    bool isAlive       = true;
    char grade         = &#39;A&#39;;

    Console.WriteLine($&quot;이름: {playerName}&quot;);
    Console.WriteLine($&quot;점수: {playerScore}&quot;);
    Console.WriteLine($&quot;이동속도: {moveSpeed}&quot;);
    Console.WriteLine($&quot;등급: {grade}&quot;);
    Console.WriteLine($&quot;생존 여부: {isAlive}&quot;);

    // 데미지 계산 예시
    int hp = 100;
    int damage = 25;
    hp = hp - damage;
    Console.WriteLine($&quot;피격 후 HP: {hp}&quot;); // 75
}</code></pre>
<hr>
<blockquote>
<p>📚 참고: <a href="https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/coding-style/identifier-names">C# 식별자 명명 규칙 - Microsoft 공식 문서</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[경일게임IT아카데미] 비전공자 부트캠프 수료 후기!]]></title>
            <link>https://velog.io/@asiatic_ricecake/%EA%B2%BD%EC%9D%BC%EA%B2%8C%EC%9E%84IT%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%88%98%EB%A3%8C-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@asiatic_ricecake/%EA%B2%BD%EC%9D%BC%EA%B2%8C%EC%9E%84IT%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%88%98%EB%A3%8C-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sun, 26 Oct 2025 09:21:09 GMT</pubDate>
            <description><![CDATA[<h1 id="🤔it-업계-중-왜-게임을">🤔IT 업계 중 왜 게임을?</h1>
<p>일단 먼저 궁금한 점이라면 비전공자인 제가 왜 이런 쪽의 길을 택했냐는 것이겠죠</p>
<p>처음부터 개발자가 꿈이었던 건 아니에요.
그냥… 뭔가 새로운 걸 도전해보고 싶다는 생각에서 시작됐죠.</p>
<p>사실 예전에 대학교 때 강의에서 파이썬을 잠깐 들은 적이 있어요. 
근데 그때는 진짜 정신없이 진도가 빨라서 따라가기도 버거웠고, 
프로젝트 경험도 없이 수업만 듣다가 흐지부지 끝나버렸습니다. 😅</p>
<p>“나랑은 안 맞나 보다…” 하면서 자연스럽게 손을 놓게 됐죠.</p>
<p>하지만 시간이 지나면서 생각이 바뀌기 시작했어요.
“나도 내 손으로 무언가를 만들어내는 기술을 갖고 싶다”는 마음이 점점 커졌거든요. 
그리고 그게 꼭 누군가에게 즐거움을 줄 수 있는 무언가였으면 좋겠다는 생각도 들었고요.</p>
<p>여러 분야를 고민하다 보니 게임 개발이 눈에 들어왔습니다.
게임은 어릴 때부터 자연스럽게 접해온 분야이기도 했고, 
전공이 아니어도 도전할 수 있는 길이라는 점도 제 상황에 잘 맞았어요.</p>
<p>그래서 “그래, 한번 제대로 해보자!” 하는 마음으로 부트캠프에 지원하게 됐습니다.
지금 생각해보면 단순한 도전이 아니라, 인생의 방향을 다시 잡는 계기였던 것 같아요. 😊</p>
<h1 id="✨-왜-경일게임it아카데미인가">✨ 왜 경일게임IT아카데미인가?</h1>
<p>일단 부트캠프를 들으시는 분들은 아마 여러 후기를 보셔서 아실겁니다.
시간 날리고 싶은거 아니면 정말 잘 선택해야 한다는 것을...</p>
<p>사실 처음 학원을 알아볼 땐 솔직히 말해서 “여기가 특별히 다른 점이 있을까?” 싶었어요.
포트폴리오 구성이나 커리큘럼만 놓고 보면 다른 곳과 크게 차이가 있어 보이진 않았거든요.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/92d8547a-6145-4cec-afbe-725e2dc3eca9/image.png" alt=""></p>
<p>전 일단 기간이 짧은 곳은 피하려고 했었습니다. 
비전공자가 소화하기에는 터무니 없는 기간이기도 하고 
특히 컨디션 조절하기 정말 어려울 것 같았습니다.</p>
<p>근데 경일은 8개월이라는 비교적 긴 기간 동안 진행되어 눈에 갔고,
무엇보다 제일 끌렸던 건 기업 협약 프로젝트였습니다. 단순히 수업만 듣고 끝나는 게 아니라, 실제 <span style="color:yellow">기업과 협력해서 프로젝트</span>를 진행한다는 점이 꽤 현실적으로 다가왔거든요.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/15e0684f-97be-410d-b48b-1a6ea9c1c419/image.png" alt=""></p>
<p>또 학원 후기를 찾아봤을 때도 긍정적인 이야기가 많았어요.
“끝까지 책임져 준다”, “실제로 취업까지 이어졌다” 
이런 말들이 단순 홍보가 아니라 진짜 수강생의 목소리처럼 느껴졌습니다.</p>
<p>그리고 결정적으로 마음이 움직인 건 합격 전화를 받았을 때였어요.
그때 담당자분이 해주신 말에서 “포기만 하지 않으면 끝까지 책임지겠다”는 강한 의지가 느껴졌거든요.</p>
<p><span style="color:yellow">그 한마디가 이상하게도 큰 믿음으로 다가왔습니다.</span></p>
<p>마지막으로 저한테는 살짝 팬심도 작용했어요 😂
게임 유튜브로 유명하신 김성회님이 1기 수료식에 직접 참여하시기도 했고
그 <code>지식백과 김성회님</code> 맞습니다!</p>
<p>“아, 게임 업계에서 이 학원이 진짜 어느 정도 인지도와 신뢰를 갖고 있구나” 싶었죠.
결국 이런 점들이 하나씩 쌓이면서 ‘여기가 맞겠다’는 확신이 생겼습니다.</p>
<h1 id="🎮-수강-후기">🎮 수강 후기</h1>
<h2 id="1-전반적인-후기">1. 전반적인 후기</h2>
<h3 id="🧑🏫-수업방식">🧑‍🏫 수업방식</h3>
<p>수업은 완전 <code>온라인</code>으로 진행되어 부담이 적었습니다.
만약 직접 오프라인으로 수업을 들으려면 개인 노트북을 지참하고 그래야 하기 때문에 불편한 점이 많았을 것 같은데 이 부분은 정말 좋았습니다.</p>
<p>그리고 <code>Zep</code>을 사용해서 수업을 진행하는데 대학교에서 게더타운을 사용해본 적 있어서 사용하는데 크게 문제는 없었습니다.</p>
<p>물론 전혀 모른다고 해도 다 친절하게 사용법 알려주시니 이런 부분에 대한 걱정은 안하셔도 됩니다.</p>
<h3 id="😱-처음-느낀-분위기---진짜-쉽지-않았다">😱 처음 느낀 분위기 - 진짜 쉽지 않았다</h3>
<p>처음 시작했을 때는 걱정이 제일 먼저 앞섰습니다.
왜냐면… 진짜 아는 게 아무것도 없었거든요. 😅
물론 새로운 걸 배운다는 설렘도 있었지만, 그보다 “내가 이걸 따라갈 수 있을까?” 하는 불안감이 더 컸던 게 사실이에요.</p>
<p>수업이 무슨 미친 속도로 달려가는 건 아니었어요.
근데 문제는 양이었습니다.
매일매일 쏟아지는 정보가 진짜 많다 보니, 어느 정도 기초가 없는 상태라면 꽤 힘들 수밖에 없어요.
“이제 막 적응했나?” 싶을 때 또 새로운 내용이 나와서 머리가 꽉 차는 느낌이었죠.</p>
<p>하지만 이미 시작한 이상 포기할 수는 없었습니다.
그래서 진짜 악으로 깡으로 버텼어요. 💪</p>
<h3 id="🧑🎓-전공자-vs-비전공자-비율">🧑‍🎓 전공자 vs 비전공자 비율</h3>
<p>의외로 비전공자도 꽤 많았습니다.
제가 느끼기엔 전공자 40%, 비전공자 60% 정도였던 것 같아요.
개발 경험이 전혀 없는 사람들도 도전하는 과정이라, 
처음부터 완벽하게 알고 들어오는 분위기는 아니에요.</p>
<h3 id="🌙-수업과-프로젝트는-난이도가-달랐다">🌙 수업과 프로젝트는 난이도가 달랐다</h3>
<p>수업할 땐 그래도 중간중간 쉬는 시간도 있었고, 복습할 틈도 조금은 있었어요.
그런데… 프로젝트에 들어가자마자 분위기가 180도 바뀌었습니다.</p>
<p>제대로 된 포트폴리오 하나 만들려면 주말 반납은 기본이고, 새벽까지 작업하는 날도 정말 많았거든요.
물론 맨날 그랬던 건 아니에요. 저도 사람인지라...</p>
<h1 id="👍해당-과정-장점">👍해당 과정 장점</h1>
<h2 id="1-과정-기간이-긴-편이다">1. 과정 기간이 긴 편이다</h2>
<p>솔직히 8개월이라는 시간이 뭔가를 완벽히 배우기엔 짧은 시간일 수도 있어요.
하지만 부트캠프 치고는 꽤 긴 편이라고 생각합니다.</p>
<p>짧은 기간에 몰아치는 다른 과정들에 비해선 진도가 어느 정도 예상 범위 안에서 진행됐고,
“진짜 아예 못 따라가겠다” 수준까진 아니었어요.
물론 힘든 날도 많았죠. 양이 많으니까요 😅</p>
<p>이게 왜 중요하냐면, 부트캠프는 결국 끝까지 달려가는 게 핵심이거든요.
너무 무리하면 금방 번아웃이 와서 중간에 포기해버리는 경우도 꽤 많습니다.
그래서 일정이 너무 짧지도 길지도 않게 적당히 ‘버틸 수 있는 시간’이라는 점이 장점으로 느껴졌어요.</p>
<p>물론 반대로, 장기 과정이 부담스러운 분들에겐 단점이 될 수도 있겠죠.</p>
<h2 id="2-기업-협약-프로젝트가-있다">2. 기업 협약 프로젝트가 있다</h2>
<p>저는 이 부분이 정말 마음에 들었어요.</p>
<p>기업에서 직접 미션 가이드를 주고, 기획반과 개발반이 팀을 꾸려 
실제 기업 과제 기반으로 프로젝트를 진행하는데요.
이게 정말 흔한 경험이 아닙니다. 
신입 개발자가 현업 피드백을 받을 수 있는 기회 자체가 많지 않거든요.</p>
<p>단순히 학원 안에서 과제만 하는 게 아니라, 기업과의 협업 구조를 미리 경험할 수 있었던 점이 정말 컸습니다.
결국 이런 경험들이 하나둘 쌓이면서, 제 포트폴리오 퀄리티에도 큰 영향을 줬다고 생각해요.</p>
<h2 id="3-멋진-운영진-강사진이-있다">3. 멋진 운영진, 강사진이 있다</h2>
<p>이건 제가 친구들의 다른 부트캠프 후기를 들으면서 더 느낀 부분인데요,
어떤 곳은 그냥 방치 수준이라고 하더라고요.
카메라 안 켜도 뭐라 안 하고, 과제 안 해도 그냥 넘어가고, 수업 시간에 자도 별말 없는 곳도 있다던데… 😅</p>
<p>근데 경일은 관리 강도가 확실히 있는 편이에요.
수업만 던져주고 끝이 아니라 출석, 피드백, 과제 체크를 꼼꼼히 해주셨고,
무엇보다도 학생 한 명 한 명을 신경 써준다는 느낌이 있었어요.</p>
<p>제가 개인적으로 좋았던 건, 고민이나 문제가 생겼을 때 
평일은 물론이고 주말이나 휴일에도 질문을 친절하게 받아주셨던 것이에요.
이 부분에서 진짜 ‘아, 이 학원은 학생을 방치하지 않는구나’라는 신뢰감이 생겼습니다.</p>
<h1 id="👎해당-과정-단점">👎해당 과정 단점</h1>
<h2 id="1-아무리-잘-가르쳐도-결국-본인이-안-하면-끝이다">1. 아무리 잘 가르쳐도, 결국 본인이 안 하면 끝이다</h2>
<p>이게 단점이라고 하긴 그렇긴 하지만 관리는 잘 해주지만 떠먹여주는 건 절대 아님! </p>
<p>아무리 체계적으로 관리해준다 해도…
솔직히 본인이 열심히 하지 않으면 아무 의미 없습니다.
출석도 관리해주고 피드백도 주지만, 그걸 실제로 흡수하고 성장시키는 건 전적으로 본인 몫이에요.</p>
<p>결국 “이건 나한테 달려 있다”는 걸 빨리 깨닫는 게 중요한 것 같습니다.
수업만 듣고 끝내는 방식으로는 절대 실력이 늘지 않아요.
따라서 꾸준히 스스로 공부하고, Search하고, 채워나가야 합니다.</p>
<p>안 그래도 긴 시간 통으로 날려버릴 수 있어요</p>
<h2 id="2-빠르게-훑는-부분도-있다-특히-vrar">2. 빠르게 훑는 부분도 있다 (특히 VR/AR)</h2>
<p>전체적으로 커리큘럼은 알차지만, 시간의 한계는 어쩔 수 없어요.
특히 VR/AR 수업이 그랬습니다.
이론 수업이 3일 정도 진행된 뒤 바로 VR 게임 프로젝트에 들어갔는데,
프로젝트 기간도 5일이라 거의 맨땅에 헤딩도 못해볼 시간이었습니다.</p>
<p>솔직히 “VR을 제대로 배웠다”보다는 “일단 한 번 경험해봤다”에 가까웠고,
시간이 부족하다 보니 깊이 있는 걸 시도하긴 어려웠던 게 아쉬웠습니다.</p>
<h2 id="3-수업만으로는-절대-다-채워지지-않는다">3. 수업만으로는 절대 다 채워지지 않는다</h2>
<p>이건 아마 모든 부트캠프의 공통적인 단점일 거예요.
수업이 끝나면 ‘이제 집에 가자~’ 하는 게 아니라,
집에 가서 다시 공부하고, 검색하고, 복습하고…
그렇게 본인이 빈틈을 스스로 채워야 합니다.</p>
<p>그렇다고 학원이 부족해서라기보단, 시간 안에 배워야 할 내용이 워낙 많기 때문이에요.
그래서 이 부분은 결국 자기 의지와 노력에 따라 결과가 크게 달라집니다.</p>
<h1 id="💡tip">💡Tip</h1>
<h2 id="1-💰-국민취업지원제도-적극-활용">1. 💰 국민취업지원제도 적극 활용!</h2>
<p>이건 학원에서도 계속 강조하지만, 정말 중요해서 한 번 더 말하고 싶어요.
👉 국민취업지원제도 1유형은 꼭 신청하세요!</p>
<p>1유형이라면 6개월 동안 출석만 잘 해도 매달 50만원씩 지원금을 받을 수 있습니다.
그리고 이 과정은 K-Digital 트레이닝 과정이라 훈련 장려금도 약 30만원 정도 나와요.
즉, 잘만 하면 지원금만으로 생활비를 어느 정도 충당할 수 있는 셈이죠.</p>
<p>2유형은 제가 들었을 땐 해당이 안 된다고 하셨는데, 이 부분은 상황마다 다를 수 있으니 꼭 따로 확인해보시는 걸 추천드려요!</p>
<h2 id="2-🚫-절대-다른-수강생들과-비교하지-마세요">2. 🚫 절대 다른 수강생들과 비교하지 마세요...</h2>
<p>누군가는 “잘하는 사람을 보면서 자극받고 성장하면 된다”라고 쉽게 말하곤 합니다.
하지만 솔직히 말해서, 그건 <code>사람의 심리에 대한 이해가 부족</code>한 말이에요.
대부분의 사람은 ‘자극’보다 ‘비교’로 인한 자존감 하락이 먼저 찾아옵니다.</p>
<p>이 과정에는 저처럼 완전 처음부터 시작하는 비전공자도 있고,
이미 전공자이거나 재능이 뛰어난 분들도 정말 많습니다.</p>
<p>근데 진짜 중요한 건 남이 아니라 <code>어제의 나</code>와 비교하는 것이에요.
괜히 다른 사람 보고 자책하거나 기 죽을 필요 전혀 없습니다.
본인의 페이스를 유지하면서 꾸준히 나아가는 게 가장 중요해요.</p>
<p>그리고 솔직히 말씀드리자면, 이 과정을 끝까지 버텨낸 것만으로도 충분히 대단한 일이라고 생각합니다.
중간에 포기하는 분들도 실제로 꽤 있으니까요. 완주 자체가 큰 성취예요.</p>
<h2 id="3-🧠-컨디션-조절도-능력입니다">3. 🧠 컨디션 조절도 능력입니다</h2>
<p>이건 진짜… 부트캠프를 겪어본 사람만 공감할 겁니다. 😂
과정이 길고 빡세다 보니, 무리하다가 건강이 안 좋아져서 중도 포기하신 분도 실제로 계셨어요.</p>
<p>아무리 급하고 조급해도, 여러분의 건강이 먼저입니다.
지치면 쉬어가도 괜찮고, 하루쯤은 재충전할 시간도 필요해요.
막말로 누가 칼을 들고 협박하는 것도 아니잖아요?</p>
<h2 id="4-🙅♀️-정말-이-길이-맞지-않다고-생각한다면">4. 🙅‍♀️ 정말 이 길이 맞지 않다고 생각한다면...</h2>
<p>부트캠프를 진행하다 보면 누구나 한 번쯤은 이런 생각을 하게 됩니다.
👉 “내가 이걸 계속해도 될까?”, “이 길이 나랑 진짜 맞는 걸까?”</p>
<p>특히 과정이 길고 강도가 높다 보니, 체력이나 멘탈이 떨어질 때 이런 고민이 자연스럽게 찾아와요.
저도 중간에 그런 순간이 있었습니다. “이거 나한테 맞는 건가?” 싶었던 때가 있었죠.</p>
<p>그럴 땐 혼자 고민만 하지 말고 꼭 운영진이나 강사진과 먼저 면담을 진행해보세요.
혼자 생각만 하고 내린 결정은 대부분 후회로 이어질 수 있어요.
실제로 많은 분들이 면담을 통해 문제를 정리하고 방향을 다시 잡거나, 현실적인 조언을 듣고 마음을 다잡는 경우도 많았습니다.</p>
<p>그리고 만약 정말 “이 길이 아니다”라는 결론을 내리게 된다면,
👉 그냥 포기 버튼을 누르는 게 아니라 나만의 다음 방향을 어느 정도 만들어두고 결정하는 걸 추천드려요.</p>
<p>그냥 중간에 ‘그만둬버리면’ 남는 건 허무함과 후회뿐입니다.
“조금만 더 해볼 걸…” 하는 생각이 분명 들 거예요.
그 시간을 헛되이 버리지 않으려면, 최소한 다음 스텝에 대한 생각이나 준비는 꼭 해두셨으면 합니다.</p>
<p>가끔은 포기가 잘못된 선택이 아닐 수도 있어요.
하지만 ‘생각 없는 포기’는 언제나 후회로 남습니다.</p>
<h1 id="🎮-마치며">🎮 마치며</h1>
<p>제가 작성한 글이 결정에 도움이 되셨을지 모르겠습니다.</p>
<p>제 글을 참고해서 후회없는 결정과 도전을 하셨으면 좋겠습니다!</p>
<p>모두 화이팅입니다 ~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Firebase] Firebase 소개 및 유니티 연동]]></title>
            <link>https://velog.io/@asiatic_ricecake/Firebase</link>
            <guid>https://velog.io/@asiatic_ricecake/Firebase</guid>
            <pubDate>Wed, 16 Jul 2025 10:34:42 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📒-firebase">1. 📒 Firebase</h1>
<p>먼저 Firebase는 Google에서 제공하는 클라우드 기반 백엔드 서비스입니다.
개발자가 직접 서버를 직접 구축하지 않고도 인증, 데이터베이스, 호스팅, 리포팅 등 같은 여러 백엔드 기능을 지원하는 프로그램입니다.</p>
<p>물론 대기업 급의 큰 기업들은 많은 백엔드 개발자들이 있지만 스타트업이거나 소규모 프로젝트로 프로그램을 만든다고 했을 때 수많은 벡엔드 기능이 필요할건데 이 기능을 모두 다 개발한다는 건 사실상 불가능에 가깝습니다. </p>
<p>그래서 그 프로그램 개발에 집중하기 위해서 Firebase 같은 벡엔드 기능을 지원하는 프로그램을 이용하여 더 수월하게 개발 할 수 있습니다.</p>
<p>벡엔드 시스템의 경우 독점 프로그램이 없습니다.
트렌드에 따라 계속 변해서 AWS나 Google Cloud나 뒤끝 같은 벡엔드 서비스를 갈아타는 경우가 많아 한 프로그램만 파서 공부하는 건 상당히 위험합니다.</p>
<p>그래서 항상 다른 프로그램을 사용할 수 있도록 벡엔드에 대한 이해를 가지고 있어야 합니다. </p>
<h2 id="1-1-📝-firebase-유니티-개발-세팅">1-1 📝 Firebase 유니티 개발 세팅</h2>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/c38ee49d-d550-48e8-a127-669e30de17e2/image.png" alt=""></p>
<p><a href="https://firebase.google.com/?hl=ko">FireBase</a></p>
<p>먼저 FireBase 사이트에 접속합니다. Google 아이디로 로그인하시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/ed2a4de4-d23f-4b26-a0a7-2ab94ffd9ce9/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/e7af8dec-38e9-4e72-8a2e-dcf92f2038f4/image.png" alt=""></p>
<p>사이트에 Go to console로 들어가시면 이 화면이 나오도록 해주시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/4713201f-ec32-45da-b020-4623efcc6f60/image.png" alt=""></p>
<p>프로젝트 이름 선정하고 여러가지 화면이 뜨실텐데 대부분은 다 계속 누르시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/b242bb5a-7b16-4f04-8e50-190af7bcc828/image.png" alt=""></p>
<p>다 완료되면 이 화면이 나오면 프로젝트가 생성된 겁니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/e078ea64-a1cf-4664-8f94-92bd22e5dbfe/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/f5a8f067-99a0-4737-b799-d40f6031b19a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/62524ed4-d5ba-464e-85e3-f5f45077e100/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/947ceb20-cdea-4384-b2b3-4fa31dc6e893/image.png" alt=""></p>
<p>해당 화면은 유니티에 연동하기 위한 사진입니다. 
여기서 중요한 건 패키지 이름의 규칙을 <code>com.회사이름.App이름</code>을 지켜주셔야 합니다.</p>
<hr>
<h3 id="1-1-1-✅-이름-규칙을-지켜야-하는-이유">1-1-1 ✅ 이름 규칙을 지켜야 하는 이유</h3>
<h4 id="1-1-1-1-✔️-충돌-방지">1-1-1-1 ✔️ 충돌 방지</h4>
<p>전 세계적으로 수많은 애플리케이션이 배포되고 있기 때문에, 고유한 패키지 이름을 사용하면 동일한 디렉토리 내에서 다른 애플리케이션과의 이름 충돌을 방지할 수 있습니다.</p>
<h4 id="1-1-1-2-✔️-보안과-신뢰성">1-1-1-2 ✔️ 보안과 신뢰성</h4>
<p>패키지 이름을 일관되게 유지하면 악성 코드나 가짜 애플리케이션의 배포를 방지하는 데 도움이 됩니다. 사용자는 올바른 패키지 이름을 통해 자신이 다운로드하는 애플리케이션이 진짜임을 확인할 수 있습니다.</p>
<h4 id="1-1-1-3-✔️-개발-환경의-일관성">1-1-1-3 ✔️ 개발 환경의 일관성</h4>
<p>많은 개발 도구와 플랫폼은 특정 형식의 패키지 이름을 요구하거나 권장합니다. Firebase와 유니티도 이러한 규칙을 따르므로, 일관된 패키지 이름을 사용하면 설정 과정이 더 원활해질 수 있습니다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/b819aa78-d1ab-4f56-88d5-9bed814ddbca/image.png" alt=""></p>
<p>그리고 Firebase는 Unity에 특화된 프로그램이 아니기 때문에 Asset Store에 Firebase 관련 Import 파일이 없어 SDK를 따로 제공해 줍니다.</p>
<p>지금 보는 사진이 다운 받은 후 Import 파일입니다. 저 중에서 사용해야 하는 기능만 유니티에 설치 하시면 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 네트워크 동기화 (PUN)]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%8F%99%EA%B8%B0%ED%99%94-PUN</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%8F%99%EA%B8%B0%ED%99%94-PUN</guid>
            <pubDate>Sat, 12 Jul 2025 05:50:35 GMT</pubDate>
            <description><![CDATA[<p>유니티와 네트워크를 동기화 하기 위해서 정말 많은 방법이 있지만 
대표적으로 Photon을 많이 이용하는데 
Photon은 Exit Games에서 개발한 멀티플레이 네트워킹 솔루션입니다.
유니티 뿐만 아니라 언리얼, HTML5 등 다양한 플랫폼에서 호환가능합니다.</p>
<p>Photon에는 여러가지 패키지가 있지만 그 중에서 연습하거나 실습할 경우에는 간편하고 난이도가 상대적으로 낮아 실습하기 좋은 PUN을 추천합니다.</p>
<p>Photon Unity Networking(PUN)은 멀티 플레이어 게임용 유니티 패키지입니다. </p>
<p>Photon에서 만든 멀티플레이어 프레임워크 중에서 가장 오래되기도 했고 입문하기 쉽고 직관적인 장점이 있긴 하지만 보안 문제로 현업에서 잘 사용하진 않습니다. </p>
<p>프로토타입 테스트에서 잠시 사용한다고는 하는데 그것도 잘 사용하지 않는다고 하고 Photon도 FUN을 집중적으로 업데이트를 하고 PUN은 사실상 현상유지로 업데이트를 합니다.</p>
<p>대부분은 FUN을 사용하거나 자체 개발하여 사용합니다.
<br/>
<br/></p>
<h1 id="1-📒-photon-설정">1. 📒 Photon 설정</h1>
<p><a href="https://www.photonengine.com/ko-kr">Photon</a></p>
<p>먼저 사이트에 들어가서 회원가입을 합니다.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/3f74cb7c-49bd-4405-8f7f-eb0579740e74/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/73c3c760-3446-45a9-907b-2f7d38fb9afe/image.png" alt=""></p>
<p>Photon 종류와 애플리케이션 이름을 작성합니다. 
여기서 Pun으로 선택하시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/956efa93-56aa-466d-b6b3-88abb7a237d0/image.png" alt=""></p>
<p><a href="https://assetstore.unity.com/packages/tools/network/pun-2-free-119922">PUN2 - FREE</a>
다음으로 에셋스토어에 PUN2를 설치한 후 유니티에 Import 해주시면 됩니다</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/30d1fb45-0b6c-455d-adf9-02ace8d7b75b/image.png" alt="">
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/38d3cc78-7e6f-49bd-ae08-e0db4a6d45b0/image.png" alt=""></p>
<p>Import 되면 PUN Wizard가 나오실 텐데 
여기에 Photon에서 만든 App 위에 저 App ID가 있습니다. 
저걸 복사하셔서 붙여넣기 하신 후 Setup Project를 누르시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/bc66162e-cff6-49c8-a2dd-1f58caf48aa0/image.png" alt=""></p>
<p>혹시 만약 실수로 PUN Wizard를 스킵하셨을 경우 Window를 눌러서 Photon Unity Networking에 PUN Wizard를 누르시면 됩니다
<br/>
<br/></p>
<h2 id="1-1-📝-parrelsync">1-1 📝 ParrelSync</h2>
<p>유니티에서 멀티게임을 개발하기 전에 무조건 필수로 필요한 툴인 ParrelSync를 설치해야 합니다!</p>
<h3 id="1-1-1-✅-사용하는-이유">1-1-1 ✅ 사용하는 이유!</h3>
<p>보통 멀티플레이어 테스트를 하려면</p>
<p>Unity에서 플레이어 1 실행
다른 빌드를 내보내서 실행파일 실행 → 플레이어 2</p>
<p>이렇게 매번 빌드해서 실행해야 하는 번거로움이 있습니다.</p>
<p>이 때 ParrelSync는 Unity 프로젝트의 클론(복사본)을 만들어서, 
같은 PC에서 여러 클라이언트를 동시에 실행할 수 있게 만듭니다!</p>
<p>즉, ParrelSync는 Unity에서 멀티플레이 게임을 만들 땐 거의 필수입니다!</p>
<p><a href="https://github.com/VeriorPies/ParrelSync">ParrelSync</a></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/c52dbeb1-99d6-4fed-a97d-ca39b56b3006/image.png" alt=""></p>
<p>Github에서 사용법이 친절하게 나와있어서 보고 설치하신 다음에 유니티에서 저렇게 나오면 설치가 제대로 된 겁니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[네트워크 계층]]></title>
            <link>https://velog.io/@asiatic_ricecake/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@asiatic_ricecake/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Sat, 12 Jul 2025 05:50:21 GMT</pubDate>
            <description><![CDATA[<p>네트워크에서 계층(Layer)은 복잡한 통신 과정을 단계별로 나누어 처리하고, 각 계층의 역할을 명확히 하여 효율적이고 표준화된 통신을 하기 위한 이론입니다.</p>
<p>대표적으로 2가지가 있습니다. OSI 7계층, TCP/IP</p>
<h1 id="1-📒-osi-7계층">1. 📒 OSI 7계층</h1>
<p>OSI 7계층은 국제표준기구(ISO)에서 만든 네트워크 통신에 대한 표준 이론입니다.</p>
<p>하지만 TCP/IP에 비해 실무에서 거의 안 쓰이는 이론입니다.</p>
<h2 id="1-1-🤔-osi-7계층이-실무에서-안쓰이는-이유">1-1. 🤔 OSI 7계층이 실무에서 안쓰이는 이유</h2>
<h3 id="1-1-1-✅-osi는-너무-이론적인-모델">1-1-1. ✅ OSI는 너무 이론적인 모델</h3>
<p>OSI는 각 계층을 너무 명확하게 분리하려고 해서 실제로는 구현이 복잡하거나 비효율적인 부분이 상당히 많습니다</p>
<p>예를 들면 표현층과 세션층은 실제 구현에서 거의 따로 구분하지 않고 보통 응용층에 통합해서 다룹니다.</p>
<h3 id="1-1-2-✅-기술-변화에-유연하지-않음">1-1-2. ✅ 기술 변화에 유연하지 않음</h3>
<p>OSI는 고정된 7계층 구조로 이루어져있어 각각의 계층은 특정 기능을 담당하며, 계층 간 인터페이스는 명확히 분리되어 있습니다.</p>
<p>그래서 새로운 기술이 생기면 기존 계층 정의에 억지로 끼워넣어야 해서 유연성이 떨어집니다.</p>
<h2 id="1-2-🤔-그럼에도-알아야-하는-이유">1-2. 🤔 그럼에도 알아야 하는 이유?</h2>
<h3 id="1-2-1✅-네트워크-문제의-원인을-계층별로-추적-필요">1-2-1.✅ 네트워크 문제의 원인을 계층별로 추적 필요</h3>
<p>네트워크 문제 발생 시 어디서 문제가 생겼는지 빠르게 원인을 찾는 것이 중요합니다!</p>
<p>문제가 생겼을 때 계층별로 분석하여 찾아 빠르게 해결하는거죠</p>
<h3 id="1-2-2-✅-네트워크-장비·보안·프로그래밍-분야에서-공통-언어처럼-사용됨">1-2-2. ✅ 네트워크 장비·보안·프로그래밍 분야에서 ‘공통 언어’처럼 사용됨</h3>
<p>네트워크 엔지니어: “지금 3계층에서 ICMP 응답 없음” → IP 문제
보안 분석가: “패킷 스니핑이 4계층까지 침투했음” → 전송층까지 노출
프로그래머: “응용층에서 REST API 호출이 실패함” → HTTP 문제</p>
<p>OSI 계층은 현업에서 커뮤니케이션을 위한 표준 언어 역할을 합니다.</p>
<h3 id="1-2-3-✅-tcpip나-기타-구조를-이해하기-위해">1-2-3. ✅ TCP/IP나 기타 구조를 이해하기 위해</h3>
<p>TCP/IP를 배우기 전에 OSI 7계층을 알면 이해하기가 더 쉽습니다.
애초에 TCP/IP 계층은 OSI 계층의 모델이 너무 이론적이라 현업에서 사용하기 위해서 만든 계층이기 때문에 OSI 계층을 기본 토대로 이루어져 있습니다.</p>
<p>결국 TCP/IP 계층을 알기 위해서는 OSI 계층의 대한 이해가 필요합니다.</p>
<h2 id="1-3-📝-계층-구조">1-3. 📝 계층 구조</h2>
<h3 id="1-3-1-✅-물리층-physical">1-3-1. ✅ 물리층 (Physical)</h3>
<p>물리층은 OSI 1계층으로 가장 아래에 있습니다.
0과 1로 된 데이터를 실제 물리적 신호로 바꾸어 전송하는 역할을 진행하는 계층입니다.</p>
<p>컴퓨터와 물리적으로 연결되는 장비들이 속하는 단계이며, 
케이블, 모뎀, 허브, 리피터 등이 여기에 속합니다.</p>
<h3 id="1-3-2-✅-데이터링크층-data-link">1-3-2. ✅ 데이터링크층 (Data Link)</h3>
<p>데이터링크층은 OSI 2계층입니다.
여기선 동일한 네트워크 내에서 발생하는 컴퓨터들 간의 통신을 다룹니다.</p>
<p>물리 계층에서 받은 데이터를 분할한 프레임에 고유한 식별자를 부여하여 오류 없이 정확하게 목적지까지 전달하는 역할을 합니다.</p>
<p>보통 MAC 주소로 데이터를 전송합니다.</p>
<h3 id="1-3-3-✅-네트워크층-network">1-3-3. ✅ 네트워크층 (Network)</h3>
<p>네트워크층은 OSI 3계층입니다.</p>
<p>데이터를 다른 네트워크로 전달하기 위해 IP 주소를 사용하고,
최적의 경로(Route)를 찾아가는 역할입니다.</p>
<p>여기서 라우팅(Routing)이라는 개념을 알면 좋은데 
데이터가 최단 경로로 목적지까지 도달하도록 길찾아주는 역할을 합니다.</p>
<p>이 계층이 있어 서울에 있는 PC에서 미국 구글 서버에 접근이 가능하도록 만드는 것입니다.</p>
<h3 id="1-3-4-✅-전송층-transport">1-3-4. ✅ 전송층 (Transport)</h3>
<p>전송층은 OSI 4계층입니다.</p>
<p>이전 1~3계층이 데이터를 보내는 것에 집중했다면,
4계층은 데이터를 어떻게 누가 받을지 집중합니다.</p>
<p>송신자와 수신자 간의 종단 간(end-to-end) 통신을 관리하고,
신뢰성있는 데이터 전송을 위해 오류검사, 복구, 흐름제어 등의 기능을 제공합니다.</p>
<p>TCP (웹, 이메일 등), UDP (게임, 스트리밍, VoIP), 포트 번호를 사용합니다.</p>
<h3 id="1-3-5-✅-세션층-session">1-3-5. ✅ 세션층 (Session)</h3>
<p>세션층은 OSI 5계층입니다.</p>
<p>통신 세션(대화)을 설정하고, 유지하며, 끊는 역할하는 관리자입니다.</p>
<p>로그인 세션 유지, 영상통화 연결 지속 같은 부분이 세션 관리라고 보시면 됩니다.</p>
<h3 id="1-3-6-✅-표현층-presentation">1-3-6. ✅ 표현층 (Presentation)</h3>
<p>표현층은 OSI 6계층입니다.</p>
<p>데이터를 송신자와 수신자가 이해할 수 있는 형식으로 변환하는 계층입니다. </p>
<p>데이터의 인코딩, 디코딩, 압축, 암호화를 위한 소프트웨어가 사용됩니다.</p>
<p>SSL/TLS 암호화(HTTPS), 영상/이미지 압축(JPEG, MPEG), 문자 인코딩(UTF-8) 등 있습니다.</p>
<h3 id="1-3-7-✅-응용층-application">1-3-7. ✅ 응용층 (Application)</h3>
<p>마지막으로 응용층은 7계층입니다.</p>
<p>사용자와 프로그램이 네트워크 서비스를 직접 사용할 수 있게 해주는 계층입니다.</p>
<p>여기서 이제 사용자가 “인터넷을 사용한다”는 것이 응용층을 사용한다고 보시면 됩니다.</p>
<p>웹사이트 접속 (크롬, 엣지 등), 이메일 보내기 (Gmail, Outlook), 구글 검색 등 실생활에서 인터넷을 한다면 대부분 응용층의 이야기 하고 보시면 됩니다.</p>
<h1 id="2-📒-tcp--ip">2. 📒 TCP / IP</h1>
<p>TCP / IP는 OSI 7계층을 실무에서 사용하기 위해 네트워크를 통한 계층을 간소화하고 신 기술의 적용을 용이하게 하기 위해 만들어졌습니다.</p>
<h2 id="2-1-📝-계층-구조">2-1. 📝 계층 구조</h2>
<h3 id="2-1-1-✅-네트워크-접근링크-계층">2-1-1. ✅ 네트워크 접근(링크) 계층</h3>
<p>물리적인 네트워크에서 데이터를 전송하기 위한 요소(하드웨어/소프트웨어)를 다루는 계층입니다.</p>
<p>OSI 1, 2계층의 역할을 하고 있습니다.</p>
<p>MAC 주소 기반으로 실제 신호로 데이터 전송하며,
장비로 허브, 스위치, 케이블등을 사용합니다.</p>
<h3 id="2-1-2-✅-인터넷-계층">2-1-2. ✅ 인터넷 계층</h3>
<p>상대 네트워크와 통신하기 위한 IP주소를 사용해 데이터를 전송합니다. </p>
<p>여기서 라우터를 이용해 패킷의 경로를 설정하고 전송합니다.</p>
<p>OSI 3계층 역할을 하고 있습니다.</p>
<p>프로토콜은 IP 주소, ICMP (Ping), ARP (MAC-IP 매핑)이 있습니다.</p>
<h3 id="2-1-3-✅-전송-계층">2-1-3. ✅ 전송 계층</h3>
<p>OSI 4계층의 역할을 하는 계층입니다.</p>
<p>TCP / UDP 방식을 사용해 데이터의 전송을 담당합니다.</p>
<h4 id="2-1-3-1-✔️-tcp-신뢰성-우선">2-1-3-1. ✔️ TCP (신뢰성 우선)</h4>
<p>데이터 전송 전 상대와 연결하고, 데이터를 조금씩 나눠 보내며 수시로 상대가 데이터를 받았는지 확인합니다. </p>
<p>상대방 컴퓨터에서 정확하게 데이터를 받았는지 확인이 가능하므로 웹사이트 방문시 대부분 이 방식이 사용됩니다.</p>
<h4 id="2-1-3-2-✔️-udp-속도-우선">2-1-3-2. ✔️ UDP (속도 우선)</h4>
<p>별도의 과정 없이 한번에 많은 양의 데이터를 보낼 수 있어 빠르지만, 상대방 컴퓨터에서 정확한 데이터가 도착하지 않을 수 있습니다.</p>
<h3 id="2-1-4-✅-응용-계층">2-1-4. ✅ 응용 계층</h3>
<p>마지막으로 응응 계층입니다.</p>
<p>OSI 5, 6, 7 계층의 역할을 하고 있습니다.</p>
<p>사용자와 직접 통신하는 앱 계층. 데이터 표현, 암호화, 세션까지 모두 포함하고 있으며, HTTP, FTP, SMTP등 응용 프로그램에서 사용되는 프로토콜을 다룹니다.</p>
<p>HTTP (웹사이트), FTP (파일 전송), DNS (도메인 → IP 변환), 이메일(SMTP/IMAP), 메신저 등 있습니다.</p>
<pre><code>┌────────────────────────────┐
│       OSI 7계층          │      TCP/IP 4계층
├────────────────────────────┤
│ 7 응용(Application)      │      │
│ 6 표현(Presentation)     │      │  →  4. 응용 계층
│ 5 세션(Session)          │      │
├────────────────────────────┤
│ 4 전송(Transport)        │  →   3. 전송 계층
├────────────────────────────┤
│ 3 네트워크(Network)       │  →   2. 인터넷 계층
├────────────────────────────┤
│ 2 데이터링크(Data Link)   │      │
│ 1 물리(Physical)         │      │  →  1. 네트워크 접근 계층
└────────────────────────────┘
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 오클루전 컬링]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EC%98%A4%ED%81%B4%EB%A3%A8%EC%A0%84-%EC%BB%AC%EB%A7%81</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EC%98%A4%ED%81%B4%EB%A3%A8%EC%A0%84-%EC%BB%AC%EB%A7%81</guid>
            <pubDate>Mon, 09 Jun 2025 11:32:02 GMT</pubDate>
            <description><![CDATA[<p>Occlusion Culling은 카메라에 보이지 않는 오브젝트를 렌더링하지 않도록 날려주는 최적화 기법입니다.</p>
<p>애초에 유니티는 기본적으로 카메라 시야 밖에 있는 오브젝트는 안나오도록 합니다. 
하지만 시야 안에서 다른 오브젝트 뒤에 가려서 안 보이는 부분이 있을 거잖아요?</p>
<p>그것까지 안 그리도록 하는 기능은 없습니다.</p>
<p>이 때 Occlusion Culling을 사용하면 가려진 오브젝트는 렌더링 하지않도록 하는 기술입니다.</p>
<h1 id="1-🖥️-occlusion-culling">1. 🖥️ Occlusion Culling</h1>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/fc325bc9-9a69-4bcb-9720-6cc0692273b5/image.png" alt=""></p>
<h2 id="1-1🖱️environment-depth">1-1.🖱️Environment Depth</h2>
<h3 id="1-1-1-🔖-environment-depth-mode">1-1-1. 🔖 Environment Depth Mode</h3>
<blockquote>
<p>Disabled: 사용 안함
Fastest: 빠르지만 정확도 낮음
Medium: 성능과 정확도의 균형을 잡은 설정
Best: 가장 정확한 환경 깊이 정보 사용함</p>
</blockquote>
<p>Best로 갈수록 가장 높은 정확도의 Occlusion이 생성되므로 프로그램 전체적인 성능이 약간 떨어질 수 있습니다.</p>
<h3 id="1-1-2-🔖-temporal-smoothing">1-1-2. 🔖 Temporal Smoothing</h3>
<p>이 옵션을 켜면 깊이 정보가 부드럽게 보정됩니다. 당연히 보정이 목적이기 때문에 큰 이슈 아니라면 무조건 켜는게 낫습니다.</p>
<h2 id="1-2🖱️human-segmentation">1-2.🖱️Human Segmentation</h2>
<p>사람의 형태를 인식해서 가상 오브젝트가 사람 뒤에 가려지도록 만드는 기능입니다.</p>
<h3 id="1-2-1-🔖-human-segmentation-stencil-mode">1-2-1. 🔖 Human Segmentation Stencil Mode</h3>
<p>사람의 외곽 실루엣을 마스크처럼 만드는 기능입니다.</p>
<h3 id="1-2-2-🔖-human-segmentation-depth-mode">1-2-2. 🔖 Human Segmentation Depth Mode</h3>
<p>사람의 거리까지 반영해서 Occlusion 처리하는 기능입니다.</p>
<p>사람이 가상 오브젝트보다 앞에 있을 때 정확한 가림 처리를 하려고 사용하는 기능입니다.</p>
<h3 id="1-2-3-🔖-occlusion-preference-mode">1-2-3. 🔖 Occlusion Preference Mode</h3>
<p>깊이 정보가 여러 소스에서 올 수 있을 때 우선순위를 결정하는 옵션입니다.</p>
<blockquote>
<p>No Preference: 우선순위 없음
Prefer Environment Occlusion: 환경 기반 우선
Prefer Human Occlusion: 사람 인식 기반 우선</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] AR]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-AR</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-AR</guid>
            <pubDate>Mon, 09 Jun 2025 00:30:38 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📒-ar의-개념">1. 📒 AR의 개념</h1>
<p>AR은 Augmented Reality의 약자입니다. 증강현실이라고 합니다.</p>
<p>AR은 간단히 말하면 실제 환경을 그대로 보면서 그 위에 가상의 요소를 실시간으로 추가해서 보여주는 기술입니다.</p>
<p>현실에 가짜 정보를 덧씌우는 기술인거죠 현실은 그대로 있고, 가상의 콘텐츠가 현실을 보조하는 역할만 하는 겁니다. </p>
<h2 id="1-1-📝-홀로그램">1-1. 📝 홀로그램</h2>
<p>흔히 홀로그램이랑 개념을 혼동하시는 분이 많으신 걸로 알고 있습니다.
둘 다 없는 가상의 오브젝트를 눈앞에 띄우는 건 동일합니다만 기술이 아예 다릅니다.</p>
<p>홀로그램은 빛의 간섭으로 3D 입체 이미지를 공중에 떠오르게 하는 기술입니다.
즉, 현실에서 빛을 이용해 보여주기 때문에 AR 기술과는 다르게 스마트폰 같은 장비가 없어도 가상의 물체가 보입니다.</p>
<p>AR에 경우 현실에는 없고 장비 안에서만 존재하기 때문에 장비가 없으면 가상의 물체가 아예 뜨지도 않습니다.</p>
<h1 id="2-🖥️-ar개발을-위한-유니티-세팅">2. 🖥️ AR개발을 위한 유니티 세팅</h1>
<p>이 부분은 사실 공식문서에 자세히 나와있어 링크 들어가셔서 참고하시면 됩니다.
<a href="https://developers.google.com/ar/develop/unity-arf/getting-started-ar-foundation?hl=ko">AR Core</a></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/2236fd1a-554c-4500-bea3-8e8f8314af8b/image.png" alt=""></p>
<ol>
<li>먼저 렌더파이프라인으로 프로젝트를 생성합니다. 3D나 2D는 상관없습니다만 저는 3D로 생성을 하겠습니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a289bdc4-abd4-4e5f-9b4e-975402554c05/image.png" alt=""></p>
<ol start="2">
<li>Build Settings에 들어가셔서 안드로이드로 빌드르 변경합니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/bbfce9b3-d191-4a85-b1d9-f19be155f61c/image.png" alt=""></p>
<ol start="3">
<li>그 다음 Player Settings에 들어가셔서 Player에 들어갑니다. Graphics APIs에서 Vulkan을 삭제합니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a9e67ab4-15bf-497b-bdc4-a2f02b10f49a/image.png" alt=""></p>
<ol start="4">
<li>Minimum API Level을 사진과 같이 설정하시면 됩니다. (Android 7.0 Nougat)</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a5bdf654-d8d2-489d-8a94-2d3d61b7af85/image.png" alt=""></p>
<ol start="5">
<li>밑에 또 내려가시면 Scripting Backend를 IL2CPP로 변경합니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/12780cce-53cf-42f5-9c96-cde116deab42/image.png" alt=""></p>
<ol start="6">
<li>여기선 ARMv7, ARM64 둘다 체크합니다</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/9468668f-3b1e-4b50-9cf2-5b54e2ebf542/image.png" alt=""></p>
<ol start="7">
<li>Package Manger에 들어가서 AR Foundation, Google ARCore XR Plugin 2개를 다운 받으시면 됩니다. 특히 AR Foundation은 설치한다면 재시작하라는 경고문이 뜹니다. 그거 Yes 누르고 재시작하면 됩니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/033c1f50-1620-471a-be72-ee2d675d8e1a/image.png" alt=""></p>
<ol start="8">
<li>Project Settings에 들어오셔서 화면과 같이 설정해주시면 됩니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a260223e-6ac2-4bac-b22a-5239623dab4f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/9aa14a85-9782-491a-b217-ad25b0a8d50a/image.png" alt=""></p>
<ol start="9">
<li>저 설정이 끝나면 XR이 나오는 것을 볼 수 있을 겁니다.
여기서 AR Session과 XR Origin을 생성해주세요!</li>
</ol>
<h2 id="2-1🖱️ar-session">2-1.🖱️AR Session</h2>
<p>AR Session은 AR 세션을 초기화하고 관리하는 역할입니다. </p>
<p>사용자의 AR 기능을 제어하고 추적을 활성화하여 연동시켜주는 겁니다.</p>
<h2 id="2-2🖱️xr-origin">2-2.🖱️XR Origin</h2>
<p>XR Origin은 AR/VR에서 플레이어의 기준점을 제공합니다.</p>
<p>XR 카메라(AR Camera)를 포함하고 있어 플레이어의 위치, 회전, 움직임 추적의 기준점을 설정합니다. 그래서 그 카메라로 실제 위치와 월드 좌표계를 연결하는 역할을 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Astar 알고리즘]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-Astar-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-Astar-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Mon, 26 May 2025 06:49:31 GMT</pubDate>
            <description><![CDATA[<p>Astar 알고리즘은 길찾기에 사용되는 대표적인 알고리즘 입니다. </p>
<p>추격자나 몬스터의 인공지능을 구현할 때 단순히 따라오도록 한다면 벽에 부딪히거나 뚫고 가거나 누가봐도 어색하게 갈 것 입니다. 그래서 원하는 장소까지 자연스럽게 이동시키도록 만드는 것이 중요합니다.</p>
<p>물론 Unity에서 NavMesh를 사용해 간편하게 적용이 가능하지만 완전하진 않습니다.</p>
<p>A* 알고리즘은 상당히 유명해 이미 구현되어 있는 코드가 많이 있습니다.
구글에 검색하면 바로 나오는 공유된 코드가 있습니다. 
링크 들어가셔서 참고하시면 됩니다.</p>
<p><a href="https://arongranberg.com/astar/">Aron Granberg - A* Pathfinding Project</a></p>
<h1 id="1-📖-a-알고리즘">1. 📖 A* 알고리즘</h1>
<p>A* 알고리즘은 다음과 같은 구성요소로 되어있습니다.</p>
<blockquote>
<p>G: 시작점에서 현재 노드까지의 거리
H: 현재 노드에서 목적지까지의 예상 거리 (휴리스틱)
F = G + H : 총 예상거리</p>
</blockquote>
<h1 id="2-📖-다익스트라dijkstra-vs-a">2. 📖 다익스트라(Dijkstra) vs A*</h1>
<p>길찾기 알고리즘의 대표적인 주자 다익스트라 알고리즘과 어떤 차이가 있을까요?</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">A* 알고리즘</th>
<th align="center">다익스트라 알고리즘</th>
</tr>
</thead>
<tbody><tr>
<td align="center">탐색 방향</td>
<td align="center">목표 지점 방향</td>
<td align="center">전 방향</td>
</tr>
<tr>
<td align="center">사용하는 값</td>
<td align="center">G + H</td>
<td align="center">G</td>
</tr>
<tr>
<td align="center">속도</td>
<td align="center">빠름</td>
<td align="center">느림(전방향 탐색)</td>
</tr>
</tbody></table>
<h2 id="2-1-🔖-다익스트라dijkstra">2-1. 🔖 다익스트라(Dijkstra)</h2>
<p>다익스트라의 경우 전 방향을 모두 살펴본 후에 가장 단거리를 찾는 방식으로
전부 탐색해서 가장 짧은 길을 찾는 것이 이 알고리즘의 핵심입니다.</p>
<p>목적지가 멀리 있든 가깝든 동일한 방식으로 탐색하기 때문에 속도가 느립니다.</p>
<p>이러한 특성으로 게임보다는 네비게이션에서 사용하면 가장 좋은 길찾기 알고리즘입니다.</p>
<h2 id="2-2-🔖-a">2-2. 🔖 A*</h2>
<p>다익스트라의 경우 모든 방향을 계산하여 단거리를 제시하지만
Astar의 경유 목적지가 정해져 있으면 그 방향만 생각합니다.</p>
<p>목적지가 저기니까 그쪽 방향부터 우선적으로 탐색하는 방식인거죠</p>
<p>여기서 H(휴리스틱)을 이용해서 목표에 가까운 쪽을 먼저 탐색하도록 만드느 것 입니다.</p>
<h1 id="3-📖-휴리스틱">3. 📖 휴리스틱</h1>
<p>그럼 휴리스틱은 무엇일까요?</p>
<p>현재 노드에서 목표 지점까지의 예상 거리를 말합니다.
A*는 이 H를 참고해서 목표 지점에 가까운 노드부터 우선적으로 탐색합니다.</p>
<p>여기서 중요한 건 장애물이 있는 경우 무시하고 계산합니다.</p>
<p>휴리스틱은 본질적으로 목표까지 얼마나 되는지를 대충 예측하는 함수기 때문에 
장애물까지 고려하면 계산이 너무 복잡해지고, 빠른 탐색이 되질 않습니다.</p>
<p>장애물은 A* 알고리즘에서 따로 처리합니다.</p>
<h2 id="3-1-✔️-맨하튼-거리">3-1. ✔️ 맨하튼 거리</h2>
<p>휴리스틱 계산의 경우 여러가지 계산 방법이 있습니다.</p>
<p>맨하튼 거리의 경우 상하좌우만 이동 가능한 격자에서 사용하는 방식입니다.</p>
<blockquote>
<p>맨하튼 거리 계산 방식
H = |x1 - x2| + |y1 - y2|</p>
</blockquote>
<p>예를 들어 (0,0) → (4,2) 라면</p>
<p>|0 - 4| + |0 - 2| = 4 + 2 = 6</p>
<p>H는 6이 되는겁니다.</p>
<pre><code>int H (Vector2Int a, Vector2Int b) 
{
    return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
}</code></pre><p>대각선 이동 불가능한 경우에 빠르게 연산이 필요한 경우에 사용합니다.</p>
<p>그래서 2D 게임이나 턴제 RPG 등에서 많이 사용하는 계산 방식입니다.</p>
<h2 id="3-2-✔️유클리디안-거리">3-2. ✔️유클리디안 거리</h2>
<p>유클리디안 거리는 피타고라스의 정리를 기반으로 실제 물리적인 거리를 측정합니다.</p>
<blockquote>
<p>H = √[(x1 - x2)² + (y1 - y2)²]</p>
</blockquote>
<p>예를 들어 (0,0) → (4,2) 라면</p>
<p>√[(4)^2 + (2)^2] = √(16 + 4) = √20 ≈ 4.47</p>
<p>H는 약 4.47이 됩니다.</p>
<pre><code>float H (Vector2 a, Vector2 b) 
{
    return Vector2.Distance(a, b);
    // Mathf.Sqrt(Mathf.Pow(a.x - b.x, 2) + Mathf.Pow(a.y - b.y, 2));
}</code></pre><p>대각선 포함한 자유 이동에서 사용합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] State Pattern]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-State-Pattern</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-State-Pattern</guid>
            <pubDate>Mon, 26 May 2025 00:20:52 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📖-state-pattern">1. 📖 State Pattern</h1>
<p>상태 패턴은 <code>객체의 상태에 따라 행동을 다르게 해야 할 때</code> 사용하는 디자인 패턴입니다.</p>
<p>객체가 가진 상태를 관리하고, 각 상태에 따른 행동을 미리 지정할 수 있습니다. </p>
<p>예를 들어봅시다.</p>
<p>플레이어 상태는 Idle, Run, Jump, Attack, Die 이런 식으로 있을 것이고,
몬스터 상태는 Patrol, Chase, Attack이 있을 것이고,
문 상태는 Open, Close, Locked가 있을 것이고,
게임 진행 상태는 Title, Playing, Paused, GameOver가 있을 것입니다.</p>
<p>간단한 게임이면 몰라도 이런 식으로 여러가지 상태가 있을 때 
한 코드에 다 집어 넣어서 관리한다면 <code>유지 보수하기가 상당히 까다롭</code>겠죠...
또 상태마다 행동 분리하면 조건문이 남발될 수 있어 <code>아도겐 코드</code>가 될 수도 있습니다.</p>
<h2 id="1-1-🖥️-상태-패턴-몬스터-예시">1-1. 🖥️ 상태 패턴 몬스터 예시</h2>
<p>만약 몬스터가 Patrol, Chase 두 가지 상태를 가진다는 가정 하에 예시를 보겠습니다. </p>
<pre><code>public interface IMonsterState
{
    public void Enter(Monster monster);
    public void Execute(Monster monster);
    public void Exit(Monster monster);
}</code></pre><p>보통 먼저 이런 식으로 인터페이스를 선언합니다.
공통점이 많다면 추상 클래스를 사용해도 무방합니다.</p>
<pre><code>public class PatrolState : IMonsterState
{
    public void Enter(Monster monster)
    {
        Debug.Log(&quot;패트롤 상태 진입&quot;);
    }

    public void Execute(Monster monster)
    {
        Debug.Log(&quot;패트롤&quot;);
    }

    public void Exit(Monster monster)
    {
        Debug.Log(&quot;패트롤 상태 종료&quot;);
    }
}</code></pre><pre><code>public class ChaseState : IMonsterState
{
    public void Enter(Monster monster)
    {
        Debug.Log(&quot;추격 상태 진입&quot;);
    }

    public void Execute(Monster monster)
    {
         Debug.Log(&quot;플레이어 추격&quot;);
    }

    public void Exit(Monster monster)
    {
        Debug.Log(&quot;추격 상태 종료&quot;);
    }
}</code></pre><p>이런 식으로 상태에 나누어서 코드를 만드는 디자인 패턴입니다.</p>
<p>여기서 사용하실 때 주의하셔야 할 점이 있습니다. 남발하듯이 상태를 나누시면 안됩니다.
<code>상태를 분리했지만 상태 간 로직 차이가 거의 없으면</code> 괜히 유지보수하기만 힘들 뿐입니다.</p>
<pre><code>public class SlowMoveState : IMonsterState
{
    public void Enter(Monster monster)
    {
        Debug.Log(&quot;천천히 움직임 상태 진입&quot;);
    }

    public void Execute(Monster monster)
    {
        Debug.Log(&quot;움직임&quot;);
    }

    public void Exit(Monster monster)
    {
        Debug.Log(&quot;천천히 움직임 상태 종료&quot;);
    }
}</code></pre><pre><code>public class FastMoveState : IMonsterState
{
    public void Enter(Monster monster)
    {
        Debug.Log(&quot;빠른 움직임 상태 진입&quot;);
    }

    public void Execute(Monster monster)
    {
        Debug.Log(&quot;움직임&quot;);
    }

    public void Exit(Monster monster)
    {
        Debug.Log(&quot;빠른 움직임 상태 종료&quot;);
    }
}</code></pre><p>보시면 로직이 동일하죠? 많이 과장된 예시이기는 합니다만...
이러한 경우에는 굳이 상태 패턴을 써서 나눌 필요가 없는 것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 유니티 2D]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0-2D</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0-2D</guid>
            <pubDate>Wed, 21 May 2025 09:03:16 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📖-3d와-2d의-차이점">1. 📖 3D와 2D의 차이점</h1>
<h2 id=""><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/8b9d3abd-6e74-4c25-8a1a-6756bd4b4c05/image.png" alt=""></h2>
<h2 id="-1"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/4de568a0-586a-4ec0-8a7b-f4c52b8f8d66/image.png" alt=""></h2>
<p>3D의 경우 오브젝트가 Mesh와 Collider가 기본적으로 세팅이 되어있는 것을 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/832f4f3a-4863-4d02-b6fb-4a9e19a9a82c/image.png" alt="">
-
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/fe8106a4-41da-43fe-92c4-4a222072fe49/image.png" alt="">
-
2D의 경우 Sprite가 있습니다.</p>
<h2 id="-2"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/4322b334-fbb6-4ab8-a52d-7e90339a48fc/image.png" alt=""></h2>
<p>카메라는 원근감이 없는 형태(Orthographic)로 설정되어 있고요.
<img src="https://velog.velcdn.com/images/asiatic_ricecake/post/9a443384-00a0-4160-bca9-ef8b8894e07e/image.png" alt="">
-
또 2D Project를 만드시면 배경이 이런 식으로 되어있는 경우를 볼 수 있을 겁니다.
이건 카메라에 Clear Flags의 설정이 SkyBox가 아닌 Solid Color로 설정되어 있기 때문입니다. </p>
<p>이 설정들은 변경할 일이 거의 없기 때문에 2D와 3D의 차이라고 생각하시면 되고 간단히 넘어가겠습니다.</p>
<h1 id="2-📖-2d-물리엔진">2. 📖 2D 물리엔진</h1>
<h2 id="-3"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/1f147894-fe66-41eb-9379-f7832d83d074/image.png" alt=""></h2>
<p>3D Rigidbody와 차이점이라면 설정만 보더라도 여러 차이점이 있기도 하고
Collider의 충돌의 경우에도 2D를 사용하고 있습니다.(BoxCollider2D, CircleCollider2D 등)</p>
<p>그렇다면 왜 물리설정과 충돌설정을 2D와 3D로 나눴을까요?</p>
<p>물리엔진 자체가 다른 것도 있긴 하지만 </p>
<p><code>성능 최적화</code>의 이유가 큽니다.</p>
<p>2D 게임에서 3D 물리 엔진을 사용하면 불필요한 z축 연산까지 하게 되는데 
그런 부분을 없애고 가볍게 동작하게 만드려고 나눈 것입니다.</p>
<p>2D 게임에서 충돌 처리할 때, 굳이 z축까지 검사할 필요는 없으니까요</p>
<h2 id="2-1-🖥️-간단한-이동-점프-구현">2-1 🖥️ 간단한 이동, 점프 구현</h2>
<p>무한 점프가 안 일어나도록 땅에 닿았을 때 점프하도록 구성하도록 구성했습니다.</p>
<p>이 코드는 레이케스트를 이용해서 지금이 밟고 있는게 지면인지 확인 후 닿았을 때 점프하도록 설정했습니다. </p>
<h2 id="-4"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/46ecec30-a547-4f36-86c0-b1086fe539a3/image.png" alt=""></h2>
<p>물론 전 레이어를 사용했지만 Tag로 찾을 수도 있고 OnCollisionEnter2D를 이용하셔도 됩니다.</p>
<pre><code>public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed;
    [SerializeField] private float jumpForce;

    [SerializeField] private Transform groundCheck; 
    [SerializeField] private float groundCheckRadius = 0.2f; 
    [SerializeField] private LayerMask groundLayer; 

    private bool isGrounded;

    private Rigidbody2D rid;
    private Vector2 inputVec;


    void Start()
    {
        rid = GetComponent&lt;Rigidbody2D&gt;();
    }

    void Update()
    {
        PlayerInput();

        isGrounded = Physics2D.OverlapCircle(groundCheck.position,
        groundCheckRadius, groundLayer);

        if (Input.GetKeyDown(KeyCode.Space) &amp;&amp; isGrounded) 
        {           
            PlayerJump();
        }
    }

    private void FixedUpdate()
    {
        PlayerMove();
    }

    private void PlayerInput()
    {
        float x = Input.GetAxis(&quot;Horizontal&quot;);
        inputVec =  new Vector2(x, 0).normalized;
    }


    private void PlayerMove()
    {
        rid.velocity = new Vector2(inputVec.x * moveSpeed, rid.velocity.y);
    }

    private void PlayerJump()
    {
        rid.velocity = new Vector2(rid.velocity.x, 0f);
        rid.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse); 
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
    }

}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 애니메이션]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98</guid>
            <pubDate>Wed, 14 May 2025 00:25:50 GMT</pubDate>
            <description><![CDATA[<p>게임이나 가장 중요한 것은 뭐니뭐니 해도 애니메이션입니다.
게임 오브젝트가 가만히 있으면 게임이 아니겠죠
움직임을 구현할 수 있도록 만들어 주는 것이 애니메이션의 목적입니다.</p>
<h1 id="1-📖-animator">1. 📖 Animator</h1>
<p>애니메이터(Animator)는 애니메이션 컨트롤러를 객체에 적용하기 위한 컴포넌트입니다.
애니메이션을 적용할 오브젝트를 선택하여 Aniamtor 컴포넌트를 추가하여 사용합니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/7fc66d84-6012-4a97-8585-4d90151f7753/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/6a4164ff-f776-4804-8dc1-bde8515e71ef/image.png" alt=""></p>
<p>지금은 Idle에 기본적으로 연결이 되어있지만 
여기서 Set as Layer Default State를 누르면 Walk를 기본 연결 할 수도 있습니다.<br><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/f6009825-1d2e-414a-b2be-121883e7769c/image.png" alt=""></p>
<p>엄청 간단히 만들었는데 이런 식으로 시간별로 위치를 조정하면서 마치 움직이는 것처럼 보이도록 만드는 것이 애니메이션입니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/2012db26-727d-44da-ad6b-7f3b2af108b7/image.gif" alt=""></p>
<h1 id="2-📖-animator-controller">2. 📖 Animator Controller</h1>
<p>애니메이션 상태를 전체적으로 관리할 수 있는데 걷기, 뛰기, 점프 등 각각의 애니메이션 클립을 등록해 두고 객체의 상태에 따라 애니메이션들을 관리하고 재생하는 일종의 작업 지시서입니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a497ef06-8286-44a9-8184-d23682961b57/image.png" alt=""></p>
<p>파라미터(Parameters)에 Bool, Float, Int, Trigger 값을 기준으로 상태 전환을 조건부로 정할 수 있습니다.</p>
<p>예를 들면 속도가 0 이상이면 걷기 애니메이션으로 전환하도록 만드는 것이죠.</p>
<blockquote>
<p>Idle → 플레이어가 이동 입력 → speed 값이 일정 이상 → Walk 상태로 전환</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a949af4d-1dc9-4bc5-a688-056f91b6c2fc/image.png" alt=""></p>
<p>결론적으로 Animator Controller은 애니메이션 상태 기획서의 역할을 하면서 제어 장치의 역할을 하는 기능입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Layer]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-Layer</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-Layer</guid>
            <pubDate>Mon, 12 May 2025 11:30:21 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📖-레이어">1. 📖 레이어</h1>
<p>레이어는 유니티에서 게임 오브젝트들을 구분하거나 분류하기 위해 사용합니다.</p>
<p>오브젝트에 레이어를 지정하여 카메라, Raycast, 충돌 감지 등을 특정 레이어만 작동하게 할 수 있습니다. 흔히 <code>태그</code>랑 <code>비슷한 기능</code>이라고 보시면 됩니다!</p>
<p>그럼 기능은 둘다 비슷한데 Tag와 Layer는 왜 나누어져 있는지 궁금하실겁니다.</p>
<p>Tag의 경우 단순히 오브젝트의 정체나 역할을 확인하는 용도로 사용합니다.
예로 이 오브젝트는 플레이어인가 적인가 판별할 때 사용하는거죠.</p>
<p>Layer의 경우 <code>비트 연산자</code>를 <code>사용</code>하기 때문에 <code>성능</code>적인 <code>측면</code>이 <code>필요</code>한 경우에 사용합니다.
그래서 충돌, 카메라, Raycast 같이 물리/렌더링 관련 처리에 사용합니다.</p>
<h1 id="2-📖-layermask">2. 📖 layerMask</h1>
<p>레이어 마스크는 특정 레이어에 속한 오브젝트들만 선택하거나 감지하도록 필터링하는 기능입니다.</p>
<p>쉽게 말하면 지정한 레이어가 있을 거잖아요?
지정한 여러 레이어를 비트 연산 방식으로 묶어서 사용할 수 있게 하는 함수입니다.</p>
<h2 id="2-1-🔖-비트-연산">2-1. 🔖 비트 연산</h2>
<p>유니티의 Layer는 내부적으로 32개(0~31)의 레이어로 이루어져 있고
CPU가 비트 연산을 매우 빠르게 처리하기 때문에 비트 연산을 사용합니다.</p>
<blockquote>
<p>✅ 1 &lt;&lt; n 
: n번 레이어의 1 생성 <br/>
✅ | (OR) 
: 이진법의 동일한 자리가 하나만 1이어도 1로 치환 <br/>
✅ &amp; (AND) 
: 이진법의 동일한 자리가 둘 다 1이라면 1로 치환</p>
</blockquote>
<h3 id="2-1-1-✔️-1--n">2-1-1. ✔️ 1 &lt;&lt; n</h3>
<pre><code>int playerMask = 1 &lt;&lt; LayerMask.NameToLayer(&quot;Player&quot;);</code></pre><p>만약 6번 레이어면 1을 좌측으로 6칸 이동, 즉 일곱번째 레이어입니다.
→ 1 &lt;&lt; 6 → 0000 0000 0100 0000 (64)</p>
<h3 id="2-1-2-✔️-or-연산">2-1-2. ✔️ OR 연산</h3>
<pre><code>int mask = (1 &lt;&lt; LayerMask.NameToLayer(&quot;Enemy&quot;)) 
| (1 &lt;&lt; LayerMask.NameToLayer(&quot;Obstacle&quot;));</code></pre><p>Enemy = 8, Obstacle = 9 라면:</p>
<p>1 &lt;&lt; 8 → 0001 0000 0000</p>
<p>1 &lt;&lt; 9 → 0010 0000 0000</p>
<p>OR 연산 → 0011 0000 0000 → 8번, 9번 레이어 둘 다 포함시킵니다.</p>
<h3 id="2-1-3-✔️-and-연산">2-1-3. ✔️ AND 연산</h3>
<pre><code>if ((mask &amp; (1 &lt;&lt; 8)) != 0)</code></pre><p>mask → 0000 0000 0011 0000 0000 (768)</p>
<p>8 → 0000 0000 0001 0000 0000 (256)    </p>
<p>= 0000 0000 0001 0000 0000 (256)</p>
<p>0이 아니므로 8번 레이어는 Enemy 레이어에 포함합니다.</p>
<pre><code>if ((mask &amp; (1 &lt;&lt; 10)) != 0)</code></pre><p>mask → 0000 0000 0011 0000 0000 (768)</p>
<p>10 → 0000 0000 0100 0000 0000 (1024)</p>
<p>= 0000 0000 0000 0000 0000 (0)</p>
<p>0 이므로 10번 레이어는 Enemy 레이어에 포함되지 않습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] UI 아키텍처 패턴]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-UI-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-UI-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Mon, 12 May 2025 11:01:04 GMT</pubDate>
            <description><![CDATA[<p>UI에서는 유지보수를 쉽기 위한 여러가지 디자인 패턴이 있습니다.
대표적으로는 MVC, MVP, MVVM가 있는데 여기선 MVC, MVP 2개만 다룰 예정입니다.</p>
<p>셋 다 목적은 같습니다!
한 곳에서 모든 것을 담당한다면 유지보수 하기 힘들기 때문에 각각 분할하여 역할을 나누는 것입니다.</p>
<h1 id="1-📖-mvc-model---view---controller">1. 📖 MVC (Model - View - Controller)</h1>
<p>MVC는 Model - View - Controller으로 분할하여 관리하는 개념입니다.</p>
<blockquote>
<p>✅ Model
: 데이터 부분을 담당합니다. <br/> (플레이어 체력, 점수 등 게임 데이터) <br/>
✅ View
: UI 표시 되는 부분을 말하는데 데이터를 그래픽으로 만들고 화면에 렌더링합니다. (유저가 보는 버튼, 텍스트, 이미지) <br/>
✅ Controller
: 실제 동작하도록 데이터를 입력 받았을 때 연산하는 로직 처리를 담당합니다. <br/> (버튼 클릭 처리)</p>
</blockquote>
<p>1️⃣ <code>PlayerModel</code>에서는 <code>데이터만 관리하고</code></p>
<pre><code>public class PlayerModel 
{
    public int Health { get; set; }
}</code></pre><p>2️⃣ <code>PlayerController</code>에서는 <code>데이터를 받아 로직을 만들고</code></p>
<pre><code>public class PlayerController 
{
    private PlayerModel model;
    private PlayerView view;

    public PlayerController(PlayerModel model, PlayerView view) 
    {
        this.model = model;
        this.view = view;
        view.OnDamage += DamagePlayer;
    }

    public void DamagePlayer(int damage) 
    {
        model.Health -= damage;
        view.UpdateHealth(model.Health);
    }
}</code></pre><p>3️⃣ <code>PlayerView</code>에서는 <code>UI에 집중</code>하도록 분할하여 관리합니다.</p>
<pre><code>public class PlayerView : MonoBehaviour 
{
    public UnityAction&lt;int&gt; OnDamage;
    public void OnClickDamageButton() 
    {
        OnDamage?.Invoke(10);
    }

    public void UpdateHealth(int health) {}
}</code></pre><h1 id="2-📖-mvp-model---view---presenter">2. 📖 MVP (Model - View - Presenter)</h1>
<p>MVP는 Model - View - Presenter로 분할하여 관리하는 개념입니다.</p>
<p>MVC와 MVP 모두 Model 변경 시 View 갱신되는 것은 같지만 차이가 있습니다.</p>
<p>MVC에서는 View가 Controller 통해 Model을 변경합니다.
Model이 변경되면 Controller가 View에 알려주거나, View가 Model에서 직접 읽습니다.</p>
<p>하지만 MVP에서는 View가 Presenter 호출만 하고
Presenter가 Model을 변경 후 Presenter가 View에 UI 갱신 명령을 주는 방식입니다.
결국 View는 Model을 직접 참조하는 형식이 아니라서 결합도가 낮습니다.</p>
<blockquote>
<p>✅ Model
: 데이터 부분만 담당 <br/>
✅ View
: UI만 담당 <br/>
✅ Presenter
: View와 Model을 연결하는데, View에만 명령을 내려줍니다. <br/></p>
</blockquote>
<p>1️⃣ Model(PlayerModel) → 데이터만 관리</p>
<pre><code>public class PlayerModel
{
    public int Health { get; private set; } = 100;

    public void TakeDamage(int damage) {
        Health = Mathf.Max(0, Health - damage);
    }
}</code></pre><p>2️⃣ View(PlayerView) → UI 표시/버튼 처리만 하도록 설계</p>
<pre><code>public interface IPlayerView 
{
    void SetPresenter(PlayerPresenter presenter);
    void DisplayHealth(int health);
}</code></pre><pre><code>public class PlayerView : MonoBehaviour, IPlayerView 
{
    public Text healthText;
    public Button damageButton;

    public PlayerPresenter presenter;

    public void Start() 
    {
        damageButton.onClick.AddListener(OnDamageButtonClicked);
    }

    public void SetPresenter(PlayerPresenter presenter) 
    {
        this.presenter = presenter;
    }

    public void DisplayHealth(int health) 
    {
        healthText.text = $&quot;Health: {health}&quot;;
    }

    private void OnDamageButtonClicked() 
    {
        presenter.DamagePlayer(10);
    }
}</code></pre><p>3️⃣ Presenter(PlayerPresenter) → Model이 변경되고, View가 갱신되도록 설계</p>
<pre><code>public class PlayerPresenter 
{
    private PlayerModel model;
    private IPlayerView view;

    public PlayerPresenter(PlayerModel model, IPlayerView view) 
    {
        this.model = model;
        this.view = view;
        this.view.SetPresenter(this);
        UpdateUI();
    }

    public void DamagePlayer(int damage) 
    {
        model.TakeDamage(damage);
        UpdateUI();
    }

    public void UpdateUI() 
    {
        view.DisplayHealth(model.Health);
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] UI]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-UI</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-UI</guid>
            <pubDate>Mon, 12 May 2025 11:00:41 GMT</pubDate>
            <description><![CDATA[<h1 id="1-📖-ui">1. 📖 UI</h1>
<p>UI는 User Interface로 사용자가 프로그램에서 
가장 직접적으로 마주하는 첫 번째 상호작용 요소입니다.</p>
<h2 id="1-1-🔖-ui-구성요소">1-1. 🔖 UI 구성요소</h2>
<p>UI는 반드시 Canvas라는 오브젝트에 포함되어 있어야 하며 
Canvas는 UI를 배치하는 평면의 도화지입니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/bfc83129-2ebf-4a28-a4df-8de313d803b4/image.png" alt=""></p>
<p>Canvas와 모든 UI는 일반 3D 오브젝트와는 다르게 UI를 화면에 표기하기 위한 2차원 사각형 내의 위치를 제어하기 위한 Rect Transform 컴포넌트가 포함되어 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/a6cd5e9a-6874-4853-905e-2f7e9e124a46/image.png" alt=""></p>
<p>여기서 Render Mode를 보시면 오버레이, 카메라, 월드 스페이스 3가지가 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/34cd48b5-00bf-4561-b9bd-1883e9f8cb95/image.png" alt=""></p>
<table>
<thead>
<tr>
<th align="center">기능</th>
<th align="center">위치</th>
<th align="center">사용</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Overlay</td>
<td align="center">카메라 상관 없이 항상 화면에 고정</td>
<td align="center">메뉴, 체력 게이지</td>
</tr>
<tr>
<td align="center">Camera</td>
<td align="center">특정 카메라 기준으로 배치</td>
<td align="center">시네마틱 UI</td>
</tr>
<tr>
<td align="center">World Space</td>
<td align="center">월드 안 3D 오브젝트처럼 배치</td>
<td align="center">NPC, player 머리 위 체력바</td>
</tr>
</tbody></table>
<hr>
<h2 id="1-2-🔖-유니티에서-사용하는-ui-시스템">1-2. 🔖 유니티에서 사용하는 UI 시스템</h2>
<h3 id="1-2-1-❌-ngui-next-gen-ui">1-2-1. ❌ NGUI (Next-Gen UI)</h3>
<p>NGUI는 Unity 공식이 아닌 외부에서 만든 UI입니다.
Unity 이전 버전까지는 Unity 자체에 기본 UI 시스템이 없어서 NGUI를 사용했습니다.</p>
<p>그래서 패키지를 따로 다운로드 후 사용이 가능했으며 
성능이 좋고 최적화가 뛰어난 장점이 있긴 합니다만...</p>
<p>유료이고 Unity 에디터와의 통합이 UGUI보다 떨어집니다. 
또 커스터마이징을 위해 코드로 많은 작업을 필요하기 때문에 진입장벽이 높습니다. </p>
<p>최근 프로젝트에서는 <code>거의 사용하지 않는</code> 구식 <code>기술</code>로 취급하는 추세긴 한데 
조금 오래된 프로젝트를 보면 아직 이 UI를 사용하고 있습니다.</p>
<h3 id="1-2-2-✔️-ugui">1-2-2. ✔️ UGUI</h3>
<p>Unity에서 공식적으로 제공하는 UI 시스템입니다.
Unity의 Canvas, Button, Text, Image 등을 말합니다.</p>
<p>유니티의 렌더링 파이프라인에 통합되어 있기 때문에 호환성이 좋습니다.
그 덕분에 이벤트와의 연결성이 좋아 버튼 클릭, 드래그 같은 입력 처리가 편리합니다.</p>
<p>C# 코드에서 쉽게 제어 가능하고 드래그 앤 드롭으로 UI를 쉽게 만들 수 있어 쉽게 배울 수 있습니다.</p>
<p>하지만 복잡한 UI나 많은 오브젝트가 있을 경우 Draw Call이 급격히 증가해서 최적화가 필수입니다.</p>
<h3 id="1-2-3-👍-ui-toolkit-최근-추천되는-ui-방식">1-2-3. 👍 UI Toolkit (최근 추천되는 UI 방식)</h3>
<p>UGUI와 마찬가지로 Unity에서 공식적으로 제공하는 UI 시스템입니다.</p>
<p>UGUI는 Canvas를 기반으로 개발하는 UI라면 UI Toolkit은 CSS, XML를 기반으로 합니다.</p>
<p>그래서 입문하기에는 UGUI가 아주 좋지만 최적화 측면에서 상당히 좋지 않아 
대규모 프로젝트에서는 UI Toolkit을 주로 사용합니다. </p>
<p>물론 가벼운 UI를 만들 때는 UGUI가 더 유리하기 때문에 게임에서 
아직까지는 UGUI를 많이 사용합니다.</p>
<p>대규모인 메타버스 플랫폼, 버츄얼 쪽 시장에서는 UI Toolkit을 많이 사용합니다.</p>
<p>CSS + XML과 유사하므로 웹 개발자라면 익숙한 기능이 많습니다만...
개발에 처음 발을 들인 사람이라면 다루기 어렵습니다.</p>
<p>대신 UI Toolkit는 GPU 친화적이며 가볍고 빠릅니다. 
그래서 대규모 UI 관리에 유리하죠.</p>
<h2 id=""><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/e7f71b7c-15e8-4dbf-a52a-6eedb548e737/image.png" alt=""></h2>
<hr>
<h2 id="1-3-🔖-위치-조정">1-3. 🔖 위치 조정</h2>
<p>앞에서 Canvas는 Rect Transform 컴포넌트 가진다고 했습니다.</p>
<p>Rect Transform은 해상도 변경시에도 부모 오브젝트의 위치에 고정하고 위치를 정렬하기 위한 앵커와 회전의 기준점이 되는 피벗을 가지고 있습니다.</p>
<h2 id="-1"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/eb91ff26-0687-4ddd-9fa2-53ae5e0b8430/image.png" alt=""></h2>
<h3 id="1-3-1-✔️-anchor">1-3-1. ✔️ Anchor</h3>
<p>UI 요소가 <code>Canvas</code>의 어디에 붙어 있을지를 결정하는 <code>기준</code>점(상대 좌표)입니다.</p>
<p>화면 크기가 변해도 Anchor 기준으로 
UI가 자동으로 위치 조절이 되어 같은 위치에 있도록 만드는 거죠.</p>
<p>즉 (0.5, 0.5) → Canvas의 가운데
(0,1) → Canvas의 좌상단 </p>
<p>이런 식으로 좌표로 기준점을 변경할 수 있고, 
Preset을 통해 선과 면을 기준으로 설정도 가능합니다.</p>
<h2 id="-2"><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/e6951c91-c010-4ea7-b4fb-31cb14a72e00/image.png" alt=""></h2>
<h3 id="1-3-2-✔️-pivot">1-3-2. ✔️ Pivot</h3>
<p>앞에서 본 Anchor는 Canvas 그 자체의 위치를 기준으로 했다면</p>
<p>Pivot은 <code>자기 자신 UI 요소</code>의 <code>중심점</code>으로 
이 점을 기준으로 크기, 회전, 위치 등을 설정합니다.</p>
<p>좌표로 본다면 (0, 0)은 왼쪽 하단, (1, 1)은 오른쪽 상단을 의미합니다.</p>
<h4 id="1-3-2-1-💡-응용">1-3-2-1. 💡 응용</h4>
<p>체력바를 왼쪽에서 오른쪽으로 줄어들게 하고 싶다면?
→ Pivot을 (0, 0.5)로 두고 왼쪽 기준으로 크기 줄입니다.</p>
<p>회전하는 UI가 중심에서 빙글빙글 돌게 하려면?
→ Pivot (0.5, 0.5)</p>
<p>이런 식으로 응용하며 UI를 완성하면 되겠죠?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 유니티 그래픽 기본 개념]]></title>
            <link>https://velog.io/@asiatic_ricecake/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0-%EA%B7%B8%EB%9E%98%ED%94%BD-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@asiatic_ricecake/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0-%EA%B7%B8%EB%9E%98%ED%94%BD-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Fri, 09 May 2025 13:00:32 GMT</pubDate>
            <description><![CDATA[<p>유니티에서 3D로 작업할 때 여러 도형 오브젝트를 만났을 겁니다.</p>
<p>그 오브젝트가 어떻게 이루어지는지 그래픽은 보통 어떻게 구성되어있는지 알아보겠습니다!</p>
<h1 id="1-📖-다면체-구성요소">1. 📖 다면체 구성요소</h1>
<p>유니티에서 원형 오브젝트를 보면 매끈한 표면으로 보일 수 있지만 사실 그렇지는 않습니다.
사진 보시면 매끄럽지 않고 표면이 거친 것을 볼 수 있습니다.</p>
<h2 id=""><img src="https://velog.velcdn.com/images/asiatic_ricecake/post/3687a86b-2cfd-4d84-a8ec-97235c085270/image.png" alt=""></h2>
<p>컴퓨터 3D 그래픽에서 모든 도형은 기본적으로 삼각형과 같은 다각형으로 이루어져 있습니다. </p>
<h2 id="1-1-🔖-vertex">1-1. 🔖 Vertex</h2>
<p>Vertex는 3D 공간상에 위치한 하나의 점으로 좌표로 표현됩니다.</p>
<p>폴리곤을 만들기 위한 기초 재료라고 보시면 됩니다.</p>
<h2 id="1-2-🔖-polygon">1-2. 🔖 Polygon</h2>
<p>Polygon은 여러 버텍스를 이어서 만든 면입니다.</p>
<p>그래픽 모델에서 가장 작은 면 단위는 폴리곤이며, 모든 모델은 삼각형이 모여 만듭니다.</p>
<p>게임 그래픽에서는 삼각형을 가장 많이 사용하는데 
어떤 형태든 삼각형으로 쪼개면 안정적으로 그릴 수 있기 때문입니다.</p>
<p>사각형 이상의 도형은 네 꼭짓점 중 하나가 다른 높이에 위치하면 하나의 평면에 존재할 수 없게 되어 비틀리는 현상이 있어서 안정적인 삼각형을 이용하는 것입니다.</p>
<h2 id="1-3-🔖-mesh">1-3. 🔖 Mesh</h2>
<p>폴리곤 무리가 모여서 만들어지는 하나의 물체 덩어리입니다. </p>
<p>모든 게임 오브젝트에 포함 되어있습니다.</p>
<hr>
<h1 id="2-📖-게임-그래픽-구성요소">2. 📖 게임 그래픽 구성요소</h1>
<h2 id="2-1-🔖-texture">2-1. 🔖 Texture</h2>
<p>Texture는 3D 오브젝트의 표면에 입히는 이미지(사진, 그림 등)을 말하는데</p>
<p>메시는 데이터로만 존재할 뿐, 외형이 존재하지 않습니다.</p>
<p>그래서 각 폴리곤에 대한 좌표를 미리 맵핑(UV Mapping)하고, 
각 좌표에 맞춰 메쉬에 마치 옷을 입히듯 이미지를 덧씌워 주는 작업이 필요한거죠.</p>
<p>마치 게임 캐릭터의 &quot;스킨&quot; 같은 역할이라고 보시면 됩니다.</p>
<p>색상, 표면, 광택 느낌 등으로 여러가지로 표현이 가능합니다.</p>
<h2 id="2-2-🔖-material">2-2. 🔖 Material</h2>
<p>물체의 표면정보를 종합적으로 가지는 속성입니다.</p>
<p>표면의 색상, 질감, 빛 반사율, 투명도 등을 설정할 수 있기 때문에</p>
<p>같은 색이더라도 다양한 설정을 통해 모델의 표면을 더 실감나게 표현할 수 있습니다.</p>
<h2 id="2-3-🔖-shader">2-3. 🔖 Shader</h2>
<p>3D 컴퓨터 그래픽에서 최종적으로 화면에 출력하는 픽셀의 색 정보를 지정해 주는 프로그램입니다.</p>
<p>Material이 어떤 식으로 보일지 계산하는 코드로 Material의 설정된 값을 받아서 빛 반사, 표면, 그림자 등을 계산합니다.</p>
]]></description>
        </item>
    </channel>
</rss>