기술 면접 - Unity(매일 2개씩)

김도현·2024년 1월 16일

기술면접

목록 보기
1/1

1. 클래스와 구조체의 차이점에 대해 설명해주세요.

1) Type차이

Struct 는 값타입이고, Class 는 참조타입이다.
※ 다른 기본 값타입(int, long 등)은 new 연산자를 내부에서 자동으로 호출한다.

  • 따라서 Struct 는 메모리에 직접 접근하므로 시간적 낭비가 적다.

1-1) Stack, Heap

구조체(Struct)는 값 타입이기에 스택 메모리에서 생성되며 속도가 빠릅니다.

  • 하지만 아래의 경우 Struct 도 Heap 에 할당한다.
    • 필드의 합이 16 byte 를 넘는 경우
    • 구조체안에 클래스 타입의 필드가 있는 경우

클래스(Class)는 참조타입이기에 힙 메모리에 생성되고 상대적으로 느립니다.

2) 상속의 차이

구제체(Struct)는 상속이 불가능하여 기능의 확장에 제약이 있다.

  • interface 상속 받을 수 있으나, class 상속 받을 수 없다.
    클래스(Class)는 상속이 가능하여 기능 확장이 가능하다.

번외

struct는 간단한 데이터의 모음Plain Old Data(POD)으로, class는 추가적인 로직이 필요한 객체로 구분해서 사용하고 있다.

  • 다음 특성을 모두 포함하지 않는다면 Struct 로 정의하는 것을 피하자.
    1) 논리적으로 하나의 값을 나타낼 때 (primitive type 처럼)
    2) 인스턴스의 크기가 16 byte 이하일 때
    3) 불변형(immutable) 일 때
    4) 박싱/언박싱이 자주 일어나지 않을 때

2. 델리게이트(Delegate)와 이벤트(Event)의 개념 및 사용 용도를 설명해주세요.

Delegate

사용자가 정의한 메서드를 참조를 위한 것이다.
시그니처(입력 매개 변수와 반환 타입)를 명시적으로 정의합니다.
용도 : 콜백

Event

변수 선언할 때 앞에 적어주면 대리자를 오직 변수를 선언한 클래스 내부에서만 사용할 수 있습니다. 즉 클래스 내부에서만 실행할 대리자니 다른 곳에서 사용하지 못하게 하라라고 컴파일러에 명시적으로 알려주는 기능을 합니다.
기능은 기존 델리게이트와 똑같은 역활을 합니다. 단 = 으로 델리게이트를 하나의 메서드로 정의하는 것은 안되며한수들이 오버라이딩될 걱정할 필요가 없습니다. +=으로 구독하던가 -=으로 구독해제할 수 있으며 호출시 위에 적어놓았듯이 선언한 스크립트 내부에서 호출해야 됩니다.외부에서 다이렉트로 접근하는 것이 불가능하기에 캡슐화가 가능합니다.

이벤트는 인터페이스 내부에 선언할 수 있습니다.
용도 : 객체의 상태 변화나, 어떠한 동작이 했을 때 알리는 용도로 사용됩니다.

3. 제네릭(Generic)이 무엇이고, 어떻게 사용하는지 간단히 설명해주세요.

제네릭이란?

형식 매게 변수형식을 매개 변수로 사용하여 형식 내부에서 형식 매개 변수로 정의된 형식을 교체하는 것입니다.

  • 외부에서 형식을 설정하며 내부 데이터 타입은 인스턴스를 생성할 때 확정 됩니다.

제네릭 형식의 장점

  • 타입 안정성을 제공한다.
  • 타입 체크와 형변환을 생략할 수 있으므로 코드가 명확하고 간결해 집니다.
  • 탑입의 종류만 바꾸면 되는 로직일 경우, 코드 재활용이 가능합니다.

타입 명명 관례

  • E - Element
  • K - Key
  • N – Number
  • T – Type
  • V - Value

4. C#에서 예외 처리에 대한 기본적인 원칙은 무엇인가요?

예외 처리란?

예외 - Exception

프로그램 실행 도중 발생하는 에러, 문법 오류(Syntax Error)와 실행 오류(Runtime Error)로 나뉘지만, 주로 런타임 상황의 에러를 의미한다.

예외 처리 - Exception Handling

프로그램이 처리되는 동안 특정한 문제가 일어났을 때 처리를 중단하고 다른 처리를 하는 것

예외 처리를 위한 코드

Try

예외 감시자, 예외가 발생할 가능성이 있는 코드의 영역을 지정

Catch

예외 처리기, try에서 발생한 예외를 확인하고 처리

