<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Unity 공부 블로그</title>
    <link>https://unity-programming-study.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 25 May 2026 09:05:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>때류기</managingEditor>
    <item>
      <title>[C++] 표준 라이브러리 std::find 제대로 알아보기</title>
      <link>https://unity-programming-study.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C++에서 컨테이너 안에서 원하는 값을 찾을 때 흔히 반복문을 직접 돌리곤 합니다. 하지만 매번 for문이나 while문을 쓰는 건 코드도 길어지고 가독성도 떨어집니다. 이럴 때 유용하게 쓸 수 있는 함수가 바로 &lt;b&gt;&amp;lt;algorithm&amp;gt;&lt;/b&gt;헤어에 포함된&lt;b&gt; std::find&lt;/b&gt;입니다. 이번 글에선 &lt;b&gt;std::find&lt;/b&gt;의 기본 개념과 특징, 장단점, 그리고 예제를 통한 사용법을 살펴보겠습니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. std::find란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;std::find&lt;/b&gt;는 반복자 범위 안에서 특정 값을 찾아주는 표준 알고리즘 함수입니다. 범위의 시작부터 끝까지 차례대로 검사하며, 조건에 맞는 값이 있으면 그 위치의 반복자를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;헤더: &amp;lt;algorithm&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 원형:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1758720585064&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;template &amp;lt;class InputIt, class T&amp;gt;
InputIt find(InputIt first, InputIt last, const T&amp;amp; value);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 first와 last는 검색할 범위를 지정하는 반복자이며, value는 찾고 싶은 값입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 선형 검색:&lt;/b&gt; 내부적으로 단순 반복문을 사용하여 처음부터 끝까지 순차적으로 비교합니다. 따라서 시간 복잡도는 O(n)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 반복자 반환:&lt;/b&gt; 원하는 값을 찾으면 그 위치의 반복자를, 못 찾으면 last 반복자를 반환합니다. 이를 통해 값의 존재 여부뿐만 아니라 위치까지 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 범용성:&lt;/b&gt; std:vector, std::list, std:array 등 반복자를 지원하는 모든 컨테이너에서 사용할 수 있습니다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 장점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 가독성:&lt;/b&gt; 반복문을 직접 쓰는 대신 한 줄로 검색 로직을 표현할 수 있어 코드가 깔끔해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 범용적 사용:&lt;/b&gt; 컨테이너의 종류와 상관없이 반복자만 있으면 동일한 방식으로 검색할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 표준화된 동작:&lt;/b&gt; C++ 표준에 정의되어 있어, 어디서든 일관된 결과를 보장합니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 단점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 성능 한계:&lt;/b&gt; 단순 선형 검색이기에 데이터가 많을수록 성능이 떨어질 수 있습니다. 정렬된 컨테이너라면 std::binary_search 같은 함수를 쓰는 게 더 효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 조건 검색 제한:&lt;/b&gt; 값이 같은지 여부만 확인합니다. 특정 조건(예: 짝수인 값 찾기, 문자열 길이가 긴 원소 찾기 등)을 사용하려면 std::find_if를 써야 합니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사용 예제&lt;/b&gt;&lt;/h2&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;pre id=&quot;code_1758720932334&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;algorithm&amp;gt; // find

