2025-07-28 면접 복기 TIL
오늘 진행된 기술 면접에서 받았던 질문들을 복기하고, 답변했던 내용에 살을 붙여 깊이 있게 정리합니다. 특히 게임 개발의 핵심인 길찾기 알고리즘과 C#의 메모리 관리, 객체 지향 개념에 대한 질문이 주를 이뤘습니다.
Part 1: 길찾기 알고리즘 (Pathfinding Algorithm)
게임 속 캐릭터가 장애물을 피해 목적지까지 가장 효율적인 경로를 찾는 것은 게임 플레이의 핵심적인 요소입니다. 이를 위해 다양한 길찾기 알고리즘이 사용됩니다.
1. 길찾기 알고리즘의 종류와 차이점
면접에서는 다양한 길찾기 알고리즘을 알고 있는지, 그리고 각 알고리즘의 특징과 차이점을 이해하고 있는지 질문했습니다.
| 알고리즘 | 핵심 특징 | 주요 용도 및 장단점 |
|---|---|---|
| DFS (깊이 우선 탐색) | 한 방향으로 끝까지 탐색 후, 막히면 돌아와 다른 경로 탐색 | 장점: 구현이 간단함. 경로가 존재 하는지 여부만 빠르게 확인할 때 유리. 단점: 최단 거리를 보장하지 않으며, 매우 비효율적인 경로를 찾을 수 있음. |
| BFS (너비 우선 탐색) | 시작 지점에서 가까운 순서대로 주변을 탐색 | 장점: 모든 간선의 가중치가 동일할 때, 최단 거리를 보장함. 단점: 경로가 길어질수록 탐색해야 할 노드가 기하급수적으로 늘어나 메모리 소모가 큼. |
| Dijkstra (다익스트라) | 가중치가 있는 그래프에서 한 정점으로부터 다른 모든 정점까지의 최단 거리를 계산 | 장점: 가중치(이동 비용)가 다른 맵에서도 정확한 최단 거리를 보장함. 단점: 목적지와 상관없이 모든 방향으로 탐색을 확장하므로, 특정 목적지를 찾는 데는 비효율적일 수 있음. (음수 가중치 처리 불가) |
| A* (A-Star) | 다익스트라에 휴리스틱(Heuristic) 추정치를 더해 탐색 방향을 최적화 | 장점: 목적지 방향으로 우선 탐색하여 매우 빠르고 효율적임. 게임 길찾기에서 가장 널리 사용됨. 단점: 휴리스틱 함수 설계에 따라 성능과 정확도가 달라질 수 있음. |
| Floyd-Warshall (플로이드-워셜) | 그래프의 모든 정점 쌍 사이의 최단 거리를 한 번에 계산 | 장점: 모든 지점 간의 최단 경로 정보가 필요할 때 유용함 (예: RTS 게임 유닛 상성 거리 계산). 단점: 시간 복잡도가 O(N³)으로 매우 높아, 노드(N)가 많은 실시간 길찾기에는 부적합함. |
2. A* 알고리즘 상세 설명
"A* 알고리즘은 길찾기 문제에서 '똑똑한 추측'을 통해 불필요한 탐색을 줄이는 가장 실용적인 해법입니다."
A* 알고리즘은 현재까지의 실제 이동 비용과 앞으로 가야 할 예상 비용을 더해, 가장 합리적인 경로를 우선적으로 탐색하는 방식입니다. 이는 다음 공식으로 표현됩니다.
F(n) = G(n) + H(n)
G(n): 실제 비용 (Past Path Cost) - 시작 노드에서 현재 노드 'n'까지 이동하는 데 소요된 실제 누적 비용입니다.H(n): 추정 비용 (Heuristic) - 현재 노드 'n'에서 최종 목적지까지 도달하는 데 필요할 것으로 '추정'되는 비용입니다. 이 추정치는 실제보다 항상 작거나 같아야 최적의 해를 보장합니다. (Admissible Heuristic)F(n): 총 예상 비용 - 이 F값이 가장 작은 노드를 우선적으로 탐색합니다. (보통 우선순위 큐(Priority Queue)를 사용)
예를 들어, H(n)을 계산하는 휴리스틱 함수로는 장애물을 무시하고 직선거리를 계산하는 유클리드 거리나, 가로/세로 이동 비용만 계산하는 맨해튼 거리가 주로 사용됩니다. 이 '똑똑한 추측' 덕분에 A*는 목적지와 전혀 상관없는 방향으로는 거의 탐색을 진행하지 않아 매우 높은 효율을 보입니다.
Part 2: C# 핵심 개념
C# 언어의 핵심적인 객체 지향 개념과 메모리 관리 방식에 대한 이해도를 확인하는 질문들이 있었습니다.
3. 인터페이스(Interface) vs 추상 클래스(Abstract Class)
두 개념 모두 '미완성된 설계도'라는 공통점이 있지만, 사용 목적과 제약 사항에서 명확한 차이가 있습니다.
| 구분 | 인터페이스 (Interface) | 추상 클래스 (Abstract Class) |
|---|---|---|
| 목적 | "무엇을 할 수 있는지"에 대한 '계약' 또는 '자격'을 정의 | 관련 클래스들의 '공통적인 특징'을 뽑아 정의 |
| 구현 | 메서드, 속성의 시그니처만 정의. 구현 코드 포함 불가 (C# 8.0부터 기본 구현 가능) | 일부 메서드는 구현을 포함할 수 있고, 일부는 추상 메서드로 남겨둘 수 있음 |
| 상속 | 다중 상속 가능 (클래스는 여러 인터페이스를 구현할 수 있음) | 단일 상속만 가능 (클래스는 하나의 클래스만 상속 가능) |
| 상태 | 필드(멤버 변수)를 가질 수 없어 상태를 저장할 수 없음 | 필드를 가질 수 있어 상태를 저장할 수 있음 |
| 사용 예시 | IComparable (비교 가능), IEnumerable (반복 가능) 등 기능적 자격을 부여할 때 |
Character (플레이어, 몬스터의 공통 특징) 등 계층 구조를 만들 때 |
핵심 요약: "날 수 있다(Flyable)"와 같은 '기능'을 여러 객체(비행기, 새, 슈퍼맨)에 부여하고 싶다면 **인터페이스**를, "포유류"라는 공통된 '종류'의 특징(체온, 새끼 낳기)을 묶고 싶다면 **추상 클래스**를 사용하는 것이 적합합니다.
4. 메모리 구조: 스택(Stack)과 힙(Heap)
C#에서 변수가 저장되는 메모리 공간은 크게 스택과 힙, 두 가지로 나뉩니다. 이 둘의 차이를 이해하는 것은 성능 최적화와 메모리 누수 방지의 기본입니다.
- 스택 (Stack):
- 구조: 접시를 쌓는 것처럼 데이터가 차곡차곡 쌓이는 LIFO(Last-In, First-Out) 구조입니다.
- 저장 대상: 값 형식(Value Types) 변수 (
int,float,bool,struct등)와 메서드 호출 시 필요한 매개변수, 지역 변수, 그리고 힙에 생성된 객체를 가리키는 **참조(주소값)**가 저장됩니다. - 생명 주기: 해당 변수가 선언된 메서드나 코드 블록({ })이 종료되면, 별도의 처리 없이도 **자동으로 메모리에서 해제**됩니다.
- 특징: 메모리 할당과 해제가 매우 빠르지만, 크기가 고정되어 있고 제한적입니다.
- 힙 (Heap):
- 구조: 거대한 창고처럼, 필요할 때마다 비어있는 공간에 데이터를 동적으로 할당하는 구조입니다.
- 저장 대상: 참조 형식(Reference Types)의 실제 데이터 (
class의 인스턴스,string, 배열 등)가 저장됩니다. - 생명 주기: 더 이상 해당 데이터를 가리키는 참조가 하나도 없을 때, **가비지 컬렉터(Garbage Collector, GC)**가 주기적으로 순회하며 메모리를 수거(해제)합니다.
- 특징: 크기가 매우 크고 동적으로 변할 수 있지만, 메모리 할당/해제 비용이 스택보다 비싸고, GC 동작 시 순간적인 성능 저하가 발생할 수 있습니다.
5. struct vs class
이 질문은 스택과 힙의 차이와 직접적으로 연결됩니다. C#에서 사용자 정의 데이터 타입을 만드는 두 가지 핵심 키워드입니다.
| 구분 | struct (구조체) |
class (클래스) |
|---|---|---|
| 형식 | 값 형식 (Value Type) | 참조 형식 (Reference Type) |
| 메모리 할당 | 주로 스택(Stack)에 할당됨 | 주로 힙(Heap)에 할당됨 (스택에는 주소만 저장) |
| 상속 | 불가능 | 가능 |
| 데이터 전달 | 변수에 할당하거나 메서드에 전달 시, 데이터 전체가 복사됨 | 데이터의 주소(참조)만 복사됨 (원본은 하나) |
| 주요 용도 | Vector3, Color처럼 작고, 불변에 가까운 데이터 구조를 표현할 때 |
복잡한 상태와 행동을 가지는 대부분의 객체를 표현할 때 (예: Player, Monster) |
결론적으로, 작은 데이터를 자주 생성하고 파괴해야 하는 경우 struct를 사용하면 GC의 부담을 줄여 성능에 이점을 볼 수 있습니다. 하지만 데이터의 크기가 크거나, 상속이 필요하거나, 여러 곳에서 동일한 데이터를 참조해야 하는 대부분의 경우에는 class를 사용하는 것이 일반적입니다.
'팀스파르타 내일배움캠프' 카테고리의 다른 글
| C# 객체지향 및 이벤트 개념 심화 정리 (1) | 2025.08.04 |
|---|---|
| Unity 대화 시스템 완전 구축 & 트러블슈팅 (1) | 2025.08.03 |
| [TIL] 경험을 위한 기술, 기술을 위한 경험: 나의 개발 북극성을 찾아서 (3) | 2025.07.23 |
| [TIL] 데이터의 확장성과 시스템의 안정성, 두 마리 토끼를 잡다 (1) | 2025.07.22 |
| [TIL] Unity 게임 개발의 3가지 핵심 시스템 구축 (0) | 2025.07.10 |