디자인패턴은 다양한 프로그래밍 언어에서도 사용할 수 있는 기법입니다.

평소 프로그래머가 되기위해 학습을 하시는분들은 동영상이나 책 등에서의 예시를 보면 [각각의 DB에 접근하기 위해 커넥션에 대한 설정을 전략패턴을 사용하여 높은 응집도와 낮은결합성, 그리고 유지보수성을 향상시킨다.] 등의 디자인패턴이 주제가되는 등 다양한 방법으로 활용됩니다.

그렇다면, 디자인패턴의 정의 와 특징, 그리고 디자인패턴을 사용함으로써 생기는 장단점들에 대해 알아보겠습니다.

 

디자인 패턴이란?

정의

객체지향의 특징과 원칙을 기반으로 특정상황에서 문제를 해결할 수 있는 재사용 가능한 기법입니다.

 

소프트웨어 설계시에 특정상황에서 자주 만나는 문제를 해결하기위해 사용할 수 있는 재사용 가능한 솔루션으로써, 디자인패턴의 종류를 명시함으로써 설계의 의도와 해결책을 함께 설명할 수 있다.

또한, 객체지향의 4가지 특징과 5개의 원칙을 사용하여 높은 응집도, 낮은 결합성, 재사용성 및 유지보수능력이 향상된다.

 

 

특징

디자인 패턴들의 공통된 특징들은 다음과 같습니다.

  • 디자인 패턴을 사용하여 코딩시의 재사용성 및 유지보수성 증가한다.
  • 3가지(생성,구조,행위)로 나뉘어진 패턴 유형으로 존재한다.
  • 정의된 디자인 패턴을 명명하여 보다 원활한 의사소통 기능 제공한다.
  • 하나의 패턴에는 4가지의 요소*(패턴 이름, 문제, 해법, 결과)를 가지고 있다.

패턴 이름 : 디자인 패턴의 이름 한두 단어로 설계의 의도, 문제와 해법을 서술한다.

문제 : 언제 패턴을 사용하는가를 서술하며, 문제를 제시함으로써 패턴을 적용하는 것이 의미있는 사례를 정의한다.

해법 : 설계를 구성하는 요소들과 그 요소들 간의 관계 책임 그리고 협력 관계를 서술한다.

결과 : 디자인 패턴을 적용해서 얻는 결과와 장단점을 서술한다.

 

장점

  • 서로 다른 언어를 사용하더라도 디자인 패턴을 제시함으로써 특정 언어에 한정되지 않고 일반화된 솔루션을 제공할 수 있다.
  • 협업시의 개발자간 의사소통시 해결 솔루션을 특정 단어를 사용하여 원활한 의사소통이 가능하다.
  • 디자인 패턴을 명확하게 인지할 시 소프트웨어 구조 파악에 용이하다.

단점 

  • 초기 설계단계에서 기존의 코드보다 더 길어지며, 데이터의 기존 처리속도가 비교적 느릴 수 있다.
  • 설계할시 초기 난이도가 더 높다.

 

디자인 패턴의 종류와 3가지 유형

생성 (Creational Patterns) 구조 (Structural Patterns) 행동 (Behavioral Patterns)
싱글 톤(SingleTon) 어댑터(Adapter) 스트레티지(Strategy)
팩토리 메서드(Factory Methods) 브릿지(Bridge) 템플릿 메서드(Template Methods)
추상 팩토리(Abstract Factory Methods) 컴포지트(Composite) 옵저버(Observer)
빌더(Builder) 데코레이터(Decorator) 스테이트(State)
프로토타입(Prototype) 퍼사드(Facade) 비지터(Visitor)
  플라이웨이트(FlyWeight) 커맨드(Command)
  프록시(Proxy) 인터프리터(Interpreter)
    이터레이터(Iterator)
    미디에이터(Mediator)
    메멘토(Memonto)
    책임 연쇄(Chain of Responsibility)

디자인 패턴은 GoF(Gang of Four)의 디자인 패턴에서 불리우며, 4명의 개발자가 최초로 집대한 책에서 시작된 종류 및 유형이 있습니다.

 

 

 

1. 생성 패턴 (Creational Patterns)

생성 패턴은 객체의 인스턴스를 생성하는 방법과 관련된 패턴들이 있습니다.

주로 객체 생성의 복잡성을 줄이고, 인스턴스 과정을 보다 유연성있게 다루는 방법을 제공하는 유형입니다.