int main() {
	std::vector&amp;lt;int&amp;gt; numbers = {10, 20, 30, 40, 50};
    auto it = std::find(numbers.begin(), numbers.end(), 30);
    
    if(it != numbers.end())
		std::cout &amp;lt;&amp;lt; &quot;찾은 값&quot; &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; std::endl;
    else
    	std::cout &amp;lt;&amp;lt; &quot;값을 찾을 수 없습니다.&quot; &amp;lt;&amp;lt; endl;
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;std::find_if 예제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건을 사용하고 싶다면 &lt;b&gt;std::find_if&lt;/b&gt;가 더 적합합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758721016877&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;auto it = std::find_if(numbers.begin(), numbers.end(), [](int n) {return % 2 == 0;});
if(it != numbers.end())
	std::cout &amp;lt;&amp;lt; &quot;첫 번째 짝수: &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; std::endl;&lt;/code&gt;&lt;/pre&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;std::find&lt;/b&gt;는 간단하지만 강력한 검색 도구입니다. 반복문을 직접 작성할 필요 없이 컨테이너에서 원하는 값을 쉽게 찾을 수 있습니다. 다만 데이터 양이 많을 때는 성능을 고려해야 하고, 조건 검색이 필요하다면 &lt;b&gt;std::find_if&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;작은 습관처럼 std::find를 사용하면 코드가 훨씬 깔끔해지고 유지보수도 편해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C++</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/53</guid>
      <comments>https://unity-programming-study.tistory.com/53#entry53comment</comments>
      <pubDate>Wed, 24 Sep 2025 22:38:24 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 표준 라이브러리 std::accumulate 이해하기</title>
      <link>https://unity-programming-study.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C++을 공부하다 보면 &lt;b&gt;&amp;lt;numeric&amp;gt;&lt;/b&gt; 헤더에 있는 &lt;b&gt;std::accumulate&lt;/b&gt;라는 함수를 만나게 됩니다. 처음에는 &quot;단순히 합을 구하는 함수인가?&quot; 하고 넘어가기 쉬운데, 알고 보면 훨씬 더 범용적으로 활용할 수 있는 강력한 함수입니다. 이번 글에서는 &lt;b&gt;std::accumulate&lt;/b&gt;가 무엇인지, 어떤 특징을 가지고 있는지, 그리고 실제 코드 예제를 통해 어떻게 활용할 수 있는지 정리해보는 시간을 가지도록 하겠습니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. std::accumulate란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;std::accumulate&lt;/b&gt;는 이름 그대로 누적(accumulate)을 수행하는 함수입니다. 보통은 컨테이너에 들어 있는 값들을 차례대로 더해서 합계를 구할 때 많이 사용하지만, 사실 덧셈을 넘어선 일반적인 누적 연산도 할 수 있습니다.&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-end=&quot;628&quot; data-start=&quot;600&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;619&quot; data-start=&quot;600&quot;&gt;헤더: &amp;lt;numeric&amp;gt;&lt;/li&gt;
&lt;li data-end=&quot;628&quot; data-start=&quot;620&quot;&gt;기본 형태:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1757923048337&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;T accumulate(InputIt first, InputIt last, T init);&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;700&quot; data-start=&quot;692&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;700&quot; data-start=&quot;692&quot;&gt;확장 형태:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1757923059414&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;T accumulate(InputIt first, InputIt last, T init, BinaryOperation op);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;784&quot; data-ke-size=&quot;size16&quot;&gt;여기서 first, last는 반복자 범위, init은 초기값, op는 원하는 이항 연산자를 의미합니다.&lt;/p&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;784&quot; 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;style5&quot; /&gt;
&lt;h2 data-end=&quot;850&quot; data-start=&quot;784&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 기본 사용법: 합 구하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;784&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;784&quot; data-ke-size=&quot;size16&quot;&gt;가장 흔한 사용법은 단순히 합계를 구하는 경우입니다. 예를 들어:&lt;/p&gt;
&lt;pre id=&quot;code_1757923192021&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;numeric&amp;gt;

using namespace std;
int main(){
	vector&amp;lt;int&amp;gt; nums = {1, 2, 3, 4, 5};
    int sum = accumulate(nums.begin(), nums.end(), 0);
    cout &amp;lt;&amp;lt; &quot;합계: &quot; &amp;lt;&amp;lt; sum &amp;lt;&amp;lt; endl; //출력 15
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 0은 초기값입니다. 만약 0대신 10을 넣으면 결과는 25가 됩니다. 즉, 단순 합계뿐 아니라 초기 값을 기반으로 누적 계산을 시작할 수 있습니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 사용자 정의 연산자 활용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;std::accumulate의 진짜 매력은 네 번째 인자인 BinaryOperation을 직접 정의할 수 있다는 점입니다. 이걸 활용하면 단순 덧셈이 아니라 곱셈, 문자열 연결, 혹은 커스텀 로직까지 가능해집니다.&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;pre id=&quot;code_1757923316407&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int product = std::accumulate(nums.begin(), nums.end(), 1, [](int a, int b){return a* b});
std::cout &amp;lt;&amp;lt; &quot;곱셈 결과: &quot; &amp;lt;&amp;lt; product &amp;lt;&amp;lt; std::endl;&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;b&gt;문자열 연결&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1757923420682&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std::vector&amp;lt;std::string&amp;gt; words = {&quot;C++&quot;, &quot; &quot;, &quot;is&quot;, &quot; &quot;, &quot;fun&quot; };
std:string setence = std:accumulate(words.begin(), words.end(), std::string(&quot;&quot;));
std:: cout &amp;lt;&amp;lt; sentence &amp;lt;&amp;lt; std::endl; //출력: C++ is fun&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. std::accumulate의 장점&lt;/b&gt;&lt;/h2&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;1. 가독성:&lt;/b&gt; 반복문을 직접 작성하지 않아도 되니 코드가 깔끔합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 범용성:&lt;/b&gt; 단순히 합계가 아니라, 연산자를 정의해서 원하는 누적 계산을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 표준화:&lt;/b&gt; C++ 표준 라이브러리에 포함되어 있어, 모든 환경에서 일관되게 사용할 수 있습니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 주의할 점&lt;/b&gt;&lt;/h2&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;1. 초기값 타입:&lt;/b&gt; 초기 값의 타입이 결과 타입을 결정하는 경우가 있습니다. 예를 들어 double합계를 구하고싶다면 초기값을 0.0, long long합계를 구하고 싶다면, 0LL으로 지정해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 큰 데이터셋에서 성능:&lt;/b&gt; 반복문과 동일한 시간 복잡도를 가지므로 성능 차이는 거의 없습니다. 하지만 너무 복잡한 연산을 넣으면 그만큼 느려질 수 있습니다.&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;std::accumulate는 이름만 보면 단순히 &amp;ldquo;합계를 구하는 함수&amp;rdquo;처럼 보이지만, 사실은 범용적인 누적 연산 도구입니다. 합, 곱, 문자열 연결, 커스텀 로직까지 다양한 곳에 활용할 수 있죠. 코드의 가독성과 간결함을 높이는 데 큰 도움이 되므로, 알고리즘 문제나 실제 프로젝트 코드에서 자주 써보면 좋습니다.&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++ std::accumulate에 대해 정리해보았습니다. 혹시 다른 흥미로운 활용법이나 더 나은 패턴이 있다면 댓글로 공유해주세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C++</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/52</guid>
      <comments>https://unity-programming-study.tistory.com/52#entry52comment</comments>
      <pubDate>Mon, 15 Sep 2025 17:06:51 +0900</pubDate>
    </item>
    <item>
      <title>[Unity] 재사용 스크롤 뷰 - 수정(Recyclable Scroll View)</title>
      <link>https://unity-programming-study.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;유니티에서 &lt;b&gt;스크롤 뷰&lt;/b&gt;를 사용할 때, &lt;b&gt;많은 양의 데이터를 표시하는 것은 성능에 큰 부담&lt;/b&gt;을 줄 수 있습니다. 예를 들어 수백 개, 수천 개의 아이템을 스크롤 뷰에 추가하면, 메모리 사용량과 성능 문제가 발생할 수 있습니다. 이때 사용하는 최적화 기법이 바로&lt;b&gt; 재사용 스크롤 뷰(Recyclable Scroll View)&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 재사용 스크롤 뷰의 개념&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;재사용 스크롤 뷰&lt;/b&gt;는 화면에 보이는 아이템만 UI요소로 생성하고, &lt;b&gt;보이지 않는 슬롯은 재사용하는 방식&lt;/b&gt;으로 동작합니다. 기본적인 스크롤 뷰는 모든 아이템을 한꺼번에 생성하는 방식이라, 아이템이 많을수록 메모리 사용량과 CPU 부하가 증가하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, 재사용 스크롤 뷰는 &lt;b&gt;보이는 아이템만 생성&lt;/b&gt;하고, 사용자가 스크롤하면 &lt;b&gt;이미 생성된 슬롯을 재배치&lt;/b&gt;하여 화면에 맞는 데이터를 업데이트하는 방식입니다. 이 방식은 메모리와 CPU 자원을 효율적으로 사용하도록 하여 &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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 왜 재사용 스크롤 뷰를 사용하는가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;size18&quot;&gt;&lt;b&gt;1) 메모리 절약&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 성능 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성 되는 UI 요소가 적기 때문에 &lt;b&gt;CPU 부하가 줄어&lt;/b&gt;듭니다. 생성과 소멸을 반복하지 않기 때문에 &lt;b&gt;불 필요한 Garbage Collection(가비지 컬렉션)의 발생을 줄여, 프레임률이 향상&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;size18&quot;&gt;&lt;b&gt;3) 부드러운 스크롤링&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 구현&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 세로형과 가로형으로 각각 나뉜&lt;b&gt; 재사용 스크롤 뷰의 구현 예제&lt;/b&gt;입니다. 이 코드에서는 &lt;b&gt;슬롯 재배치&lt;/b&gt;와 &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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;세로형 스크롤 뷰 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세로형 스크롤 뷰는 &lt;b&gt;데이터를 세로로 나열&lt;/b&gt;하며, 보이는 영역에 따라 아이템을 추가로 로드하고, 보이지 않는 슬롯은 재사용하는 방식으로 동작합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728387747665&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Collections.Generic;
using UnityEngine;

public abstract class RecyclableVerticalScrollView&amp;lt;T&amp;gt; : MonoBehaviour
{
    [Header(&quot;Components&quot;)]
    [SerializeField] protected ScrollRect _scrollRect;
    [SerializeField] protected RectTransform _contentRect;
    [SerializeField] protected RecyclableScrollSlot&amp;lt;T&amp;gt; _slotPrefab;

    [Space]
    [Header(&quot;Option&quot;)]
    [SerializeField] protected int _bufferCount = 5; // 추가적으로 미리 로드할 슬롯의 개수
    [SerializeField] protected float _spacing; // 아이템 간의 간격

    [Space]
    [Header(&quot;VerticalScrollView Option&quot;)]
    [SerializeField] protected int _itemsPerRow = 1; // 한 줄에 보여줄 아이템 수
    [SerializeField] protected float _topOffset; // 스크롤 뷰의 위쪽 여백
    [SerializeField] protected float _bottomOffset; // 스크롤 뷰의 아래쪽 여백
    [SerializeField] protected float _horizontalOffset; // 가로 여백

    protected LinkedList&amp;lt;RecyclableScrollSlot&amp;lt;T&amp;gt;&amp;gt; _slotList = new LinkedList&amp;lt;RecyclableScrollSlot&amp;lt;T&amp;gt;&amp;gt;(); // 슬롯 리스트
    protected List&amp;lt;T&amp;gt; _dataList = new List&amp;lt;T&amp;gt;(); // 데이터를 저장하는 리스트
    protected float _itemHeight; // 슬롯의 높이
    protected float _itemWidth; // 슬롯의 너비
    protected int _poolSize; // 재사용할 슬롯의 수
    protected int _tmpfirstVisibleIndex; // 현재 첫 번째로 보이는 아이템의 인덱스
    protected int _contentVisibleSlotCount; // 현재 화면에 보이는 슬롯 개수


     /// &amp;lt;summary&amp;gt;초기 설정&amp;lt;/summary&amp;gt;
     public virtual void Init(List&amp;lt;T&amp;gt; dataList)
     {
        _dataList = dataList;

        RectTransform scrollRectTransform = _scrollRect.GetComponent&amp;lt;RectTransform&amp;gt;();
        // 슬롯 크기
        _itemHeight = _slotPrefab.Height;
        _itemWidth = _slotPrefab.Width;

        // 전체 높이 계산
        int totalRows = Mathf.CeilToInt((float)_dataList.Count / _itemsPerRow);
        float contentHeight = _itemHeight * totalRows + ((totalRows - 1) * _spacing) + _topOffset + _bottomOffset;

        //Anchor값 고정(계산 오류 방지)
        _contentRect.anchorMax = new Vector2(1f, 1f);
        _contentRect.anchorMin = new Vector2(0f, 1f);

        //contentRect의 높이 계산
        _contentVisibleSlotCount = (int)(scrollRectTransform.rect.height / _itemHeight) * _itemsPerRow;
        _contentRect.sizeDelta = new Vector2(_contentRect.sizeDelta.x, contentHeight);

        // 슬롯 생성 및 리스트에 추가
        _poolSize = _contentVisibleSlotCount + (_bufferCount * 2 * _itemsPerRow);
        int index = -_bufferCount * _itemsPerRow;
        for (int i = 0; i &amp;lt; _poolSize; i++)
        {
            RecyclableScrollSlot&amp;lt;T&amp;gt; item = Instantiate(_slotPrefab, _contentRect);
            _slotList.AddLast(item);
            item.Init();
            UpdateSlot(item, index++);
        }
        _scrollRect.onValueChanged.AddListener(OnScroll);
    }


    public void UpdateData(List&amp;lt;T&amp;gt; dataList)
    {
        _dataList = dataList;

        //예비 슬롯들을 고려해 index 세팅 및 Update
        int index = _tmpfirstVisibleIndex - _bufferCount * _itemsPerRow;
        foreach (RecyclableScrollSlot&amp;lt;T&amp;gt; item in _slotList)
        {
            UpdateSlot(item, index);
            index++;
        }
    }


    protected void OnScroll(Vector2 scrollPosition)
    {
        float contentY = _contentRect.anchoredPosition.y;

        //현재 인덱스 위치 계산 
        int firstVisibleRowIndex = Mathf.Max(0, Mathf.FloorToInt(contentY / (_itemHeight + _spacing)));
        int firstVisibleIndex = firstVisibleRowIndex * _itemsPerRow;

        // 만약 이전 위치와 현재 위치가 달라졌다면 슬롯 재배치
        if (_tmpfirstVisibleIndex != firstVisibleIndex)
        {
            int diffIndex = (_tmpfirstVisibleIndex - firstVisibleIndex) / _itemsPerRow;

            // 현재 인덱스가 더 크다면 (위로 스크롤 중)
            if (diffIndex &amp;lt; 0)
            {
                int lastVisibleIndex = _tmpfirstVisibleIndex + _contentVisibleSlotCount;
                for (int i = 0, cnt = Mathf.Abs(diffIndex) * _itemsPerRow; i &amp;lt; cnt; i++)
                {
                    RecyclableScrollSlot&amp;lt;T&amp;gt; item = _slotList.First.Value;
                    _slotList.RemoveFirst();
                    _slotList.AddLast(item);

                    int newIndex = lastVisibleIndex + (_bufferCount * _itemsPerRow) + i;
                    UpdateSlot(item, newIndex);
                }
            }

            // 이전 인덱스가 더 크다면 (아래로 스크롤 중)
            else if (diffIndex &amp;gt; 0)
            {
                for (int i = 0, cnt = Mathf.Abs(diffIndex) * _itemsPerRow; i &amp;lt; cnt; i++)
                {
                    RecyclableScrollSlot&amp;lt;T&amp;gt; item = _slotList.Last.Value;
                    _slotList.RemoveLast();
                    _slotList.AddFirst(item);

                    int newIndex = _tmpfirstVisibleIndex - (_bufferCount * _itemsPerRow) - i;
                    UpdateSlot(item, newIndex);
                }
            }

            _tmpfirstVisibleIndex = firstVisibleIndex;
        }
    }


    protected void UpdateSlot(RecyclableScrollSlot&amp;lt;T&amp;gt; item, int index)
    {
        //현재 Index의 행과 열을 계산
        int row = 0 &amp;lt;= index ? index / _itemsPerRow : (index - 1) / _itemsPerRow;
        int column = Mathf.Abs(index) % _itemsPerRow;

        // X축 및 Y축 위치 계산 (가로를 기준으로 중앙 정렬 및 피벗 보정)
        Vector2 pivot = item.RectTransform.pivot;
        float totalWidth = (_itemsPerRow * (_itemWidth + _spacing)) - _spacing;
        float contentWidth = _contentRect.rect.width;
        float offsetX = (contentWidth - totalWidth) / 2f;
        float adjustedY = -(row * (_itemHeight + _spacing)) - _itemHeight * (1 - pivot.y);
        float adjustedX = column * (_itemWidth + _spacing) + _itemWidth * pivot.x;
        adjustedX += offsetX + _horizontalOffset;
        adjustedY -= _topOffset;
        item.RectTransform.localPosition = new Vector3(adjustedX, adjustedY, 0);

        //Index가 입력된 DataList의 크기를 넘어가거나 0미만이면 슬롯을 끄고 Update를 진행하지 않는다.
        if (index &amp;lt; 0 || index &amp;gt;= _dataList.Count)
        {
            item.gameObject.SetActive(false);
            return;
        }
        else
        {
            item.UpdateSlot(_dataList[index]);
            item.gameObject.SetActive(true);
        }
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가로형&lt;/b&gt;&lt;b&gt; 스크롤 뷰 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가로형 스크롤 뷰는 세로형 스크롤 뷰와 유사하게 동작하지만, &lt;b&gt;데이터를 가로로 나열&lt;/b&gt;하고 &lt;b&gt;스크롤 방향이 좌우로 변경&lt;/b&gt;된다는 차이가 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728387954355&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Collections.Generic;
using UnityEngine;

public abstract class RecyclableHorizontalScrollView&amp;lt;T&amp;gt; : MonoBehaviour
{
    [Header(&quot;Components&quot;)]
    [SerializeField] protected ScrollRect _scrollRect;
    [SerializeField] protected RectTransform _contentRect;
    [SerializeField] protected RecyclableScrollSlot&amp;lt;T&amp;gt; _slotPrefab;

    [Space]
    [Header(&quot;Option&quot;)]
    [SerializeField] protected int _bufferCount = 5; // 추가적으로 미리 로드할 슬롯의 개수
    [SerializeField] protected float _spacing; // 아이템 간의 간격

    [Space]
    [Header(&quot;HorizontalScrollView Option&quot;)]
    [SerializeField] protected int _itemsPerColumn = 1; // 한 열에 보여줄 아이템 수
    [SerializeField] protected float _leftOffset; // 스크롤 뷰의 왼쪽 여백
    [SerializeField] protected float _rightOffset; // 스크롤 뷰의 오른쪽 여백
    [SerializeField] protected float _verticalOffset; // 세로 여백

    protected LinkedList&amp;lt;RecyclableScrollSlot&amp;lt;T&amp;gt;&amp;gt; _slotList = new LinkedList&amp;lt;RecyclableScrollSlot&amp;lt;T&amp;gt;&amp;gt;(); // 슬롯 리스트
    protected List&amp;lt;T&amp;gt; _dataList = new List&amp;lt;T&amp;gt;(); // 데이터를 저장하는 리스트
    protected float _itemHeight; // 슬롯의 높이
    protected float _itemWidth; // 슬롯의 너비
    protected int _poolSize; // 재사용할 슬롯의 수
    protected int _tmpfirstVisibleIndex; // 현재 첫 번째로 보이는 아이템의 인덱스
    protected int _contentVisibleSlotCount; // 현재 화면에 보이는 슬롯 개수
    
    
    /// &amp;lt;summary&amp;gt;초기 설정&amp;lt;/summary&amp;gt;
    public virtual void Init(List&amp;lt;T&amp;gt; dataList)
    {
        _dataList = dataList;

        _scrollRectTransform = _scrollRect.GetComponent&amp;lt;RectTransform&amp;gt;();
        // 슬롯 크기
        _itemHeight = _slotPrefab.Height;
        _itemWidth = _slotPrefab.Width;

        // 전체 너비 계산
        int totalColumns = Mathf.CeilToInt((float)_dataList.Count / _itemsPerColumn);
        float contentWidth = _itemWidth * totalColumns + (totalColumns &amp;gt; 0 ? (totalColumns - 1) * _spacing : 0) + _leftOffset + _rightOffset;

        //Anchor값 고정(계산 오류 방지)
        _contentRect.anchorMax = new Vector2(1f, 1f);
        _contentRect.anchorMin = new Vector2(0f, 1f);

        //contentRect의 높이 계산
        _contentVisibleSlotCount = (int)(_scrollRectTransform.rect.width / _itemWidth) * _itemsPerColumn;
        _contentRect.sizeDelta = new Vector2(contentWidth - _scrollRectTransform.rect.width, _contentRect.sizeDelta.y);

        // 슬롯 생성 및 리스트에 추가
        _poolSize = _contentVisibleSlotCount + (_bufferCount * 2 * _itemsPerColumn);
        int index = -_bufferCount * _itemsPerColumn;
        for (int i = 0; i &amp;lt; _poolSize; i++)
        {
            RecyclableScrollSlot&amp;lt;T&amp;gt; item = Instantiate(_slotPrefab, _contentRect);
            _slotList.AddLast(item);
            item.Init();
            UpdateSlot(item, index++);
        }
        _scrollRect.onValueChanged.AddListener(OnScroll);
    }


    /// &amp;lt;summary&amp;gt;슬롯의 정보를 갱신하는 함수&amp;lt;/summary&amp;gt;
    public void UpdateData(List&amp;lt;T&amp;gt; dataList)
    {
        _dataList = dataList;

        //예비 슬롯들을 고려해 index 세팅 및 Update
        int index = _tmpfirstVisibleIndex - _bufferCount * _itemsPerColumn;
        foreach (RecyclableScrollSlot&amp;lt;T&amp;gt; item in _slotList)
        {
            UpdateSlot(item, index);
            index++;
        }
    }


    /// &amp;lt;summary&amp;gt;ScrollRect 이벤트와 연동하여 슬롯의 위치를 변경하는 함수&amp;lt;/summary&amp;gt;
    protected void OnScroll(Vector2 scrollPosition)
    {
        float contentX = _contentRect.anchoredPosition.x;

        //현재 인덱스 위치 계산 
        int firstVisibleRowIndex = Mathf.Max(0, Mathf.FloorToInt(contentX / (_itemWidth + _spacing)));
        int firstVisibleIndex = firstVisibleRowIndex * _itemsPerColumn;

        // 만약 이전 위치와 현재 위치가 달라졌다면 슬롯 재배치
        if (_tmpfirstVisibleIndex != firstVisibleIndex)
        {
            int diffIndex = (_tmpfirstVisibleIndex - firstVisibleIndex) / _itemsPerColumn;

            // 현재 인덱스가 더 크다면 (위로 스크롤 중)
            if (diffIndex &amp;lt; 0)
            {
                int lastVisibleIndex = _tmpfirstVisibleIndex + _contentVisibleSlotCount;
                for (int i = 0, cnt = Mathf.Abs(diffIndex) * _itemsPerColumn; i &amp;lt; cnt; i++)
                {
                    RecyclableScrollSlot&amp;lt;T&amp;gt; item = _slotList.First.Value;
                    _slotList.RemoveFirst();
                    _slotList.AddLast(item);

                    int newIndex = lastVisibleIndex + (_bufferCount * _itemsPerColumn) + i;
                    UpdateSlot(item, newIndex);
                }
            }

            // 이전 인덱스가 더 크다면 (아래로 스크롤 중)
            else if (diffIndex &amp;gt; 0)
            {
                for (int i = 0, cnt = Mathf.Abs(diffIndex) * _itemsPerColumn; i &amp;lt; cnt; i++)
                {
                    RecyclableScrollSlot&amp;lt;T&amp;gt; item = _slotList.Last.Value;
                    _slotList.RemoveLast();
                    _slotList.AddFirst(item);

                    int newIndex = _tmpfirstVisibleIndex - (_bufferCount * _itemsPerColumn) - i;
                    UpdateSlot(item, newIndex);
                }
            }

            _tmpfirstVisibleIndex = firstVisibleIndex;
        }
    }


    /// &amp;lt;summary&amp;gt;슬롯의 데이터를 업데이트하고 위치를 갱신하는 함수&amp;lt;/summary&amp;gt;
    protected void UpdateSlot(RecyclableScrollSlot&amp;lt;T&amp;gt; item, int index)
    {
        //현재 Index의 행과 열을 계산
        int column = 0 &amp;lt;= index ? index / _itemsPerColumn : (index - 1) / _itemsPerColumn;
        int row = Mathf.Abs(index) % _itemsPerColumn;

        Vector2 pivot = item.RectTransform.pivot;
        // 중앙 행의 기준점 (짝수와 홀수에 따라 다름)
        float rowOffsetY;
        if (_itemsPerColumn % 2 == 0) // 짝수인 경우
        {
            // 짝수일 때는 중앙값이 두 행 사이에 위치
            float middleRow = (_itemsPerColumn / 2f) - 0.5f;
            rowOffsetY = -(row - middleRow) * (_itemHeight + _spacing);
        }
        else // 홀수인 경우
        {
            // 홀수일 때는 중앙 행을 기준으로 위/아래로 정렬
            int middleRow = (_itemsPerColumn - 1) / 2;
            rowOffsetY = row == middleRow ? 0 : row &amp;lt; middleRow ? -(middleRow - row) * (_itemHeight + _spacing) : row &amp;gt; middleRow ? (row - middleRow) * (_itemHeight + _spacing) : 0;
        }

        // 피벗 보정 값
        float pivotAdjustmentY = -_itemHeight * (0.5f - pivot.y);

        // X축 및 Y축 위치 계산 (세로를 기준으로 중앙 정렬 및 피벗 보정)
        float scrollViewWidth = _contentRect.rect.width;
        float adjustedX = -(scrollViewWidth * 0.5f) + (column * (_itemWidth + _spacing)) + _itemWidth * pivot.x;
        float pivotAdjustmentX = _itemWidth * (0.5f - pivot.x);
        float adjustedY = rowOffsetY + _verticalOffset + pivotAdjustmentY;
        adjustedX += pivotAdjustmentX;
        adjustedX += _leftOffset;
        item.RectTransform.anchoredPosition = new Vector2(adjustedX, adjustedY);

        //Index가 입력된 DataList의 크기를 넘어가거나 0미만이면 슬롯을 끄고 Update를 진행하지 않는다.
        if (index &amp;lt; 0 || index &amp;gt;= _dataList.Count)
        {
            item.gameObject.SetActive(false);
        }
        else
        {
            item.UpdateSlot(_dataList[index]);
            item.gameObject.SetActive(true);
        }
    }&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;재사용 스크롤 뷰 슬롯 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가로형, 세로형 재사용 스크롤 뷰의 &lt;b&gt;ContentRect 항목에 생성되는 슬롯&lt;/b&gt; 클래스입니다. 특별한 기능은 없지만 자식 클래스에서 &lt;b&gt;함수를 구현하여 여러가지 기능을 추가&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728388060242&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using UnityEngine;

public abstract class RecyclableScrollSlot&amp;lt;T&amp;gt; : MonoBehaviour
    {
        [SerializeField] protected RectTransform _rectTransform;
        public RectTransform RectTransform =&amp;gt; _rectTransform;
        public float Height =&amp;gt; _rectTransform.rect.height;
        public float Width =&amp;gt; _rectTransform.rect.width;

        public abstract void Init();
        public abstract void UpdateSlot(T data);
    }&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 사용법&lt;/b&gt;&lt;/h2&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;EnabledRecyclableScrollView 클래스는 세로형 스크롤 뷰를 구현한 예시이며, Slot 클래스는 각 슬롯이 데이터를 표시하는 방법을 정의합니다.&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;&lt;b&gt;1) EnabledRecyclableScrollView 클래스 &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 클래스는&lt;b&gt; 세로형 스크롤 뷰&lt;/b&gt;에서 &lt;b&gt;정수형 데이터를 스크롤하여 보여주는 역할&lt;/b&gt;을 합니다. &lt;b&gt;Start&lt;/b&gt; 메서드에서 슬롯의 수를 정의한 후, 해당 슬롯의 데이터 리스트를 초기화하여&lt;b&gt; Init&lt;/b&gt; 메서드를 통해 재사용 스크롤 뷰를 초기화합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728388429370&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class EnabledRecyclableScrollView : RecyclableVerticalScrollView&amp;lt;int&amp;gt;
{
    [SerializeField] private int _slotCount; // 생성할 슬롯 수

    void Start()
    {
        List&amp;lt;int&amp;gt; dataList = new List&amp;lt;int&amp;gt;();
        
        // 슬롯 수에 맞춰 데이터 리스트를 초기화
        for (int i = 0; i &amp;lt; _slotCount; i++)
        {
            dataList.Add(i); // 0부터 _slotCount까지의 숫자를 추가
        }

        // 스크롤 뷰 초기화
        Init(dataList);
    }
}&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;size18&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Start&lt;/b&gt; 메서드에서 사용자가 정의한 슬롯 수만큼 데이터를 생성하고, 이를 Init 메서드를 통해 스크롤 뷰에 전달합니다.&lt;/li&gt;
&lt;li&gt;재사용 스크롤 뷰는 데이터 리스트를 받아 그에 맞는 슬롯을 화면에 표시합니다.&lt;/li&gt;
&lt;li&gt;슬롯의 개수는 &lt;b&gt;_slotCount&lt;/b&gt; 변수를 통해 설정됩니다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2)Slot 클래스&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 클래스는 &lt;b&gt;스크롤 뷰의 각 슬롯을 정의&lt;/b&gt;하며, 슬롯에 표시할 텍스트를 갱신하는 역할을 합니다.&amp;nbsp;&lt;br /&gt;UpdateSlot 메서드는 데이터가 변경될 때마다 슬롯의 UI요소를 업데이트합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728388512698&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Slot : RecyclableScrollSlot&amp;lt;int&amp;gt;
{
    [SerializeField] private Text _text; // 슬롯에 표시할 텍스트 UI

    // 슬롯 초기화 (필요 시 추가 설정 가능)
    public override void Init()
    {
    }

    // 슬롯 업데이트 메서드 (데이터 변경 시 호출)
    public override void UpdateSlot(int data)
    {
        // 슬롯에 정수형 데이터를 텍스트로 변환하여 표시
        _text.text = data.ToString();
    }
}&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;size18&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;UpdateSlot&lt;/b&gt; 메서드는 int형 데이터를 받아 이를 &lt;b&gt;텍스트로 변환한 후&lt;/b&gt;, 슬롯에 연결된 텍스트 UI에 적용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Init&lt;/b&gt; 메서드는 추가적인 초기화 작업이 필요할 때 사용하며, 예제에서는 비워두었습니다.&lt;/li&gt;
&lt;li&gt;슬롯이 보이게 되면 새로운 데이터에 맞게 업데이트되어 &lt;b&gt;UI요소&lt;/b&gt;에 적용됩니다.&lt;/li&gt;
&lt;/ul&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;&lt;b&gt;유니티 적용법&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2557&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HYxV8/btsJXW1omRk/Wl93X0eVR2oXIaTjzgyza0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HYxV8/btsJXW1omRk/Wl93X0eVR2oXIaTjzgyza0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HYxV8/btsJXW1omRk/Wl93X0eVR2oXIaTjzgyza0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHYxV8%2FbtsJXW1omRk%2FWl93X0eVR2oXIaTjzgyza0%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;2557&quot; height=&quot;918&quot; data-origin-width=&quot;2557&quot; data-origin-height=&quot;918&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;2524&quot; data-origin-height=&quot;1095&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccYU0I/btsJX7VVgM4/wlXM4tD546VmvKKytR4IRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccYU0I/btsJX7VVgM4/wlXM4tD546VmvKKytR4IRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccYU0I/btsJX7VVgM4/wlXM4tD546VmvKKytR4IRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccYU0I%2FbtsJX7VVgM4%2FwlXM4tD546VmvKKytR4IRk%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;2524&quot; height=&quot;1095&quot; data-origin-width=&quot;2524&quot; data-origin-height=&quot;1095&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. &lt;/b&gt;슬롯을 생성 후 Text를 추가, 화살표와 같이 오브젝트를 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. &lt;/b&gt;해당 슬롯을 프리팹화 시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.&lt;/b&gt; 스크롤 뷰를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4.&lt;/b&gt; 제작한 클래스를 스크롤 뷰 컴포넌트로 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5.&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 실행 이미지 및 영상&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1523&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnZ6dM/btsJZN9E1Jl/yZopEHuRIRCusUdjFN17TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnZ6dM/btsJZN9E1Jl/yZopEHuRIRCusUdjFN17TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnZ6dM/btsJZN9E1Jl/yZopEHuRIRCusUdjFN17TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnZ6dM%2FbtsJZN9E1Jl%2FyZopEHuRIRCusUdjFN17TK%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;1523&quot; height=&quot;918&quot; data-origin-width=&quot;1523&quot; data-origin-height=&quot;918&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤 뷰 실행 움짤.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k6NX1/btsJYJUKwvK/0abYkKBHVVbqdEKCaFPSvk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k6NX1/btsJYJUKwvK/0abYkKBHVVbqdEKCaFPSvk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k6NX1/btsJYJUKwvK/0abYkKBHVVbqdEKCaFPSvk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/k6NX1/btsJYJUKwvK/0abYkKBHVVbqdEKCaFPSvk/img.gif&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;600&quot; height=&quot;338&quot; data-filename=&quot;스크롤 뷰 실행 움짤.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&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;위처럼 수행 후 에디터를 구동했을 때의 모습입니다. 총 10000개의 데이터를 넣었지만 슬롯은 19개만 사용되는 모습을 보실 수 있습니다. 이처럼 데이터량 대비 적은 슬롯을 재사용 하며 10000개의 데이터를 표시할 수 있게 됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 적용 전, 후 비교&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;재사용 스크롤 뷰 비활성화.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gh1IC/btsJ0aXJldo/UigKGE2tVOkNIKnXFfdXx0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gh1IC/btsJ0aXJldo/UigKGE2tVOkNIKnXFfdXx0/img.gif&quot; data-alt=&quot;적용 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gh1IC/btsJ0aXJldo/UigKGE2tVOkNIKnXFfdXx0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/Gh1IC/btsJ0aXJldo/UigKGE2tVOkNIKnXFfdXx0/img.gif&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;600&quot; height=&quot;338&quot; data-filename=&quot;재사용 스크롤 뷰 비활성화.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;적용 전&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;재사용 스크롤 뷰 활성화.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QjNPq/btsJ0f5IIzK/Lb5ttdf1tc8lFiJOkkkH90/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QjNPq/btsJ0f5IIzK/Lb5ttdf1tc8lFiJOkkkH90/img.gif&quot; data-alt=&quot;적용 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QjNPq/btsJ0f5IIzK/Lb5ttdf1tc8lFiJOkkkH90/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/QjNPq/btsJ0f5IIzK/Lb5ttdf1tc8lFiJOkkkH90/img.gif&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;600&quot; height=&quot;338&quot; data-filename=&quot;재사용 스크롤 뷰 활성화.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;적용 후&lt;/figcaption&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;&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;1245&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTsBcN/btsJYcpln7D/pJVnyiKDca7QYkRppUR8wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTsBcN/btsJYcpln7D/pJVnyiKDca7QYkRppUR8wk/img.png&quot; data-alt=&quot;Statistics 전 후 차이&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTsBcN/btsJYcpln7D/pJVnyiKDca7QYkRppUR8wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTsBcN%2FbtsJYcpln7D%2FpJVnyiKDca7QYkRppUR8wk%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;1245&quot; height=&quot;453&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Statistics 전 후 차이&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 10000개의 데이터를 스크롤 뷰에 입력하고 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용을 하지 않았을 경우 &lt;b&gt;(스크롤 전 - fps80~81 cpu11~13ms, 스크롤 중 - fps15~21 cpu47~62ms)&lt;/b&gt; 속도가 저하되고 스크롤 뷰가 버벅되는 문제가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용을 한 후엔(&lt;b&gt;스크롤 전 - fps1000~1400 cpu0.7~1.2ms, 스크롤 중 - fps600~1100 cpu0.9~1.5ms) &lt;/b&gt;적용 전보다 fps와 cpu 처리 속도가 큰 폭으로 상승하는 것을 보실 수 있습니다.&lt;b&gt;(본문 이미지 차이 fps 17.7 =&amp;gt; 671.7, cpu 56.4ms =&amp;gt; 1.5ms)&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;재사용 스크롤 뷰(Recyclable Scroll View)&lt;/b&gt;는 유니티에서 많은 양의 데이터를 스크롤 뷰로 처리할 때 유용한 성능 최적화 도구입니다. 이 기법을 사용하면 메모리와 CPU 사용량을 줄일 수 있으며, &lt;b&gt;부드러운 스크롤 경험&lt;/b&gt;을 제공할 수 있습니다. 특히, UI 성능이 중요한 모바일 게임이나 대규모 리스트를 다루는 애플리케이션에서 매우 유용하게 사용됩니다.&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제가 면접에서 질문 받은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;b&gt;재사용 스크롤 뷰를&lt;/b&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;학습하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;작성했습니다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>Unity 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/51</guid>
      <comments>https://unity-programming-study.tistory.com/51#entry51comment</comments>
      <pubDate>Tue, 8 Oct 2024 21:34:26 +0900</pubDate>
    </item>
    <item>
      <title>[C#] LINQ(Language Integrated Query)</title>
      <link>https://unity-programming-study.tistory.com/47</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서&lt;b&gt; LINQ&lt;/b&gt;는 데이터를 쉽게 검색, 필터링, 정렬, 변환할 수 있도록 돕는 기능입니다. LINQ는 데이터를 쿼리하는 방식에 통일성을 제공하며, 데이터베이스, 컬렉션, XML, Entity Framework 등 다양한 데이터 소스에 적용할 수 있습니다. 이번 글에서는 &lt;b&gt;LINQ가 무엇인지&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. LINQ란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 C# 언어에서 &lt;b&gt;데이터를 쿼리하는 표준화된 방법을 제공하는 기능&lt;/b&gt;입니다. LINQ는 컬렉션, 배열, 데이터베이스, XML, 파일 등 여러 &lt;b&gt;데이터 소스에 대해 일관된 방식으로 데이터를 검색&lt;/b&gt;할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 &lt;b&gt;SQL 쿼리 문법과 비슷한 방식으로 데이터를 쿼리할 수 있도록 지원&lt;/b&gt;하며,&amp;nbsp; &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;LINQ는 주로 다음과 같은 세 가지 방식으로 데이터를 쿼리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. LINQ to Objects:&lt;/b&gt; 메모리 내 컬렉션(배열, 리스트 등)에서 데이터 쿼리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. LINQ to SQL / LINQ to Entities:&lt;/b&gt; 데이터베이스에서 데이터를 쿼리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. LINQ to XML:&lt;/b&gt; XML 문서에서 데이터를 쿼리&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 일관된 쿼리 문법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 &lt;b&gt;통합된 쿼리 문법을 사용&lt;/b&gt;합니다. 즉, 메모리 내의 컬렉션이나 데이터베이스, XML, 웹 서비스 등 다양한 데이터 소스에 대해 &lt;b&gt;일관된 방식으로 데이터를 쿼리&lt;/b&gt;할 수 있습니다. C#의 구문에 통합되어 있기 때문에, SQL 같은 쿼리 문법을 코드 내부에서 간편하게 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 강력한 필터링, 정렬 및 변환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 데이터를 &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;size18&quot;&gt;&lt;b&gt;3) 컴파일 타임 검증&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 정적 타입 검사를 지원하여 쿼리를 작성할 때 &lt;b&gt;컴파일 타임에 오류를 감지&lt;/b&gt;할 수 있습니다. SQL과 달리 문자열로 쿼리를 작성하지 않으므로 더 안전한 쿼리 작성을 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) 지연 실행(Deferred Execution)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 기본적으로 지연 실행을 지원합니다. 이는 쿼리가 정의되었을 때 즉시 실행되지 않고, 데이터가 실제로 요청될 때 실행되는 방식입니다. 이를 통해 불필요한 데이터를 미리 처리하지 않도록 최적화된 쿼리를 작성할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 장점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 코드 가독성 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 &lt;b&gt;데이터 처리 로직을 간결하고 읽기 쉽게&lt;/b&gt; 만들어 줍니다. 복잡한 데이터 처리를 여러 줄의 코드로 작성하던 작업을 단 몇 줄의 쿼리로 표현할 수 있으며, SQL 문법과 유사하여 쿼리 작성을 쉽게 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 통일된 데이터 쿼리 방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 컬렉션, 데이터베이스, XML등 다양한 데이터 소스를 대상으로 &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;size18&quot;&gt;&lt;b&gt;3) 타입 안정성(Type Safety)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ 쿼리는 &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;size18&quot;&gt;&lt;b&gt;4) 유연한 데이터 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 데이터의 &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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 단점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 유용한 도구이지만, 몇 가지 단점과 제약 사항도 있습니다. LINQ를 사용할 때 이러한 단점들을 이해하고 적절하게 사용해야 성능이나 코드의 유지보수성에 문제가 발생하지 않도록 할 수 있습니다.&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;&lt;b&gt;1) 성능 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;[1] 지연 실행(Deferrend Execution)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 기본적으로 &lt;b&gt;지연 실행&lt;/b&gt;을 사용합니다. 이는 쿼리가 정의될 때 바로 실행되지 않고, 데이터를 실제로 사용할 때 실행되는 방식입니다. 이런 동작은 상황에 따라 성능 문제를 야기할 수 있습니다. 특히 LINQ 쿼리를 여러 번 호출하는 경우 &lt;b&gt;매번 쿼리가 실행되어 성능이 저하&lt;/b&gt;될 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726843073287&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var evenNumbers = numbers.Where(n =&amp;gt; n % 2 == 0);  // 여기서 실행되지 않음
Console.WriteLine(evenNumbers.Count());  // 쿼리가 여기서 실행됨
Console.WriteLine(evenNumbers.First());  // 또다시 쿼리가 실행됨&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 &lt;u&gt;evenNumbers&lt;/u&gt; 쿼리는 두 번 실행됩니다. &lt;u&gt;ToList()&lt;/u&gt;나 &lt;u&gt;ToArray()&lt;/u&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;[2] 큰 데이터셋에서의 성능 저하&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 간결하고 일기 쉬운 코드를 제공하지만,&lt;b&gt; 대량의 데이터 처리 시에는 성능이 저하&lt;/b&gt;될 수 있습니다. 특히, 반복적으로 데이터를 변환하거나 복잡한 필터링을 수행하는 경우, 전통적인 반복문에 비해 느리게 동작할 수 있습니다. LINQ는 내부적으로&lt;b&gt; 반복자(iterator)&lt;/b&gt;를 사용하므로, 대량의 데이터를 다룰 때는 추가적인 오버헤드가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결 방법:&lt;/b&gt; 성능이 중요한 경우, &lt;u&gt;for&lt;/u&gt;나&lt;u&gt; foreach &lt;/u&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 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) 복잡한 쿼리에서의 가독성 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 단순한 쿼리에서는 코드의 가독성을 높여주지만,&lt;b&gt; 쿼리가 복잡해질수록 가독성이 떨어질 수 있습니다.&lt;/b&gt; 특히, 여러 연산자를 체이닝하거나 중첩된 쿼리를 사용하는 경우, 코드가 길고 복잡해져서 유지보수가 어려워질 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726843315213&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var result = data.Where(x =&amp;gt; x.Age &amp;gt; 30)
                 .OrderBy(x =&amp;gt; x.Name)
                 .Select(x =&amp;gt; new { x.Name, x.Age })
                 .GroupBy(x =&amp;gt; x.Age)
                 .Where(g =&amp;gt; g.Count() &amp;gt; 1);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 여러 연사자를 체이닝하여 쿼리를 작성하면, 코드가 복잡해지고 이해하기 어려울 수 있습니다. SQL에 익숙하지 않은 개발자나 팀원에게는 이 코드가 오히려 가독성을 저하시킬 수 있습니다.&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;&lt;b&gt;3) 디버깅 어려움&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 데이터 처리 로직을 간결하게 작성할 수 있지만, &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;/p&gt;
&lt;pre id=&quot;code_1726843449439&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var filtered = numbers.Where(n =&amp;gt; n % 2 == 0).ToList();  // 중간 결과 확인 가능&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4) 쿼리 성능 최적화의 어려움&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 SQL로 변환되어 실행될 수 있지만, &lt;b&gt;복잡한 쿼리는 성능이 저하될 수 있습니다&lt;/b&gt;. 특히 &lt;b&gt;LINQ to SQL&lt;/b&gt;이나&lt;b&gt; Entity Framework&lt;/b&gt;에서 사용되는 경우, SQL로 변환되는 과정에서 &lt;b&gt;비효율적인 쿼리가 생성&lt;/b&gt;될 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726843535648&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var employees = db.Employees
                  .Where(e =&amp;gt; e.Department.Name == &quot;HR&quot;)
                  .OrderBy(e =&amp;gt; e.Name)
                  .ToList();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 LINQ쿼리가 내부적으로 SQL로 변환될 때, 잘못된 방식으로 최적화되지 않거나 비효율적인 쿼리가 생성될 수 있습니다. 이는 데이터베이스 성능에 영향을 미칠 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방법:&lt;/b&gt; 복잡한 데이터베이스 쿼리의 경우 &lt;b&gt;직접 SQL을 작성&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5) 비표준화된 쿼리 실행&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ를 사용하면 SQL과 비슷한 방식으로 데이터를 쿼리할 수 있지만, LINQ의 쿼리가 항상 &lt;b&gt;SQL 표준을 따르지 않을 수 있습니다.&lt;/b&gt; 이로 인해 LINQ가 생성하는 SQL쿼리가 효율적이지 않거나, 특정 데이터베이스와의 호환성 문제를 일으킬 수 있습니다. 또한&amp;nbsp; LINQ쿼리는 SQL에서 지원히자 않는 C#구문을 사용할 수 있기 때문에, 모든 쿼리가 SQL로 변환될 수는 없습니다.&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;&lt;b&gt;6) 메모리 사용 증가&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 데이터를 처리할 때&lt;b&gt; 즉시 실행과 지연 실행을 혼합하여 사용할 수 있지만&lt;/b&gt;, 컬렉션을 처리하는 과정에서 추가적인 &lt;b&gt;메모리 사용을 초래&lt;/b&gt;할 수 있습니다. 특히 &lt;u&gt;ToList(), ToArray()&lt;/u&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;u&gt; IEnumerable&lt;/u&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 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7) 복잡한 쿼리 작성 제한&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 기본적으로&lt;b&gt; 간단한 데이터 쿼리를 쉽게 처리하는 데 최적화&lt;/b&gt;되어 있습니다. 그러한 &lt;b&gt;복잡한 데이터베이스 연산&lt;/b&gt;(예: 복잡한 조인, 서브쿼리, 커스텀 SQL 함수 등)을 처리할 때는 &lt;b&gt;제약이 발생&lt;/b&gt;할 수 있습니다. 이런 경우 LINQ로는 표현하기 어려운 쿼리를 작성해야 할 때 제한이 따를 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ는 크게 &lt;b&gt;쿼리 구문(Query Syntax)&lt;/b&gt;과 메&lt;b&gt;서드 구문(Metod Syntax)&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;size18&quot;&gt;&lt;b&gt;1) 쿼리 구문(Query Syntax)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 구문은 SQL과 비슷한 방식으로 데이터를 쿼리하는 구문입니다. &lt;u&gt;&lt;b&gt;from, where, select&lt;/b&gt;&lt;/u&gt; 등의 키워드를 사용하여 데이터를 처리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726926721113&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        List&amp;lt;int&amp;gt; numbers = new List&amp;lt;int&amp;gt; { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        // 쿼리 구문으로 짝수만 필터링
        var evenNumbers = from n in numbers
                          where n % 2 == 0
                          select n;

        Console.WriteLine(&quot;짝수만 출력:&quot;);
        foreach (var number in evenNumbers)
        {
            Console.WriteLine(number);  // 출력: 2, 4, 6, 8, 10
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 from, were, select 키워드를 사용하여 짝수만 필터링하는 쿼리를 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL 문법과 유사하게 데이터를 처리할 수 있습니다.&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;size18&quot;&gt;&lt;b&gt;2) 메서드 구문(Method Syntax)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 구문은 LINQ에서 제공하는 &lt;b&gt;확장 메서드&lt;/b&gt;를 사용하여 데이터를 처리하는 방식입니다. 메서드 구문은 체이닝을 통해 쿼리를 연결할 수 있어, 가독성과 유연성이 높습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726926788333&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        List&amp;lt;int&amp;gt; numbers = new List&amp;lt;int&amp;gt; { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        // 메서드 구문으로 짝수만 필터링
        var evenNumbers = numbers.Where(n =&amp;gt; n % 2 == 0);

        Console.WriteLine(&quot;짝수만 출력:&quot;);
        foreach (var number in evenNumbers)
        {
            Console.WriteLine(number);  // 출력: 2, 4, 6, 8, 10
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 구문에서는 &lt;u&gt;&lt;b&gt;Where&lt;/b&gt;&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 주요 연산자&lt;/b&gt;&lt;/h2&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;1) Where&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;조건에 맞는 데이터를 필터링&lt;/b&gt;하는 연산자입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726926984954&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var evenNumbers = numbers.Where(n =&amp;gt; n % 2 == 0);&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) Select&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를&lt;b&gt; 변환하거나 선택&lt;/b&gt;하는 연산자입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726927006620&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var squares = numbers.Select(n =&amp;gt; n * n);&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) OrderBy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 &lt;b&gt;오름차순으로 정렬&lt;/b&gt;하는 연산자입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726927027172&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var orderedNumbers = numbers.OrderBy(n =&amp;gt; n);&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4) GroupBy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 &lt;b&gt;특정 기준에 따라 그룹화&lt;/b&gt;하는 연산자입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726927215055&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var groupedNumbers = numbers.GroupBy(n =&amp;gt; n % 2 == 0 ? &quot;Even&quot; : &quot;Odd&quot;);&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5) Sum, Average, Count&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;집계 연산을 수행&lt;/b&gt;하는 메서드들입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726927047226&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sum = numbers.Sum();
double average = numbers.Average();
int count = numbers.Count();&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6) First, FristOrDefault&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리스트에서 첫 번째 값을 반환&lt;/b&gt;하는 연산자입니다. FirstOrDefault는 &lt;b&gt;조건에 맞는 값이 없을 경우 기본값(default)을 반환&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726927095616&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int firstEven = numbers.First(n =&amp;gt; n % 2 == 0);&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#의 &lt;b&gt;LINQ&lt;/b&gt;는 데이터를 쿼리하는 방식에 통일성을 제공하며, &lt;b&gt;데이터 필터링, 정렬, 변환&lt;/b&gt; 등을 간단하게 처리할 수 있는 도구입니다. LINQ는 컬렉션에서 데이터를 처리할 때 뿐만 아니라, &lt;b&gt;데이터베이스, XML&lt;/b&gt; 등 다양한 데이터 소스에서 동일한 문법으로 데이터를 처리할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ를 잘 활용하면 복잡한 데이터를 처리하는 코드를 단순화할 수 있으며, 코드의 가독성과 유지보수성 또한 크게 향상시킬 수 있습니다. LINQ의 다양한 연산자를 이해하고 활용하여, 효율적인 데이터 처리를 시작해보세요!&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 C# LINQ에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/47</guid>
      <comments>https://unity-programming-study.tistory.com/47#entry47comment</comments>
      <pubDate>Fri, 20 Sep 2024 00:28:51 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 확장 메서드(Extension Methods)</title>
      <link>https://unity-programming-study.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서 &lt;b&gt;확장 메서드(Extension Method)&lt;/b&gt;는 기존의 클래스나 구조체를 변경하지 않고, &lt;b&gt;새로운 메서드를 추가&lt;/b&gt;할 수 있는 기능입니다. 이 기능을 통해 기존 코드에 손을 대지 않고도 클래스의 동작을 확장할 수 있으며, 특히&lt;b&gt; LINQ&lt;/b&gt;에서 자주 사용되는 기능이기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 C#의 확장 메서드가 무엇인지, 그 특징과 사용 이유, 실제로 어떻게 구현하고 사용하는지에 대해 설명하겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 확장 메서드란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드는 &lt;b&gt;기존 클래스나 구조체를 변경하지 않고&lt;/b&gt;도, &lt;b&gt;새로운 메서드를 추가하여 동작을 확장&lt;/b&gt;할 수 있게 해줍니다. 이 메서드는&lt;b&gt; 정적(static) 클래스&lt;/b&gt; 안에서 정의되며, 첫 번째 매개변수로&lt;b&gt; this&lt;/b&gt; 키워드를 사용해 확장할 대상을 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 C#에서 제공하는 클래스나, 사용자가 작성한 클래스, 구조체, 인터페이스에 확장 메서드를 추가할 수 있으며, 해당 클래스나 구조체를 수정할 필요 없이 마치 원래 클래스의 메서드인 것처럼 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;예제&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1726831609508&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static class StringExtensions
{
    // 확장 메서드: 문자열의 첫 글자를 대문자로 변환
    public static string ToCapitalized(this string str)
    {
        if (string.IsNullOrEmpty(str)) return str;
        return char.ToUpper(str[0]) + str.Substring(1).ToLower();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서&lt;u&gt; ToCapitalized&lt;/u&gt;는 &lt;u&gt;string&lt;/u&gt; 클래스에 새롭게 추가된 것처럼 동작하는 &lt;b&gt;확장 메서드&lt;/b&gt;입니다. 이 메서드는 정적 클래스 안에서 정의되었으며, 첫 번째 매개변수로&lt;u&gt; this string str&lt;/u&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 기존 코드 수정 없이 기능 확장&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;b&gt;제3의 코드를 수정할 수 없는 경우 유용&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;size18&quot;&gt;&lt;b&gt;2) 정적 클래스에서 정의&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드는 반드시 &lt;b&gt;정적 클래스(static class)&lt;/b&gt;에서 정의되어야 하며, 첫 번째 매개변수로&lt;b&gt; this 키워드&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;size18&quot;&gt;&lt;b&gt;3) 내부적으로 정적 메서드&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 코드의 재사용성과 간결성&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;size18&quot;&gt;&lt;b&gt;2) 외부 라이브러리나 기존 클래스를 수정하지 않고 기능 확장&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;size18&quot;&gt;&lt;b&gt;3) LINQ와 같은 기능 구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장메서드는 LINQ와 같은 기능을 쉽게 구현하는 데 중요한 역할을 합니다. LINQ의 여러 메서드(&lt;u&gt;Where&lt;/u&gt;, &lt;u&gt;Select&lt;/u&gt;, &lt;u&gt;OrderBy&lt;/u&gt; 등)는 모두 확장 메서드로 구현되어 있으며, 컬렉션을 다루는 로직을 매우 간결하게 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) 가독성 향상&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 기본 확장 메서드 예제&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1726832052901&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static class StringExtensions
{
    // 문자열의 첫 글자를 대문자로 변환하는 확장 메서드
    public static string ToCapitalized(this string str)
    {
        if (string.IsNullOrEmpty(str)) return str;
        return char.ToUpper(str[0]) + str.Substring(1).ToLower();
    }
}

