✅ 1. C# 언어 기초 및 문법
📌 Q1. ref와 out의 차이는 무엇인가요?
모범 답변:
- ref: 호출 전에 반드시 초기화 필요, 함수 내에서 수정 가능
- out: 호출 전 초기화 불필요, 함수 내에서 반드시 값을 할당해야 함
- 다중 반환 시 out 사용이 적절, ref는 기존 값을 수정할 때 사용
심화 질문 & 답변:
- Q: in 키워드는 언제 쓰나요?
A: C# 7.2부터 도입. 읽기 전용 참조 전달. 구조체를 복사 없이 안전하게 전달할 때 사용 - Q: ref struct는 어떤 경우에 사용하나요?
A: 스택 전용 구조체. 예: Span. 힙 할당, 박싱, async 불가
📌 Q2. params 키워드는 언제 사용하나요?
모범 답변:
- 가변 인자 리스트를 받을 때 사용. 마지막 매개변수로만 선언 가능. params int[] values 형태로 다수의 인자 받음.
심화 질문 & 답변:
- Q: params object[]는 어떤 경우에 사용하나요?
A: 모든 타입을 받을 수 있어 범용적. 단, 박싱/언박싱 오버헤드 유의 - Q: LINQ에서 params는 어떻게 활용되나요?
A: Enumerable.Concat(params IEnumerable[] sources) 등에서 활용됨
📌 Q3. nullable type과 null-coalescing operator(??, ??=, ?.)의 역할은?
모범 답변:
- Nullable 타입: int?, bool? → null을 값으로 가질 수 있음
- ??: null이면 오른쪽 반환
- ??=: null이면 오른쪽을 할당
- ?.: null-safe 접근 연산자
심화 질문 & 답변:
- Q: ?.과 ??를 함께 사용할 수 있나요?
A: 예, obj?.Property ?? defaultValue 처럼 null-safe + fallback 가능 - Q: Nullable과 boxing 문제는?
A: Nullable boxing 시 실제 값 또는 null 참조가 됨. 언박싱 시 InvalidCastException 주의
📌 Q4. readonly와 const의 차이는?
모범 답변:
- const: 컴파일 타임 상수, 기본형만 가능
- readonly: 런타임 상수, 생성자에서 할당 가능, 참조형 가능
심화 질문 & 답변:
- Q: static readonly와 const의 차이?
A: const는 값 자체를 참조, static readonly는 메모리 상에 위치 - Q: readonly struct의 장점?
A: 불변성 보장 + 복사 최적화
📌 Q5. Value Type과 Reference Type의 차이는?
모범 답변:
- Value Type: 스택에 할당, 복사 시 값 자체가 복제
- Reference Type: 힙에 할당, 참조만 전달
- 예: int, float(값형), class, string(참조형)
심화 질문 & 답변:
- Q: 구조체를 참조로 전달하고 싶을 땐?
A: ref, in, out을 통해 참조 전달 - Q: string은 왜 참조형인데 불변인가요?
A: string은 immutable reference type. 값 변경 시 새 인스턴스 생성
✅ 2. 객체지향 프로그래밍(OOP)
📌 Q1. C#에서 캡슐화, 상속, 다형성을 각각 어떻게 구현하나요?
모범 답변:
- 캡슐화: 접근 제한자(private, protected, public)로 외부 노출 제어
- 상속: : 키워드로 클래스 상속 (class B : A)
- 다형성: virtual, override, 인터페이스 구현 등을 통해 런타임에 다른 동작 수행
심화 질문 & 답변:
- Q: 캡슐화는 단순한 정보 은닉을 넘어서 어떤 장점이 있나요?
A: 구현을 숨기고 인터페이스만 제공함으로써 변경에 유연하고 유지보수 용이함. - Q: C#에서 다중 상속이 안 되는 이유는?
A: Diamond 문제(다이아몬드 상속 문제) 방지 목적. 대신 인터페이스 다중 구현 지원
📌 Q2. 추상 클래스와 인터페이스의 차이점은?
모범 답변:
- 추상 클래스: 단일 상속, 필드/생성자/구현 메서드 포함 가능
- 인터페이스: 다중 구현 가능, 구현만 정의 (C# 8부터 default 구현 허용)
- 공통 구현이 필요하면 추상 클래스, 설계 계약은 인터페이스 사용
심화 질문 & 답변:
- Q: C# 8 이후 인터페이스 default 구현은 어떤 상황에서 유용한가요?
A: 기존 구현에 영향 없이 기능을 추가하고 싶을 때, 하위 호환성 유지 가능 - Q: 인터페이스 상속 간 충돌은 어떻게 해결하나요?
A: 명시적 구현을 통해 충돌된 메서드를 분리 구현 가능
📌 Q3. virtual, override, new 키워드의 차이는?
모범 답변:
- virtual: 부모 클래스에서 오버라이딩 가능하게 정의
- override: 자식 클래스에서 재정의
- new: 부모의 메서드를 숨기고 새로운 메서드를 정의 (hiding)
심화 질문 & 답변:
- Q: new를 사용했을 때 런타임에 어떤 문제가 발생할 수 있나요?
A: 부모 타입으로 접근하면 부모 메서드가 호출되어 의도와 다르게 동작할 수 있음 - Q: override와 new를 혼용하면?
A: 컴파일은 가능하지만 혼란을 유발하고 유지보수가 어려움
📌 Q4. sealed 키워드는 언제 쓰며 어떤 역할을 하나요?
모범 답변:
- sealed는 클래스 또는 메서드가 더 이상 상속/오버라이딩되지 않도록 막음
- 성능 최적화(가상 호출 제거), 의도 명확화에 유리
심화 질문 & 답변:
- Q: sealed override는 어떤 경우에 쓰이나요?
A: 상속받은 메서드는 오버라이딩하되, 자식 클래스에서 재정의하지 못하게 제한 - Q: sealed 클래스가 많아지면 확장성은 어떻게 되나요?
A: 확장보다 안정성을 우선할 때 유리하지만, 과도하면 오히려 유연성 저하
📌 Q5. C#에서 다형성을 어떻게 활용해봤나요?
모범 답변:
- 인터페이스 기반 설계로 확장 가능한 시스템 구성
- 예: 다양한 공격 방식 구현 시 IAttackable 인터페이스로 다형성 처리
- 팩토리 패턴, 상태 패턴 등에서도 다형성 적극 활용
심화 질문 & 답변:
- Q: 다형성을 활용한 대표적인 디자인 패턴 예시는?
A: 전략 패턴, 상태 패턴, 템플릿 메서드 패턴 등 - Q: 다형성과 성능의 trade-off는?
A: virtual 호출은 정적 호출보다 느리지만, 설계 유연성과 유지보수성 측면에서 가치 있음
✅ 3. 이벤트와 델리게이트
📌 Q1. 델리게이트(delegate)란 무엇이며 언제 사용하나요?
모범 답변:
- 메서드 참조를 저장하는 형식. 함수 포인터 개념
- 이벤트 기반 프로그래밍, 콜백 처리, 동적 실행 등에서 사용
- delegate void MyDelegate(int x);
심화 질문 & 답변:
- Q: 델리게이트 체인에 예외가 발생하면 어떻게 되나요?
A: 기본적으로 앞의 메서드 실행 후 예외 발생 시 이후 메서드는 실행되지 않음 - Q: 멀티캐스트 delegate는 어떤 방식으로 처리되나요?
A: 내부적으로 InvocationList 배열에 여러 메서드를 보관함
📌 Q2. 이벤트(event)와 델리게이트의 차이점은?
모범 답변:
- 이벤트는 델리게이트를 캡슐화한 형태로 외부에서 직접 호출 불가
- 델리게이트는 메서드 참조자, 이벤트는 구독자 관리 인터페이스 역할
- 안전한 이벤트 기반 아키텍처 구성 시 event 사용
심화 질문 & 답변:
- Q: 이벤트를 수동으로 구현하려면?
A: add/remove 접근자를 정의해 델리게이트를 제어 - Q: 이벤트 핸들러에 파라미터가 필요할 땐?
A: EventHandler사용. T는 EventArgs를 상속한 타입
📌 Q3. Action, Func, Predicate는 각각 언제 사용하나요?
모범 답변:
- Action: 반환값 없는 델리게이트 (Action
) - Func: 반환값 있는 델리게이트 (Func<int, string>)
- Predicate
: Func<T, bool>과 동일, 명시적으로 bool 반환
심화 질문 & 답변:
- Q: Func와 Predicate의 차이는?
A: Predicate는 가독성과 의도를 명확히 표현할 때 사용 - Q: 제너릭 Action/Func의 최대 인자는 몇 개인가요?
A: 16개까지 가능. 그 이상은 custom delegate를 정의해야 함
📌 Q4. 익명 메서드와 람다 표현식의 차이는?
모범 답변:
- 익명 메서드: delegate 키워드 사용
- 람다 표현식: => 문법 사용
- 람다가 간결하고 표현력 강함. 대부분 람다로 대체됨
심화 질문 & 답변:
- Q: 람다 표현식 내부에서 외부 변수 캡처 시 주의할 점은?
A: Closure 발생. 반복문 변수 캡처 시 같은 변수 참조 문제 생김 (foreach vs for) - Q: 익명 메서드와 람다의 IL 코드 차이는?
A: 컴파일러가 동일한 익명 클래스/메서드로 변환하지만 문맥 처리 방식이 다름
✅ 4. 비동기 프로그래밍
📌 Q1. async와 await 키워드의 동작 방식은?
모범 답변:
- async는 비동기 메서드 정의
- await는 해당 작업 완료 시점까지 메서드 실행 중지 → 이후 continuation 실행
- 스레드 블로킹 없이 동시성 향상 가능
심화 질문 & 답변:
- Q: SynchronizationContext의 역할은?
A: await 이후 어느 스레드에서 continuation을 실행할지 결정. UI 앱에서는 주 스레드 유지 - Q: ConfigureAwait(false)의 의미?
A: 컨텍스트 복원을 건너뛰어 백그라운드에서 continuation 실행. 서버 앱에서 성능 향상
📌 Q2. Task, Task, ValueTask의 차이는?
모범 답변:
- Task: 비동기 작업 결과를 나타냄
- Task
: 결과 값을 반환 - ValueTask
: 반환 비용 절감, 재사용 가능하지만 주의가 필요
심화 질문 & 답변:
- Q: ValueTask는 어떤 상황에서 사용하면 안 되나요?
A: 여러 번 await 하거나, .Result 접근 시 예외 발생 가능 → 단일 await에만 사용 권장 - Q: Task의 상태 확인 방법은?
A: IsCompleted, IsFaulted, IsCanceled 속성으로 확인 가능
📌 Q3. async void는 어떤 경우에 사용하는 것이 적절한가요?
모범 답변:
- 일반적으로 async void는 예외 처리 어려움 때문에 지양
- 단, 이벤트 핸들러에서는 반환 타입이 void여야 하므로 예외적으로 사용
심화 질문 & 답변:
- Q: async void에서 예외가 발생하면 어디서 잡을 수 있나요?
A: AppDomain.CurrentDomain.UnhandledException 또는 TaskScheduler.UnobservedTaskException에서만 가능 - Q: 예외 로깅을 위해선 어떻게 처리해야 하나요?
A: try-catch로 예외 감싸고 로그 기록 → UI 메세지 출력 등
📌 Q4. 게임에서 비동기를 사용할 수 있는 예시는?
모범 답변:
- 리소스 로딩 (씬 전환, 애셋 로딩 등)
- 서버 통신 (REST API, 소켓 I/O)
- 파일 저장/읽기
- 다운로드 진행
심화 질문 & 답변:
- Q: Unity에서 async/await 사용 시 주의점은?
A: Unity는 싱글 스레드 기반 → 메인 스레드 접근 시 반드시 MainThreadDispatcher 같은 메커니즘 필요 - Q: Resources.LoadAsync는 어떻게 사용하나요?
A: var handle = Resources.LoadAsync(path); yield return handle; 또는 Addressables 기반 사용
✅ 5. 메모리 관리 및 GC
📌 Q1. C#의 가비지 컬렉션(GC) 방식은 어떻게 되나요?
모범 답변:
C#은 세대별(Generational) 가비지 컬렉션을 사용합니다. 객체는 Generation 0, 1, 2로 나뉘며, 짧은 생명 객체는 Generation 0에서, 오래 살아남은 객체는 Generation 2에서 관리됩니다.
GC는 mark-and-sweep 알고리즘을 기반으로 작동하며, Stop-the-world 방식으로 실행됩니다.
심화 질문 & 답변:
- Q: Large Object Heap(LOH)은 언제 생성되고 어떻게 관리되나요?
A: 약 85,000 bytes 이상인 객체는 LOH에 저장되며, Generation 2 수집 시에만 GC 대상이 됩니다. - Q: GC.Collect()는 사용해도 되나요?
A: 명시적으로 호출 가능하지만, 대부분의 경우 성능 저하를 초래하므로 피해야 합니다. 단기 메모리 측정이나 즉시 해제가 필요한 상황에서는 예외적으로 사용됩니다.
📌 Q2. IDisposable과 using 문은 어떤 경우에 사용하나요?
모범 답변:
IDisposable은 비관리 리소스(파일, DB, 네이티브 핸들 등) 를 수동으로 정리할 때 사용됩니다.
using 문은 try-finally 구문 없이 Dispose() 호출을 보장해줍니다.
심화 질문 & 답변:
- Q: IDisposable 구현 시 어떤 패턴을 따라야 하나요?
A: Dispose 패턴 (Dispose + Finalizer) 을 구현해 리소스 누수 방지합니다. - Q: using vs try-finally 차이는?
A: 기능적으로 동일하지만 using이 간결하고 안전합니다.
📌 Q3. WeakReference는 언제 유용하게 쓸 수 있나요?
모범 답변:
객체를 참조는 하되, GC가 수거할 수 있도록 하고 싶은 경우에 사용합니다.
캐시, 이벤트 핸들러에서 메모리 누수 방지용으로 활용됩니다.
심화 질문 & 답변:
- Q: 일반 참조와 WeakReference의 동작 차이는?
A: 일반 참조는 객체가 GC 대상이 되지 않지만, WeakReference는 GC 대상이 됩니다. - Q: WeakReference 사용 시 단점은?
A: null 가능성이 있으므로 항상 TryGetTarget()으로 존재 여부 확인이 필요합니다.
📌 Q4. 구조체를 잘못 사용하면 GC에 어떤 영향을 주나요?
모범 답변:
구조체(ValueType)는 스택에 할당되므로 GC 부담이 적지만,
박싱 발생 시 힙에 할당되어 GC 부하를 유발합니다.
심화 질문 & 답변:
- Q: 박싱이 발생하는 경우는?
A: 구조체를 object, interface 등 참조형으로 캐스팅할 때 발생합니다. - Q: 박싱 방지 방법은?
A: 제네릭 사용, 인터페이스 직접 구현 대신 명시적 코드 작성 등
✅ 6. 자료구조 및 컬렉션
📌 Q1. List와 LinkedList의 차이점은?
모범 답변:
- List
: 배열 기반, 인덱스 접근 O(1), 삽입/삭제 O(n) - LinkedList
: 노드 기반, 삽입/삭제 O(1) (위치 알고 있을 경우), 인덱스 접근 X
심화 질문 & 답변:
- Q: Unity에서 List
를 선호하는 이유는?
A: 인덱스 기반 순회가 빠르고, 구조가 단순하며 GC 부담이 적음 - Q: LinkedList는 어떤 상황에 유리한가요?
A: 중간 삽입/삭제가 빈번하고 순차 접근 위주일 때 유리
📌 Q2. Dictionary<TKey, TValue>와 ConcurrentDictionary의 차이는?
모범 답변:
- Dictionary: 단일 스레드용, 빠른 조회
- ConcurrentDictionary: 멀티 스레드 환경에서 thread-safe하게 작동
심화 질문 & 답변:
- Q: ConcurrentDictionary는 내부적으로 어떻게 동기화를 하나요?
A: 락 스트라이핑(lock striping) 기법 사용 – 버킷 단위로 락을 분할 - Q: Dictionary에서 키가 없을 때의 처리 방법은?
A: TryGetValue() 또는 ContainsKey()로 안전하게 처리
📌 Q3. HashSet을 사용할 때의 장점은?
모범 답변:
- 중복을 허용하지 않으며, Add, Contains의 평균 시간복잡도는 O(1)
- 집합 연산(Union, Intersect 등)에 강력
심화 질문 & 답변:
- Q: List.Contains()와 HashSet.Contains()의 성능 차이는?
A: List: O(n), HashSet: O(1). 많은 검색 시 HashSet 유리 - Q: HashSet에서 해시 충돌은 어떻게 처리되나요?
A: 내부적으로 체이닝(chaining) 방식 또는 버킷 사용
📌 Q4. 컬렉션에서 성능상 주의할 점이 있다면?
모범 답변:
- List의 Add()는 O(1)이지만, 크기 초과 시 재할당으로 O(n) 발생
- 컬렉션을 순회하며 수정 시 InvalidOperationException 발생 위험
- foreach는 GC 발생 가능
심화 질문 & 답변:
- Q: GC를 줄이기 위한 컬렉션 사용 팁은?
A: Capacity 사전 설정, Clear() 후 재사용, for 루프 활용 - Q: 구조체를 컬렉션에 넣으면 문제가 있나요?
A: 복사 발생으로 성능 저하 가능. 값 변경 시 유의해야 함
✅ 7. LINQ
📌 Q1. LINQ를 사용하는 장점은?
모범 답변:
- 선언형 쿼리로 가독성 및 유지보수 향상
- 다양한 컬렉션 및 DB 소스에 동일한 쿼리 표현 적용 가능
- Select, Where, OrderBy 등 체이닝 가능
심화 질문 & 답변:
- Q: LINQ의 성능 단점은?
A: 반복자 기반으로 성능은 루프보다 느림. 복잡한 쿼리는 성능 저하 - Q: IEnumerable vs IQueryable 차이는?
A: IEnumerable: 메모리 내 데이터 대상, IQueryable: DB로 쿼리 전달 가능 (EF 등)
📌 Q2. Select, Where, GroupBy, Join의 예시를 설명해 주세요.
모범 답변:
csharp
복사편집
var result = people .Where(p => p.Age > 20) .Select(p => p.Name) .ToList();
- Where: 조건 필터링
- Select: 변환
- GroupBy: 그룹화
- Join: 두 컬렉션 결합
심화 질문 & 답변:
- Q: GroupBy와 ToLookup의 차이점은?
A: GroupBy는 지연 실행, ToLookup은 즉시 실행. 결과도 다소 차이 있음 - Q: Join에서 내부 키가 null일 경우는?
A: null 키는 조인 안됨. left outer join으로 대체 필요
📌 Q3. LINQ의 deferred execution은 무엇인가요?
모범 답변:
LINQ 연산은 대부분 지연 실행(deferred execution)을 기반으로 하며,
foreach, ToList(), Count() 등을 호출하기 전까지 실제 수행되지 않습니다.
심화 질문 & 답변:
- Q: 왜 deferred execution이 중요한가요?
A: 성능 최적화, 조건 변경, 체이닝 최적화 가능 - Q: deferred execution의 단점은?
A: 실행 시점 예측이 어려워 디버깅 복잡. 여러 번 실행 시 중복 비용 발생
✅ 8. 쓰레딩 및 동기화
📌 Q1. lock 키워드의 역할은 무엇인가요?
모범 답변:
lock 키워드는 임계 구역(critical section)을 지정하여 하나의 스레드만 해당 코드에 접근할 수 있도록 보장합니다. 내부적으로는 Monitor.Enter()와 Monitor.Exit()으로 구현됩니다.
심화 질문 & 답변:
- Q: lock이 과도하면 어떤 문제가 발생하나요?
A: 데드락 가능성, 성능 저하 (병렬성 저하), 경쟁 상태로 인한 지연 - Q: lock 대상 객체는 어떤 기준으로 선택해야 하나요?
A: private한 오브젝트를 사용하는 것이 안전. this, typeof(...)는 위험
📌 Q2. Monitor, Mutex, Semaphore의 차이점은?
모범 답변:
- Monitor: 프로세스 내에서 동기화, 가장 가볍고 성능 좋음 (lock의 내부 구현)
- Mutex: 프로세스 간 동기화 가능. OS 커널 리소스를 사용하므로 무거움
- Semaphore: 최대 허용 개수를 지정. 제한된 동시 접근 필요 시 사용
심화 질문 & 답변:
- Q: SemaphoreSlim과 Semaphore의 차이는?
A: SemaphoreSlim은 경량화된 클래스 (in-process 전용). Semaphore는 OS 리소스를 포함해 IPC 지원 - Q: Monitor.Wait() / Pulse()는 언제 사용하나요?
A: 스레드 협력(Cooperative Threading)이 필요할 때 대기/신호 메커니즘 구현 가능
📌 Q3. Thread vs Task의 차이점은?
모범 답변:
- Thread: OS 수준의 쓰레드, 직접 생성, 자원 소비 많음
- Task: 스레드 풀 기반, 재사용성 높고 가벼움. 비동기 흐름과 연계 쉬움 (async/await)
심화 질문 & 답변:
- Q: Task가 항상 Thread보다 좋은가요?
A: CPU 바운드 작업에서 쓰레드 직접 생성이 유리한 경우도 있음.
Task는 I/O 바운드 + 비동기 흐름에 적합
📌 Q4. volatile 키워드의 용도는?
모범 답변:
volatile은 변수의 값을 캐시하지 않고 항상 메인 메모리에서 읽도록 보장합니다.
멀티 스레드 환경에서 최신 값을 읽기 위해 사용됩니다.
심화 질문 & 답변:
- Q: volatile은 어떤 한계를 가지고 있나요?
A: atomicity(원자성)를 보장하지 않습니다. ++ 연산 등의 복합 연산에는 효과 없음 - Q: volatile을 대체할 수 있는 것은?
A: Interlocked, lock, Thread.MemoryBarrier() 등의 명시적 동기화 방식
✅ 9. Unity 관련 (게임 클라이언트 특화)
📌 Q1. Update, FixedUpdate, LateUpdate의 차이점은?
모범 답변:
- Update(): 매 프레임 호출, 입력 처리 등에 적합
- FixedUpdate(): 일정 시간 간격(물리 프레임)으로 호출, Rigidbody 물리 연산에 적합
- LateUpdate(): 모든 Update() 호출 이후 호출, 카메라 추적 등에 적합
심화 질문 & 답변:
- Q: FixedUpdate에서 물리 연산을 하지 않으면 문제가 생기나요?
A: 네, Update에서 직접 Rigidbody 위치를 수정하면 물리 연산이 꼬여 비정상적 동작 가능 - Q: FixedUpdate는 프레임 드랍 시 어떻게 보정되나요?
A: 여러 번 연속 호출되며 보정함 (Time.fixedDeltaTime 유지됨)
📌 Q2. 코루틴(Coroutine)의 내부 동작 원리는?
모범 답변:
Unity 코루틴은 IEnumerator를 반환하며, Unity의 메인 루프에서 상태를 추적하며 yield된 결과에 따라 다음 프레임으로 넘깁니다.
심화 질문 & 답변:
- Q: 코루틴이 멀티스레드인가요?
A: 아닙니다. 코루틴은 싱글 스레드(메인 스레드)에서 실행됩니다. 비동기성은 흐름 제어를 통해 구현 - Q: StopCoroutine()은 어디서 중단하나요?
A: 메인 루프의 코루틴 실행 큐에서 해당 이터레이터 제거로 중단됩니다
📌 Q3. Unity에서 이벤트 기반 설계를 어떻게 해봤나요?
모범 답변:
- Action, event, delegate를 활용해 UI 갱신, 상태 전이, 메시지 브로드캐스트 등에 사용
- 예: OnPlayerDie 이벤트를 통해 HP 0일 때 다른 시스템이 반응하도록 구성
심화 질문 & 답변:
- Q: 이벤트 중심 설계의 장점과 단점은?
A: 장점: 느슨한 결합, 확장성 / 단점: 디버깅 어려움, 메모리 누수 가능성 - Q: UnityEvent와 C# 이벤트 차이점은?
A: UnityEvent는 에디터에서 연결 가능, 직렬화됨. 성능은 일반 C# 이벤트가 우수
📌 Q4. ScriptableObject를 사용하는 이유는?
모범 답변:
ScriptableObject는 데이터 중심 설계를 위해 사용되며, 메모리 상에 중복 없이 존재하는 설정값을 에셋으로 저장할 수 있습니다.
인스턴스 없이 공유 가능한 데이터 설계에 적합합니다.
심화 질문 & 답변:
- Q: MonoBehaviour와의 차이는?
A: MonoBehaviour는 GameObject에 붙어야 하지만, ScriptableObject는 독립적으로 존재 - Q: 실시간 변경 감지는 어떻게 하나요?
A: OnValidate() 또는 C# 이벤트와 결합해 실시간 반영 가능
📌 Q5. GC를 줄이기 위한 Unity 최적화 방법은?
모범 답변:
- new 할당 최소화, 오브젝트 풀링
- foreach 대신 for
- StringBuilder 사용
- 구조체 활용 (주의해서)
- 이벤트 해지, MonoBehaviour 제거 시 참조 제거
심화 질문 & 답변:
- Q: Unity GC는 언제 작동하나요?
A: .NET GC와 동일하게 메모리 압박 또는 할당량 초과 시 발생. 예측 불가 - Q: UI 시스템에서 GC가 자주 발생하는 이유는?
A: Text, String.Format, ToString() 사용 시 문자열 할당이 빈번하게 발생
✅ 10. 게임 클라이언트 실무/아키텍처
📌 Q1. C#으로 만든 네트워크 클라이언트에서 패킷 처리는 어떻게 하나요?
모범 답변:
- TCP/UDP 소켓 또는 WebSocket 기반으로 통신 구현
- 수신 버퍼에서 패킷 단위로 분할/조립하여 처리
- 패킷 헤더에 길이/ID를 포함시켜 메시지 파싱
심화 질문 & 답변:
- Q: 패킷 누락, 중복, 순서 뒤바뀜 문제 해결법은?
A: 패킷 ID, 시퀀스 넘버, ACK 기반 재전송 프로토콜 사용 - Q: C#에서 SocketAsyncEventArgs를 사용하는 이유는?
A: 비동기 I/O 처리에 효율적이며, 메모리 할당 최소화 가능 (object pooling 적합)
📌 Q2. C#에서 싱글톤 패턴은 어떻게 구현하나요? 단점은?
모범 답변:
| 1 2 3 4 5 | public class Singleton { private static Singleton _instance = new Singleton(); public static Singleton Instance => _instance; private Singleton() {} } Colored by Color Scripter | cs |
|---|
단점:
- 전역 접근으로 테스트 어려움
- 의존성 주입 불가 → 코드 결합도 증가
심화 질문 & 답변:
- Q: Unity에서 싱글톤 MonoBehaviour는 어떻게 구현하나요?
A: DontDestroyOnLoad를 사용한 static 인스턴스 관리 - Q: 싱글톤 남용을 방지하는 방법은?
A: DI(Dependency Injection), 서비스 로케이터 패턴 사용 고려
📌 Q3. 메시지 큐 또는 이벤트 큐 시스템을 C#으로 어떻게 만들 수 있을까요?
모범 답변:
- Queue
를 기반으로 생산자-소비자 패턴 구현 - 이벤트는 Dictionary<EventType, Action> 구조로 관리
- Enqueue, Dequeue, Dispatch 함수 구성
심화 질문 & 답변:
- Q: Unity에서 Update마다 이벤트를 소비하려면?
A: Update()에서 큐 순회 후 Dispatch - Q: 멀티스레드 환경에서 큐 사용 시 유의할 점은?
A: ConcurrentQueue 사용, 또는 lock으로 보호
📌 Q4. 대형 게임에서 C# 코드의 성능 병목을 어떻게 해결했는지?
모범 답변:
- 프로파일링 도구 (Profiler, Deep Profile, JetBrains DotTrace 등) 사용
- GC 최적화, 빈번한 연산 캐싱, Update 분할
- 구조 변경 (컴포넌트 분리, 데이터 중심 설계)
심화 질문 & 답변:
- Q: C#에서 핫스팟(Hotspot) 최적화는 어떻게 하나요?
A: 구조체 사용, 함수 인라인화, for 루프 기반 처리 - Q: Unity에서 ECS/DOTS를 사용하는 이유는?
A: 데이터 중심, 캐시 친화 구조, 병렬 처리 최적화 가능 (CPU 자원 최대 활용)
'면접 준비' 카테고리의 다른 글
| [면접 준비] 게임 클라이언트 그래픽스 면접 질문 정리 (0) | 2025.08.25 |
|---|---|
| [면접 준비] 자료구조 항목 정리 (0) | 2025.08.05 |
| [면접 준비] 운영체제 항목 정리 (0) | 2025.08.05 |
| [면접 준비] 네트워크 항목 정리 (0) | 2025.08.05 |
| [면접 준비] C++ 항목 정리 (0) | 2025.08.05 |