즉, 생성 패턴을 사용함으로써 생기는 주요 장점으로는 유연성 및 재사용성을 증가할 수 있습니다.

 

생성 패턴의 주요 특징으로는 시스템이 어떤 구체 클래스를 사용하는지에 대한 정보를 캡슐화 하며, 클래스의 인스턴스들이 어떻게 만들고 어떻게 서로 연관되어있는지의 정보은닉화를 제공합니다.

 

 

생성 패턴은 클래스 생성 패턴과 객체 생성 패턴으로 구분할 수 있습니다.

  • 클래스 생성 패턴 : 인스턴스로 만들 클래스를 다양하게 만들기 위한 용도로 상속을 사용한다.
  • 객체 생성 패턴 : 인스턴스화 작업을 다른 객체에게 넘긴다.

 

2. 구조 패턴 (Structural Patterns)

구조 패턴은 클래스나 객체를 조합하여 더 큰 구조를 형성하는 방법으로써 구조 패턴의 디자인 패턴을 사용하여 기존의 적용 전 기본 구조보다 효율성과 유연성을 개선합니다.

즉, 코드 확장성 및 유지보수 용이성, 재사용성에 중점을 두고 있습니다..

 

구조패턴의 주요 특징으로는 서로 독립적으로 개발한 클래스 라이브러리를 하나인 것처럼 바인딩을 할 수 있습니다.

또한 여러 인터페이스를 합성하여 서로 다른 인터페이스의 통일된 추상화를 제공하며, 인터페이스나 구현을 복합하는게 아닌 객체를 합성하는 방법을 제공합니다.

 

 

3. 행동 패턴 (Behavioral Patterns)

행동 패턴은 객체나 클래스 간의 협력 방법을 다룹니다. 해당 패턴을 사용함으로써 한 객체가 수행할 수 없는 작업을 여러개의 객체로 분배하여 사용하여 높은 응집도 및 낮은 결합성을 유지하는데 중점을 두고 있습니다.

 

즉, 행동 패턴을 사용하여 객체 간의 제어 구조가 아닌 객체들을 어떻게 연결할 것인지에 대한 것에 중점을 둠으로써 높은 응집도 및 낮은 결합성을 유지하는데 도움을 주는 디자인 패턴입니다.

 


정리

 

디자인 패턴은 소프트 웨어 설계시에 생기는 문제들을 해결하기위해 사용하는 재사용 가능한 솔루션이다.

디자인 패턴은 4가지의 요소를 중점으로 고안되었으며, 디자인 패턴은 3가지의 유형으로 나뉠 수 있다.

각각의 디자인 패턴을 사용함으로써 얻을 수 있는 장점으로는 코드의 유지보수 및 확장성, 유연성 증가 등이 있다.

 

예시) 템플릿 메서드 패턴을 통하여 공통적인 부분을 상위 클래스에서 높은 응집도를 나타냄으로써, 기존의 적용 전 코드보다 상대적으로 적은 코드로 인한 빌드 시간을 단축시킬 수 있다. 빌드시간이 단축되었다는건 처리시간을 보다 효율적으로 나타내었으며 즉 프로그램의 유지보수성을 향상시켰다고 볼 수 있다.

언리얼 엔진과 C++코드를 사용한 학습을 진행하던중, 수학적인 계산이 필요한 경우가 있었습니다.

학습을 진행하던 중 KismetMathLibrary의 함수를 사용하게 되었고, 사용한 함수 외에도 유용한 다른 함수들이 어떤것이 있는지에 대해 알아보았습니다.

이번 포스팅에서는 KismetMathLibrary의 함수들에 대해 알아보겠습니다.

 

Kismet

언리얼 엔진에서의 Kismet은 UE3에서 도입된 비주얼 스크립팅 시스템입니다.

코드를 작성하지 않고 노드 기반 인터페이스로 이벤트, 조건, 액션 등을 연결하여 동작을 제어할 수 있었습니다.

UE4부터 비쥬얼 스크립팅은 BluePrint을 채용하게 되었고, 기존의 Kismet은 엔진 내부에서 다양한 기능을 가지는 범용 클래스로 변경되었습니다.

 

그 중 UKismetMathLibrary는 수학 계산과 관련된 함수들을 제공하는 클래스입니다.

해당 클래스의 주요 함수들에 대해 몇가지 알아보겠습니다.

 

 

UKismetMathLibrary