public class Program
{
    public static void Main()
    {
        string example = &quot;hello world&quot;;
        // 확장 메서드 사용
        string capitalized = example.ToCapitalized();
        Console.WriteLine(capitalized);  // 출력: &quot;Hello world&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 &lt;u&gt;ToCapitalized&lt;/u&gt; &lt;b&gt;확장 메서드&lt;/b&gt;는 &lt;u&gt;string&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) LINQ 스타일의 확장 메서드 예제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드는 LINQ와 같은 방식으로 사용할 수 잇으며, 컬렉션을 처리하는 로직을 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726832134048&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static class CollectionExtensions
{
    // int 리스트에서 짝수만 반환하는 확장 메서드
    public static IEnumerable&amp;lt;int&amp;gt; GetEvenNumbers(this IEnumerable&amp;lt;int&amp;gt; numbers)
    {
        foreach (int number in numbers)
        {
            if (number % 2 == 0)
            {
                yield return number;
            }
        }
    }
}

public class Program
{
    public static void Main()
    {
        List&amp;lt;int&amp;gt; numbers = new List&amp;lt;int&amp;gt; { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        // 확장 메서드를 사용하여 짝수만 필터링
        IEnumerable&amp;lt;int&amp;gt; evenNumbers = numbers.GetEvenNumbers();

        Console.WriteLine(&quot;짝수만 출력:&quot;);
        foreach (int number in evenNumbers)
        {
            Console.WriteLine(number);  // 출력: 2, 4, 6, 8, 10
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 &lt;u&gt;GetEvenNumbers&lt;/u&gt;는 컬렉션을 필터링하는 LINQ스타일의 확장 메서드입니다. 기존의&lt;u&gt; List&amp;lt;int&amp;gt;&lt;/u&gt;에서 짝수만 필터링하는 메서드를 정의하여 LINQ와 비슷한 방식으로 사용할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사용 제약&lt;/b&gt;&lt;/h2&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;size18&quot;&gt;&lt;b&gt;1) 정적 클래스에서만 정의 가능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드는 반드시 &lt;b&gt;정적 클래스&lt;/b&gt;에서 정의되어야 하며, 클래스 내부에서 &lt;b&gt;this 키워드를 사용하여 확장할 대상을 지정&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;size18&quot;&gt;&lt;b&gt;2) 클래스의 인스턴스 메서드와 충돌 가능&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 비공개 멤버에 접근 불가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장 메서드는 해당 클래스의 &lt;b&gt;공개(public) 멤버에만 접근&lt;/b&gt;할 수 있습니다. 클래스 내부의&lt;b&gt; 비공개(private) 멤버에는 접근할 수 없습니다.&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#의 &lt;b&gt;확장 메서드&lt;/b&gt;는 클래스나 구조체의 동작을 확장하는 강력한 기능을 제공합니다. 이를 통해 기존 코드를 수정하지 않고도 새로운 기능을 추가할 수 있으며, LINQ와 같은 기능을 쉽게 구현할 수 있습니다. 또한 외부 라이브러리나 기존 클래스의 동작을 변경하지 않고도 메서드를 추가할 수 있기때문에, 확장 메서드는 코드의 유지보수성과 재사용성을 크게 향상시킬 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 C# 확장메서드에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/46</guid>
      <comments>https://unity-programming-study.tistory.com/46#entry46comment</comments>
      <pubDate>Fri, 13 Sep 2024 23:20:38 +0900</pubDate>
    </item>
    <item>
      <title>[Unity] 생명주기(Life Cycle)</title>
      <link>https://unity-programming-study.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서 MonoBehaviour는 모든 스크립트가 상속받는 기본 클래스입니다. 게임 오브젝트의 동작을 정의하고 제어할 때 사용되며, 이 클래스의 메서드들은 특정한 순서에 따라 &lt;b&gt;생명주기(lifecycle)동안 자동으로 호출&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;MonoBehaviour에 대해서는 다음에 알아보도록 하고, 이번 글에서는 생명주기에 대해서 알아보겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 생명주기란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity의 생명주기는 게임 오브젝트의 상태에 따라&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 생명주기 메서드 및 호출 순서&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;생명주기.jfif&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;2397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ngEyR/btsJrKmJn05/ZObgNgKPTqfNEFYW4ncF91/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ngEyR/btsJrKmJn05/ZObgNgKPTqfNEFYW4ncF91/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ngEyR/btsJrKmJn05/ZObgNgKPTqfNEFYW4ncF91/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FngEyR%2FbtsJrKmJn05%2FZObgNgKPTqfNEFYW4ncF91%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;1151&quot; height=&quot;2397&quot; data-filename=&quot;생명주기.jfif&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;2397&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;1)Awake():&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;&lt;b&gt;2) OnEnable():&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;&lt;b&gt;3) Reset():&lt;/b&gt; &lt;b&gt;컴포넌트가 처음 추가될 때&lt;/b&gt; 또는 &lt;b&gt;Unity 에디터의 Reset 버튼&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;4) Start():&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;5) FixedUpdate():&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;6) OnTriggerXXX():&lt;/b&gt; 오브젝트가 &lt;b&gt;Trigger 콜라이더와 충돌&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;7) OnCollisionXXX():&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;8) Update():&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;9) LateUpdate():&lt;/b&gt; 모든 &lt;b&gt;Update() 메서드가 완료된 후&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;10) OnApplicationQuit():&lt;/b&gt; 애플리케이션이 &lt;b&gt;종료되기 직전&lt;/b&gt;에 호출. Unity에디터에서&lt;b&gt; Play 모드를 중지&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;11) OnDisable():&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;12) OnDestroy():&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 생명주기의 중요성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity의 생명주기를 이해하는 것은 게임 오브젝트의 상태 변화를 적절히 처리하는데 있어 매우 중요합니다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 메서드는 특정 시점에 호출되므로, 이를 적절히 사용하여 초기화, 업데이트, 정리 작업을 효율적으로 수행할 수 있습니다. 특히 게임의 성능과 유연성을 높이기 위해 &lt;b&gt;각 메서드의 적절한 사용&lt;/b&gt;이 필요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Awake()와 Start()의 차이:&lt;/b&gt; Awake()는 오브젝트가 활성화되기 전 호출되며, Start()는 첫 프레임 전에 호출됩니다. 상호작용이 필요한 초기화 작업은 Start()에서 처리하는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FixedUpdate()와 Update()의 차이:&lt;/b&gt; FixedUpdate()는 물리 엔진과 관련된 연산을 처리하는데 사용하는 것이 좋으며, Update()는 프레임 기반으로 게임 로직을 처리하는 데 적합합니다. &lt;u&gt;(물리 관련 연산을 Update에서 진행할 경우 실행중인 하드웨어 성능에 따라 다른 결과를 얻을 수 있습니다.)&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LateUpdate()의 사용:&lt;/b&gt; LateUpdate()는 주로 카메라 이동이나 다른 오브젝트의 업데이트 후에 동작해야 할 로직을 처리할 때 사용합니다.&lt;/li&gt;
&lt;/ul&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 Unity 생명주기에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/44</guid>
      <comments>https://unity-programming-study.tistory.com/44#entry44comment</comments>
      <pubDate>Wed, 4 Sep 2024 23:05:03 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 참조 매개변수 전달 (ref, out)</title>
      <link>https://unity-programming-study.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서 &lt;b&gt;ref&lt;/b&gt;와 &lt;b&gt;out&lt;/b&gt; 키워드는 메서드에서 매개변수를 참조로 전달할 때 사용됩니다. 일반적으로 메서드는 매개변수의 값을 복사하여 전달하는&lt;b&gt; 값 전달 방식&lt;/b&gt;을 사용하지만, ref와 out을 사용하면 참조 전달이 가능합니다. 이를 통해 메서드가 호출된 변수의 값을 직접 변경할 수 있습니다.&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;이 글에서는 ref와 out 키워드의 사용법, 차이점, 그리고 예제를 통해 알아보도록 하겠습니다!&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. ref 키워드란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref(Reference)키워드는 메서드에 &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;size18&quot;&gt;&lt;b&gt;ref 키워드 사용 조건:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수는 메서드에 전달되기 &lt;b&gt;전에&lt;/b&gt; &lt;b&gt;반드시 초기화&lt;/b&gt;되어 있어야 합니다.&lt;/li&gt;
&lt;li&gt;메서드 내부에서 이 변수를 읽고 쓸 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725460251816&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class RefExample
{
    public void MultiplyByTwo(ref int number)
    {
        number *= 2;  // number의 값을 두 배로 변경
    }
}

public class Program
{
    public static void Main()
    {
        int myNumber = 5;
        RefExample example = new RefExample();
        
        example.MultiplyByTwo(ref myNumber);  // 변수 myNumber를 참조로 전달
        Console.WriteLine(myNumber);  // 출력: 10
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서&lt;b&gt; MultiplyByTwo&lt;/b&gt; 메서드는 &lt;b&gt;ref&lt;/b&gt; 키워드를 사용해&lt;b&gt; number&lt;/b&gt;를 참조로 전달받습니다. 따라서 메서드 내부에서 값을 변경하면,&lt;b&gt; myNumber&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. out 키워드란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;out 키워드는 메서드에서 매개변수를 &lt;b&gt;참조로 전달&lt;/b&gt;하지만, 주로 &lt;b&gt;값을 반환&lt;/b&gt;하는 용도로 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;out 매개변수는 메서드가 반환할 값을 담을 변수로 사용되며, &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;size18&quot;&gt;&lt;b&gt;out 키워드 사용 조건:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수는 메서드에 전달되기 전에&lt;b&gt; 초기화되지 않아도&lt;/b&gt; 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메서드 내부에서 이 변수에 값을 할당&lt;/b&gt;해야 하머, &lt;b&gt;반환 시 반드시 값을 설정&lt;/b&gt;해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725460378324&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class OutExample
{
    public void GetUserData(out string name, out int age)
    {
        name = &quot;Alice&quot;;  // 값 할당
        age = 30;        // 값 할당
    }
}

public class Program
{
    public static void Main()
    {
        string userName;
        int userAge;
        
        OutExample example = new OutExample();
        example.GetUserData(out userName, out userAge);  // out 매개변수로 값 반환
        
        Console.WriteLine($&quot;Name: {userName}, Age: {userAge}&quot;);  // 출력: Name: Alice, Age: 30
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 &lt;b&gt;GetUserData&lt;/b&gt; 메서드는 &lt;b&gt;name&lt;/b&gt;과 &lt;b&gt;age&lt;/b&gt;를 &lt;b&gt;out&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. ref와 out의 차이점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 초기화 여부&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ref:&lt;/b&gt; 변수는 메서드에 전달되기 &lt;b&gt;전에 반드시 초기화&lt;/b&gt;되어 있어야 합니다. 메서드가 호출되기 전에 이미 변수가 값이 있어야 하며, 메서드는 이 값을 수정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;out:&lt;/b&gt; 변수는 메서드에 전달되기 전에&lt;b&gt; 초기화하지 않아도&lt;/b&gt; 됩니다. 메서드가 실행되기 전에는 값이 없어도 되며, 메서드가 값을 할당하여 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 메서드 내부에서 값 할당 여부&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ref:&lt;/b&gt; &lt;b&gt;메서드 내부에서 변수를 읽고 쓸 수&lt;/b&gt; 있습니다. 메서드가 호출될 때 변수를 참조로 전달받아 기존 값을 수정하거나 유지할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;out:&lt;/b&gt; 메서드 내부에서 변수에&lt;b&gt; 반드시 값을 할당&lt;/b&gt;해야 합니다. 메서드가 값을 반환하기 위한 용도로 사용되며, 메서드 내에서 값을 할당하지 않으면 컴파일 오류가 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 주요 목적&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ref:&lt;/b&gt; 주로 &lt;b&gt;기존 값을 수정하거나 변경할 때 사용&lt;/b&gt;됩니다. 메서드에 전달된 변수를 참조로 전달하여 메서드 내부에서 그 값을 수정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;out:&lt;/b&gt; 주로 &lt;b&gt;값을 반환&lt;/b&gt;할 때 사용됩니다. 메서드가 여러 값을 반환해야 할 때, 반환 값으로 변수를 참조하여 결과를 전달하는 용도로 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) 사용 용도&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ref:&lt;/b&gt; 변수를 참조로 전달하여 메서드 내에서 값을 수정하고, 수정된 값을 메서드 외부에서도 사용해야할 때 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;out:&lt;/b&gt; 메서드에서 &lt;b&gt;여러 값을 반환&lt;/b&gt;해야 하거나, 메서드 내에서 값이 초기화되어 외부로 전달될 때 사용됩니다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. ref와 out을 사용하는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 참조 전달로 인한 성능 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref와 out을 사용하면 값 자체를 복사하지 않고, 그 값에 대한 참조를 전달하기 때문에 큰 데이터 구조를 다룰 때 메모리 효율성이 높아집니다. 값 타입 변수를 그대로 복사하는 경우 메모리 사용량이 증가할 수 있지만, 참조를 통해 전달하면 메모리 사용량을 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 메서드에서 여러 값을 반환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#의 메서드는 기본적으로 한 개의 값을 반환할 수 있지만, out키워드를 사용하면 메서드에서 여러 값을 반환할 수 있습니다. 이를 통해 복잡한 데이터를 메서드에서 한번에 처리하고 반환할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 값 수정 및 반환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref를 사룔하면 메서드 내부에서 값을 수정하여 외부로 변경된 값을 반환합니다. 이는 메서드 호출 전에 변수의 상태가 필요하며, 이를 변경하여 외부에 반영하고 싶을 때 유용합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) ref 키워드 사용 방법&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725460951019&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class RefExample
{
    public void Increment(ref int number)
    {
        number++;  // 값을 1 증가
    }
}

public class Program
{
    public static void Main()
    {
        int myNumber = 10;
        RefExample example = new RefExample();
        
        example.Increment(ref myNumber);  // myNumber를 참조로 전달
        Console.WriteLine(myNumber);  // 출력: 11
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 &lt;b&gt;Increment&lt;/b&gt;&amp;nbsp; 메서드는&lt;b&gt; ref&lt;/b&gt; 키워드를 사용해 &lt;b&gt;number&lt;/b&gt;를 참조로 전달받아 값을 1 증가 시킵니다. 메서드 외부에서 &lt;b&gt;myNumber&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) out 키워드 사용 방법&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725461003813&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Calculator
{
    // 두 정수를 나누고 몫, 나머지, 성공 여부를 반환하는 메서드
    public bool Divide(int numerator, int denominator, out int quotient, out int remainder)
    {
        if (denominator != 0) // 0으로 나누는 것은 불가능하므로 체크
        {
            quotient = numerator / denominator;   // 몫 계산
            remainder = numerator % denominator;  // 나머지 계산
            return true;  // 성공 시 true 반환
        }
        else
        {
            quotient = 0;  // 기본값 할당
            remainder = 0; // 기본값 할당
            return false;  // 실패 시 false 반환
        }
    }
}

public class Program
{
    public static void Main()
    {
        Calculator calculator = new Calculator();
        
        int quotient;   // 몫을 받을 변수
        int remainder;  // 나머지를 받을 변수
        
        // 두 수를 나누기
        bool isSuccess = calculator.Divide(10, 3, out quotient, out remainder);
        
        if (isSuccess)
        {
            Console.WriteLine($&quot;몫: {quotient}, 나머지: {remainder}&quot;);  // 출력: 몫: 3, 나머지: 1
        }
        else
        {
            Console.WriteLine(&quot;0으로 나눌 수 없습니다.&quot;);
        }
        
        // 0으로 나누기 시도
        isSuccess = calculator.Divide(10, 0, out quotient, out remainder);
        
        if (isSuccess)
        {
            Console.WriteLine($&quot;몫: {quotient}, 나머지: {remainder}&quot;);
        }
        else
        {
            Console.WriteLine(&quot;0으로 나눌 수 없습니다.&quot;);  // 출력: 0으로 나눌 수 없습니다.
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 &lt;b&gt;Divide&lt;/b&gt; 메서드는 두 정수의 나눗셈 결과를 &lt;b&gt;out&lt;/b&gt; 매개변수로 전달받아, 몫과 나머지를 반환합니다. 또한 메서드가&amp;nbsp; bool값을 리턴하기에 해당 변수를 통해 나눌 수 있는지 없는지를 확인할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;ref&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;b&gt;초기화 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;메서드 호출 전에 초기화 필요&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;메서드 호출 전에 초기화 불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;b&gt;값 할당 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;메서드 내부에서 읽고 쓰기 가능&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;메서드 내부에서 반드시 값 할당&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;b&gt;사용 목적&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;변수의 기존 값을 수정하는 용도&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;메서드에서 값을 반환하는 용도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;b&gt;주요 사용 사례&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;변수 수정, 상태 변경&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;다중 값 반환, 초기화가 필요 없는 경우&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref와 out은 C#에서 참조로 값을 전달하고 반환하는 두 가지 주요 방법입니다.&lt;b&gt; ref는 기존 값을 수정할 때,&lt;/b&gt; &lt;b&gt;out은 메서드에서 여러 값을 반환할 때 유용&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 C# ref와 out 키워드에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/43</guid>
      <comments>https://unity-programming-study.tistory.com/43#entry43comment</comments>
      <pubDate>Sat, 31 Aug 2024 21:31:47 +0900</pubDate>
    </item>
    <item>
      <title>[Unity] 속성(Attribute)</title>
      <link>https://unity-programming-study.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서 &lt;b&gt;Attribute(속성)&lt;/b&gt;는 &lt;b&gt;클래스, 메서드, 변수 등의 요소에 메타데이터를 추가하여, 특정 기능을 부여하거나 Unity 에디터에서의 동작을 제어하는 데 사용&lt;/b&gt;됩니다. 이 글에서는 Unity에서 자주 사용되는 Attribute에 대해 설명하며, 각각의 사용 방법과 예제를 통해 알아보겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Attribute(속성)란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Attribute&lt;/b&gt;는 &lt;b&gt;클래스, 메서드, 필드 또는 프로퍼티에 추가되는 메타데이터&lt;/b&gt;입니다. 이 메타데이터는 &lt;b&gt;런타임 또는 컴파일 타임에 특정 기능을 적용하거나, Unity 에디터에서의 동작을 변경하는 역할&lt;/b&gt;을 합니다. 예를 들어, Unity에서 &lt;b&gt;SerializeField&lt;/b&gt;, &lt;b&gt;Range&lt;/b&gt;, &lt;b&gt;Tooltip&lt;/b&gt;과 같은 Attribute는 에디터에서 변수를 시각화하고 편집하는 방식을 제어합니다.&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;Attribute는 &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;size18&quot;&gt;&lt;b&gt;예제:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725504756216&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Tooltip(&quot;This is a player's health value.&quot;)]
[SerializeField]
private int _playerHealth = 100;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 &lt;b&gt;Tooltip&lt;/b&gt;과 &lt;b&gt;SerializeField&lt;/b&gt;는 Unity에서 자주 사용되는 Attribute입니다.&lt;b&gt; Tooltip&lt;/b&gt;은 해당 변수를 마우스 오버할 때 설명을 표시하고, &lt;b&gt;SerializeField&lt;/b&gt;는 비공개 변수라도 Unity 에디터에서 직렬화할 수 있게 만들어, 인스펙터 창에 표기가 되도록 합니다. Attribute 명령어 설명은 아래에서 진행하겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1)메타데이터 역할&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Attruibute는 클래스, 메서드 또는 필드에 메타데이터를 추가하여, &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;size18&quot;&gt;&lt;b&gt;2) 에디터에서의 시각적 컨트롤&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서 Attribute는 주로 &lt;b&gt;에디터에서 변수의 표시 방식을 제어하는 데 사용&lt;/b&gt;됩니다. Range, Tooltip, Header와 같은 Attribute는 Unity 에디터에서 변수를 더 직관적으로 표시하도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 코드의 유지보수와 가독성 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Attribute를 사용하면 코드의 특정 부분에 대해 &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;size18&quot;&gt;&lt;b&gt;4) 사용자 정의 Attribute&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서는 내장된 Attribute 외에도 &lt;b&gt;사용자 정의 Attribute를 만들어 특정한 기능을 구현&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서 Attribute를 사용하는 이유는 다양하지만, 주된 이유는 에디터에서의&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 직관적인 변수 제어&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서는 변수가 에디터에서 어떻게 표시될지 제어할 수 있습니다. 예를 들어,&lt;b&gt; Range&lt;/b&gt;를 사용하면 슬라이더를 통해 변수를 조정할 수 있고, &lt;b&gt;Tooltip&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;size18&quot;&gt;&lt;b&gt;2) 비공개 변수의 직렬화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SerializeField&lt;/b&gt;와 같은 Attribute를 사용하면 비공개 변수를 직렬화하여 에디터에서 값을 설정할 수 있습니다. 이는 클래스 내부의 캡슐화를 유지하면서도 에디터에서 값 조정이 가능하게 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 특정 동작을 제어&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RequireComponent&lt;/b&gt;와 같은 Atrribute를 사용하면, 스크립트가 특정 컴포넌트를 반드시 필요로 하도록 강제할 수 있습니다. 이처럼 Attribute를 통해 런타임 시 특정 동작을 제어할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) 코드의 유지보수성 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Attribute를 통해 코드에 메타데이터를 추가하면, 다른 개발자나 미래의 자신이 코드를 읽을 때 더 쉽게 이해할 수 있습니다. 설명이나 경고를 추가하는 Attribute는 코드의 유지보수성을 향상시킬 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 자주 사용되는 Attribute&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) SerializeField&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SerializeField&lt;/b&gt;는 &lt;b&gt;비공개(private) 변수를 Unity 에디터에서 직렬화&lt;/b&gt;할 수 있게 해줍니다. 기본적으로 비공개 변수는 에디터에서 표시되지 않지만, SerializeField를 사용하면 이를 가능하게 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505586492&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[SerializeField]
private int _playerHealth = 100;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Tooltip&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Tooltip&lt;/b&gt;은 Unity에디터에서 &lt;b&gt;변수 위에 마우스를 올렸을 때 설명&lt;/b&gt;을 보여줍니다. 이 Attribute는 변수의 의미나 용도를 쉽게 설명할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505633295&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Tooltip(&quot;This is the player's health.&quot;)]
[SerializeField]
private int _playerHealth = 100;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) Range&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Range&lt;/b&gt;는 숫자형 변수에 범위를 설정하여, 에디터에서 &lt;b&gt;슬라이더를 통해 값을 설정&lt;/b&gt;할 수 있게 합니다. 이 Attribute는 주로 float 또는 int 변수에 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505680890&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Range(0, 100)]
public int _playerHealth = 50;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4)Header&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Header&lt;/b&gt;는 에디터에서 &lt;b&gt;변수들 위에 제목을 표시&lt;/b&gt;하여, 변수들을 그룹화하고 설명할 수 있습니다. 이를 통해 에디터에서 변수를 더 깔끔하게 정리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505714439&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Header(&quot;Player Settings&quot;)]
public int _playerHealth = 100;

[Header(&quot;Enemy Settings&quot;)]
public int _enemyHealth = 50;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5)RequireComponent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RequireComponent&lt;/b&gt;는 &lt;b&gt;특정 컴포넌트가 해당 스크립트에 필요할 때 사용&lt;/b&gt;하는 Attribute입니다. 이 Attribute를 사용하면, 컴포넌트가 없는 오브젝트에 스크립트를 추가할 때 자동으로 해당 컴포넌트가 추가됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505766069&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
    // Rigidbody가 자동으로 추가됩니다.
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6) HideInInspector&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HideInInspector&lt;/b&gt;는&lt;b&gt; 공개(public)된 변수를 에디터에서 숨길 때 사용&lt;/b&gt;됩니다. 이 Attribute를 사용하면 변수는 외부 클래스에서 접근할 수 있지만, 에디어에서는 보이지 않게 할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505826992&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[HideInInspector]
public int _hiddenValue = 42;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;7) ContextMenu&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ContextMenu&lt;/b&gt;는 에디터의 &lt;b&gt;인스펙터 창에서 특정 메서드를 오른쪽 클릭 메뉴로 실행&lt;/b&gt;할 수 있게 해줍니다. 디버깅하거나 테스트 목적으로 유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505874430&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Player : MonoBehaviour
{
    [ContextMenu(&quot;Reset Player Health&quot;)]
    public void ResetHealth()
    {
        Debug.Log(&quot;Player health reset!&quot;);
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8) ExecuteInEditMode&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ExecuteInEditMode&lt;/b&gt;는 &lt;b&gt;MonoBehaviour가 에디터 모드에서도 실행&lt;/b&gt;되도록 만듭니다. 일반적으로 MonoBehaviour는 플레이 모드에서만 실행되지만, 이 Attribute를 사용하면 에디터 모드에서도 Update, Start와 같은 메서드가 호출됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725505941386&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ExecuteInEditMode]
public class EditorScript : MonoBehaviour
{
    private void Update()
    {
        Debug.Log(&quot;Running in Edit Mode&quot;);
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;9) Space&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Space&lt;/b&gt;는 매개변수 없이 사용될 수 있으며,&lt;b&gt; 기본적으로 고정된 크기의 간격을 추&lt;/b&gt;가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드에서는 인스펙터에 표기된 _playerHealth, _playerScore, _playerLevel 사이의 기본 간격이 추가됩니다. 이는 인스펙터에서 변수를 보다 구분하기 쉽게 만들어 줍니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725506135843&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class SpaceExample : MonoBehaviour
{
    public int _playerHealth;

    [Space]  // 기본 간격 추가
    public int _playerScore;

    [Space]  // 또 다른 간격 추가
    public int _playerLevel;
}&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity에서 &lt;b&gt;Attribute&lt;/b&gt;는 매우 강력한 도구로, 에디터에서의 변수 제어부터 런타임 동작에 이르기까지 다양한 용도로 사용됩니다. &lt;b&gt;SerializeField, Range, Tooltip&lt;/b&gt;과 같은 내장 Attribute는 에디터에서 &lt;b&gt;변수를 더 직관적으로 관리&lt;/b&gt;하게 해주며, &lt;b&gt;RequireComponent나 ExecuteInEditMode&lt;/b&gt; 같은 Attribute는 &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;또한, 사용자 정의 Attribute를 만들어 &lt;b&gt;특정한 동작을 추가하거나 기능을 확장&lt;/b&gt;할 수도 있습니다. 이러한 Attribute는 개발을 더욱 효율적이고 직관적으로 만들어 주며, &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;이 글에서 소개한 Attribute들을 잘 활용하면, Unity에서의 개발 작업을 훨씬 더 원활하고 생산적으로 진행할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 Unity Attribute(속성)에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>Unity 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/42</guid>
      <comments>https://unity-programming-study.tistory.com/42#entry42comment</comments>
      <pubDate>Sat, 24 Aug 2024 00:25:18 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 오버로딩과 오버라이딩 (Overloading &amp;amp; Overriding)</title>
      <link>https://unity-programming-study.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#은 객체 지향 프로그래밍 언어로, &lt;b&gt;다형성(Polymorphism)을 지원&lt;/b&gt;합니다. 다형성의 중요한 두가지 개념이 바로 &lt;b&gt;오버로딩(Overloading)&lt;/b&gt;과 &lt;b&gt;오버라이딩(Overriding)&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 오버로딩(Overloading) 이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩(Overloading)은 &lt;b&gt;같은 이름의 메서드를 여러 개 정의하는 기법으&lt;/b&gt;로, 메서드의 매개변수의 수나 타입을 다르게 설정하여 동일한 메서드 이름을 여러 용도로 사용할 수 있게 해줍니다. C#에서는 메서드 오버로딩뿌만 아니라 생성자 오버로딩도 지원합니다.&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;size18&quot;&gt;&lt;b&gt;예제:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725107866104&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Calculator
{
    // 두 정수의 합을 구하는 메서드
    public int Add(int a, int b)
    {
        return a + b;
    }

    // 세 정수의 합을 구하는 메서드 (오버로딩)
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }

