오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 61일차(최종프로젝트 12일차 면접준비 2!)

2024. 1. 29. 08:59스파르타코딩클럽 게임개발

반응형

Struct와 Class 비교

Struct와 Class는 C#같은 얻어에서 데이터를 저장하는 방법이다.

이들은 데이터 구조를 정의하고 해당 데이터를 처리하기위해 사용되지만

Struct와 Class는 몇 가지 중요한 차이점을 가지고 있다.

1. 값 타입 vs. 참조 타입

  • Struct는 값 타입(Value Type)이며, Class는 참조 타입(Reference Type)
  • Struct는 변수에 직접 값을 저장하며, 스택(Stack)에 할당
  • Class는 객체의 주소(참조)를 변수에 저장하며, 힙(Heap)에 할당

2. 사용 목적

  • Struct는 주로 간단한 데이터 구조에 사용된다. 예를 들어, 좌표(x, y)나 날짜(date)와 같은 작은 데이터를 저장하는 데 사용된다.
  • Class는 보다 복잡한 데이터 구조와 행동을 정의할 때 사용된다. Class는 메소드, 이벤트, 속성 등을 포함하여 객체의 행동을 모델링할 수 있다.

3. 상속 가능 여부

  • Class는 상속(Inheritance)을 지원한다. 즉, 다른 클래스로부터 상속받아 새로운 클래스를 생성할 수 있다. 이를 통해 코드 재사용과 계층 구조를 구축할 수 있다.
  • Struct는 상속이 불가능하다. 즉, 다른 Struct로부터 상속받을 수 없다. Struct는 단순한 데이터 구조를 위해 설계되었기 때문에 상속의 기능이 필요하지 않다.

4. 할당 방식과 성능

  • Struct는 값이 복사되어 할당된다. 따라서 Struct를 다른 변수에 할당하면 해당 값이 복사되어 전달된다.
  • Class는 참조가 할당되며, 변수는 객체의 주소를 가리킵니다. 따라서 Class를 다른 변수에 할당하면 참조가 전달된다.
  • Struct는 작은 크기의 데이터를 처리할 때 효율적이다. 값이 복사되기 때문에 메모리 사용량이 적다.
  • Class는 객체의 주소를 처리하기 때문에 메모리 사용량이 더 크지만, 객체의 크기가 크거나 여러 곳에서 공유되는 경우 유용하다.
더보기

면접 대비 답변

Struct와 Class는 C#에서 데이터를 저장하고 조작하는 데 사용되는 두 가지 주요 타입이다.

이들은 비슷해보이지만 몇 가지 핵심적인 차이점이 있다

첫째로, Struct는 값 타입이고, 스택에 할당되어 직접 값을 저장한다.

반면, Class는 참조 타입으로, 힙에 할당되어 변수에 객체의 주소를 저장된다.

둘째로, 사용 목적에 따라 선택한다.

Struct는 간단한 데이터 구조를 위해 사용되며, 좌표나 날짜와 같은 작은 데이터를 처리할 때 적합하다.

반면 Class는 복잡한 데이터 및 행동을 모델링할 때 사용된다.

셋째로, 상속 가능 여부가 다르다.

Class는 다른 클래스로부터 상속받을 수 있어 코드 재사용과 계층 구조를 구축하는데 유용하다.

그러나 Struct는 상속을 지원하지 않는다.

마지막으로, Struct는 값이 복사되어 할당되므로 메모리를 효율적으로 사용하고,

Class는 참조를 처리하므로 메모리 사용량이 더 크지만, 객체의 크기가 크거나 공유될 필요가 있을 때 유용하다.

 

가비지 컬렉터(Garbage Collector, GC)란?

가비지 컬렉터는 프로그램이 동적으로 할당한 메모리 중에서 필요 없게 된 부분을 자동으로 회수하는 메모리 관리 기법.

이는 프로그래머가 직접 메모리를 관리하는 데서 발생할 수 있는 오류를 방지하고,

더 안정적인 프로그램을 작성할 수 있게 도와준다.

1.가비지 컬렉터의 작동식