FindLookAtRotation : Start에 있는 객체가 Target 객체를 바라보는 회전 값을 반환합니다.

FRotator UKismetMathLibrary::FindLookAtRotation(const FVector& Start, const FVector& Target)
{
	return MakeRotFromX(Target - Start);
}

 

ComposeRotators : Rotator A와 B의 합한 값을 반환합니다.

FRotator UKismetMathLibrary::ComposeRotators(FRotator A, FRotator B)
{
	FQuat AQuat = FQuat(A);
	FQuat BQuat = FQuat(B);

	return FRotator(BQuat*AQuat);
}

 

RandomFloatInRange, RandomIntegerInRange, RandomInitVector : 주어진 범위 내에서 무작위 값을 생성합니다.

Cos, Sin, Tan : 삼각함수 값을 반환합니다.

※ 해당 함수들은 FMath의 함수들을 반환합니다. 즉, FMath 클래스 내 함수와 동일합니다.

double UKismetMathLibrary::RandomFloatInRange(double Min, double Max)
{
	return FMath::FRandRange(Min, Max);
}	

 

 

Lerp : 선형 보간을 수행하며, A와 B를 V의 비율에 따라 계산합니다.

  • V가 0일경우 A의 100%, 1일경우 B의 100%의 값을 계산합니다.
double UKismetMathLibrary::Lerp(double A, double B, double V)
{
	return A + V*(B-A);
}	

 

 

MakeTransform : 물리적인 객체를 이동하거나 회전시킬 때 사용합니다.

FTransform UKismetMathLibrary::MakeTransform(FVector Translation, FRotator Rotation, FVector Scale)
{
	return FTransform(Rotation, Translation, Scale);
}

 

 

 

FInterpTo : UI 애니메이션 또는 숫자 등의 속도를 제어합니다.

double UKismetMathLibrary::FInterpTo(double Current, double Target, double DeltaTime, double InterpSpeed)
{
	return FMath::FInterpTo(Current, Target, DeltaTime, InterpSpeed);
}

 

 

NormalizeAxis : 해당 각도를 -180 ~ 180의 값으로 변환하여 반환합니다.

float UKismetMathLibrary::NormalizeAxis(float Angle)
{
	return FRotator::NormalizeAxis(Angle);
}

 

 

GetDirectionUnitVector : From에서 To까지의 벡터 값을 받아옵니다. 위치가 같을시 (0,0,0)을 반환합니다.

FVector UKismetMathLibrary::GetDirectionUnitVector(FVector From, FVector To)
{
	return (To - From).GetSafeNormal();
}

 

 

ProjectPointOnToPlane : 정규화된 벡터로 정의된 평면에 해당 벡터를 투영합니다.

※ 화면 상의 위치를 특정 평면으로 매핑하는 경우 사용합니다.

FVector UKismetMathLibrary::ProjectPointOnToPlane(FVector Point, FVector PlaneBase, FVector PlaneNormal)
{
	return FVector::PointPlaneProject(Point, PlaneBase, PlaneNormal);
}

 

이 외에도 다양한 함수들이 존재하며, 그 중 언리얼 엔진을 사용한 클라이언트 개발자가 프로젝트 제작 시 자주 사용하는 것들에 대해 알아보았습니다.

언리얼 공식 사이트 - UKismetMathLibrary 클래스 

 

 

C++을 사용한 WinAPI 및 D3DX 환경에서는 메모리 공간을 효율적으로 사용하기 위해 생성자 및 소멸자를 사용하여 메모리 누수를 방지하였습니다. 

언리얼 엔진을 통한 게임 개발시에는 생성한 객체 및 자원들을 개발자가 아닌 엔진에게 메모리 관리를 담당하여 개발자의 편의성 및 프로그램 메모리를 관리 및 최적화 하는 가비지 컬렉션(Garbage Collection)이 존재합니다.

이번 포스팅에서는 언리얼 엔진의 GC에 대해 알아보겠습니다.

 

 

Garbage Collection

GC는 동적으로 생성한 객체들이 저장되는 영역인 Heap영역에 메모리가 할당되어 있는 객체들을 대상으로 사용됩니다.

언리얼 엔진을 사용하는 환경에서의 장단점에 대해 알아보겠습니다.

 

 

 