    // 두 실수의 합을 구하는 메서드 (오버로딩)
    public double Add(double a, double b)
    {
        return a + b;
    }
}&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;위 예제에선 'Add'메서드는 같은 이름을 가지지만, 매개변수의 타입과 수가 다르게 정의되어있습니다. 이를 통해 'Add' 메서드는 다양한 유형의 덧셈 연산을 수행할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 오버로딩의 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 C#에서 다형성을 구현하는 중요한 방법 중 하나입니다. 다음은 오버로딩의 주요 특징입니다.&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;size18&quot;&gt;&lt;b&gt;1) 같은 이름, 다른 시그니처&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 동일한 이름을 가진 여러 메서드를 정의할 수 있지만, 각 메서드는 다른 &lt;b&gt;매개변수 시그니처&lt;/b&gt;를 가져야 합니다. 시그니처는 메서드의 매개변수 타입, 수, 순서 등을 의미합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725107987034&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void Print(int number) { }
public void Print(string text) { }
public void Print(int number, string text) { }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 세 메서드는 모두 'Print'라는 동일한 이름을 가지고 있지만, 각각의 시그니처가 다르기 때문에 오버로딩이 가능합니다.&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;size18&quot;&gt;&lt;b&gt;2) 반환 타입은 오버로딩과 무관&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 오직 메서드의 시그니처에만 영향을 받습니다. 즉, 반환 타입이 다르다고 해서 메서드를 오버로딩할 수 있는 것은 아닙니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725108052064&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public int Calculate(int a) { return a * 2; }
public double Calculate(int a) { return a * 2.0; } // 오류: 매개변수 시그니처가 동일하므로 오버로딩 불가&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 컴파일 타임 다형성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 컴파일 타임 다형성(Compile-time Polymorphism)을 제공하여, 컴파일러는 메서드 호출 시점에 매개변수 타입과 수를 기반으로 적절한 메서드를 선택합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 오버로딩을 사용하는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 코드 가독성 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 의미의 작업을 수행하는 메서드들이 동일한 이름을 가지도록 함으로써, 코드의 가독성을 높일 수 있습니다. 예를 들어, 여러 타입의 덧셈 작업을 각각 다른 이름의 메서드로 정의하는 대신, 모두 'Add'라는 이름으로 정의하면 코드가 더 명확해 질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 유지보수성 향상&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;size18&quot;&gt;&lt;b&gt;3)매개변수에 따른 다양한 동작&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 오버로딩 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 기본 메서드 오버로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 일반적인 오버로딩은 매개변수의 타입이나 수를 변경하여 동일한 이름의 메서드를 여러 개 정의하는 것 입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725108340422&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Printer
{
    public void Print(string text)
    {
        Console.WriteLine(text);
    }

    public void Print(int number)
    {
        Console.WriteLine(number);
    }

    public void Print(string text, int number)
    {
        Console.WriteLine($&quot;{text}: {number}&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 'Print'메서드는 문자열, 정수, 문자열과 정수의 조합을 출력하는 세 가지 오버로드를 제공합니다.&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;size18&quot;&gt;&lt;b&gt;2) 생성자 오버로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 메서드뿐만 아니라 생성자(Constructor)에도 적용할 수 있습니다. 생성자 오버로딩을 통해 객체를 다양한 방법으로 초기화할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725108393485&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    // 기본 생성자
    public Person()
    {
        Name = &quot;Unknown&quot;;
        Age = 0;
    }

    // 이름만 초기화하는 생성자
    public Person(string name)
    {
        Name = name;
        Age = 0;
    }

    // 이름과 나이를 초기화하는 생성자
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드에서 'Person' 클래스는 세 가지 생성자를 가지고 있습니다. 이를 통해 객체를 다양한 방식으로 초기화할 수 있습니다.&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;size18&quot;&gt;&lt;b&gt;3) 연산자 오버로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서도 연산자도 오버로딩할 수 있습니다. 연산자 오버로딩을 통해 사용자 정의 타입에 대해 기본 연산자를 정의할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725108512194&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ComplexNumber
{
    public int Real { get; set; }
    public int Imaginary { get; set; }

    public ComplexNumber(int real, int imaginary)
    {
        Real = real;
        Imaginary = imaginary;
    }

    // '+' 연산자 오버로딩
    public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2)
    {
        return new ComplexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 '+' 연산자가 'ComplexNumber' 타입에 대해 오버로딩되어, 두 복소수를 더하는 기능을 제공합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 오버라이딩(Overriding)이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버라이딩(Overriding)&lt;/b&gt;은 &lt;b&gt;부모 클래스에서 정의된 메서드를 자식 클래스에서 재정의하여 사용하는 기법&lt;/b&gt;입니다. 오버라이딩은 &lt;b&gt;런타임 다형성(Runtime Polymorphism)&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; 'virtual'&lt;/b&gt; 키워드로 정의되어 있어야 하며, 자식 클래스에서는 &lt;b&gt;'override'&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;size18&quot;&gt;&lt;b&gt;예제:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725108851311&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine(&quot;Animal sound&quot;);
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine(&quot;Bark&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 'Animal' 클래스의 'Speak' 메서드는 'Dog'클래스에서 오버라이딩되어, 개가 짖는 소리(&quot;Bark&quot;)를 출력하도록 재정의되었습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 오버라이딩의 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1)동일한 시그니처&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버라이딩된 메서드는 부모 클래스에서 정의된 메서드와 동일한 시그니처(이름, 매개변수 타입, 수, 순서)를 가져야합니다. 시그니처가 다를 경우, 이는 오버로딩이 되지 오버라이딩이 되지는 않습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725109045131&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak() { }
}

public class Dog : Animal
{
    public override void Speak() { } // 정상: 시그니처 동일
    // public override void Speak(int volume) { } // 오류: 매개변수가 다르면 오버라이딩 불가
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 'virtual', 'override', 'sealed' 키워드&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;virtual: 부모 클래스에서 메서드를 오버라이딩할 수 있도록 정의할 때 사용합니다.&lt;/li&gt;
&lt;li&gt;override: 자식 클래스에서 부모 클래스의 메서드를 재정의할 때 사용합니다.&lt;/li&gt;
&lt;li&gt;sealed: 자식 클래스에서 오버라이딩된 메서드를 더 이상 다른 클래스에서 오버라이딩하지 못하도록 막을 때 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1725109138200&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak() { }
}

public class Dog : Animal
{
    public sealed override void Speak() { } // 더 이상 오버라이딩 불가
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 런타임 다형성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버라이딩은 런타임 다형성을 제공합니다. 이는 프로그램 실행 중에 어떤 메서드가 호출될지 결정되며, 부모 클래스의 참조 변수가 자식 클래스의 인스턴스를 참조할 때 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725109177967&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Animal myDog = new Dog();
myDog.Speak(); // 출력: Bark&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 'myDog'은 'Animal' 타입이지만, 실제로는 'Dog'클래스의 인스턴스를 참조하고 있습니다. 따라서 'Speak' 메서드는 'Dog' 클래스에서 재정의된 메서드가 호출됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 오버라이딩을 사용하는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 다형성 구현&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;size18&quot;&gt;&lt;b&gt;2) 상속 관계에서 기능 확장&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;size18&quot;&gt;&lt;b&gt;3) 코드 재사용&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;8. 오버라이딩 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버라이딩을 사용하는 방법은 간단합니다. 부모 클래스에서 virtual로 정의된 메서드를 자식 클래스에서 override키워드를 사용해 재정의하면 됩니다. 몇 가지 예제를 통해 오버라이딩을 사용하는 방법을 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 기본 메서드 오버라이딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 클래스에서 정의된 메서드를 자식 클래스에서 오버라이딩하여 새로운 동작을 구현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725109636221&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine(&quot;Animal sound&quot;);
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine(&quot;Bark&quot;);
    }
}

