<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발 연대기</title>
    <link>https://zoehw10101.tistory.com/</link>
    <description>킹숭이 코딩 중인가요</description>
    <language>ko</language>
    <pubDate>Tue, 7 Apr 2026 04:50:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>킹숭이</managingEditor>
    <image>
      <title>개발 연대기</title>
      <url>https://tistory1.daumcdn.net/tistory/6159926/attach/f1ce5ff0dd9d4d499c9687a3fb9d7c52</url>
      <link>https://zoehw10101.tistory.com</link>
    </image>
    <item>
      <title>[C# 주저리] 면접 대비 질문</title>
      <link>https://zoehw10101.tistory.com/39</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;Virtaul&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- virtaul의 경우는 컴파일 타임이 아니라 런타임에 함수 호출을 결정하는 키워드라고 알고 있음 virtaul 을 사용한 함수는 자식이 오버라이딩 함으로서 재정의 할 수 있고 이런 virtual 함수가 존재하는 클래스는 virtual table이 생성되어 이러한 vtable을 통해서 RTTI의 정보를 빼오기 때문에 런타임에 함수 호출을 결정할 수 있다. 동적 다형성이 가능한데, 아무래도 런타임에 확인하는 방식이다보니 런타임 오버헤드가 발생할 수 있다는 점이 단점이기 때문에 재정의를 할 필요가 없다면 사용하지 않는 것이 좋다고 알고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;virtaul table의 경우는 가상함수가 존재하는 부모와 자식에게 클래스 별로 메모리에 존재하는 것으로 알고 있는데, 이런 객체의 경우는 vtable를 가리키는 포인터가 존재하기 때문에 이럴 활용해서 table을 호출할 수 있고, 만약 부모를 기준으로 자식 타입를 호출하게 되면 자식의 virtaul 함수가 호출되고 부모 타입으로 호출하게 되면 부모의 함수가 호출되는 방식이라고 알고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;abstract class&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 추상 클래스는 혼자서 객체화 될 수 없다. 객체화가 가능한 클래스가 이 클래스를 통해서 다형성을 구현할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- Interface와 달리 멤버 변수를 사용할 수 있으며 상속이 가능한 형태이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- vtable은 클래스마다 하나씩 생성되는 고정된 배열로 함수의 메모리 주소를 담고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- vptr은 객체가 생성될 때 해당 객체의 메모리 첫 부분에 v-table을 가리키는 포인터가 숨겨져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RTTI는 가상 함수 테이블과 밀접한 관련이 있다. dynamic_cast나 typeid같은 연산자가 이 정보를 사용해서 런타임에 안전한 타입 변환이 가능한지 확인한다. 가상함수가 없는 클래스는 RTTI 정보가 없으므로 dynamic_cast를 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상속이 있는 클래스에는 virtaul 소멸자를 사용하는 것이 좋다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 부모 소멸자가 virtual이 아니라면 (부모* i = new 자식()) 형태에서 delete 시 자식의 소멸자가 호출되지 않아 메모리 누수가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Delegate 와 Event&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Delegate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 함수에 대한 포인터이다. 변수에 숫자를 담는 것처럼, 변수에 함수를 담아서 전달하거나 호출할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 클래스 외부에서 직접 호출 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. = 연산자로 덮어쓰기 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 함수의 매개변수 전달, 콜백&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Event&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 델리게이트의 래퍼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 외부 호출 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. +=, -= 연산자만 사용 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 상태 변화 통지, Observer 패턴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Interface&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 내가 Interface를 활용한 시점은 Monster의 FSM을 구현할 당시 Enter, Execute, Exit를 집어넣고 상속하여 사용했던 것이 가장 기억에 남는다. 약간 데이터를 무조건 같은 매개변수와 이름으로 상속 받아야 한다는 점에서 순수 가상 함수와 비슷하다는 느낌을 받았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인터페이스란 멤버에 대한 선언만을 포함하며, 구현은 하지 않는 계약이다. 이를 구현하는 클래스나 구조체는 해당 멤버들을 반드시 구현해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 한 클래스가 여러 인터페이스를 동시에 구현할 수 있으며, &lt;s&gt;모든 멤버는 기본적으로 public으로 변경할 수 없다.&lt;/s&gt; 최신 C#에서는 디폴트 인터페이스 메서드가 도입되어 인터페이스도 구현체를 가질 수 있고 private 멤버도 선언 가능하다. 또한 구현을 강제하며, 반드시 구현해야 하는 기능을 정의할 때 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스 -&amp;gt; 행위에 집&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상 클래스 -&amp;gt; 본질에 집중&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 인터페이스란 무엇이며, 언제 사용하는 것이 좋은가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 인터페이스란 멤버에 대한 선언만을 포함하며, 무조건 구현하도록 강제하는 계약입니다. 보통 한 클래스에 여러 인터페이스를 구현할 수 있으며, 모든 멤버는 기본적으로 public이며 접근제한자를 변경할 수 없다는 특징을 가지고 있습니다. 어떤 오브젝트에 대해 무조건 구현해야 하는 함수가 존재한다면 Interface를 통해서 강제하는 경우에 사용될 텐데, 저 같은 경우 프로젝트에서 FSM 패턴을 구현할 때 무조건 Enter, Excute, Exit를 구현해야 했기에 Interface를 통해 강제하여 함수를 무조건 정의할 수 있도록 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 다중으로 구현한다면 어떤 것이 좋은가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 다중으로 구현해본 적은 없지만, 만약 가능하다면 한 클래스가 다양한 기능을 수행할 수 있는 장점이 생길 것 같습니다. 예를 들어서 Moving을 하는데 필수적인 움직임과, Render를 하는데 있어 필수적인 함수를 함께 제공하는 오브젝트는 둘의 기능을 가질 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- virtaul과 Interface의 차이는 무엇인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 둘다 확장성과 다형성을 구현하는데 사용하지만 사용 용도와 방식에 차이가 존재합니다. virtual의 경우는 이 함수를 필수적으로 구현하겠다고 계약할 때 사용하며, virtual은 기본적으로 구현된 함수를 제공하는데 더해 구현 용도는 선택 사항입니다. 그렇기 때문에 Interface는 필수적으로 구현해야 하는 마치 순수 가상 함수와 좀더 비슷한 느낌인 것 같고, virtaul은 공통 로직을 부모 클래스에 정의하고 공통적으로 사용한다는 점에서 차이가 존재하는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 순수 가상 함수와 Interface의 차이는 무엇인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 순수 가상 함수와 Interface는 구현을 강제한다는 점에서 유사한 역할을 합니다. 하지만 순수 가상 함수의 경우 같은 부모를 가지고 있는 상속 관계에서 사용됩니다. C++의 경우 Interface라는 개념이 존재하지 않기 때문에 이를 통해서 강제합니다. Interface의 경우는 상속 관계에 존재하지 않는 전혀 다른 오브젝트더라도 공통적인 계약을 할 수 있다는 차이가 있습니다. 순수 가상 함수는 단일 상속만 가능하며, Interface는 다중 구현이 가능하다는 차이점이 가장 큰 것 같습니다.,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;+ 순수 가상함수는 추상 함수 외에 필드/변수, 일반 메소드 생성자 등을 포함할 수 있지만, Interface는 오직 선언만 가능&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;string/StringBuilder&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- C#의 string은 불변 객체로, 문자열이 생성되면 그 값을 변경할 수 없다. 문자열을 수정하는 모든 작업은 새로운 string 객체를 생성해서 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 문자열에 문자를 추가하거나 수정하는 작업을 반복적으로 수행할 경우, 기존 문자열을 수정하는 것이 아니라 새로운 메모리 공간을 할당하게 된다. 이런 이유로 문자열 수정 작업이 많이 필요한 경우 성능이 저하될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- StringBuilder는 가변 객체로 문자열을 수정하는 과정에서 새로운 객체를 생성하지 않고 같은 메모리 공간을 사용하여 문자열을 변경한다. StringBuilder는 내부적으로 버퍼를 사용해 효율적으로 문자열을 추가하거나 변경할 수 있어 반복적인 문자열 조작 시 메모리 할당과 가비지 컬렉션의 부담을 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- string : &lt;b&gt;불변 객체&lt;/b&gt;, 반복적으로 수정 시 &lt;b&gt;새로운 메모리에 할당&lt;/b&gt;하여 메모리 사용량 증가 및 성능 저하, 문자열이 고정된 경우 유용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- StringBuilder : &lt;b&gt;가변 객체&lt;/b&gt;, &lt;b&gt;버퍼를 활용&lt;/b&gt;하여 반복적으로 수정하는 문자열에 유용, 대량의 문자열을 반복적으로 수정할 때 유용하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- string과 StringBuilder의 차이점은 무엇인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: string 의 경우 불변 객체로 값을 변경할 수 없습니다. 만약 수정을 하게 된다면 새로운 메모리에 string 객체를 생성하게 되는 것이기 때문에 반복적으로 수정한다면 메모리 사용량이 늘어나고 성능이 저하될 수 있습니다. 반대로, StringBuilder의 경우 가변 객체로 내부 버퍼를 사용하기 때문에 반복적으로 대량의 문자열을 수정할 때 유용하다고 알고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- StringBuilder 사용 시 유의할 점은 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: StringBuilder는 문자열 조작 시에 적합하지만, 단순하고 적은 양의 문자열을 변경할 경우 string이 더 효율적입니다. 그 이유는 StringBuilder는 내부 버퍼를 관리하는데 추가적인 메모리 연산이 들기 때문에 만약 적은 양의 문자열을 변경한다면 차자리 string을 사용하는 것이 더 낫다고 알고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- String이 불변인 이유는 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 문자열 변경 시 새로운 인스턴스를 생성해서 메모리 단편화를 줄이며, 문자열 변경이 불가해 보안 상의 이유도 존재한다고 알고 있습니다. 그리고 여러 스레드에서 문자열을 안전히 공유할 수 있다는 이유인 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;문자열 인턴풀&quot; =&amp;gt; 똑같은 문자열이 여러 개 생기지 않도록 메모리를 공유하기 위함인데, 불변이어야만 공유가 안전함&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;오버로딩과 오버라이딩의 차이점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 뇌를 더듬더듬 살펴보면 오버로딩의 경우 반환 값 타입과&amp;nbsp; 매개변수 개수 및 타입을 제외한 이름이 같은 함수를 의미하고, 오버라이딩은 상속 관련인데,,,, 상속,,, 부모에서 정의된 함수를 자식에서 다시 재정의하는 것... 중복 정의? virtaul함수가 오버라이딩인 것으로 알고 있음....&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 오버로딩 : 동일한 이름의 메서드만 정의하되, 각 &lt;b&gt;메서드의 매개변수 목록을 다르게 설정&lt;/b&gt;하는 것을 의미한다. 매개변수의 타입, 개수, 순서가 다르면 서로 다른 메서드로 인식한다. &lt;b&gt;컴파일 시점에 어떤 메서드를 호출할 지 결정&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 오버라이딩 : 상속 관계에서 자식 클래스가 &lt;b&gt;부모 클래스 메서드를 재정의하는 것&lt;/b&gt;을 의미한다.같으 메서드를 구현하여 부모 클래스의 매서드를 변경하거나 확장할 수 있다. 이를 통해 다형성이 구현되며, &lt;b&gt;런타임 시점에서 실제 객체의 타입에 따라 호출&lt;/b&gt;되는 메서드가 달라진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 반환 타입의 경우 오버로딩은 무관하지만, 오버라이딩은 부모와 같아야 함.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 오버로딩과 오버라이딩의 차이점은 무엇인가요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: 오버로딩의 경우 같은 메서드의 이름은 같되, 매개변수 목록을 달리하는(순서, 타입, 개수) 것을 의미합니다. 오버라이딩의 경우 상속 관계에서 부모의 함수를 그대로 자식이 확장하거나 변경하는 경우를 의미합니다. 그렇기 때문에 오버로딩은 컴파일 시점에 불릴 함수가 결정되지만, 오버라이딩은 객체의 타입에 따라서 런타임에 불릴 함수를 호출하는 것으로 알고 있습니다. 또 다른 차이점은 오버로딩은 반환 값이 달라도 상관 없지만, 오버라이딩은 부모와 같아야 합니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;C#과 C++ 메모리 사용 방식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 내가 알고 있는 차이점은 C#은 가비지 컬렉션이라는 것이 존재해서 메모리를 자동으로 관리하여 사용하지 않는 객체를 삭제시키지만 C++은 내가 직접 할당하고 삭제해야 하는 것으로 알고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 또 다른 차이점이라하면 C#은 .Net 라이브러리를 사용하고 C++은 독립적인 언어라는 점? 그래서 C#이 좀더 편한데, 대신에 C++이 성능이 좋다고 함. 아마 가비지 컬렉션으로 인해서 주기적으로 오브젝트가 사용되지 않는 지 확인하지 않기 때문이겠지?&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;근데 알기로는 요새는 딱히 큰 차이는 없다고는 하는데 알아봐야 할 듯...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- C#은 .&lt;b&gt;Net 환경&lt;/b&gt;에서 주로 애플리케이션 개발에 사용되며, &lt;b&gt;자동 메모리 관리 GC를 지원&lt;/b&gt;하여 안정적이고 생산적인 개발 환경을 제공한다. 순수한 객체 지향 언어이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- C++은 메모리 &lt;b&gt;성능을 직접 관리&lt;/b&gt;할 수 있어 프로그래밍 성능이 중요한 애플리케이션에 적합하다. 또한 다양한 운영체제에서 네이티브 애플리케이션을 지원하는 &lt;b&gt;플랫폼 독립적 언어&lt;/b&gt;이다. 객체 지향 뿐만 아니라, 절차적 프로그래밍, 함수형 프로그래밍을 지원하는 &lt;b&gt;다중 패러다임 언어&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++은 성능이 좋다 =&amp;gt; 원하는 시점에 즉시 파괴가 가능하지만 GC가 언제 동작할지 몰라 예측하기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;C++의 new/delete 동작 방식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 기억나는 바로는 new의 경우에는 힙 메모리에 객체를 동적으로 생성하고 delete의 경우에는 객체를 제거... 어케 제거했더라...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;operate delete랑 delete가 있는 걸로 알고 있는데...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- new의 경우 내부에 존재하는 operate new 연산자를 통해서 해당 넘겨준 객체의 크기만큼 메모리를 할당해주며 new를 통해서 생성자를 호출한다. 이 때문에 new는 객체 타입에 맞는 포인터를 전달한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 추가로 malloc의 경우 넘겨준 크기만큼 메모리 할당만 하고 void*를 반환하여 원하는 타입으로 명시적 캐스팅이 필요하다.&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- delete는 메모리 해제 전에 소멸자를 먼저 호출한다. (소멸자 호출 -&amp;gt; 메모리 해제)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;C#에서 struct와 class의 차이&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- struct : &lt;b&gt;값&lt;/b&gt; 타입으로 &lt;b&gt;스택&lt;/b&gt;에 저장된다. 작고 수명이 짧은 데이터에 적합, 값 복사가 빈번히 일어날 수 있다. 상속 지원 x&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- class : &lt;b&gt;참조&lt;/b&gt; 타입이며 &lt;b&gt;힙&lt;/b&gt;에 저장된다. 기본적인 접근 제한자가&lt;b&gt; private&lt;/b&gt;이며 상속을 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 접근 제한자를 명시하지 않으면 internal(기본 값) 혹은 멤버의 경우 private이다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;C++ string_view vs C# ReadOnlySpan&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;템플릿(C++)과 제네릭(C#)의 차이점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;- 템플릿이라 하면 일단 C++에서 사용되는 한 함수를 여러 타입이 사용할 수 있도록 해서 코드 중복을 줄일 수 있고,,,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;함수 템플릿이랑 ,클래스 템플릿이 있다는 거...&amp;nbsp; 뭔지는 까먹음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 둘 다 데이터 타입을 일반화하여 코드의 재사용을 높이는 기술. 내부 동작과 철학에 큰 차이가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 템플릿&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 실제 물건을 새로 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 컴파일러가 컴파일 타임에 타입을 결정한다. 코드 중복을 줄이기 위해 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 타입별로 코드를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 메타 프로그래밍이 가능하다 (템플릿 특수화 같은)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 제네릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 하나의 상자에 다양한 물건을 안전하게 담을 수 있도록 하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 컴파일 타임에 체크( 잘못된 타입이 들어오는 것을 방지 )하고 런타임에 타입 안정성을 제공한다. 다양한 타입에 대해 동일한 로직을 구현할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 런타임에 타입 정보를 유지해서 박싱 없이 최적화된 코드를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; Object라는 코드를 공유하므로 메모리 사용이 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 메타 프로그래밍이 불가능하다 (단순 타입 안정성 보장 목적)&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 템플릿과 제네릭의 차이에 대해서 설명하세요&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿은 하나의 함수에 여러 타입들이 동일한 방식으로 같은 코드를 여러 번 치지 않고도 사용할 수 있도록 하는 것이다. 템플릿 특수화 같은 메타프로그래밍이 가능하며, 컴파일러가 &lt;b&gt;컴파일 타임에 그 타입에 맞는 코드를 생성&lt;/b&gt;해준다. 장점으로 템플릿은 프로그래머가 코드를 중복적으로 사용하지 않아도 되지만, 단점으로는 아무래도 컴파일러가 타입을 사용한 만큼 코드를 생성하는 방식이다보니 &lt;b&gt;코드 팽창&lt;/b&gt;이 일어날 수 있다.&lt;br /&gt;&lt;br /&gt;제네릭의 경우 C#, Java에서 사용되는 개념인데 하나의 상자에 다양한 물건을 안전하게 넣는 느낌이다. 컴파일 타임에 이 타입이 안전한지 체크하고, &lt;b&gt;런타임&lt;/b&gt;에 제공하는 방식으로 사용한다. 실제 내부에서는 Object 등으로 변환되어 &lt;b&gt;하나의 함수만 존재&lt;/b&gt;한다. 타입 소거를 통해 하나의 &lt;b&gt;공통된 코드를 공유&lt;/b&gt;하므로 메모리 측면에서 효율적이다. 템플릿과 달리 메타 프로그래밍이 불가하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 템플릿을 왜 헤더 파일에 작성해야 하는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿 정의와 선언이 동시에 필요하기 때문에 헤더 파일에 작성해야 합니다. 컴파일 타임에 인스턴스화 되므로 정의가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 템플릿 특수화란 무엇인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿 특수화란 일반 템플릿 처럼 모든 타입을 허용하는 것이 아니라, 특수한 타입에 대해서만 템플릿을 적용하는 것을 의미합니다. 특수화에는 모든 매개변수를 전부 구체적인 타입으로 제한하는 완전 특수화 방식과, 일부분만 제한하는 부분 특수화 방식이 존재합니다. 이를 통해서 해당 타입에 적합한 코드나 동작을 제공할 수 있습니다. 이를 통해 보다 최적화되고 안전한 동작을 보장하기 위해서 사용됩니다. 이를 통해 코드의 품질과 효율성을 높일 수 있다고 알고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 함수 템플릿과 클래스 템플릿의 차이점은 무엇인가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 템플릿은 여러 타입에 대해 동일한 동작 방식을 사용할 수 있도록 하는 역할을 합니다. 다양한 타입에 대해 중복 없이 정의해, 함수 호출 시에 컴파일러가 인자에 맞는 구체적인 함수를 인스턴스화 시줍니다. 함수 호출 시 컴파일러가 자동 추론하며, 부분 특수화는 지원하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 템플릿은 데이터를 저장하거나, 자료구조 및 클래스를 여러 타입에 맞게 재사용할 수 있는 클래스입니다. 특정 타입에 얽메이지 않고 작동하며 vector나 map 처럼 컨테이너 클래스를 구현할 때 사용됩니다. 템플릿 인자 추론을 지원해서 암시적 호출이 가능하고, 부분 특수화가 가능해 구체적인 구현이 가능합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;프랜드 클래스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;프랜드 클래스를 알기론 A 클래스와 B클래스가 서로 참조했을 때 함께 참조되어 꼬이는 문제가 발생하는 걸로 알고 있다. 이때 friend 를 사용하면 이런 클래스가 있다고 알려만 주고 자세한 세부사항까지 알지 않아도 되는 것으로 알고 꼬이지 않게 하는 방식으로 알고 있는데... 이건 전방선언이랑 순환참조 문제구나&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;프랜드란 &lt;b&gt;private, protected 로 보호된 멤버에 접근&lt;/b&gt;할 수 있도록 허용된 클래스 키워드로, 프랜드 클래스와 프랜드 함수로 일부 특정 부분을 프랜드 기능을 사용하거나 is-a도 has-a도 아닌 개별적인 객체에 대해서 조작할 수 있게끔한다.하지만 이런 프랜드 클래스의 경우 캡슐화 원칙을 희생하며 불가피하게 두 객체나 함수간의 결합도를 올리는 방식이기에 유의해서 사용해야 한다. 연산자 오버로딩이나, 내부 상태의 효율적인 테스트에서는 유용하게 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;프랜드 클래스란 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;- 프랜드 클래스란 &lt;b&gt;private, protected 멤버에도 접근이 가능하게 할 수 있도록 하는 클래스 키워드&lt;/b&gt;로, 프랜드 클래스를 사용하면 독립적인 객체에 대해서도 조작할 수 있게끔 한다는 특징이 있다. 이런 프랜드의 경우는 &lt;b&gt;캡슐화의 원칙을 희생&lt;/b&gt;해서 불가피하게 두 객체의&lt;b&gt; 결합도를 올리는 방식&lt;/b&gt;이기에 잘 사용하지 않는다. 하지만 디버깅을 하거나 연산자 오버로딩 등에 사용하면 유용하게 테스트가 가능하기 때문에 이런 경우에 유용하게 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;어째서 연산자 오버로딩이 프랜드 함수가 유용한가?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;- 연산자 오버로딩은 이항 연산자의 경우 좌변 및 우변에 대한 동등한 변환을 허용해야 하는 상황이 많습니다. 원래는 좌변 피 연산자에만 암묵적 형 변환을 적용하지만 프랜드 함수를 구현하면 두&lt;b&gt; 피연산자에 대해 동등한 암묵적 형 변환&lt;/b&gt;을 지원하며 클래스 내부 멤버에 접근이 가능하다는 장점이 존재합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;박싱/언박싱&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 박싱 : 값 타입을 참조 타입으로 변환하여 힙에 저장합니다&lt;span style=&quot;color: #7e98b1;&quot;&gt; int i =123; object&amp;nbsp; o = i;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 언박싱 : 박싱된 객체를 다시 값 타입으로 변환한다. 힙 메모리에 있는 객체에서 원래의 값을 꺼내 스택으로 복사한다. 박싱된 타입과 꺼내려는 타입이 정확히 일치해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 : 박싱이 일어날 때마다 힙 메모리에 새로운 객체가 생성되어 &lt;b&gt;메모리 사용량이 늘어난다.&lt;/b&gt; 또한&lt;b&gt; GC에 부담&lt;/b&gt;이 있다. 힙에 생성된 객체는 나중에 가비지 컬렉터가 치워야 하기 때문이다. 단순 값 복사보다 더 느린 작업에 될 수 있다. =&amp;gt; 비싼 작업&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제네릭 : 제네릭이 방식/언박싱을 방지하기 위해서이다. 제네릭 이전에는 모든 데이터를 object로 받아 int를 넣을 때마다 박싱이 일어나 힙에 메모리 사용량이 늘어났지만, 제네릭 이후 List&amp;lt;int&amp;gt;를 만들면 처음부터 int로 처리하므로 박싱이 일어나지 않는다. =&amp;gt; 값복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;박싱을 피하기 위해 타입 전용의 기계어 코드를 따로 생성한다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;&quot;&lt;/li&gt;
&lt;li&gt;&quot;C#의 **interface와 abstract class**를 실무에서 어떤 기준으로 나누어 사용하시나요?&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;인라인 함수란 무엇인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8cb3be;&quot;&gt;- 인라인 함수란 함수 호출에 대한 오버헤드를 줄이기 위해서 컴파일 타임에 함수 호출 부분에 직접 코드를 삽입하는 방식으로 처리하는 함수라고 알고 있음. 프로그래머가 inline 키워드를 붙여 사용하거나 컴파일러가 알아서 인라인화 시키는 두가지 방법이 있고, 이러한 인라인 함수는 함수 호출에 대한 오버헤드를 줄여줘서 짧으면서도 간결한 함수인데 자주 호출하는 함수에 대해서 유용하다고 알고 있음, 물론 재귀함수나 반복문이 존재하면 인라인 함수에는 적합하지 않고 보통 Getter Setter가 자주 인라인화되는 걸로 알고 있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;가비지 컬렉션이란?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;내가 알고 있는 바로 가비지 컬렉션은 힙에 할당된 사용되지 않는 메모리들을 자동으로 해제해주는 메모리 관리 시스템이라고 알고 있다. 마크 앤 쉽? 이런 방식으로 사용하는 걸로 알고 있는데 일단 C# JAVA에서 사용되고,,, 자동으로 관리하고 있기 때문에 프로그래머가 메모리 관리를 해주지 않아도 된다는 점이 장점이지만 반대로 가비지 컬렉션이 실행될 때마다 부하가 발생할 수 있는 단점이 발생할 수 있고, 때문에 직접적으로 관리하는 C++보다 성능이 안 좋을 수 있다. GC는 0,1, 2세대로 나눠 관리하는데 이거에 대해서는 좀더 자세히 공부해봐야 할 것 같고,,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;박싱, 언박싱이 이뤄지면 가비기 컬렉션이 좀더 많이 일하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 힙 메모리에 더이상 참조되지 않는 객체를 찾아내어 자동으로 메모리에서 해제하는 프로세스. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 유니티에서 사용되는 작동 원리는 &lt;b&gt;Mark &amp;amp; Sweep&lt;/b&gt;이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Mark표시로 Root 객체로부터 연결된 모든 객체를 추적하여 &lt;b&gt;사용 중임을 표시&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Sweep : 표시되지 않은 객체는 &lt;b&gt;메모리에서 삭제&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&amp;gt; 최신 유니티 버전은 Incremental GC를 지원해서 한 번에 모든 가비지를 치우지 않고 여러 프레임에 걸쳐 조금씩 나눠 처리하여 게임이 멈추는 현상을 최소화 하는 것으로 최소화 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가비지 컬렉션은 성능에 영향을 준다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 어떤 메모리가 필요 없는지 검사하는 동안 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;CPU 부하가 발생하여&lt;/span&gt;&amp;nbsp; 게임의 메인 로직이 잠시 멈춘다&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 메모리를 지우고 난 후 메모리 사이가 듬성 듬성해져, 큰 객체를 할당하려 할 때 공간은 춫ㅇ분해도 연속된 공간이 없어 메모리 부족 현상이 발생해 추가적인 힙 확장이 일어난다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GC를 유발하는 상황들&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. string을 새로운 메모리 공간이 할당된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 업데이트 함수 안에 new를 할당하는 경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Boxing이 일어나는 경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. LINQ를 사용하는 경우 편리하지만 내부적으로 많은 임시 객체를 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;최적화 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 문자열을 자주 변경하는 경우에는 stringBuilder를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 자주 생성 및 해제하는 객체의 경우 오브젝트 풀을 활용하여 재사용 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 데이터 뭉치가 작고 빈번하게 사용된다면 힙이 아닌 스택에 저장되는 struct를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; C#의 GC에서 세대별 관리(0, 1, 2세대)는 어떤 원리인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0세대 : GC를 한 번도 겪지 않는 갓 생성된 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1세대 : GC를 1회 겪은 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2세대 : GC를 2회 이상 겪은 객체 (전체를 의미)&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Awake() Start() 차이점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Awake() : 의 경우는 프리팹을 통해서 객체가 인스턴스화 된 직후에 한 번 호출되는 곳이라고 알고 있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Start() : 의 경우 첫 프레임이 시작되기 전에 한 번 호출되는 것으로 알고 있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;GameObject 와 Component와 Prefab의 차이&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GameObject : 아무 것도 없는 빈 그릇이라고 설명할 수 있을 것 같다. Transform은 존재하지만 Component가 없이 외형이나 물리를 가질 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component : GameObject에 붙일 수 있는 그릇이다. 여기에 Mesh Renderer나 Rigidbody등을 붙일 수 있따.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 이 둘은 Componsition 관계(합성 관계)라고 볼 수 있다. GameObject는 혼자 사용할 수 있지만 Component 없이 씬에 표현할 수 없고 Compoennt는 GameObject 없이 단독으로 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prefab : GameObject와 Componet의 집합인다 설정을 조율한 데이터 파일이라고 할 수 있을 것 같다. Prefab을 씬에 배치하면 이 Prefab을 토대로 한 Instance가 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;UGUI 를 최적화 하는 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UGUI의 가장 큰 특징은 레이아웃을 변경할 때마다 리빌드된다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리빌드 또한 일어나는 비용 요소 중 하나이기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 변하지 않는 것과 변하는 것을 구분해서 캔버스를 구분하게 되면 변하지 않는 것들까지 리빌드되는 것을 방지할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 마우스에 영향이 가지 않는 것은 RayCast Target이라는 옵션을 끔으로서 리빌드 시 발생하는 비용을 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 코드를 작성할 때 SetActive()를 사용하면 리빌드가 발생하기 때문에 Alpha 값을 조정하거나, Canvas를 Disable 하는 방식을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;리플렉션&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실행 중인 프로그램이 자기 자신의 구조를 들여다보고 수정할 수 있는 기능, 프로그램이 자신의 정보를 스스로 파헤쳐보는 기술&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일반적으로 코드는 컴파일 시점에 타입이 결정되지만, 리플렉션을 사용하면 런타임에 다음을 수행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 객체의 정확한 타입 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 클래스 내부의 필드, 속성, 메서드 목록 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 이름만으로 특정 메서드를 호출하거나 필드 값 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. prviate 선언된 접근 제한 멤버에도 접근 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 사용할까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 스크립트를 짜면 유니티 에디터가 변수 이름을 읽어와 화면에 보여주는 원리가 리플렉션이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 직렬화 : 객체의 데이터를 JSON이나 XML로 변환할 때, 어떤 필드가 있는지 자동으로 찾아낼 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 플러그인/모듈 시스템 : 컴파일 시점에는 알 수 없었던 외부 DLL 파일의 클래스를 로드하여 실행할 때 필수적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리플렉션은 강력하지만 굉장히 비싼 기술이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일 최적화를 거치지 않고 런타임에 일일이 이름을 대조하며 찾기에 성능 오버헤드가 일어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 이름을 문자열로 찾다가 오타가 나면 런타임에 앱에 튕기게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;UGUI 와 UI ToolKit의 차이&lt;/h4&gt;</description>
      <category>이론/C++ 이론</category>
      <category>=</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/39</guid>
      <comments>https://zoehw10101.tistory.com/39#entry39comment</comments>
      <pubDate>Wed, 17 Dec 2025 05:01:48 +0900</pubDate>
    </item>
    <item>
      <title>2025-12-17</title>
      <link>https://zoehw10101.tistory.com/38</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;포트폴리오도 전부 작성하고, 영상 편집도 끝났고 (담당 영상은 따로 찍을 지 고민 중)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 코드를 살펴볼 차례다. 면접 때 어떤 질문이 들어올 지 감은 안 잡히지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재미나이가 꽤 면접 질문을 잘 짚어주는 것 같다. 그래서 재미나이 구독하고 열심히 물어볼 예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(밀리의 서재 구독했는데 하루에 10장 볼까말까다. 볼 시간이 없다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 이슈는...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 오빠가 경찰 공무원 시험에 합격해서 엄마가 완전 행복해보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나더러 취업 천천히 하라고 하는 거 보니까 이제 여유가 느껴지는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오빠도 이번 포폴 잘했다고 용돈을 쥐여줬든데 좋긴 하지만 묘하게 기분이 털 뽑다가 끊긴 느낌이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(기분이 안 좋을 건 아닌데 좋지도 안 좋지도 않고 애매한 그 이상한 느낌)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나도 취업하고 돈 모아서 하고 싶은 걸 하고 싶다는 생각이 든다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나야 술 좋아하니까 술집을 차리고 싶기도 하고, 그냥 돈 차곡차곡 모으고 싶은 느낌도 들고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 끝나니까 굉장히 뿌듯해서 계속 코딩하고 싶다는 생각도 들기도 하고...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 당장 열심히 하면 뭐든 되겠지 뭐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 ㅠ 취업 먼저...&lt;/p&gt;</description>
      <category>일기</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/38</guid>
      <comments>https://zoehw10101.tistory.com/38#entry38comment</comments>
      <pubDate>Wed, 17 Dec 2025 03:07:17 +0900</pubDate>
    </item>
    <item>
      <title>[Unity 포트폴리오] 이터널리턴 코발트 프로토콜 모작 완성!</title>
      <link>https://zoehw10101.tistory.com/37</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/459925649&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bOjjdL/hyZPbao2r1/h6JRM8mH4hNqavTSXPjhNK/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/d4wagD/hyZPntx6rX/t5sCiXuWWk236GbaMxGj30/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;'개발 연대기'에서 업로드한 동영상&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/459925649?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=X-dOCzEdTfs&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=X-dOCzEdTfs&lt;/a&gt;&lt;/p&gt;</description>
      <category>이론/엔진</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/37</guid>
      <comments>https://zoehw10101.tistory.com/37#entry37comment</comments>
      <pubDate>Sun, 14 Dec 2025 19:42:33 +0900</pubDate>
    </item>
    <item>
      <title>[Unity 오류] InvalidOperationException: Collection was modifie / 반복자 오류</title>
      <link>https://zoehw10101.tistory.com/36</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQb0LY/dJMcafykl9Q/tWfl4KrA5RHhyyWWeJaKg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQb0LY/dJMcafykl9Q/tWfl4KrA5RHhyyWWeJaKg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQb0LY/dJMcafykl9Q/tWfl4KrA5RHhyyWWeJaKg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQb0LY%2FdJMcafykl9Q%2FtWfl4KrA5RHhyyWWeJaKg0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1093&quot; height=&quot;136&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기존 오류 코드&lt;/h4&gt;
&lt;pre id=&quot;code_1765001399756&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;   private void CheckBushStatus()
   {
       Vector3 center = transform.TransformPoint(_bushCollider.center);
       Vector3 halfExtents = _bushCollider.size / 2f;
       Quaternion rotation = transform.rotation;
       Collider[] hitColliders = Physics.OverlapBox(center, halfExtents, rotation);

       List&amp;lt;int&amp;gt; currentInsidePlayersId = new List&amp;lt;int&amp;gt;();
       foreach (Collider hitCollider in hitColliders)
       {
           PlayerController pc = hitCollider.gameObject.GetComponent&amp;lt;PlayerController&amp;gt;();
           if (pc != null)
           {
               currentInsidePlayersId.Add(pc.Id);
           }
       }

       foreach (int oldId in _insidePlayersId)
       {
           if (!currentInsidePlayersId.Contains(oldId))
           {
               GameObject exGo = Managers.Object.FindById(oldId);
               if (exGo != null &amp;amp;&amp;amp; exGo.TryGetComponent&amp;lt;PlayerController&amp;gt;(out PlayerController exPc))
                   BushExitRender(exPc);
           }
       }
   }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜라이더 내부에 있는 객체 목록을 통해서 Bush를 구현했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 OnTriggerExit, OnTriggerEnter를 사용해도 되지만, 점멸을 사용할 때 OnTriggerExit가 호출이 되지 않아서 투명화가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속 지속되는 문제를 경험했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 FixedUpdate 문에서 계속해서 확인하고 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; InvalidOperationException: Collection was modifie 오류가 발생했다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;foreach 루프를 순회하는 도중에 발생한 것인데, 추측 상으로 C++을 공부했을 때 순회하는 도중 List가 변경된다면 반복자는 변경되지 않기 때문에 문제가 발생한다고 공부했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서는 반복자(Eumerator)라는 객체를 사용하는데, 이는 순회가 완료될 때까지 절대 변경되어서는 안 된다는 것을 전제로 한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 도중에 수정/제거를 하게 되면 컬렉션의 상태가 불안정하고 판단하고 즉시 오류를 발생시켜 프로그램을 충돌을 막는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;해결책&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;foreach문을 사용하는 것이 아닌 for 루프로 변경해야 한다. 특히 제거 작업이 수반될 때는 역방향 for루프가 가장 안전하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 요소를 제거했을 때 발생하는 인덱스 변화가 아직 처리하지 않은 요소에 영향을 주지 않기 때문에 &quot;인덱스 안전성&quot; 을 확보할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1765001966469&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  private void CheckBushStatus()
  {
      Vector3 center = transform.TransformPoint(_bushCollider.center);
      Vector3 halfExtents = _bushCollider.size / 2f;
      Quaternion rotation = transform.rotation;
      Collider[] hitColliders = Physics.OverlapBox(center, halfExtents, rotation);

      List&amp;lt;int&amp;gt; currentInsidePlayersId = new List&amp;lt;int&amp;gt;();
      foreach (Collider hitCollider in hitColliders)
      {
          if (hitCollider.TryGetComponent&amp;lt;PlayerController&amp;gt;(out PlayerController pc))
              currentInsidePlayersId.Add(pc.Id);
      }

      List&amp;lt;int&amp;gt; currentInsidePlayersId = new List&amp;lt;int&amp;gt;();
      for (int i = _insidePlayersId.Count - 1; i &amp;gt;= 0; i--) 
      {
          int oldId = _insidePlayersId[i]; 

          if (!currentInsidePlayersId.Contains(oldId))
          {
              GameObject exGo = Managers.Object.FindById(oldId);
              if (exGo != null &amp;amp;&amp;amp; exGo.TryGetComponent&amp;lt;PlayerController&amp;gt;(out PlayerController exPc))
              {
                  BushExitRender(exPc);
              }
          }
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안에 있는 객체를 확인한 후, 안전하게 역방향 반복문을 활용해 로직을 안전하게 처리한다.&lt;/p&gt;</description>
      <category>이론/엔진</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/36</guid>
      <comments>https://zoehw10101.tistory.com/36#entry36comment</comments>
      <pubDate>Sat, 6 Dec 2025 15:22:08 +0900</pubDate>
    </item>
    <item>
      <title>[Unity] Line Shader 관련</title>
      <link>https://zoehw10101.tistory.com/35</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;Shader&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Outline 필요함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 플레이어를 마우스로 가리킬 때 빨간색 Outline이 생겨야 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 맵에 가려질 때 플레이어가 파란색으로 투영되어야 함. (X-Ray Shader)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;X-Ray Shader&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AdaUQ/dJMcabbx1nB/MDOZ6tZKwUtGoFbyybctW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AdaUQ/dJMcabbx1nB/MDOZ6tZKwUtGoFbyybctW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AdaUQ/dJMcabbx1nB/MDOZ6tZKwUtGoFbyybctW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAdaUQ%2FdJMcabbx1nB%2FMDOZ6tZKwUtGoFbyybctW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;471&quot; height=&quot;357&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1763889040720&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	SubShader {
		Tags { &quot;RenderType&quot;=&quot;Opaque&quot; &quot;Queue&quot;=&quot;Geometry&quot; &quot;RenderPipeline&quot;=&quot;UniversalPipeline&quot; }
		LOD 200

		// Pass 1: 가려진 부분
		Pass {
			Name &quot;OccludedPass&quot;
			Tags { &quot;LightMode&quot; = &quot;SRPDefaultUnlit&quot; }
			
			ZWrite Off
			ZTest Greater
			Blend SrcAlpha OneMinusSrcAlpha
			Cull Back
			
			Stencil {
				Ref [_StencilRef]
				Comp NotEqual  
				Pass Keep 
				ReadMask [_StencilReadMask]
			}
			
			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include &quot;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl&quot;

			struct Attributes {
				float4 positionOS : POSITION;
			};

			struct Varyings {
				float4 positionCS : SV_POSITION;
			};

			CBUFFER_START(UnityPerMaterial)
				half4 _OccludedColor;
			CBUFFER_END

			Varyings vert(Attributes input) {
				Varyings output;
				output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
				return output;
			}

			half4 frag(Varyings input) : SV_Target {
				return _OccludedColor;
			}
			ENDHLSL
		}

		// Pass 2: 보이는 부분
		Pass {
			Name &quot;ForwardLit&quot;
			Tags { &quot;LightMode&quot; = &quot;UniversalForward&quot; }
			
			ZWrite On
			ZTest LEqual
			Cull Back
			
			Stencil {
				Ref [_StencilRef]
				Comp [_StencilComp]
				Pass [_StencilOp]
				ReadMask [_StencilReadMask]
				WriteMask [_StencilWriteMask]
			}
			
			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include &quot;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl&quot;
			#include &quot;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl&quot;

			struct Attributes {
				float4 positionOS : POSITION;
				float3 normalOS : NORMAL;
				float2 uv : TEXCOORD0;
			};

			struct Varyings {
				float2 uv : TEXCOORD0;
				float3 normalWS : TEXCOORD1;
				float3 positionWS : TEXCOORD2;
				float4 positionCS : SV_POSITION;
			};

			TEXTURE2D(_MainTex);
			SAMPLER(sampler_MainTex);
			TEXTURE2D(_1st_ShadeMap);
			SAMPLER(sampler_1st_ShadeMap);
			TEXTURE2D(_Emissive_Tex);
			SAMPLER(sampler_Emissive_Tex);

			CBUFFER_START(UnityPerMaterial)
				float4 _MainTex_ST;
				half4 _BaseColor;
				half4 _1st_ShadeColor;
				half4 _2nd_ShadeColor;
				half4 _Emissive_Color;
				half4 _OverColor;
				half _AddValOffset;
				half _CurrPos;
				half _BaseColor_Step;
				half _BaseShade_Feather;
				half _ShadeColor_Step;
				half _1st2nd_Shades_Feather;
				half _Use_BaseAs1st;
				half _Unlit_Intensity;
				half _GI_Intensity;
			CBUFFER_END

			Varyings vert(Attributes input) {
				Varyings output;
				
				VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
				VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS);
				
				output.positionCS = vertexInput.positionCS;
				output.positionWS = vertexInput.positionWS;
				output.normalWS = normalInput.normalWS;
				output.uv = TRANSFORM_TEX(input.uv, _MainTex);
				
				return output;
			}

			half4 frag(Varyings input) : SV_Target {
				half4 baseColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * _BaseColor;
				
				Light mainLight = GetMainLight();
				half3 normalWS = normalize(input.normalWS);
				half NdotL = dot(normalWS, mainLight.direction);
				
				// 툰 셰이딩 
				half lightIntensity = NdotL * 0.5 + 0.5;
				half toonStep = step(_BaseColor_Step, lightIntensity);
				
				if (_BaseShade_Feather &amp;gt; 0.0001)
				{
					toonStep = smoothstep(_BaseColor_Step - _BaseShade_Feather * 0.5, 
					                      _BaseColor_Step + _BaseShade_Feather * 0.5, 
					                      lightIntensity);
				}
				
				half4 shadeMap = _Use_BaseAs1st &amp;gt; 0.5 ? baseColor : SAMPLE_TEXTURE2D(_1st_ShadeMap, sampler_1st_ShadeMap, input.uv);
				half4 firstShade = shadeMap * _1st_ShadeColor;
				
				half shade2Step = step(_ShadeColor_Step, lightIntensity);
				if (_1st2nd_Shades_Feather &amp;gt; 0.0001)
				{
					shade2Step = smoothstep(_ShadeColor_Step - _1st2nd_Shades_Feather * 0.5, 
					                        _ShadeColor_Step + _1st2nd_Shades_Feather * 0.5, 
					                        lightIntensity);
				}
				half4 secondShade = shadeMap * _2nd_ShadeColor;
				
				// 셰이드 믹스
				half4 shadedColor = lerp(secondShade, firstShade, shade2Step);
				half4 finalColor = lerp(shadedColor, baseColor, toonStep);
				
				// 조명 적용
				finalColor.rgb *= _Unlit_Intensity;
				
				half3 ambient = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w) * _GI_Intensity * 0.3;
				finalColor.rgb += ambient * baseColor.rgb;
				
				// Emissive
				half4 emissive = SAMPLE_TEXTURE2D(_Emissive_Tex, sampler_Emissive_Tex, input.uv) * _Emissive_Color;
				finalColor.rgb += emissive.rgb;
				
				// Overlay Color
				half maskValue = saturate((_CurrPos - _AddValOffset) * 10.0);
				finalColor.rgb = lerp(finalColor.rgb, _OverColor.rgb, _OverColor.a * maskValue);
				
				return finalColor;
			}
			ENDHLSL
		}
	}
	Fallback &quot;Hidden/Universal Render Pipeline/FallbackError&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제점 1&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PmkVB/dJMcahpi23T/KtMf7FKbHAWr532HbxviX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PmkVB/dJMcahpi23T/KtMf7FKbHAWr532HbxviX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PmkVB/dJMcahpi23T/KtMf7FKbHAWr532HbxviX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPmkVB%2FdJMcahpi23T%2FKtMf7FKbHAWr532HbxviX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;353&quot; height=&quot;436&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 맵이나 특정 오브젝트에 대해서만 X-Ray가 적용되어야 하는데 무기에 가려져 함께 X-Ray 영향을 받아버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 스탠실 버퍼를 배운 적이 있는데, x-ray에 영향을 받지 않는 플레이어, 무기의 경우 오브젝트에 대해서 스탠실 번호를 100으로 지정한 후 제외하고자 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1763890161053&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt; [Header(&quot;X-Ray Settings&quot;)]
 [SerializeField] private int xRayIgnoreStencilID = 100;
 
 #region Shader
 void InitializeXRay()
 {
     SetupPlayerWeaponXRay();
 }

 void SetupPlayerWeaponXRay()
 {
     SetXRayGroup(gameObject, xRayIgnoreStencilID);

     if (_eqipWeapon != null)
         SetXRayGroup(_eqipWeapon, xRayIgnoreStencilID);
 }
 public void SetxRayFromPlayer(GameObject player)
 {
      SetXRayGroup(player, xRayIgnoreStencilID);
 }
 void SetXRayGroup(GameObject root, int stencilID)
 {
     Renderer[] renderers = root.GetComponentsInChildren&amp;lt;Renderer&amp;gt;(true);

     foreach (Renderer renderer in renderers)
     {
         foreach (Material mat in renderer.materials)
         {
             if (mat.shader.name.Contains(&quot;Toon_DoubleShadeWithFeather&quot;))
             {
                 if (mat.HasProperty(&quot;_StencilRef&quot;))
                 {
                     mat.SetInt(&quot;_StencilRef&quot;, stencilID);
                     mat.SetInt(&quot;_StencilComp&quot;, (int)UnityEngine.Rendering.CompareFunction.Always);
                     mat.SetInt(&quot;_StencilOp&quot;, (int)UnityEngine.Rendering.StencilOp.Replace);
                 }
             }
         }
     }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제점 2&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bz3L0V/dJMcagw9L6V/BPe03PIi4tdM6pJCZMrwk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bz3L0V/dJMcagw9L6V/BPe03PIi4tdM6pJCZMrwk1/img.png&quot; width=&quot;620&quot; height=&quot;662&quot; data-widthpercent=&quot;72.54&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;1477&quot; data-origin-width=&quot;1384&quot; style=&quot;width: 71.6984%; margin-right: 10px;&quot; id=&quot;kEditorPhotosEditingImage-2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bz3L0V/dJMcagw9L6V/BPe03PIi4tdM6pJCZMrwk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz3L0V%2FdJMcagw9L6V%2FBPe03PIi4tdM6pJCZMrwk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;1477&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d380U7/dJMcadUGzhB/pYL5Tn71K6yrBEZVuInSVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d380U7/dJMcadUGzhB/pYL5Tn71K6yrBEZVuInSVk/img.png&quot; data-origin-width=&quot;144&quot; data-origin-height=&quot;406&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;27.46&quot; data-filename=&quot;blob&quot; style=&quot;width: 27.1388%;&quot; id=&quot;kEditorPhotosEditingImage-3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d380U7/dJMcadUGzhB/pYL5Tn71K6yrBEZVuInSVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd380U7%2FdJMcadUGzhB%2FpYL5Tn71K6yrBEZVuInSVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;144&quot; height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기본 Scene에서는 X-Ray의 영향을 안 받는데, 다른 Scene에서는 Black Outline이 X-Ray의 영향을 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 살펴보니까 모델 내에 Black Outline만 영향을 받는듯 하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 그래서 Black Outline Shader 내에서 스탠실 버퍼를 지정해줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1763889048218&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Shader &quot;Custom/Outliner&quot;
{
    Properties
    {
        _Color (&quot;Outline Color&quot;, Color) = (1,0,0,1)
        _Width (&quot;Outline Width&quot;, Range(0.0, 0.1)) = 0.03
        
        [Header(Stencil)]
        _StencilRef (&quot;Stencil Reference&quot;, Float) = 0
        [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp (&quot;Stencil Comparison&quot;, Float) = 8
    }
    SubShader
    {
        Tags { &quot;RenderType&quot;=&quot;Opaque&quot; &quot;Queue&quot;=&quot;Geometry+1&quot; &quot;RenderPipeline&quot;=&quot;UniversalPipeline&quot; }
        
        Pass
        {
            Name &quot;Outline&quot;
            Tags { &quot;LightMode&quot; = &quot;SRPDefaultUnlit&quot; }
            
            Cull Front
            ZWrite On
            ZTest LEqual
            
            Stencil
            {
                Ref [_StencilRef]
                Comp [_StencilComp]
                Pass Keep
            }
            
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include &quot;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl&quot;
            
            half4 _Color;
            float _Width;
            
            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
            };
            
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
            };
            
            Varyings vert(Attributes input)
            {
                Varyings output;
                float3 normalOS = normalize(input.normalOS);
                float3 expandedPos = input.positionOS.xyz + normalOS * _Width;
                output.positionCS = TransformObjectToHClip(expandedPos);
                return output;
            }
            
            half4 frag(Varyings input) : SV_Target
            {
                return _Color;
            }
            ENDHLSL
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #c0d1e7; color: #000000; text-align: left;&quot;&gt; Comp = Always: XRay와 관계없이 항상 표시 &lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결과물&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T1i7G/dJMcaiaFR22/FxkuANOu2VQELp9h92lb6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T1i7G/dJMcaiaFR22/FxkuANOu2VQELp9h92lb6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T1i7G/dJMcaiaFR22/FxkuANOu2VQELp9h92lb6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT1i7G%2FdJMcaiaFR22%2FFxkuANOu2VQELp9h92lb6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;741&quot; height=&quot;354&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2023&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIIzHv/dJMcac2ygvJ/trWklUbkuQrCMdDmS09fUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIIzHv/dJMcac2ygvJ/trWklUbkuQrCMdDmS09fUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIIzHv/dJMcac2ygvJ/trWklUbkuQrCMdDmS09fUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIIzHv%2FdJMcac2ygvJ%2FtrWklUbkuQrCMdDmS09fUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;317&quot; data-origin-width=&quot;2023&quot; data-origin-height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;✅상대 씬에서도 X-Ray가 잘 구성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;✅Black Outline에 영향을 받지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;✅X-Ray 영향 받지 않는 오브젝트는 스탠실로 구분했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+추가&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfP5XH/dJMcadtCJeb/CVxDOqjUyBAsSubek5wEK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfP5XH/dJMcadtCJeb/CVxDOqjUyBAsSubek5wEK1/img.png&quot; data-origin-width=&quot;895&quot; data-origin-height=&quot;826&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.7507%; margin-right: 10px;&quot; data-widthpercent=&quot;46.29&quot; id=&quot;kEditorPhotosEditingImage-6&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfP5XH/dJMcadtCJeb/CVxDOqjUyBAsSubek5wEK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfP5XH%2FdJMcadtCJeb%2FCVxDOqjUyBAsSubek5wEK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;895&quot; height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1m523/dJMcahW8Vwz/Qfsgj62RPeKZsIc9lO0rJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1m523/dJMcahW8Vwz/Qfsgj62RPeKZsIc9lO0rJK/img.png&quot; data-origin-width=&quot;562&quot; data-origin-height=&quot;447&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;53.71&quot; style=&quot;width: 53.0865%;&quot; id=&quot;kEditorPhotosEditingImage-7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1m523/dJMcahW8Vwz/Qfsgj62RPeKZsIc9lO0rJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1m523%2FdJMcahW8Vwz%2FQfsgj62RPeKZsIc9lO0rJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;562&quot; height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Before &amp;gt; After&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 겸사 겸사 Smooth/Emissive를 Shader에 추가해 조금 더 예쁘게 만들어 주었음.&lt;/p&gt;</description>
      <category>이론/엔진</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/35</guid>
      <comments>https://zoehw10101.tistory.com/35#entry35comment</comments>
      <pubDate>Sun, 23 Nov 2025 18:41:46 +0900</pubDate>
    </item>
    <item>
      <title>[VR 게임] Beat Saber 후기</title>
      <link>https://zoehw10101.tistory.com/34</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;583&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Kwdx/dJMcafyeqGj/n4gTVRwU4qMXJbK2GqLprK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Kwdx/dJMcafyeqGj/n4gTVRwU4qMXJbK2GqLprK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Kwdx/dJMcafyeqGj/n4gTVRwU4qMXJbK2GqLprK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Kwdx%2FdJMcafyeqGj%2Fn4gTVRwU4qMXJbK2GqLprK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1470&quot; height=&quot;583&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;583&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 가장 좋아하는 VR 게임인 Beat Saber.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근 일주일간 저녁에 하루 2시간씩 Beat Saber를 하기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전혀 멀미가 나지 않으면서도 동적이라 굉장히 즐겨하는 편이 되어버렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 꽤 하드 모드 정도는 깰 수 있는 실력이 되었는데, 그럼에도 아직은 좀 벅찬 난이도를 가진 레벨이 존재하긴 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어려운 부분은 땀이 흐를 정도로 벅찬 게 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;운동도 되고&lt;span&gt; 깼을 때 만족감이 꽤 크다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 아무래도 무료를 전부 깨고 유료를 사자! 라고 생각했던 터라 물론 아직 유료 레벨을 구매하지 않았다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;같은 노래를 여러 번 깨고 있는데 지루하긴 한 것 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;단점이라고 생각되는 부분은 VR 기기 상 렉으로 가끔 버벅일 때가 있는데, 특히 비트 세이버를 할 때 버벅인다면 화가 좀 나는 편이긴 하다. 그리고 원룸에서는 벽에 좀 기기를 부딪히게 된다는 정도?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VR 게임으로서는 왜 가장 인기가 많은 지 알 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 하기 쉽고, VR의 장점 중 하나인 동적인 동작을 살릴 수 있으면서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어려운 게임을 깨는 내가 점점 멋있어 보인다는 점이 킥인 듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨리 무료 하드 모드를 전부 깨고 유료 패키지랑 휘두를 수 있는 봉까지 사서 익스트림 모드까지 깨는 고수가 되고 싶다^^&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일기</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/34</guid>
      <comments>https://zoehw10101.tistory.com/34#entry34comment</comments>
      <pubDate>Thu, 20 Nov 2025 10:46:44 +0900</pubDate>
    </item>
    <item>
      <title>2025-11-20</title>
      <link>https://zoehw10101.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;코딩할 때 제일 고민되는 것 중 하나가 영역 싸움이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 어떤 의미로 만든 구조체, 클래스인지 모르니까 의미만 비슷했을 때 쓰게 되면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 그 의미가 아니게 되었을 때 조금 당황스럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의미가 맞았을 때 함께 사용하는 게 코드를 줄이는데 좋을 것이라고 생각하는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 사용했다가 봉변당하면 분리해야 하는 변수가 생겨 버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물어보는 게 가장 베스트긴 한데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물어보는 것도 잘 못하거니와, 사소한 걸 너무 많이 물어보게 되면 좀 미안한 느낌이 든다.&lt;/p&gt;</description>
      <category>일기</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/33</guid>
      <comments>https://zoehw10101.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 20 Nov 2025 10:36:31 +0900</pubDate>
    </item>
    <item>
      <title>[VR 게임] no man's sky 후기</title>
      <link>https://zoehw10101.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xsmWy/dJMcaiayCNL/onSGd6FvTyj7reeSkAYa0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xsmWy/dJMcaiayCNL/onSGd6FvTyj7reeSkAYa0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xsmWy/dJMcaiayCNL/onSGd6FvTyj7reeSkAYa0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxsmWy%2FdJMcaiayCNL%2FonSGd6FvTyj7reeSkAYa0k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;270&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;no mans sky 유명한 VR 게임이라고 해서 해보았다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아쉽게도 멀미가 많은 나로서는 멀미가 굉장히 심해서 30분 정도 하고 쉬고, 30분 하고 쉬고...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;근데 게임은 되게 재미있고 몰입감도 괜찮아서 끊기지 않고 오래토록 하고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특히 재미있었던 건 날아다닐 수 있는 부스터같은 게 있었는데 그걸 탈 때마다 진짜 나는 느낌이 실감났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그리고 총 뽑는 것도 등에 총이 있는 것 처럼 꺼낼 수 있는데 그 부분도 마음에 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그래픽 좋은 게임으로 유명하길래 VR에서 구경했던 영상만큼 그래픽이 좋겠지 싶었는데, 사실 기대 이상이진 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;물론 VR이 오큘러스 2라서 엄청 좋을 수는 없겠지만, 충분히 몰입감을 줄 만한 그래픽에 만족했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이것저것 만져볼 만한 것들이 많아서 원숭이처럼 만져보고 부숴보고.. 비트 세이버 다음으로 접한 2번째 게임이라&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런지 처음 세상을 접한 아기마냥 잔뜩 구경했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;UI가 많고 처음에 뭘 해야할 지 제대로 설명해주지 않아서 익숙해지는 데 시간이 걸렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아직 메인 스토리의 중심으로 들어가보진 않았지만 초반에 난해한 만큼 즐길 요소가 굉장히 많아보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;쉴 시간이 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;쭉&lt;/span&gt;&amp;nbsp;생긴다면 이어서 해보고 싶다.&lt;/p&gt;</description>
      <category>일기</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/32</guid>
      <comments>https://zoehw10101.tistory.com/32#entry32comment</comments>
      <pubDate>Tue, 4 Nov 2025 21:23:29 +0900</pubDate>
    </item>
    <item>
      <title>[Undead Survivor] 창작 게임 소개</title>
      <link>https://zoehw10101.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 만들기 전 남자친구가 카피바라GO 라는 게임에 빠져 매일 하는 걸 보고 비슷하게 모작하고 싶다는 생각이 들었다. 그렇게 만들 게 된 게 이 포트폴리오&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 어떤 Asset을 사용할까 고민하다 골드메탈 님의 Asset을 발견하곤 조금 짬뽕시켰다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기획에는 약한지 조금 어떻게 만들어야 할 지 고민하고 손을 놓을까 하다가 기본 기능 구현까지만 목표로 하기로 하고 개발했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;게임 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 기간 : 2주(6월)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모바일 로그라이크 게임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주 구현 : UI 로직, Folder 기능, 데이터 관리 등..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcR3ho/dJMcabbo6qK/sqpOgKHYosK0Ah82kq3H31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcR3ho/dJMcabbo6qK/sqpOgKHYosK0Ah82kq3H31/img.png&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;817&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6847%; margin-right: 10px;&quot; data-widthpercent=&quot;33.46&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcR3ho/dJMcabbo6qK/sqpOgKHYosK0Ah82kq3H31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcR3ho%2FdJMcabbo6qK%2FsqpOgKHYosK0Ah82kq3H31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;459&quot; height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3OJzK/dJMcafkzt5Q/KQVlpN0QblttFzQnuuKQK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3OJzK/dJMcafkzt5Q/KQVlpN0QblttFzQnuuKQK0/img.png&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;823&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.305%; margin-right: 10px;&quot; data-widthpercent=&quot;33.07&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3OJzK/dJMcafkzt5Q/KQVlpN0QblttFzQnuuKQK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3OJzK%2FdJMcafkzt5Q%2FKQVlpN0QblttFzQnuuKQK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;457&quot; height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSEziC/dJMcacBnKHx/JhQhOB4K12QvSVYVs1fZE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSEziC/dJMcacBnKHx/JhQhOB4K12QvSVYVs1fZE1/img.png&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;817&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6847%;&quot; data-widthpercent=&quot;33.47&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSEziC/dJMcacBnKHx/JhQhOB4K12QvSVYVs1fZE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSEziC%2FdJMcacBnKHx%2FJhQhOB4K12QvSVYVs1fZE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;459&quot; height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 공격 패턴 : 플레이어 vs 몬스터&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYCvW/dJMcaiBBdfz/q7AK71bFEHPYtWyJYKBkQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYCvW/dJMcaiBBdfz/q7AK71bFEHPYtWyJYKBkQ0/img.png&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;415&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.6387%; margin-right: 10px;&quot; data-widthpercent=&quot;50.22&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYCvW/dJMcaiBBdfz/q7AK71bFEHPYtWyJYKBkQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYCvW%2FdJMcaiBBdfz%2Fq7AK71bFEHPYtWyJYKBkQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcrvYh/dJMcaiawQ05/gCbnVmu7FRCoiQjwKhEuPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcrvYh/dJMcaiawQ05/gCbnVmu7FRCoiQjwKhEuPK/img.png&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;415&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1985%;&quot; data-widthpercent=&quot;49.78&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcrvYh/dJMcaiawQ05/gCbnVmu7FRCoiQjwKhEuPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcrvYh%2FdJMcaiawQ05%2FgCbnVmu7FRCoiQjwKhEuPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;447&quot; height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 플레이어와 몬스터는 번갈아가며 상대에게 공격을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공격 시 타겟의 색상을 빨간색으로 변경했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwAk9Q/dJMcajtJV16/4k0ZqcjqgAC3DIzDsLUF7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwAk9Q/dJMcajtJV16/4k0ZqcjqgAC3DIzDsLUF7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwAk9Q/dJMcajtJV16/4k0ZqcjqgAC3DIzDsLUF7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwAk9Q%2FdJMcajtJV16%2F4k0ZqcjqgAC3DIzDsLUF7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;393&quot; height=&quot;356&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 플레이어가 공격할 수 있는 무기는 5가지이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuvfyX/dJMcabJe42b/6hMpDTTxJKPldg9d5NKM2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuvfyX/dJMcabJe42b/6hMpDTTxJKPldg9d5NKM2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuvfyX/dJMcabJe42b/6hMpDTTxJKPldg9d5NKM2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuvfyX%2FdJMcabJe42b%2F6hMpDTTxJKPldg9d5NKM2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;447&quot; height=&quot;145&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.- 무기가 총으로 바뀔 때부터는 움직이지 않고 Bullet을 쏜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>이론/프로젝트 분석</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/31</guid>
      <comments>https://zoehw10101.tistory.com/31#entry31comment</comments>
      <pubDate>Tue, 4 Nov 2025 21:07:57 +0900</pubDate>
    </item>
    <item>
      <title>[Server] 클라이언트 - 서버 연결</title>
      <link>https://zoehw10101.tistory.com/30</link>
      <description>&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1723&quot; data-origin-height=&quot;1497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JFYzk/dJMcaiO8b35/Z6H6FAXpdi4ebxNKnB54R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JFYzk/dJMcaiO8b35/Z6H6FAXpdi4ebxNKnB54R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JFYzk/dJMcaiO8b35/Z6H6FAXpdi4ebxNKnB54R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJFYzk%2FdJMcaiO8b35%2FZ6H6FAXpdi4ebxNKnB54R1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;641&quot; height=&quot;557&quot; data-origin-width=&quot;1723&quot; data-origin-height=&quot;1497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;</description>
      <category>이론/프로젝트 분석</category>
      <author>킹숭이</author>
      <guid isPermaLink="true">https://zoehw10101.tistory.com/30</guid>
      <comments>https://zoehw10101.tistory.com/30#entry30comment</comments>
      <pubDate>Tue, 28 Oct 2025 03:09:35 +0900</pubDate>
    </item>
  </channel>
</rss>