Finally

예외가 발생하든 안 하든 무조건 실행시켜야 할 때 사용

  • try블록에서 할당된느 리소스 해제와 같이 try블록에서 예외가 throw되는지 여부와 관계없이 실행되는 코드

Throw

직접 예외 발생시키기

when

예외필터, catch문에 조건식을 추가할 수 있다.

ApplicationException: ApplicationException

클래스를 상속받아서 사용자가 직접 예외 클래스를 만들 수 있음

사용시기

예외 처리는 상당히 무거운 작업이므로 남용할 경우 비정상적인 종료는 방지할 수 있으나 성능저하가 발생한다.

예외 처리 적용시 권장사항

1) if으로 처리가 가능한 것들은 if으로 해결한다.

  • if에 비해 catch가 성능 소모가 크다.
    • try-catch는 예외 발생 지점의 스택을 거슬러 올라가서 모두 추적 및 기록하는데 이 과정에서 성능소모가 크게 발생한다.
      2) 메서드에 한해서는 넘겨받는 인자값이 올바른지 확인하고 예외 처리를 한다.
      3) 예외 타입을 명시하지 않은 catch은 스레드마다 한 번만 전역적으로 둔다. 그 외에는 예외 타입을 명시한다.
      4) 성능상 문제가 발생할 수 있는 예외 처리 메서드는 예외 처리가 없는 메서드를 함께 제공한다.
      5) try/finally는 언제나 사용해도 괜찮다.

5. LINQ(Language-Integrated Query)이란 무엇이며, 어떻게 사용되는지 예를 들어 설명해주세요.

LINQ란?

언어 통합 쿼리는 당양한 데이터 소스를 쿼리로 조작하기 위한 일관되고 직관적인 방법을 제공하는 c# 언어 확장 집합이다. LINQ를 사용하면 친숙한 SQL 유사 구문 또는 메서드 기반 접근 방식을 사용하여 개체, 컬렉션, 데이터베이스, XML 등을 퀴리할 수 있다.

주요기능

LINQ to objects - 배열, 컬렉션, 제네릭 컬렉션에서 LINQ를 사용하여 원하는 데이터를 추출할 수 있습니다.
LINQ to XML - XML 문서에서 LINQ를 사용하여 원하는 데이터를 추출할 수 있습니다.
LINQ to SQL - SQL 서버의 데이터베이스와 함께 동작할 수 있습니다.
LINQ to DataSet - DataSet에 LINQ를 사용하여 원하는 데이터를 추출할 수 있습니다.

LINQ의 장점

  • 가독성과 표현력 : LINQ는 복잡한 데이터 작업을 간결하고 선언적인 방식으로 표현할 수 있도록 하여 코드를 단순화하고 가독성을 향상시킨다.
  • 타입 안정성 및 컴파일 검사 : LINQ의 중요한 장점 중 하나는 C# 유형 시스템과의 통합니다.
    즉 컴파일 타임 검사를 통해 쿼리가 유효하고 형식이 안전한지 확인할 수 있다.
  • 코드 재사용성 : LINQ를 사용하면 쿼리를 한 번 작성하고 여러 데이터 소스에서 재사용이 가능하다.
    이는 코드 재사용성을 촉진하고 중복성을 줄이며 유지 관리성을 향상시킨다. 또한 LINQ 쿼리는 메서드 또는 속성으로 쉽게 캡슐화되어 모듈식 및 조직화된 코드를 사용할 수 있다.
  • C#과의 원활한 통합 : 언어 확장으로서 LINQ는 나머지 C#언어와 원활하게 통합된다. LINQ를 람다 식, 익명 형식 및 예외 처리와 같은 다른 언어 기능과 결합할 수 있다. 이 시너지를 통해 표현력 있고 효율적인 코드를 작성하여 복잡한 데이터 작업을 쉽게 처리할 수 있다.

사용법

// Query 구문
var querySyntaxResult = from number in numbers
                        where number % 2 == 0
                        orderby number descending
                        select number;
// Method 구문
var methodSyntaxResult = numbers
                        .Where(number => number % 2 == 0)
                        .OrderByDescending(number => number)
                        .Select(number => number);                

1) 정렬

정렬 작업은 하나 이상의 특성을 기준으로 시퀀스 요소를 정렬하는 작업입니다.

메서드 이름설명C# 쿼리 식 구문
OrderBy값을 오름차순으로 정렬합니다.orderby
OrderByDescending값을 내림차순으로 정렬합니다.orderby … descending
ThenBy2차 정렬을 오름차순으로 수행합니다.orderby …, …
ThenByDescending2차 정렬을 내림차순으로 수행합니다.orderby …, … descending
Reverse컬렉션에서 요소의 순서를 반대로 바꿉니다.