public class Cat : Animal
{
    public override void Speak()
    {
        Console.WriteLine(&quot;Meow&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 Dog와 Cat 클래스는 Animal 클래스의 Speak 메서드를 오버라이딩하여 각각 다른 소리를 출력합니다.&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;size18&quot;&gt;&lt;b&gt;2) 기본 동작 유지 및 확장&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버라이딩 메서드에서 부모 클래스의 기본 동작을 유지하면서 추가 기능을 구현할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725109689180&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine(&quot;Animal sound&quot;);
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        base.Speak(); // 부모 클래스의 기본 동작 호출
        Console.WriteLine(&quot;Bark&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 Dog 클래스의 Speak 메서드는 부모 클래스의 Speak 메서드를 호출한 후, 추가로 &quot;Bark&quot;를 출력합니다.&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;size18&quot;&gt;&lt;b&gt;3) sealed 키워드로 오버라이딩 막기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 클래스에서 오버라이딩된 메서드가 더 이상 다른 클래스에서 오버라이딩되지 않도록 sealed키워드를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1725109753812&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine(&quot;Animal sound&quot;);
    }
}

public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine(&quot;Bark&quot;);
    }
}

public class Bulldog : Dog
{
    // 오류: Dog 클래스의 Speak 메서드는 sealed로 인해 오버라이딩 불가
    // public override void Speak()
    // {
    //     Console.WriteLine(&quot;Bulldog bark&quot;);
    // }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 Dog 클래스의 Speak 메서드는 sealed로 지정되어 있어, Bulldog 클래스에서 오버라이딩할 수 없습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h2&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;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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 C# 오버로딩과 오버라이딩에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/41</guid>
      <comments>https://unity-programming-study.tistory.com/41#entry41comment</comments>
      <pubDate>Tue, 20 Aug 2024 20:51:22 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 람다식(Lambda Expression)</title>
      <link>https://unity-programming-study.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C#에서&lt;/b&gt;람다식(Lambda Expression)은&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 람다식이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은&lt;b&gt; 익명 함수(Anonymous Function)의 한 종류&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;/p&gt;
&lt;pre id=&quot;code_1724155833071&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(parameters) =&amp;gt; expression&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;parameters'는 입력 매개변수를, 'expresstion'은 실행할 코드 블록을 나타냅니다. 일반적으로 람다식은 짧고 간단한 함수들을 표현하기 위해 사용됩니다.&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;pre id=&quot;code_1724155883312&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = x =&amp;gt; x * x;
Console.WriteLine(square(5)); // 출력: 25&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 'x =&amp;gt; x * x'가 람다식입니다. 이 식은 'x'라는 매개 변수를 받아 'x * x'를 반환하는 익명 함수를 나타냅니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 람다식의 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 C#에서 &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;size18&quot;&gt;&lt;b&gt;1) 익명성&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 간결성&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;pre id=&quot;code_1724156185024&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public int Square(int x)
{
    return x * x;
}&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;b&gt;람다식으로 표현:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724156197050&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = x =&amp;gt; x * x;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 함수형 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 C#에서 함수형 프로그래밍의 일부 개념을 구현할 수 있게 해줍니다. 함수형 프로그래밍은 함수를 일급 시민(First-Class Citizen)으로 취급하며, 함수 자체를 변수에 할당하거나 다른 함수에 전달 할 수 있습니다.&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;size18&quot;&gt;&lt;b&gt;4) 표현식과 문&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;pre id=&quot;code_1724156306274&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = x =&amp;gt; x * x;&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;b&gt;여러줄로 구성:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724156323336&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int, int&amp;gt; add = (x, y) =&amp;gt;
{
    int result = x + y;
    return result;
};&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5) 타입 추론&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;pre id=&quot;code_1724156391815&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = (int x) =&amp;gt; x * x;&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;b&gt;타입 추론:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724156416299&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = x =&amp;gt; x * x;&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 람다식을 사용하는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 코드의 간결화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 코드를 간결하게 만들어 가독성을 높입니다. 특히, LINQ(Language Integrated Query)와 함께 사용될 때 매우 유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724156607757&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] numbers = { 2, 3, 4, 5 };
var squaredNumbers = numbers.Select(x =&amp;gt; x * x);
Console.WriteLine(string.Join(&quot;, &quot;, squaredNumbers)); // 출력: 4, 9, 16, 25&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 고차 함수(Higher-Order Function) 활용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 함수를 인자를 전달하거나, 함수를 반환하는 고차 함수를 쉽게 구현할 수 있게 해줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724156731388&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, Func&amp;lt;int, int&amp;gt;&amp;gt; add = x =&amp;gt; y =&amp;gt; x + y;
var addFive = add(5);
Console.WriteLine(addFive(3)); // 출력: 8&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) 즉시 실행 및 콜백&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 로직을 즉시 실행하거나, 비동기 작업에서 콜백으로 사용할 때 유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724156931684&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void A()
{
	Action&amp;lt;string&amp;gt; greet = name =&amp;gt; Console.WriteLine($&quot;Hello, {name}!&quot;);
	B(greet);
}