가비지 컬렉터는 주로 두 가지 방식으로 메모리를 회수한다.

  • 참조 추적(Reference Counting): 각각의 객체가 몇 개의 참조를 가지고 있는지 추적하고, 참조하는 객체가 없을 경우 그 객체를 가비지로 판단하여 회수한다.이 방식은 구현이 비교적 간단하지만, 서로 참조하는 객체들이 순환 참조를 형성할 경우 가비지로 인식하지 못하는 문제가 있다.
  • 트레이싱(Tracing): 루트(root)에서 시작해 접근 가능한 객체만을 '살아 있는' 객체로 판단하고, 접근 불가능한 객체를 가비지로 판단하여 회수한다.. 이 방식은 순환 참조 문제를 해결할 수 있지만, 전체 메모리를 탐색해야 하므로 비용이 크다는 단점이 있다.

2.가비지 컬렉터의 활용

자바, 파이썬, C# 등의 언어는 내장된 가비지 컬렉터를 사용하여 메모리 관리를 자동화하고, 프로그래머는 객체를 생성하고 사용하면서 메모리 할당과 해제에 대해 신경 쓸 필요가 없게 된다. 이런 메모리 관리 방식 덕분에 개발자는 프로그램의 안정성을 높일 수 있다.

 

더보기

면접 대비 답변

가비지 컬렉터는 프로그램이 동적으로 할당한 메모리 중 필요 없게 된 부분을 자동으로 회수하는 메모리 관리 기법이다. 이로 인해 프로그래머가 메모리 관리에 대해 심하게 걱정하지 않아도 되며, 프로그램의 안정성을 높일 수 있다.

가비지 컬렉터는 크게 참조 추적과 트레이싱 두 가지 방법을 사용한다. 참조 추적은 객체가 얼마나 많은 참조를 가지고 있는지 추적하고, 참조가 없어지면 메모리를 회수한다. 반면에 트레이싱은 루트에서 시작해 접근 가능한 객체만을 살아 있는 것으로 판단하고, 접근 불가능한 객체를 가비지로 판단하여 회수하며 순환 참조 문제를 해결하지만 전체 메모리를 탐색해야 하므모 비용이 크다.

즉 가비지 컬렉터 덕분에 프로그래머는 메모리 할당과 해제에 대해 직접 관리할 필요가 없다. 

가비지 컬렉션(GC) 최소화 전략

가비지 컬렉션은 프로그램이 동적으로 할당한 메모리를 자동으로 회수하는 메모리 관리 기법이다. 하지만, 가비지 컬렉션의 동작은 시스템의 성능에 영향을 줄 수 있으므로, 이를 최소화하거나 회피하기 위한 다양한 전략이 필요하다.

1. 객체 풀링(Object Pooling)

객체 풀링은 미리 생성된 객체 집합에서 필요한 객체를 가져오는 기법이다. 객체를 필요할 때마다 생성하고 파괴하는 대신에 재사용한다. 이는 메모리 할당과 해제에 따른 오버헤드를 줄이고, GC의 동작을 줄이는 데 효과적이다.

2. 값 형식(Value Types) 사용

가능하면 참조 형식보다 값 형식을 사용하면 GC의 부담을 줄일 수 있다. 값 형식은 스택에 할당되기 때문에 GC의 대상이 되지 않는다. 값 형식을 사용하면, 메모리 할당과 해제에 대한 오버헤드를 줄일 수 있다.

3. 캐싱(Caching)

자주 사용되는 데이터를 캐시에 저장하여 재사용함으로써 GC의 부담을 줄일 수 있다. 캐싱은 메모리 사용량을 줄이고, 데이터 접근 시간을 단축하는 데 효과적이다.

4. 최적화된 데이터 구조 선택

데이터 구조를 잘 선택하면 메모리 사용량을 줄이고, 따라서 GC의 부담을 줄일 수 있다. 예를 들어, 배열 대신 연결 리스트를 사용하면 메모리 사용량을 줄일 수 있다.

5. 'null' 사용

사용이 끝난 객체에 대한 참조를 'null'로 설정하여 GC가 해당 객체를 수집할 수 있도록 한다. 이는 불필요한 메모리 사용을 줄이는 데 도움이 된다.

6. GC 설정 최적화