언리얼 엔진에서의 GC 특징

  • 마크 앤 스윕(Mark and Sweep) 알고리즘을 기반으로 동작한다.
    • Mark : GC 루트에서 시작해 연결된 객체를 "사용 중"으로 마킹하는 단계
    • Sweep : 마킹되지 않은 객체를 해제한다.
  • UObject를 관리한다.
  • AddToRoot() 또는 RemoveFromRoot()를 사용하여 특정 객체를 GC루트로 추가/제거 할 수 있다.
    • 최초 탐색 목록으로 설정하여 메모리가 회수되지 않는다.
  • 관리되는 모든 언리얼 오브젝트의 정보를 저장하는 GUObjectArray 전역변수를 통해 관리하며, 각 요소에 설정된 Flag를 통해 RootSet, Garbage 플래그를 구분하여 시스템이 자동으로 회수한다.

 

마크 앤 스윕 (Mark and Sweep)

  1. 힙 영역에서의 최초 검색을 시작하는 루트 오브젝트를 표시한다.
  2. 루트 오브젝트가 참조하는 객체를 찾아 마크(Mark)한다.
  3. 마크된 객체로부터 다시 참조하는 객체를 찾아 마크하고, 이를 반복한다.
  4. GC가 더이상 참조하지않는 (마크되지 않은)객체들의 메모리를 회수한다.(Sweep).

※ 탐색하는 과정은 DFS(깊이 우선 탐색) 방식으로 이루어지며, 필요에 따라 BFS(너비 우선 탐색)으로 이루어진다.

※ 또한 해시 테이블을 사용하여 탐색 중 방문한 객체를 기록, UObject의 고유 식별자를 키로 저장하여 중복 탐색을 방지한다.

 

 

장점

  • 개발자가 아닌 엔진에게 메모리 관리를 담당하여, 논리적으로 메모리를 관리, 최적화를 할 수 있다.
  • 해제된 메모리에 대한 접근을 방지하여 개발자의 실수를 방지할 수 있다.
    • 메모리 누수(Leak) : delete를 사용하지 않아 힙에 메모리가 그대로 남아있을 때
    • Dangling : 이미 해제한 객체를 다시 한번 해제할려 할 때
    • Wild : 값이 초기화 되지않아 잘못된 주소(nullptr)를 가르킬 때 

단점

  • 개발자가 객체를 직접 소멸시에도 GC는 해당 객체를 Unreachable 처리 전까지는, 추적을 계속한다.
    • 오버헤드가 발생할 수 있다.
  • GC가 메모리는 해제하는 시간을 명확하게 파악하기 어렵다.
  • 언리얼 엔진의 GC는 UPROPERTY를 사용하지 못하는 일반 C++ 클래스는 관리하지 않는다.
    • 개발자가 FGCObject 클래스를 상속, AddReferenceObjects 함수를 구현하여 관리할 수 있다.

 

 

가비지 콜렉터의 구성 옵션

편집 - 프로젝트 세팅 - 엔진 - 가비지컬렉션 설정 옵션

 

언리얼5에서 추가된 GC의 기능

1. GC 병렬화 (Parallel Garbage Collection)

  • GC작업이 멀티스레드 환경에서 병렬로 수행하도록 최적화가 되어 처리 속도가 향상되었다.
  • 객체 참조 그래프 생성 및 탐색 과정에서 병렬처리가 이루어진다.

2. Incremental GC 성능 향상 (점진적 가비지 컬렉션)

  • GC작업을 여러 프레임에 걸쳐 나눠 수행하여 큰 규모의 객체 그래프에서도 GC로 인한 지연을 최소화한다.
  • gc.TimeLimit, gc.NumRetriesBeforeForcingGC와 같은 설정을 통해 GC가 실행되는 방식을 조절할 수 있다.

3. 클러스터 기반 GC

  • 객체를 클러스터 단위로 관리하여 관련 객체를 함께 처리할 수 있다.
  • 개별 객체마다 사용되던 GC 비용을 최소화 하여 성능을 향상시킬 수 있다.

그 외에도 다양한 기능들이 언리얼5에서 추가, 개선되었으며 공식 홈페이지의 학습 문서를 통해 확인할 수 있습니다.

 

 


출처 및 참고내역

 

https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-object-handling?application_version=4.27

https://dev.epicgames.com/community/learning/knowledge-base/ePKR/unreal-engine-garbage-collector-internals

https://dev.epicgames.com/community/learning/knowledge-base/xaY1/unreal-engine-primer-debugging-garbage-collection-performance

+ Recent posts