2) 집합

집합 작업은 동일 컬렉션이나 별개 컬렉션(또는 집합)에 동등한 요소가 있는지 여부에 따라 결과 집합을 생성하는 쿼리 작업입니다.

메서드 이름설명
Distinct컬렉션에서 중복 값을 제거합니다.
Except두 번째 컬렉션에 표시되지 않는 한 컬렉션의 요소를 의미하는 차집합을 반환합니다.
Intersect두 컬렉션에 각각 표시되는 요소를 의미하는 교집합을 반환합니다.
Union두 컬렉션 중 하나에 표시되는 고유한 요소를 의미하는 합집합을 반환합니다.

3) 데이터 필터링

데이터 필터링은 지정된 조건을 충족하는 요소만 포함하도록 결과 집합을 제한하는 작업입니다.

메서드 이름설명C# 쿼리 식 구문
OfType지정된 형식으로 캐스트할 수 있는지 여부에 따라 값을 선택합니다.
Where조건자 함수를 기반으로 하는 값을 선택합니다.where

4) 수량자 작업

수량자 작업은 시퀀스에서 조건을 충족하는 요소가 일부인지 전체인지를 나타내는 것을 참/거짓으로 반환합니다.

메서드 이름설명
All시퀀스의 모든 요소가 조건을 만족하는지를 확인합니다.
Any시퀀스의 임의의 요소가 조건을 만족하는지를 확인합니다.
Contains시퀀스에 지정된 요소가 들어 있는지를 확인합니다.

5) 프로젝션 작업

프로젝션은 주로 이후에 사용할 속성으로만 구성된 새 양식으로 개체를 변환하는 작업입니다.

메서드 이름설명C# 쿼리 식 구문
Select변환 함수를 기반으로 하는 값을 프로젝션합니다.select
SelectMany변환 함수를 기반으로 하는 값의 시퀀스를 프로젝션한 다음 하나의 시퀀스로 평면화합니다.여러 from 절 사용

6) 데이터 분할

LINQ의 분할은 요소를 다시 정렬한 후 섹션 중 하나를 반환하지 않고 입력 시퀀스를 두 개의 섹션으로 나누는 작업입니다.

연산자 이름설명
Skip시퀀스에서 지정한 위치까지 요소를 건너뜁니다.
SkipWhile요소가 조건을 충족하지 않을 때까지 조건자 함수를 기반으로 하여 요소를 건너뜁니다.
Take시퀀스에서 지정된 위치까지 요소를 사용합니다.
TakeWhile요소가 조건을 충족하지 않을 때까지 조건자 함수를 기반으로 하여 요소를 사용합니다.

7) 조인 작업

두 데이터 소스를 조인하는 것은 한 데이터 소스의 개체를 공통 특성을 공유하는 다른 데이터 소스의 개체와 연결하는 작업입니다.

메서드 이름설명C# 쿼리 식 구문
Join키 선택기 함수를 기준으로 두 시퀀스를 조인한 다음 값 쌍을 추출합니다.join … in … on … equals …
GroupJoin키 선택기 함수를 기준으로 두 시퀀스를 조인한 다음 결과로 생성된 일치 항목을 요소마다 그룹화합니다.join … in … on … equals … into …

8) 데이터 그룹화

그룹화는 데이터를 그룹에 넣어 각 그룹의 요소가 공통 특성을 공유하게 하는 작업입니다.

메서드 이름설명C# 쿼리 식 구문
GroupBy공통 특성을 공유하는 요소를 그룹화합니다. 각 그룹은 IGrouping<TKey,TElement> 개체로 표시됩니다.group … by
ToLookup키 선택기 함수에 따라 Lookup<TKey,TElement>(일대다 사전)에 요소를 삽입합니다.

9) 생성 작업

생성은 값의 새 시퀀스를 만드는 작업을 나타냅니다.

메서드 이름설명
DefaultIfEmpty빈 컬렉션을 기본값을 갖는 singleton 컬렉션으로 바꿉니다.
Empty비어 있는 컬렉션을 반환합니다.
Range일련의 숫자를 포함하는 컬렉션을 생성합니다.
Repeat반복되는 값이 하나 들어 있는 컬렉션을 생성합니다. 

10) 같음 연산

해당 요소가 동일하고 같은 수의 요소를 포함 하는 두 시퀀스는 같은 것으로 간주됩니다.