GC의 작동 방식을 이해하고, 이를 최적화하는 것도 중요하다. 예를 들어, GC의 수집 주기를 조정하거나, GC가 동작하는 시점을 직접 제어할 수도 있다. 이러한 최적화를 통해 GC의 성능을 개선하고, 전체 시스템의 성능을 향상시킬 수 있다.

7. 파이널라이저(Finalizer) 사용 최소화

파이널라이저는 객체가 가비지 컬렉션에 수집되기 전에 마지막으로 수행해야 할 작업을 정의한다. 하지만, 파이널라이저를 가진 객체는 가비지 컬렉션 과정에서 추가적인 부담을 주므로, 가능하면 파이널라이저의 사용을 피하거나 최소화해야 한다. 파이널라이저는 가비지 컬렉션 프로세스를 늦추고, 메모리 회수를 지연시킬 수 있다.

8. IDisposable 패턴 구현

관리되지 않는 자원은 가비지 컬렉터에 의해 자동으로 해제되지 않는다. 따라서, 이러한 자원을 사용하는 클래스는 IDisposable 인터페이스를 구현하여 자원을 적절히 해제해야 한다. Dispose 메소드 내에서 필요한 클린업 작업을 수행하여, 가비지 컬렉션의 부담을 줄이고 메모리 누수를 방지할 수 있다.

9. WeakReference 사용

WeakReference는 가비지 컬렉터가 수집 가능한 참조를 만들어준다. 이는 참조되는 객체가 더 이상 필요하지 않으면 가비지 컬렉터에 의해 수집될 수 있도록 한다. 이 방법은 캐시와 같이 참조를 유지해야 하는 경우에 유용하며, 메모리 부족 상황을 피할 수 있다.

이와 같은 전략들을 적절히 활용하면, GC의 부담을 줄이고 시스템의 성능을 향상시킬 수 있다. 하지만 이러한 전략들이 항상 효과적인 것은 아니며, 각 상황에 따라 적절한 전략을 선택하고 적용해야 한다.

 

더보기

가비지 컬렉션은 프로그램이 동적으로 할당한 메모리를 자동으로 회수하는 중요한 메모리 관리 기법인데, 이의 동작은 시스템의 성능에 영향을 줄 수 있어 이를 최소화하거나 회피하기 위한 전략이 필요하다.

먼저, 객체를 필요할 때마다 생성하고 파괴하는 대신 미리 생성된 객체 집합에서 필요한 객체를 가져오는 '객체 풀링'을 사용하면 GC의 동작을 줄일 수 있다. 또한, 가능한 한 참조 형식보다 '값 형식'을 사용하면 GC의 부담을 줄일 수 있다. 값 형식은 스택에 할당되기 때문에 GC의 대상이 되지 않는다.

자주 사용되는 데이터를 '캐시'에 저장하여 재사용함으로써 GC의 부담을 줄일 수 있다. 또한, 데이터 구조를 잘 선택하면 메모리 사용량을 줄이고, 따라서 GC의 부담을 줄일 수 있다.

사용이 끝난 객체에 대한 참조를 'null'로 설정하여 GC가 해당 객체를 수집할 수 있도록 한다. 그리고 GC의 작동 방식을 이해하고 이를 최적화하는 것도 중요하다. 예를 들어, GC의 수집 주기를 조정하거나, GC가 동작하는 시점을 직접 제어할 수도 있다.

또한, 파이널라이저는 객체가 가비지 컬렉션에 수집되기 전에 마지막으로 수행해야 할 작업을 정의하지만, 파이널라이저를 가진 객체는 가비지 컬렉션 과정에서 추가적인 부담을 주므로, 파이널라이저의 사용을 최소화해야 한다.

관리되지 않는 자원을 사용하는 클래스는 IDisposable 인터페이스를 구현하여 자원을 적절히 해제해야 한다. 그리고 WeakReference를 사용하여 가비지 컬렉터가 수집 가능한 참조를 만들 수 있다.

이와 같은 전략들을 적절히 활용하면, GC의 부담을 줄이고 시스템의 성능을 향상시킬 수 있다. 하지만 이러한 전략들이 항상 효과적인 것은 아니며, 각 상황에 따라 적절한 전략을 선택하고 적용해야 한다.

반응형