기술 면접 준비 - (11~18)

이준호·2024년 2월 3일
0

📌 기술면접 준비 (11 ~ 18)



11. 델리게이트(Delegate)의 개념에 대해 설명해주세요.

델리게이트(Delegate)는 C#에서 함수에 대한 참조를 저장하는 타입입니다. 즉, 함수를 가리키는 포인터와 같습니다. 메서드의 시그니처(매개변수 및 반환타입)에 따라 델리게이트의 타입이 결정되고, 타입 안정성과 다중 호출(Multicast)를 제공하며, 이를 이용해 이벤트 핸들링이나 콜백 메소드 등에서 특정 함수를 동적으로 호출할 수 있습니다. 보통 유니티에서는 게임 이벤트 처리나 비동기(Async) 작업의 콜백 등에 활용되며 코드의 모듈화와 유지보수성에 도움이 됩니다.

콜백 메소드(Callback Function) : 다른 함수의 인자로써 이용되는 함수, 어떤 이벤트에 의해 호출되어지는 함수.

이벤트 핸들링(Evnet Handling) : 특정 이벤트가 발생했을 때, 그에 대응하는 동작

이벤트 핸들러(Event Handler) : 이벤트 핸들링에서 이벤트에 대응하는 동작을 수행하는 함수나 메서드.
(이벤트에 가입하는 구독자 측에서는 이벤트가 발생했을 때, 어떤 명령들을 실행할지 지정해주는 것.)








12. ‘delegate’, ‘event’, ‘action’, ‘func’ 간의 차이를 설명해주세요.

Delegate : 델리게이트는 메서드에 대한 참조를 저장하는 객체입니다. 델리게이트 타입은 메서드의 매개변수 타입, 반환타입 을 기반으로 정의됩니다.

Event : 이벤트는 델리게이트의 특별한 형태로 "특정 클래스 내에서"만 발생하도록 제한된 "델리게이트"입니다. 클래스 외부에서 직접 호출되는 것을 방지하고, 안전한 이벤트 처리가 가능합니다.

Action : 액션은 "반환값이 없는 메소드"를 참조하는 "델리게이트"입니다.
다만, 액션은 제네릭을 사용하여 참조하는 메서드의 매개변수 타입을 지정할 수 있습니다.

Func : 펑션은 "반환값이 있는 메소드"를 참조하는 "델리게이트"입니다. 펑션 또한 제네릭을 사용하여 참조하는 메소드의 매개변수 타입과 반환타입을 지정할 수 있습니다.

a. (꼬리질문) 프로젝트에 적용해 본 경험이 있다면 설명해주세요.

Event / Action : Input System 옵저버 패턴
InputSystem에서 플레이어의 입력을 감지하면 event Action를 사용하여 On@@Enent?.Invoke() 해당 키의 감지가 필요한 구독자들에게 뿌려주는 형식으로 사용했습니다.

Func : Behavior Tree Action(Leaf) Node
Enemy의 AI를 구현하기 위해 Behavior Tree를 사용했었는데, 그 중에 말단 노드 Action(Leaf) Node를 각각의 클래스가 아닌 Func 형식으로 사용하여 생성자 파라미터에 메소드를 넣게 하여 BT를 구성할 때, 액션노드에 필요한 메소드를 구현하고 생성자를 통해 파라미터에 메소드를 넣어 실행하는 방식으로 사용하였습니다.


13. 람다식(Lambda Expression)이 무엇인지 설명해주세요.

람다식(Lamda Expression)은 익명 함수를 간결하게 선언하는 방법입니다. 메서드처럼 입력 매개변수를 받고, 실행할 내부 코드를 가지지만 이름이 없습니다.
람다식은 주로 Delegate, Action, Func, LINQ등에서 자주 사용됩니다. 메소드의 매개변수로 전달하거나, 메소드의 반환값으로 사용이 가능합니다.

람다 : 캡처된다?? 주변 변수를 캡처링? 하면서 메모리 누수등의 단점이 있다?


14. 콜백이란 무엇인가요? 사용해봤는지?

