유니티 면접 대비 이것저것
두서 없이 정리
답변은 gpt4.0, 구글링, 노션ai, 기타등등
UniRx
https://skuld2000.tistory.com/31
요약하면 비동기적 데이터 흐름을 처리하는 프로그래밍 기법인 Reactive programming - 즉 반응형 프로그래밍을 유니티에서 사용할 수 있도록 일본의 개발자가 만든 유니티 전용 반응형 프로그래밍 지원툴이다.
반응형 프로그래밍이란 옵저버 패턴을 사용해서 값의 변화, 이벤트의 발생 등을 감지해서 해당 상황에 값을들 필터링, 버퍼링, 변화, 연산, 가공등을 할 수 있게 해주는 것.
유니티 코루틴에서 Yield와 LINQ를 생각하면 이해가 쉬울듯.
LINQ
유니티에서 LINQ(Language Integrated Query)는 데이터 컬렉션에 대해 강력하고 유연한 쿼리 기능을 제공하는 .NET의 프로그래밍 기능입니다. LINQ를 사용하면, 배열, 리스트, 또는 다른 컬렉션 유형의 데이터를 SQL 스타일의 쿼리로 쉽게 조작하고 필터링할 수 있습니다. 유니티에서는 이를 통해 게임 오브젝트, 컴포넌트 목록 등을 효과적으로 다룰 수 있습니다.
LINQ의 장단점은 다음과 같습니다:
장점
- 가독성: LINQ 쿼리는 선언적이며, SQL과 유사한 구문을 사용하기 때문에 읽기 쉽고 이해하기 쉽습니다. 이는 코드의 유지보수성을 높여줍니다.
- 통합된 쿼리 언어: 다양한 데이터 소스(배열, 리스트, XML, 데이터베이스 등)에 대해 동일한 쿼리 구문을 사용할 수 있습니다. 이는 학습 곡선을 줄여주고, 다양한 데이터 소스를 동일한 방식으로 처리할 수 있게 합니다.
- 강력한 필터링, 정렬, 그룹화 기능: LINQ는 복잡한 데이터 조작과 변환을 단순화합니다. 데이터를 필터링, 정렬, 그룹화하는 등의 작업을 간결하고 효율적으로 수행할 수 있습니다.
- 컴파일 시간 검사: LINQ는 컴파일 시간에 쿼리를 검사하여, 실행 시간 에러를 줄여줍니다.
단점
- 성능 저하 가능성: LINQ 쿼리는 때때로 직접적인 반복문이나 조건문보다 느릴 수 있습니다. 특히 대용량 데이터를 처리할 때 성능 저하가 발생할 수 있습니다.
- 디버깅 어려움: LINQ 쿼리는 디버깅이 복잡할 수 있습니다. 특히 복잡한 쿼리의 경우, 어디에서 문제가 발생했는지 파악하기 어려울 수 있습니다.
- 학습 곡선: LINQ의 고급 기능은 학습하기가 다소 복잡할 수 있으며, SQL이나 함수형 프로그래밍에 익숙하지 않은 개발자에게는 어려울 수 있습니다.
- 오버헤드: 간단한 작업을 위해 LINQ를 사용하는 것은 때때로 오버헤드를 초래할 수 있으며, 이는 특히 게임 개발과 같은 성능이 중요한 환경에서 고려해야 할 사항입니다.
요약하면, LINQ는 유니티 개발에서 데이터를 효율적이고 가독성 높게 처리할 수 있는 강력한 도구입니다. 그러나 성능과 복잡도 측면에서 고려해야 할 부분들이 있으므로, 사용 시 이러한 점들을 염두에 두는 것이 중요합니다.
비동기 프로그래밍
비동기 프로그래밍은 프로그램이 일련의 작업을 동시에 또는 병렬로 수행할 수 있도록 하는 프로그래밍 방식입니다. 이 방식의 핵심은 프로그램이 특정 작업을 기다리는 동안 다른 작업을 계속 진행할 수 있다는 점입니다.
비동기 프로그래밍의 주요 특징과 이점은 다음과 같습니다:
- 효율성과 반응성 향상: 비동기 프로그래밍을 사용하면 프로그램이 네트워크 요청, 파일 I/O 작업 등과 같은 시간이 오래 걸리는 작업을 기다리는 동안 멈추지 않고 다른 작업을 계속 처리할 수 있습니다. 이로 인해 애플리케이션이 사용자에게 더 반응적으로 느껴질 수 있습니다.
- 자원 사용 최적화: 동기식 프로그래밍에서는 작업이 완료될 때까지 기다리면서 CPU 같은 시스템 자원이 유휴 상태에 머물 수 있습니다. 비동기 프로그래밍은 이러한 자원을 보다 효율적으로 활용하여, 여러 작업을 동시에 진행할 수 있게 합니다.
- 코드 구조 개선: 비동기 프로그래밍을 적용하면, 코드를 더 명확하고 관리하기 쉬운 형태로 작성할 수 있습니다. 특히, 모던 프로그래밍 언어에서 제공하는 **async**와 await 같은 구문을 사용하면, 비동기 코드를 거의 동기 코드처럼 간결하고 이해하기 쉽게 작성할 수 있습니다.
- 확장성 증가: 비동기 프로그래밍은 애플리케이션의 확장성을 향상시킵니다. 많은 요청이나 데이터를 처리해야 하는 서버 애플리케이션에서 비동기 처리는 성능에 큰 영향을 미칩니다.
비동기 프로그래밍은 많은 장점을 가지고 있지만, 오류 처리, 디버깅, 자원 관리 등의 측면에서 복잡성을 추가할 수 있습니다. 따라서 프로그램의 요구 사항과 환경에 맞게 적절한 비동기 전략을 선택하고, 코드를 주의 깊게 관리하는 것이 중요합니다.
유니티에서의 비동기 프로그래밍 사용예
유니티에서 비동기 프로그래밍을 구현하는 주요 방법은 다음과 같습니다:
- Coroutines: 코루틴은 유니티에서 가장 일반적으로 사용되는 비동기 프로그래밍 기법 중 하나입니다. **IEnumerator**를 반환하는 함수를 사용하여 구현되며, yield return 문을 통해 실행을 일시 중단하고 유니티의 다음 프레임이나 특정 시간이 지난 후에 계속 실행할 수 있습니다. 코루틴은 비교적 간단한 비동기 작업에 적합하며, 유니티의 게임 루프와 잘 통합됩니다.
- Async/Await: C# 5.0 이상에서 사용 가능한 **async**와 await 키워드를 통해 비동기 프로그래밍을 구현할 수 있습니다. 이 방법은 유니티에서 네트워킹, 데이터 로딩, 긴 계산 작업 등을 비동기적으로 처리하는 데 유용합니다. async 함수는 Task 또는 **Task<T>**를 반환하며, await 키워드를 사용하여 비동기적으로 완료될 작업을 기다립니다.
- UnityWebRequest: 네트워크 통신과 관련된 비동기 작업을 위해 UnityWebRequest 클래스를 사용할 수 있습니다. 이 클래스는 웹 서버와의 HTTP 통신을 비동기적으로 처리하는 데 사용됩니다. UnityWebRequest는 내부적으로 비동기 작업을 관리하여, 네트워크 응답을 기다리는 동안 게임의 다른 부분이 계속 작동할 수 있게 합니다.
- Thread와 ThreadPool: 유니티에서는 C#의 표준 스레딩 기능을 사용하여 별도의 스레드에서 작업을 수행할 수 있습니다. 이 방법은 CPU 집약적 작업이나 긴 계산을 병렬로 수행할 때 유용합니다. 하지만 유니티의 메인 스레드와의 동기화와 스레드 안전성을 고려해야 합니다.
- Custom Yield Instructions: 유니티는 코루틴에서 사용할 수 있는 다양한 사용자 정의 대기 명령을 제공합니다. 예를 들어, WaitForSeconds, WaitForEndOfFrame, WaitUntil, WaitWhile 등이 있으며, 이를 통해 보다 세밀한 비동기 제어가 가능합니다.
각각의 방법은 특정 상황과 요구 사항에 따라 선택되어야 하며, 성능과 효율성을 고려하여 적절히 사용되어야 합니다. 예를 들어, 간단한 지연이 필요한 경우에는 코루틴이 적합할 수 있고, 복잡한 데이터 처리나 네트워킹은 async/await 또는 별도의 스레드를 사용할 수 있습니다.
반응형 프로그래밍
반응형 프로그래밍(Reactive Programming)은 데이터 흐름과 변화 전파에 중점을 둔 프로그래밍 패러다임입니다. 이 방식은 데이터 스트림과 변화의 전파를 중심으로 하여, 데이터의 변화가 발생할 때마다 이에 자동으로 반응하여 프로그램이 동작하도록 설계됩니다.
반응형 프로그래밍의 주요 특징과 이점은 다음과 같습니다:
- 데이터 스트림 중심: 반응형 프로그래밍에서는 모든 것을 스트림(stream)으로 볼 수 있습니다. 사용자 입력, 변수 값의 변화, 프로퍼티, 캐시 데이터 등이 스트림으로 표현되며, 이 스트림은 시간에 따라 다른 값을 방출합니다.
- 선언적인 스타일: 반응형 프로그래밍은 선언적 프로그래밍 방식을 사용합니다. 개발자는 '무엇을' 할지를 정의하고, '어떻게' 그 일을 수행할지는 프레임워크나 라이브러리에 맡깁니다. 이는 코드를 보다 직관적이고 간결하게 만들어줍니다.
- 데이터 변화에 자동 반응: 데이터 스트림이 변경될 때마다 자동으로 반응하여 새로운 데이터를 처리합니다. 이는 동적인 데이터 흐름을 쉽게 관리할 수 있게 해 주며, 사용자 인터페이스, 네트워크 요청 등 다양한 영역에서 유용하게 사용됩니다.
- 비동기 프로그래밍과의 통합: 반응형 프로그래밍은 자연스럽게 비동기 프로그래밍과 연결됩니다. 비동기적인 데이터 스트림을 쉽게 관리하고, 이벤트 기반의 프로그래밍을 강화합니다.
- 에러 처리의 용이성: 스트림을 통해 데이터를 처리하는 방식은 에러를 스트림의 일부로 취급하므로, 에러 처리를 보다 일관적이고 중앙집중적으로 관리할 수 있게 해줍니다.
반응형 프로그래밍은 RxJava, RxJS, Rx.NET, UniRx (유니티) 등 다양한 라이브러리와 언어를 통해 구현될 수 있으며, 복잡한 데이터 흐름과 사용자 인터페이스, 네트워킹, 실시간 데이터 처리 등 다양한 영역에서 유용하게 사용됩니다. 이 패러다임은 특히 동적이고 상호작용이 많은 애플리케이션을 개발할 때 그 장점이 잘 드러납니다.
함수형 프로그래밍
함수형 프로그래밍(Functional Programming, FP)은 프로그래밍 패러다임 중 하나로, 계산을 수학적 함수의 평가로 취급하고, 상태 변경과 가변 데이터를 피하는 것을 강조합니다. 이 접근 방식은 프로그램의 예측 가능성과 유지 보수성을 높이는 데 도움이 됩니다.
함수형 프로그래밍의 핵심 개념은 다음과 같습니다:
- 불변성(Immutability): 데이터는 생성 후 변경되지 않습니다. 변경이 필요한 경우, 기존 데이터를 수정하는 대신 새로운 데이터를 생성합니다.
- 순수 함수(Pure Functions): 같은 입력에 대해 항상 같은 출력을 반환하며, 외부 상태에 의존하지 않고 외부 상태를 변경하지 않는 함수입니다.
- 함수의 일급 객체(First-Class Functions): 함수를 일반 값처럼 사용할 수 있습니다. 예를 들어, 함수를 변수에 할당하거나, 다른 함수의 인자로 전달하거나, 함수에서 반환할 수 있습니다.
- 고차 함수(Higher-Order Functions): 함수를 인자로 받거나 함수를 결과로 반환하는 함수입니다.
- 함수 합성(Function Composition): 여러 함수를 조합하여 새로운 함수를 만드는 것입니다.
- 레이지 평가(Lazy Evaluation): 필요할 때까지 계산을 미루는 것으로, 성능 최적화에 사용될 수 있습니다.
유니티에서의 함수형 프로그래밍 예시
유니티에서도 함수형 프로그래밍의 원리를 적용할 수 있습니다. 예를 들어, LINQ를 사용하는 것이 하나의 방법입니다. LINQ는 컬렉션에 대한 쿼리를 함수형 스타일로 작성할 수 있게 해줍니다.
csharpCopy code
using System.Linq;
using UnityEngine;
public class FunctionalExample : MonoBehaviour
{
void Start()
{
var numbers = new[] {1, 2, 3, 4, 5};
var evenNumbers = numbers.Where(n => n % 2 == 0); // 함수형 스타일의 필터링
foreach (var num in evenNumbers)
{
Debug.Log(num);
}
}
}
이 코드에서 Where 메서드는 LINQ의 함수형 기능을 활용하여 짝수만 필터링합니다. 이러한 스타일은 선언적이며 부수 효과가 없어, 유지 보수가 용이하고 버그 발생 가능성을 줄여줍니다.
또한, 유니티에서는 람다 표현식이나 익명 함수를 사용하여 이벤트 리스너나 콜백을 작성할 때도 함수형 프로그래밍 개념을 적용할 수 있습니다.
함수형 프로그래밍은 유니티 개발에 있어 강력한 도구이며, 특히 복잡한 데이터 처리, 비동기 프로그래밍, UI 이벤트 처리 등에 유용하게 사용될 수 있습니다.
DOTS (Data-Oriented Technology Stack)
DOTS는 유니티에서 제공하는 데이터 지향적인 프로그래밍 기술 스택으로, 게임의 성능을 극대화하기 위해 설계되었습니다. 이 기술 스택의 핵심은 게임 개발을 위한 새로운 방식의 접근법을 제공하는 것으로, 이를 통해 개발자들은 더 높은 성능과 다중 스레딩 환경을 쉽게 활용할 수 있게 됩니다.
DOTS의 주요 구성 요소는 다음과 같습니다:
- Entity Component System (ECS): ECS는 개체(Entity), 구성 요소(Component), 시스템(System)의 세 가지 주요 요소로 구성됩니다. 각 개체는 하나 이상의 구성 요소를 가질 수 있으며, 각 구성 요소는 데이터를 담고 있습니다. 시스템은 이러한 구성 요소의 데이터를 처리합니다. 이 접근법은 데이터와 로직을 분리하며, 메모리 레이아웃을 최적화하여 성능을 향상시킵니다.
- Job System: Job System은 데이터 처리를 병렬 작업으로 분리하여 다중 코어 프로세서의 이점을 최대한 활용할 수 있도록 합니다. 이 시스템을 통해 성능 저하 없이 많은 수의 개체를 동시에 처리할 수 있습니다.
- Burst Compiler: Burst Compiler는 고성능 C# 코드를 생성하기 위한 컴파일러입니다. 이는 .NET 코드를 매우 효율적인 네이티브 코드로 변환하여, ECS 및 Job System의 성능을 극대화합니다.
DOTS의 이점은 주로 성능에 있습니다. 데이터 지향적인 설계는 메모리 액세스를 최적화하고, 병렬 처리를 통해 CPU의 여러 코어를 효율적으로 사용할 수 있도록 도와줍니다. 이는 특히 대규모 게임 환경이나 높은 프레임 속도를 요구하는 애플리케이션에 유용합니다.
그러나 DOTS는 전통적인 객체 지향 프로그래밍과는 다른 패러다임을 제공하기 때문에 새로운 학습 곡선이 필요하며, 기존의 유니티 프로젝트를 DOTS로 전환하는 것은 상당한 노력을 요구할 수 있습니다. 따라서 DOTS를 사용하기로 결정하기 전에 프로젝트의 요구 사항과 팀의 전문성을 고려하는 것이 중요합니다.
ECS (Entity Component System)
ECS (Entity Component System)
- 개념: ECS는 데이터 지향적인 게임 개발 방식으로, 엔티티(Entity), 컴포넌트(Component), 시스템(System)의 세 부분으로 구성됩니다.
- Entity: 게임 내의 개체나 오브젝트를 나타냅니다. 엔티티 자체는 단순히 ID나 참조로 존재하며, 실제 데이터나 기능은 가지고 있지 않습니다.
- Component: 엔티티에 부착되어 데이터를 제공하는 구조체입니다. 위치, 속도, 건강 상태 등의 데이터를 담고 있습니다.
- System: 컴포넌트의 데이터를 기반으로 실제 게임 로직을 처리합니다. 예를 들어, 물리 시스템, 렌더링 시스템, AI 시스템 등이 있습니다.
- 목적: ECS는 데이터와 로직을 분리하여 성능을 최적화하고, 유지 보수를 용이하게 합니다. 특히 대규모 게임에서의 성능 개선에 중점을 둡니다.
- 유니티와의 관계: 유니티는 DOTS (Data-Oriented Technology Stack)를 통해 ECS 패러다임을 지원하며, 이를 통해 개발자들은 더 높은 성능과 다중 스레딩의 이점을 활용할 수 있습니다.
NTT (Network Transform Toolkit)
- 개념: NTT(Network Transform Toolkit)은 유니티에서 네트워크 게임 개발 시, 오브젝트의 위치, 회전, 스케일과 같은 변환 정보를 네트워크를 통해 동기화하는 데 사용되는 도구나 라이브러리를 의미합니다. (참고로, 'NTT'는 공식적인 유니티 용어가 아니며, 네트워크 변환을 처리하는 도구나 툴킷을 일반적으로 지칭합니다.)
- 목적: 멀티플레이어 게임에서 각 플레이어의 게임 오브젝트 위치를 실시간으로 동기화하는 것이 주요 목적입니다. 이는 플레이어 간 일관된 게임 경험을 보장하는 데 필수적입니다.
- 구현 방식: NTT는 일반적으로 네트워크 상태, 예를 들어, 연결 속도와 지연 시간을 고려하여 효율적인 동기화를 달성합니다. 이는 인터폴레이션(Interpolation)과 엑스트라폴레이션(Extrapolation) 기술을 사용하여 네트워크 지연으로 인한 오브젝트의 움직임 불일치를 최소화합니다.
ECS와 NTT는 각각 게임의 내부 로직 처리와 네트워크를 통한 멀티플레이어 상호작용 처리에 중요한 역할을 합니다. ECS는 게임의 성능 최적화에 중점을 두는 반면, NTT는 네트워크 환경에서의 일관된 게임 경험 제공에 초점을 맞춥니다.
스트럭쳐 클래스 차이, 어느상황에 뭘쓰는게 좋은가?
Struct타입은 값타입이고 Class는 참조타입.
따라서 스트럭쳐는 스택영역에 할당되고 클래스는 힙영역에 할당.
내부 변수가 몇개 없고 메모리가 16mb이하라면 스트럭쳐가 유리, 이외에는 클래스가 유리
스트럭쳐는 값타입이라 생성자가 필요없음. 클래스는 생성이 필요.
유니티에서 구조체를 쓰면 어떤 장점이 있나요?
구조체는 유니티에서 클래스보다 가볍고 메모리 측면에서 효율적입니다. 또한 구조체를 사용하면 값을 복사하여 사용하기 때문에, 상속과 같은 문제를 회피할 수 있습니다.
박싱 / 언박싱
박싱은 값형식을 참조형식으로 변환하는것을 말함.
인트형이나 플롯형을 오브젝트타입으로 변환하는거?
아무튼 스택영역에 있던 값타입을 힙영역으로 바꾸면서 메모리손해가 발생한다.
반대로 언박싱은 참조타입이던 객체를 값형식으로 캐스팅하는것.
유니티 라이프 사이클
Awake : 객체가 생성될 때 제일처음 한번만 실행 / 보통 초기화 함수
OnEnable : 객체가 활성화 될때마다 실행
Start : 활성화 된 객체의 업데이트가 호출되기 전 한번만 실행 / 보통 초기화 함수
FixedUpdate : 일정프레임마다 호출되는 업데이트 함수
Update : 매프레임 호출되는 업데이트 함수
LateUpdate : 매 업데이트가 호출되고 난 뒤 호출되는 업데이트 함수
OnDisable : 오브젝트가 비활성화 될 때 실행
OnDestroy : 오브젝트가 삭제될 때 실행
더 자세한건 공식문서
https://docs.unity3d.com/kr/530/Manual/ExecutionOrder.html
이벤트 함수 실행 순서(Execution Order of Event Functions) - Unity 매뉴얼
Unity 이벤트 함수는 사전에 정해진 순서대로 실행됩니다. 실행 순서는 다음과 같습니다.
docs.unity3d.com
유니티에서 스택영역과 힙영역에 할당되는 객체들
유니티에서 값(Value) 타입으로 선언된 변수들은 스택(Stack) 메모리 영역에 할당됩니다. 반면 참조(Reference) 타입으로 선언된 변수들은 힙(Heap) 메모리 영역에 할당됩니다. 이는 값 타입 변수들이 복사되었을 때 스택에서 복사가 이루어지지만 참조 타입 변수들은 해당 객체의 주소값이 복사됩니다.
유니티에서 스택(Stack) 영역에 할당된 메모리와 힙(Heap) 영역에 할당된 메모리의 차이점은 다음과 같습니다.
- 스택 영역: 값(Value) 타입으로 선언된 변수들이 스택 메모리 영역에 할당됩니다. 스택은 메모리가 자동으로 관리되며, 변수가 함수나 블록의 범위를 벗어나면 자동으로 제거됩니다. 스택은 작은 메모리 블록을 할당하고 해제하는 데 빠르며, 메모리 블록은 참조되는 순서대로 저장됩니다. 따라서 스택은 데이터를 빠르게 접근할 수 있습니다.
- 힙 영역: 참조(Reference) 타입으로 선언된 변수들이 힙 메모리 영역에 할당됩니다. 힙은 큰 메모리 블록을 할당하고 해제하는 데 시간이 더 많이 소요됩니다. 또한 메모리 블록은 임의의 순서로 저장됩니다. 따라서 힙은 데이터에 접근하는 데는 스택보다 더 많은 시간이 걸리지만, 메모리의 크기가 동적으로 변경될 수 있습니다. 이는 배열과 같은 구조체를 할당할 때 유용합니다.
유니티에서 가비지컬렉터 동작 방식.
유니티에서 가비지 컬렉터(Garbage Collector)는 할당된 메모리를 정리하는 프로세스입니다. 유니티에서는 참조 카운트(Reference Counting) 방식이 아닌, 마크 앤 스위핑(Mark and Sweep) 방식을 사용합니다.
마크 앤 스위핑 방식은 다음과 같이 동작합니다.
- 가비지 컬렉터가 실행될 때마다, 모든 메모리 영역의 객체에 대해 마크(Mark)를 합니다.
- 마크된 객체들의 참조를 탐색하면서, 참조되지 않은 객체를 스위핑(Sweep)합니다.
- 스위핑된 객체들은 메모리에서 해제됩니다.
이 방식은 참조 카운트 방식보다는 복잡하지만, 더 효율적입니다. 참조 카운트 방식은 객체를 참조하는 모든 객체의 수를 추적해야 하기 때문에, 메모리 관리 오버헤드가 크고, 순환 참조(Circular Reference)와 같은 문제가 발생할 수 있습니다.
즉, 유니티에서는 가비지 컬렉터가 자동으로 메모리를 정리하기 때문에, 개발자들은 메모리 관리에 대한 직접적인 관여가 필요하지 않습니다. 다만, 가비지 컬렉터가 실행될 때마다 일시적으로 프로그램이 멈추는 경우가 있으므로, 이를 최소화하기 위해 메모리 사용을 최적화하는 것이 좋습니다.
etc...
자료구조에 대해서
디자인패턴에 대해서
코루틴에 대해서
상속과 인터페이스
abstract와 virtual