public void B(Action&amp;lt;string&amp;gt; action)
{
	action(&quot;World&quot;); // 출력: Hello, World!
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) LINQ와의 통합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 LINQ쿼리에서 사용되는 주요 구성 요소입니다.&amp;nbsp; LINQ쿼리에서 데이터를 필터링하거나 변환할 때 람다식을 사용하면 매우 직관적이고 간결한 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724157015585&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] numbers = { 1, 2, 3, 4, 5, 6 };
var evenNumbers = numbers.Where(x =&amp;gt; x % 2 == 0);
Console.WriteLine(string.Join(&quot;, &quot;, evenNumbers)); // 출력: 2, 4, 6&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;&amp;nbsp;&lt;/p&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 람다식의 단점&lt;/b&gt;&lt;/h2&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;size18&quot;&gt;&lt;b&gt;1. 디버깅의 어려움&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 익명 함수로, 이름이 없기 때문에 디버깅이 복잡해질 수 있습니다. 특히, 여러 개의 중첩된 람다식이나 복잡한 LINQ쿼리를 디버깅할 때는 호출 스택에서 어떤 람디식이 실행 중인지 파악하기 어렵습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724158845958&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var numbers = new[] { 1, 2, 3, 4, 5 };
var result = numbers.Where(x =&amp;gt; x % 2 == 0).Select(x =&amp;gt; x * x);&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;&lt;b&gt;2. 복잡한 로직에 부적합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 간단한 로직을 포현할 때 매우 유용하지만, 복잡한 로직을 담기에는 적합하지 않습니다. 여러 줄의 코드나 복잡한 조건이 포함된 람다식은 가독성을 떨어트리고 유지보수를 어렵게 할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724158911217&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var complexCalculation = (int x, int y) =&amp;gt;
{
    if (x &amp;gt; y)
        return x * y;
    else if (x == y)
        return x + y;
    else
        return x - y;
};&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;&lt;b&gt;3. 타입 안전성 문제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 컴파일러가 매개변수의 타입을 추론할 수 있지만, 일부 상황에서는 타입 추론이 올바르지 않거나 명확하지 않을 수 있습니다. 특히 복잡한 표현식에서 타입 오류가 발생할 수 있으며, 이런 경우 명시적으로 타입을 지정해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724158966147&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var calculate = (x, y) =&amp;gt; x + y; // 컴파일러가 x와 y의 타입을 잘못 추론할 수 있음&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. 익명 함수의 재사용 불가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 익명 함수이므로, 동일한 로직을 여러 곳에서 사용해야 할 경우, 코드의 중복이 발생할 수 있습니다. 메서드나 함수로 정의된 코드와 달리, 람다식은 별도의 이름이 없기 때문에 재사용성이 떨어집니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159008982&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 동일한 람다식을 여러 번 작성해야 하는 경우
var list1 = numbers.Where(x =&amp;gt; x &amp;gt; 5).ToList();
var list2 = numbers.Where(x =&amp;gt; x &amp;lt; 3).ToList();&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;&lt;b&gt;5. 가독성 저하&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식을 남용하거나 너무 복잡하게 사용할 경우, 코드의 가독성이 저하될 수 있습니다. 특히, 람디식에 익숙하지 않은 개발자나 팀에서는 이러한 코드를 이해하기 어려울 수 있습니다. 가독성은 코드 유지 보수성에 중요한 요소이므로, 적잘한 사용이 필요합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159071162&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var result = list.Where(x =&amp;gt; x.Prop1 &amp;gt; 10 &amp;amp;&amp;amp; x.Prop2 &amp;lt; 20)
                 .Select(x =&amp;gt; new { x.Prop1, x.Prop2 })
                 .OrderBy(x =&amp;gt; x.Prop1)
                 .ThenByDescending(x =&amp;gt; x.Prop2)
                 .ToList();&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식을 사용하는 방법은 매우 다양하며, 대부분의 경우 함수와 대리자(delegate)와 함께 사용됩니다. 아래에 다양한 예제를 통해 람다식 사용 방법을 설명하겠습니다.&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;size18&quot;&gt;&lt;b&gt;1) 단순한 람다식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 람다식은 매개변수를 받아서 단일 표현식을 수행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159171679&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int&amp;gt; square = x =&amp;gt; x * x;