콜백(Callback)은 특정 이벤트나 조건이 발생했을 때, 함수 또는 메서드를 다른 함수나 메서드의 매개변수로 전달해서 호출되도록 하는 프로그래밍 패턴입니다. 콜백은 비동기적인 작업이나 이벤트의 처리를 구현할 수 있으며, 델리게이트, Action, Fun 등 대리자나 대리자 파생형등에서 콜백을 구현할 수 있고 async같은 비동기 처리를 이용해 콜백을 구현할 수 있습니다.
저는 로딩씬을 구현할 때 콜백을 활용해본 경험이 있습니다. 게임에서 다음(새로운)씬을 로드하는 동안, 로딩 씬을 통해 다음 씬에 필요한 정보들을 미리 가져오면서 로딩씬에서 그 진행도를 보여주었습니다. 'SceneManager.LoadSceneAsync'를 사용하였는데, 'LoadSceneAsync'는 비동기 작업을 반환하므로 로딩이 완료되었을 때 어떤 동작을 해야하는지를 콜백으로 구현하였습니다.'LoadSceneAsync'의 'AsyncOperation'을 사용하여 로딩 진행상황을 UI에 나타내고, 로딩이 완료되면 콜백 함수에서 로딩씬을 종료하고 새로 로드된 씬으로 활성화 시키는 작업을 수행하였습니다.


15. 정렬 알고리즘이란 무엇이며, 사용 이유에 대해 설명해주세요.

정렬 알고리즘은 데이터를 특정 기준에 따라 순서대로 정렬하는 방법을 말합니다. 정렬 알고리즘에는 "버블 정렬", "선택 정렬", "퀵 정렬", "병합 정렬", "힙 정렬" 등 다양한 종류가 있습니다.
또한 이 정렬 알고리즘은 '데이터 분석', '검색', '그래픽스', '물리 계산', '알고리즘 최적화' 등 다양한 분야에서 사용됩니다.
정렬 알고리즘을 사용하는 이유로는 정렬된 데이터가 검색(Serch)에 효율적이기 때문입니다. 예를 들자면, 이진 검색 알고리즘 같은 정렬된 데이터에서 특정 값을 매우 빠르게 찾을 수 있게 해줍니다.
데이터가 정렬되어 있다면 데이터의 최소/최댓값 이나 중간값 등을 찾기가 매우 쉬워집니다.
C# 유니티에서는 리스트와 배열에 .Sort 내장 함수와 .Reverse 를 제공해주어 오름차순 및 내림차순으로 쉽게 정렬이 가능합니다.


16. 선택 정렬과 버블 정렬에 대해 설명해주시고, 코드를 작성해보세요.

선택 정렬 : 선택 정렬은 정렬하고자 하는 배열중 최솟값(or 최댓값)을 찾아 맨 앞의 값과 위치를 바꿔주고, 다음으로 작은 값(or 큰 값)을 찾아 그 다음 번째 위치의 값과 바꿔주는 과정을 반복합니다. 이렇게 끝까지 반복하면 정렬된 값들을 얻을 수 있습니다.