메서드 이름설명
SequenceEqual쌍 단위 방식으로 요소를 비교하여 두 시퀀스가 서로 같은지 확인합니다.

11) 요소 작업

요소 작업은 시퀀스에서 특정 단일 요소를 반환합니다.

메서드 이름설명
ElementAt컬렉션의 지정된 인덱스에 있는 요소를 반환합니다.
ElementAtOrDefault컬렉션의 지정된 인덱스에 있는 요소를 반환하거나 인덱스가 범위를 벗어나면 기본값을 반환합니다.
First컬렉션의 첫 번째 요소 또는 특정 조건에 맞는 첫 번째 요소를 반환합니다.
FirstOrDefault컬렉션의 첫 번째 요소 또는 특정 조건에 맞는 첫 번째 요소를 반환합니다. 이러한 요소가 없으면 기본값을 반환합니다.
Last컬렉션의 마지막 요소 또는 특정 조건에 맞는 마지막 요소를 반환합니다.
LastOrDefault컬렉션의 마지막 요소 또는 특정 조건에 맞는 마지막 요소를 반환합니다. 이러한 요소가 없으면 기본값을 반환합니다.
Single컬렉션의 유일한 요소 또는 특정 조건에 맞는 유일한 요소를 반환합니다. 반환할 요소가 없거나 두 개 이상 있는 경우 InvalidOperationException을 throw합니다.
SingleOrDefault컬렉션의 유일한 요소 또는 특정 조건에 맞는 유일한 요소를 반환합니다. 반환할 요소가 없는 경우 기본값을 반환합니다. 반환할 요소가 두 개 이상 있는 경우 InvalidOperationException을 throw합니다.

12) 데이터 형식 변환

변환 메서드는 입력 개체의 형식을 변경합니다.

메서드 이름설명C# 쿼리 식 구문
AsEnumerableIEnumerable<T>로 형식화된 입력을 반환합니다.
AsQueryable(제네릭) IEnumerable을 (제네릭) IQueryable로 변환합니다.
Cast컬렉션의 요소를 지정된 형식으로 캐스트합니다.명시적 형식 범위 변수를 사용합니다.
예: from string str in words
OfType지정된 형식으로 캐스트할 수 있는지 여부에 따라 값을 필터링합니다.
ToArray컬렉션을 배열로 변환합니다. 이 메서드는 쿼리를 강제로 실행합니다.
ToDictionary키 선택기 함수에 따라 Dictionary<TKey,TValue>에 요소를 배치합니다. 이 메서드는 쿼리를 강제로 실행합니다.
ToList컬렉션을 List<T>로 변환합니다. 이 메서드는 쿼리를 강제로 실행합니다.
ToLookup키 선택기 함수에 따라 Lookup<TKey,TElement>(일 대 다 사전)에 요소를 배치합니다. 이 메서드는 쿼리를 강제로 실행합니다.

13) 연결 작업

연결은 한 시퀀스를 다른 시퀀스에 추가하는 작업을 나타냅니다.

메서드 이름설명C# 쿼리 식 구문
Concat두 시퀀스를 연결하여 하나의 시퀀스를 구성합니다.해당 사항 없음.

집계 작업

집계 작업에서는 값의 컬렉션에서 하나의 값을 계산합니다.

메서드 이름설명
Aggregate컬렉션 값에 대해 사용자 지정 집계 작업을 수행합니다.
Average값 컬렉션의 평균 값을 계산합니다.
Count컬렉션에서 요소(선택적으로 조건자 함수를 충족하는 요소만) 개수를 계산합니다.
LongCount큰 컬렉션에서 요소(선택적으로 조건자 함수를 충족하는 요소만) 개수를 계산합니다.
Max컬렉션의 최대값을 확인합니다.
Min컬렉션의 최소값을 확인합니다.
Sum컬렉션에 있는 값의 합계를 계산합니다.

사용법

LINQ는 쿼리 구문매서드 구문이라는 2가지 구문 스타일을 제공한다. 쿼리 구문은 SQL과 유사하며 데이터 쿼리에 대한 선언적 접근방식을 제공하는 방면 메서드 구문은 메서드 체인을 사용하여 동일한 결과를 얻을 수 있다.

6. Unity에서 컴포넌트(Component)란 무엇이고, 어떻게 사용되나요?

컴포넌트란?

프로그래밍에 있어 재사용 및 교체가 가능한 부품이다.
게임에서 오브젝트와 동작에 관한 기본 구성 요소라고 할 수 있다.
컴포넌트는 모든 게임 오브젝트의 작동과 관련한 부품입니다.