Console.WriteLine(square(9)); // 출력: 81&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 매개변수가 여러 개인 람다식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 매개변수를 받는 람다식도 정의할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159207734&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int, int&amp;gt; add = (x, y) =&amp;gt; x + y;
Console.WriteLine(add(3, 4)); // 출력: 7&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;size18&quot;&gt;&amp;nbsp;&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;b&gt;3) 매개변수 없이 사용 가능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매개변수가 없는 람다식도 정의할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159372452&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;string&amp;gt; greet = () =&amp;gt; &quot;Hello, World!&quot;;
Console.WriteLine(greet()); // 출력: Hello, World!&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) 문 블록 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 하나의 표현식 대신 여러 줄의 문으로 구성된 블록을 포함할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159398987&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Func&amp;lt;int, int, int&amp;gt; multiplyAndAdd = (x, y) =&amp;gt;
{
    int result = x * y;
    return result + y;
};
Console.WriteLine(multiplyAndAdd(3, 4)); // 출력: 16&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5) 대리자와 함께 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 대리자(delegate)와 함께 사용되어 익명 함수를 대리자에할당할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159448772&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Action&amp;lt;string&amp;gt; displayMessage = message =&amp;gt; Console.WriteLine(message);
displayMessage(&quot;Lambda expressions are powerful!&quot;); // 출력: Lambda expressions are powerful!&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6) 이벤트 핸들러로 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 핸들러로 람다식을 사용하면 짧고 간결한 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159698814&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Button myButton = new Button();
myButton.Click += (sender, args) =&amp;gt; Console.WriteLine(&quot;Button clicked!&quot;);&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;7) LINQ에서 람다식 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LINQ쿼리에서 람다식을 사용하여 데이터를 필터링하거나 변환할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159472911&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] numbers = { 1, 2, 3, 4, 5 };
var doubledNumbers = numbers.Select(x =&amp;gt; x * 2);
Console.WriteLine(string.Join(&quot;, &quot;, doubledNumbers)); // 출력: 2, 4, 6, 8, 10&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8) 익명 형식과의 결합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 익명 형식과 함께 사용하여 더 복잡한 데이터를 쉽게 처리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1724159500294&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var students = new[]
{
    new { Name = &quot;John&quot;, Age = 18 },
    new { Name = &quot;Jane&quot;, Age = 20 },
    new { Name = &quot;Jake&quot;, Age = 19 }
};