void SelectionAlgorithm(int[] value)
{
	int temp = 0;
	int minIndex = 0;

	for (int i = 0; i < value.Length - 1; i++)
    {
    	minIndex = i;
    	for (int j = i; j < value.Length; j++)
  		{
  			if (value[j] < value[minIndex]
            {
            	minIndex = j;
            }
  		}

        temp = value[minIndex];
        value[minIndex] = value[i];
        value[i] = temp;
    }
}       

버블 정렬 : 버블 정렬은 인접한 두 원소를 비교하여 크기가 큰(or 작은) 값을 앞으로 보내는 방식입니다. 이 과정을 배열의 크기 - 1 만큼 (0부터 시작하기에) 반복하면 정렬된 값들을 얻을 수 있습니다.

void BubbleSort(int[] value)
{
    int temp = 0;

    for (int i = 0; i < value.Length - 1; i++)
    {
        for (int j = 0; j < value.Length - 1 - i; j++)
        {
            if (value[j] > value[j + 1])
            {
                temp = value[j];
                value[j] = value[j + 1];
                value[j + 1] = temp;
            }
        }
    }
}                                       

두 정렬 모두 조건식에 따라 오름차순/내림차순이 가능합니다.
하지만 이 두 정렬 알고리즘은 시간 복잡도가 O(n^2)이므로, 데이터의 양이 많아질수록 효율이 매우 떨어집니다.


17. 스택, 힙 메모리란 무엇이며 어떤 차이가 있는지 비교해서 설명해주세요.

스택(Stack) : 스택은 값 형식(Value Type)이 저장됩니다. 프로그램을 실행하는데 필요한 메모리 공간으로, 메소드가 호출되는데 필요한 메모리가 스택에 저장됩니다. 필요한 메모리란, 메소드가 사용하는 코드 즉 "지역변수", "매개변수(파라미터)", 리턴값 등이 있습니다. 컴퓨터 메모리는 한계가 존재하기 때문에, 무턱대고 코드를 메모리에 저장하면 메모리 한계(Stack Overflow)에 부딪혀 더이상 정보를 저장할 수 없습니다. 그래서 메모리를 효율적으로 사용하기 위해, 함수의 호출이 종료되면 그에 따른 스택 메모리도 자동으로 해체되며 LIFO(Last In First Out, 후입선출) 방식으로 가장 나중에 저장된 값을 먼저 반환합니다.

힙(Heap) : 힙은 참조 형식(Reference Type)이 저장됩니다. 힙에서는 new키워드를 이용해서 생성한 메모리가 저장됩니다. 클래스를 생성할 때 new 키워드로 생성하기 때문에, 메소드가 아닌 "전역변수"도 힙에 저장됩니다. "배열", "컬렉션", "일반화 컬렉션"도 new 키워드로 생성하기 때문에 힙에 저장됩니다. 힙은 메모리 제한이 없기 때문에 클래스는 힙에 저장됩니다. 스택 메모리에서 메모리 주소를 할당하고 그 주소는 힙 메모리를 가르키는 지정표가 되어 힙 메모리에서 주소에 맞는 값에 접합니다. 스택에서는 LIFO 방식으로 메모리를 삭제하지만 힙에서는 힙의 값을 가리키는 주소가 스택에 저장되어있지 않으면 값은 존재하지만 접근이 불가능합니다. C#에서는 이렇게 주소가 삭제되어 접근이 불가능한 힙 메모리들을 GC(Garbage Colector)가 삭제해주지만, 언제 GC가 삭제할지는 모릅니다.

데이터의 복구가 가능한 이유중 하나가 힙 메모리 때문입니다. 어떠한 정보를 삭제할떄 그 정보가 아직 힙에 저장되어 있다면 컴퓨터는 스택 메모리안의 해당 주소값만 삭제합니다. 그렇기에 주소가 없어서 접근은 불가능하지만, 아직 정보는 힙에 살아있습니다. 다만 GC가비지 컬랙터가 삭제하지 전까지만 입니다.

스택은 "접근 속도"가 빠르고, "메모리 크기"에 제한이 있습니다, "삭제"는 LIFO방식으로 삭제되며, "변수 접근"이 해당 메소드 내에서만 접근이 가능합니다.

힙은 "접근 속도"가 상대적으로 느립니다. "메모리 크기"에는 제한이 없고, "삭제"는 GC가 알아서 삭제합니다. "변수 접근"이 전역적으로 접근이 가능합니다.


18. 값 형식과 참조 형식의 차이에 대해 설명해주세요.

값 형식(Value Type)은 데이터가 변수에 직접 저장되는 형식입니다. "int", "float", "double", "bool", "char" 등과 "구조체(Struct)", "열거형(Enum)" 등 기본적으로 제공되는 데이터 타입이 해당됩니다. 값 형식은 변수가 다른 변수에 할당된다면, 그 값이 복사되서 새로운 메모리 공간에 저장이 됩니다. 그렇기에 원본 변수와 복사된 변수는 서로 독립적인 메모리 공간을 가지고, 변수의 변경이 다른 변수에게 영향을 주지 않습니다.
참조 형식(Reference Type)은 메모리 힙(Heap)영역에 데이터가 저장되고, 스택에 변수 해당 데이터의 참조(주소)를 저장합니다. "클래스", "인터페이스", "배열", "델리데이트" 등의 클래스 및 컬랙션 전역변수가 해당됩니다. 참조 현식의 변수가 다른 변수에 할당이 되면, 참조가 복사가 되어 같은 메모리의 공간을 가르키게 됩니다(주소의 복사). 따라서 변수의 변경이 같은 참조를 가지는 다른 변수에 영향을 주기에 "얕은 복사", "깊은 복사"를 유의하며 잘 생각하고 사용하여야 합니다.

값과 참조 형식의 차이점으로는
저장 방식 및 메모리의 위치 :
값 형식은 변수가 값을 지접 저장하고(스택메모리) 참조 형식은 변수가 값의 주소를 저장하고(스택 메모리에는 값의 주소를 저장) 실제 값은 힙 메모리에 저장됩니다.
값의 할당 :
값 형식의 경우는 다른 변수에 할당하면 값이 복사가 되어서 완전히 새로운 복사본이고 독립적이지만, 참조 형식의 경우는 다른 변수에 할당하면 주소가 복사가 되어 두 변수는 같은 객체(값)을 가리키게 됩니다.
가변성:
값 형식은한번 생성하면 값을 변경할 수가 없습니다. 값을 변경하려고 하면 새로운 값을 가진 객체가 생성됩니다.참조 형식은 값 형식과 다르게 객체의 상태를 변경할 수 있습니다.

profile
No Easy Day

0개의 댓글