사용방법

객체에 원하는 기능이 있는 컴포넌트를 하나씩 추가해주는 형태로 사용이 가능합니다.
인스펙터(Inspector)아래에 Add Component를 사용해 원하는 기능이 있는 컴포넌트를 추가하면 됩니다.

7. 프리팹(Prefab)이 무엇이며, 어떻게 사용하는지 간단히 설명해주세요.

프리팹(Prefab)이란?

미리 만들어 놓은 게임 오브젝트, 템플릿이다.
프리팹은 Asset에 저장되어 있으며, 프리팹 인스턴스(Prefab Instance)를 생성하여, 월드 상에서 동작한다.
프리팹으로부터 원하는 만틈의 프리팹 인스턴스를 생성할 수 있다. 생성된 프리팹 인스턴스는 서로 독립적으로 동작하며, 프리팹 인스턴스의 프로퍼티를 수정해도 다른 프리팹 인스턴스에 영향을 주지 않는다.

등록

만들어놓은 게임 오브젝트를 에셋 폴더에 드래그로 옮기면 prefab으로 생성이 가능하다.

수정

씬에 올려진 prefab의 객체를 수정해도 그 객체에만 적용되지만(전체적용도 가능합니다), prefab 원본을 수정 시 모든 씬에 올려진 prefab에 모두 적용

생성

생성하는 방법
1). prefab을 드래그해서 씬에 올리는 방법
2). 코드로 Instantiate로 생성하는 방법

장점

동일한 객체를 반복적으로 활용할 때 새롭게 만들지 않고 재활용할 수 있고 수정이 용이하여 편리하다.

8. 씬(Scene)과 프로젝트(Project)의 차이점은 무엇인가요?

씬은 Unity내에서 저장가능한 하나의 장면으로 각각 고유한 캐릭터, 환경 장애물, 장식, UI를 포함하고 있는 레벨 저장소 또는 스테이지라고 할 수 있습니다.

프로젝트는 여러가지 장면, 자산을 갖고있으며 이를 활용하여 해당 프로젝트가 게임, 이미지 뷰어, 건축물의 3d가 될 수 있습니다.

9. 코루틴(Coroutine)이란 무엇이며, 어떻게 활용되나요?

코루틴이란 비동기 코드를 구현하기 위한 방법 중 하나로 일반적인 메서드 처럼 보이지만, 중간에 일시 중지되어 다른 코루틴을 실행하고 나중에 중단한 지점부터 계속해서 실행이 가능합니다.
시간의 경과에 따른 명령을 줄 때나 동시에 여러가지 일을 진행하고자 할 때 사용됩니다.

10. Unity에서 물리 충돌과 트리거의 차이에 대해 설명해주세요.

Collider

충돌체라는 뜻을 갖고있는 Collider는 물리 충돌 처리를 위한 클래스이다.

  • Static Collider = collider만 존재하는 객체
    • Static Collider를 이동시 일반 Collider사용 보다 자원소모가 커집니다.

Collision(충돌)

두 개의 collider(콜라이더)가 서로 물리적으로 충돌하는 상태를 의미한다.
충돌 이벤트가 발생할 때, 물리적 힘이 작용하고 물체들은 서로 밀려난다.

  • 처리 함수 : OnCollisionEnter, OnCollisionStay, OnCollisionExit

충돌하기 위해서는 다른 조건이 필요하다.

  • 1). 충돌한 2객체 중 하나는 꼭 Rigidbody라는 컴포넌트가 있어야한다.
    • IsKinematic은 off이여야 한다.
  • 2). 충돌할 객체 둘 다 모두 Collider 컴포넌트를 가지고 있어야 한다.
    • IsKinematic은 off이여야 한다.

Trigger (트리거)

collider 중 하나가 trigger로 설정된 상태를 의미한다.
RigidBody 컴포넌트가 있더라도 충돌 시 물리적인 힘이 작용하지 않는다.

  • 처리 함수: OnTriggerEnter, OnTriggerStay, OnTriggerExit

충돌하기 위해서는 다른 조건이 필요하다.

  • 1). 충돌한 2객체 중 하나는 꼭 Rigidbody라는 컴포넌트가 있어야한다.
  • 2). 충돌할 객체 둘 다 모두 Collider 컴포넌트를 가지고 있어야 한다.
    • 둘 중 하나라도 IsTrigger은 On이여야 한다.

번외

Collider로 물체를 이동하면 자원소모가 크므로 Rigidbody나 다른 방법을 이용하는 것이 최적화에 도움이 됩니다.

0개의 댓글