var adults = students.Where(s =&amp;gt; s.Age &amp;gt;= 19).Select(s =&amp;gt; s.Name);
Console.WriteLine(string.Join(&quot;, &quot;, adults)); // 출력: Jane, Jake&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 C#에서 매우 강력한 기능으로, 간결한 코드 작성과 더 나은 가독성을 제공하는 데 큰 역할을 합니다. 익명 메서드를 표현하는 람다식은 특히 LINQ, 델리게이트, 이벤트 처리, 고차 함수와 함께 사용될 때 그 진가를 발휘합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 소개한 람다식의 특징, 사용 이유, 그리고 다양한 사용 방법을 통해, 더 효율적이고 표현력 있는 C# 코드를 작성할 수 있게 될 것입니다. C# 프로그래밍에서 람다식을 적극적으로 활용해 보세요!&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;지금까지 C# 람다식에 대해 알아보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;현재 글의 내용 중 틀린 부분이나, 지적하실 내용이 있으시다면 언제든지 알려주세요! 읽어주셔서 감사합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>CS 공부</category>
      <author>때류기</author>
      <guid isPermaLink="true">https://unity-programming-study.tistory.com/40</guid>
      <comments>https://unity-programming-study.tistory.com/40#entry40comment</comments>
      <pubDate>Fri, 16 Aug 2024 23:33:52 +0900</pubDate>
    </item>
  </channel>
</rss>