기술 면접 질의 응답 1~13 및 추가 질문 1~4
1. float 와 int 의 표현 가능한 수의 범위가 다른 이유는 무엇인가?
- 답
수를 표현하는 방식이 다르기 때문입니다.
int형의 경우, 부호 표현 및 이진수로 표현된 수를 나타내는 4바이트의 값을 가집니다
float형의 경우, 같은 4바이트지만, 부호를 표현하는 sign bit, 자릿수를 표현하는 exponent bit, 값을 표현하는 mantissa bit 로 구분되어 표현됩니다.
참고 ) https://indrawer.tistory.com/48
2. ref와 out 의 사용 시 차이는 무엇인가?
- 답
ref의 매개 변수는 사용하기 전에 초기화 되지만, out의 매개 변수는 이를 전달하기 전에 명시적으로 초기화할 필요가 없고 이전의 값은 모두 무시한다는 차이가 있습니다.
변수에 ref 키워드를 적용하면, 호출되는 메서드에 변수에 대한 참조 자체가 전달되며, 메서드가 실행되는 동안, 변경 내용이 저장되게 됩니다. 그렇기에 메서드에서 추가적으로 연산을 한 이후, 넘겨주는 용도로 많이 사용됩니다.
out 의 경우, ref와 유사하게 메서드에 참조를 전달하지만, 초기값을 무시하므로, 메서드 내부적으로 처리한 값을 다른 곳에서 사용해야 할 때 주로 사용합니다.
특히 ref의 경우 Mathf.SmoothDamp / Lerp / Moveto 같은 함수에서 많이 사용하고, out의 경우, Paycasthit에서 hit한 물체의 정보를 반환하는 장소 등에 많이 사용됩니다.
참고 ) https://codingcoding.tistory.com/56
건오님 질의응답
ref는 값을 넘겼을 때 추가적으로 연산을 해서 넘겨주는 용도로 많이 사용되며 주로 Mathf.SmoothDamp / Lerp / Moveto 같은 함수에 많이 사용됩니다.
out은 초기 설정과 상관없이 함수 내부적으로 처리한 값을 다른 곳에서 사용해야 할 때 사용하며 주로 Raycasthit에서 hit한 물체의 정보를 반환하는 (데이터 형식) 곳에 사용됩니다.
공통점으로 두 키워드 모두 참조(주소) 형태로 전달하기에 잘 사용하면 메모리를 절약할 수 있습니다.
3. 접근제한자란 무엇이며, 각각 어떤 차이가 있는지 비교해서 설명하라
- 답
외부로부터 타입과 그 타입의 멤버들로의 접근을 제한하여 무분별한 수정을 방지하여 보안을 강화하기 위해 사용되며, private, public, protected, internal, protected internal로 5가지가 존재합니다
가장 많이 쓰이는 접근제한자는 private, protected, public이며, 각각 타입 내부에서만 사용, 타입 외부에서는 접근할 수 없지만 타입 내부 또는 상속받은 경우 사용 가능, 어디에서나 사용 하다는 특징이 있습니다.
참고 ) https://developer-talk.tistory.com/457
4. struct와 class 를 비교해서 설명하라
- 답
구조체 형식은 class와 유사하게 데이터와 관련 기능을 캡슐화 할 수 있는 값 형식입니다
대표적으로 struct의 경우, 값 형식으로 스택의 영역에 할당되어 저장되기에 바로 사용 가능하지만, class의 경우, 참조 형식으로 힙에 할당하는 값의 주소를 가지게 되므로, new 키워드를 통해 주소값을 참조하여 사용해야 합니다
그 외에도, 구조체의 경우, 상속이 불가능하지만, class 의 경우 상속이 가능합니다
5. 가비지 컬렉터에 대해 설명하라
- 답
메모리의 관리 방법 중에 하나입니다.
프로그래머가 메모리를 할당한 후 해제를 안 하여 생기는 버그를 해결하기 위해 가비지 컬렉션이라는 시스템이 내장되었습니다.
가비지 컬렉션은 시스템에서 더 이상 사용하지 않는 동적 할당된 메모리 블럭을 찾아 자동으로 다시 사용 가능한 자원으로 회수하는데 이 과정에서 회수해야하는 자원을 모으는 역할을 수행하는 부분을 가비지 컬렉터라고 합니다
이런 가비지 컬렉터는 메모리 할당 / 사용 중인 메모리 인식 / 사용하지 않는 메모리 인식 와 같은 역할을 수행합니다
참고 ) https://blog.metafor.kr/163
6. 가비지 컬렉터를 회피하기 위한 전략은 무엇이 있나
- 답
메모리 할당 최소화, 가비지 컬렉션 메소드 직접 호출 피하기, IDisposable 인터페이스 사용, 소멸자 사용 최소화, 값 타입 사용 등의 방법으로 가비지 컬렉터로 인한 성능 저하 문제를 회피할 수 있습니다.
추가 질문 1. 객체 지향 프로그래밍과 절차 지향 프로그래밍이란
- 답
객체 지향 프로그래밍이란 프로그래밍에 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체로 만든 후, 객체들 간의 상호작용을 통해 로직을 구성하는 방식입니다
c++, c#, java 등에서 해당 방식을 사용합니다
유지 보수가 간단하며, 코드 재사용성이 용이한 장점과 처리 속도가 상대적으로 느리고, 객체가 많으면 용량이 커질 수 있다는 단점이 있습니다.
절차 지향 프로그래밍이란 프로그램 전체가 유기적으로 연결되도록 만들어 순차적으로 처리되도록 만드는 프로그래밍 기법입니다.
c언어에서 사용하는 방식으로 처리 속도가 상대적으로 빠르다는 장점과, 유지 보수가 어렵고, 디버깅이 어렵다는 단점이 있습니다.
하드웨어의 빠른 발전을 통해 객체 지향 프로그래밍의 단점이 크게 부각되지 않게 되어 많은 언어가 객체 지향 프로그래밍을 사용하고 있습니다.
참고 ) https://jeong-pro.tistory.com/95
추가 질문 2. 객체 지향 프로그래밍의 특징은?
- 답 :
객체 지향 프로그래밍의 특징으로는 캡슐화 / 상속 / 다형성 / 추상화 으로 4가지가 있습니다.
캡슐화란 대표적으로 클래스가 있으며, 데이터와 메서드를 결합시켜 묶어놓은 것으로 재활용이 원활하고 접근제한자를 통해 정보은닉에도 장점을 보입니다.
상속이란 상위 클래스와 하위 클래스의 관계를 나타내는 것으로 상위 클래스의 데이터와 메서드를 하위 클래스에 물려주거나 물려받는 것을 나타냅니다
이는 재사용성이 높고, 데이터와 메서드의 자유로운 사용 및 추가가 가능하다는 장점이 있습니다.
다형성이란 어떤 요소에 여러 개념을 넣어 놓은 것으로 오버라이딩과 오버로딩을 통해 같은 이름의 행위를 여러 개 정의하거나 상위 클래스의 행위를 하위 클래스에서 재정의해 사용할 수 있도록 하는 기능입니다.
추상화란 객체의 공통된 속성과 행위를 뽑아내는 것으로 중요한 정보만을 표현해 프로그램을 간단하게 만들 수 있습니다.
추가 질문 3. 유니티의 생명주기에 대해 설명하라
- 답 :
Awake -> OnEnable -> Start -> FixedUpdate -> OnTrigger와 OnCollision -> Update -> LateUpdate -> OnDisable -> OnDestroy -> OnApplicationQuit 의 생명주기를 가집니다
Awake 는 스크립트가 실행될 때 한 번만 호출되며 Start 이전에 실행되기에 초기화 순서를 정할 수 있습니다
OnEnable 은 인스펙터에서 체크를 통해 게임 오브젝트를 활성화 할 때 사용되며, 활성화 할 때마다 호출됩니다.
Start 는 Update 함수가 호출 되기 전에 한 번만 호출됩니다.
FixedUpdate 는 주로 물리 엔진을 사용하는 경우 일정 시간 간격으로 힘을 가할 때 사용하는 함수로 일정한 발생 주기마다 호출됩니다.
Update 는 프레임마다 호출되는 함수로 게임의 핵심 로직에 사용됩니다. 주기가 일정하지 않습니다.
LateUpdate 는 모든 Update 함수가 실행되고 나서 호출되며, 주로 카메라 이동 로직에 사용합니다.
OnDisable 은 게임 오브젝트 또는 스크립트가 비활성화 되었을 때 호출됩니다.
OnDestroy 는 오브젝트 생존 기간의 마지막 프레임이 업데이트 된 후 실행됩니다.
OnApplicationQuit 는 응용 프로그램 종료 전에 모든 오브젝트에서 호출됩니다.
참고 ) https://itmining.tistory.com/47
추가 질문 4. Json과 SO란 무엇이고 차이점은 무엇인가?
- 답
Json과 SO는 모두 데이터를 관리하는 방식 중의 하나 입니다. Json은 자바스크립트에서 객체를 만들 때 사용하는 표현식을 의미하며, 단순히 데이터를 표시하는 데이터 포맷입니다.
기본적으로 Key와 Value값을 가지며, 장점으로 쉽고 빠르며, 언어에 독립적으로 사용할 수 있다는 점이 있고, 단점으로는 하나의 값을 변경하더라도 엑셀에서 Json으로 변환 후 유니티에 추가하는 과정을 거쳐야 하기 때문에 번거로울 수 있다는 점이 있습니다.
SO는 스크립터블 오브젝트로 유니티에서 제공하는 대량의 데이터를 저장하는데 사용할 수 있는 데이터 컨테이너입니다.
프로젝트 진행 시 유니티 에디터에서 바로 수정할 수 있는 장점이 있지만, 유저 데이터와 같이 가변적인 데이터는 사용할 수 없다는 점이 있습니다.
참고 )https://wergia.tistory.com/189
https://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=138040
https://m.blog.naver.com/cdw0424/221472590996
##################################################################
둘 모두 데이터를 관리하는 방식
so
meta파일(읽기 전용)이 됨 -> 유저 데이터와 같이 가변적인 데이터는 so로 쓰면 안 됨
so는 유니티에 내장되어 있어 값 하나 변경한다면 바로 unity에서 수정 가능
json
엑셀로 변환해 편하게 보기 쉬움
값을 하나 변경하면
데이터테이블(엑셀) -> json -> db -> api(클라이언트)
해당과정을 거쳐야 함 -> 번거로움
##################################################################
7. 가비지 컬렉션이란 무엇인가
- 답
메모리의 관리 방법 중 하나로, 더 이상 쓸모 없어진 메모리를 가비지라고 하고, 이 가비지를 효과적으로 처리하는 작업을 가비지 컬렉션이라고 한다.
가비지 컬렉션 Mark and Sweep 알고리즘에 따라 동작하, 가비지 컬렉터가 접근할 수 있는 모든 변수나 객체들을 스캔하면서 어떤 객체를 가르키는지 찾는 과정을 Mark라고 하고, Mark되어 있지 않은 객체들을 힙에서 제거하는 것을 Sweep이라고 한다.
참고) 가비지 컬렉션, 컬렉터(Garbage Collection)란? :: 은유 개발 블로그 (metafor.kr)
마크 앤 스윕 알고리즘(번역) : 네이버 블로그 (naver.com)
8. 박싱과 언박싱에 대해 설명하고 사용 시 주의점에 대해 말하라
- 답
값 형식의 변수의 타입을 참조 형식인 object형으로 형 변환하는 것을 박싱이라고 하고, object형에서 다시 원상태로 복귀시키는 것을 언박싱이라고 합니다.
박싱을 하는 과정은 하위 차원에서 상위 차원으로의 형변환이기 때문에, 암시적 형변환이 가능하지만, 언박싱은 그 반대이기에 명시적 형변환을 해야하는 주의점이 있습니다.
또한, 값형은 스택에 저장되지만, 참조형은 힙에 저장되기에, 언박싱의 과정에서 가비지가 발생하게 됩니다.
그리고 박싱과 언박싱의 과정은 참조형 변수를 선언하며 힙 영역에 할당하는데 걸리는 시간보다 4~20배 정도 더 걸리기 때문에 사용 시, 성능적인 부분에서 주의할 필요가 있습니다.
참고) [c#] 박싱(boxing), 언박싱(unboxing) 개념과 사용 이유 (tistory.com)
9. 배열, List, ArrayList, Dictionary의 차이점을 설명하고 dictionary의 구현 방법과 검색이 빠른 이유를 설명하라
- 답
넷 모두 데이터 집합으로, 집합의 크기가 정해져 있는지, 데이터의 타입이 동일한지에 따라 구분할 수 있습니다.
배열은 크기가 정해져 있고 동일한 타입을 가지는 데이터의 집합이고,
리스트는 크기가 정해져 있지 않고 동일한 타입을 가지 데이터의 집합이며,
어레이리스트는 크기가 정해져 있지 않고 데이터의 타입이 동일하지 않아도 되는 데이터의 집합이고,
딕셔너리는 크기가 정해져 있지 않고 키와 값을 한 쌍으로 갖는 데이터의 집합입니다.
딕셔너리는 c#에서 자료구조의 해시테이블과 같은 역할을 하며, 검색하고자 하는 키를 입력받아, 해시함수를 통해 얻은 해시를 배열의 인덱스로 환산하여 데이터에 접근하는 방식으로 구현됩니다.
구조상 키만 입력하면 해시함수만 거치면 키에 해당하는 값에 접근할 수 있기 때문에 검색이 빠릅니다.
검색 시
배열의 시간복잡도 : O(1) 인덱스 번호를 통해 바로 접근
리스트의 시간복잡도 : O(n) 각 노드에 다음 노드의 주소가 들어있으므로, 순차적으로 접근
어레이리스트의 시간복잡도 : O(n) 리스트와 동일
딕셔너리의 시간복잡도 : O(1) : 키 값을 통해 바로 접근
참고) [C#] 배열, 리스트, 딕셔너리 (Array, List, Dictionary) (tistory.com)
[C#]컬렉션, ArrayList (tistory.com)
[자료구조] 해시 테이블 (Hash Table) (tistory.com)
연결리스트(Linked List)와 배열(Array), 그리고 시간복잡도의 차이에 대해 : 네이버 블로그 (naver.com)
10. 제네릭이란 무엇인지 설명하라
- 답
클래스를 정의할 때, 데이터 요소의 타입을 확정하지 않고, 데이터 타입 자체를 타입 파라미터 받아들이도록 설정해주는 기능입니다.
클래스명과 함께 구체적인 데이타 타입을 함께 지정해 사용하며, 이렇게 하면 일부 상이한 데이타 타입 때문에 여러 개의 클래스들을 따로 만들 필요가 없어지게 되어 재사용성을 크게 늘릴 수 있습니다.
클래스 이외에도 인터페이스나 메서드에도 적용될 수 있습니다.
참고) C# 제네릭 - C# 프로그래밍 배우기 (Learn C# Programming) (csharpstudy.com)
11. 델리게이트(Delegate)의 개념에 대해 설명하라
- 답
델리게이트는 메서드를 다른 메서드의 인자로 전달하거나, 메서드를 변수로 저장하거나, 메서드를 이벤트에 연결하는 동작이 가능하도록 해주는 매서드를 참조하는 형식입니다.
다른 클래스에서 직접적인 접근 없이 해당 함수를 사용하기 위해 주로 사용됩니다.
참고) 델리게이트 (delegate) (velog.io)
[c#] 델리게이트(delegate) 개념 | += , -= (tistory.com)
[C#] 델리게이트(delegate) - 델리게이트, 콜백 사용 방법 및 사용 이유 (tistory.com)
12. 'delegate', 'event', 'action', 'func' 간의 차이를 설명하라 또한 프로젝트에서 적용해본 경험에 대해 말하라
- 답
delegate, action, func은 모두 대리자로 메소드에 대한 참조 변수를 만들기 위해 존재합니다.
이 중 delegate가 가장 기본적인 형태입니다.
action과 func은 프로그래머가 일일이 delegate를 정의하지 않아도 되게 c# 내부적으로 정의하고 있는 대리자로, action은 인자만 존재하는 delegate, func은 인자와 결과값이 모두 존재하는 delegate입니다.
event는 클래스 내부에서만 실행할 대리자로 다른 곳에서 사용하지 못하게 하도록 컴파일러에 명시적으로 알려주는 기능을 합니다.
delegate가 callback의 용도로 사용되며, 인터페이스 내부에서 선언할 수 없지만, event는 객체의 상태 변화나 사건의 발생을 알리는 용도로 사용되고, 인터페이스 내부에서 선언할 수 있습니다.
프로젝트에서 적용해 본 경험 추가하기
https://velog.io/@sunbei00/C-delegate-Event-Func-Action
13. 람다식( Lambda Expression)에 대해 설명하라
- 답
람다식이란 접근자, 이름, return문이 없는 익명 함수로서, 코드를 간결하게 만들고, 지연 연산으로 성능을 높이고, 반복 관련 코드의 불필요한 부분들을 제거할 수 있습니다.
참고) C# 람다식 - C# 프로그래밍 배우기 (Learn C# Programming) (csharpstudy.com)
[C#]람다식, 람다표현식(Lambda expression) (tistory.com)