C++ 템플릿, STL, 정렬, 디자인 패턴 학습
오늘 학습한 내용
오늘은 C++의 템플릿과 STL의 기본 개념을 학습하고, vector 정렬 방법과 객체 정렬 방법을 실습했습니다. 또한 싱글톤, 데코레이터, 옵저버 패턴을 C++, C#, Unity C# 관점에서 비교하며 정리했습니다.
1. C++ 템플릿
템플릿은 타입을 고정하지 않고, 나중에 사용할 때 타입을 결정할 수 있게 해주는 기능입니다.
template <typename T>
T bigger(T a, T b) {
return a > b ? a : b;
}
위 코드에서 T는 타입 자리표시자입니다. int, double, string 등 여러 타입에 대해 같은 함수를 재사용할 수 있습니다.
STL의 vector<int>, pair<string, int>, map<string, double> 등도 템플릿을 기반으로 만들어진 자료구조입니다.
2. STL 정리
STL은 C++에서 제공하는 표준 템플릿 라이브러리입니다. 자료구조와 알고리즘을 직접 구현하지 않고 사용할 수 있게 해줍니다.
| Container | vector, map, set, queue, stack | 데이터를 저장 |
| Iterator | begin(), end() | 컨테이너 순회 |
| Algorithm | sort, find, count | 정렬, 탐색 등 처리 |
| Function Object | greater<int>(), lambda | 정렬 기준 등 지정 |
특히 vector는 동적 배열로 가장 자주 사용되며, map과 unordered_map은 key-value 구조를 다룰 때 유용합니다.
3. sort를 이용한 정렬
vector<int>를 내림차순으로 정렬할 때는 sort의 세 번째 인자로 비교 기준을 전달합니다.
sort(v.begin(), v.end(), greater<int>());
또는 람다식을 사용할 수도 있습니다.
sort(v.begin(), v.end(), [](int a, int b) {
return a > b;
});
vector<Movie>처럼 사용자 정의 구조체를 정렬할 때는 특정 멤버 변수를 기준으로 비교합니다.
sort(movies.begin(), movies.end(), [](const Movie& a, const Movie& b) {
return a.rating > b.rating;
});
이 코드는 rating이 높은 영화가 앞에 오도록 정렬합니다.
4. C++ class의 접근 제한
C++에서 class는 기본 접근 제한자가 private입니다. 따라서 추상 클래스의 순수 가상 함수를 외부에서 사용하려면 public을 명시해야 합니다.
class MovieProcessor {
public:
virtual void process(vector<Movie>& movies) = 0;
virtual ~MovieProcessor() = default;
};
상속도 마찬가지로 class RatingSorter : MovieProcessor라고 작성하면 private 상속이 됩니다. 다형성을 위해서는 public 상속을 사용해야 합니다.
class RatingSorter : public MovieProcessor {
public:
void process(vector<Movie>& movies) override {
// 구현
}
};
5. 싱글톤 패턴
싱글톤 패턴은 프로그램에서 객체가 단 하나만 존재해야 할 때 사용하는 패턴입니다.
C++에서는 보통 Meyers Singleton 방식으로 구현합니다.
class GameManager {
private:
GameManager() = default;
public:
GameManager(const GameManager&) = delete;
GameManager& operator=(const GameManager&) = delete;
GameManager(GameManager&&) = delete;
GameManager& operator=(GameManager&&) = delete;
static GameManager& GetInstance() {
static GameManager instance;
return instance;
}
};
= delete는 기존 객체를 삭제한다는 뜻이 아니라, 해당 함수의 사용을 금지한다는 의미입니다. 싱글톤에서는 복사 생성자와 대입 연산자를 막아 객체가 여러 개 생기는 것을 방지합니다.
C#에서는 보통 static readonly 또는 Lazy<T>를 사용합니다.
public sealed class GameManager
{
private static readonly GameManager instance = new GameManager();
public static GameManager Instance => instance;
private GameManager() { }
}
Unity에서는 MonoBehaviour 특성상 new로 생성하지 않고, Awake()에서 인스턴스를 관리합니다.
6. 데코레이터 패턴
데코레이터 패턴은 기존 객체를 수정하지 않고, 객체를 감싸는 방식으로 기능을 추가하는 패턴입니다.
예를 들어 기본 데미지에 화염 데미지, 치명타 데미지를 순서대로 추가할 수 있습니다.
C++에서는 보통 unique_ptr를 사용해 객체 소유권을 관리합니다.
unique_ptr<Damage> damage = make_unique<BasicDamage>(20);
damage = make_unique<FireDamage>(move(damage));
damage = make_unique<CriticalDamage>(move(damage));
이 구조는 다음과 같이 동작합니다.
CriticalDamage -> FireDamage -> BasicDamage
데코레이터 패턴은 버프, 무기 강화, 데미지 계산처럼 기능 조합이 많은 시스템에 적합합니다. 다만 중간 데코레이터를 제거하기 어렵기 때문에 실제 게임에서는 버프 리스트 방식이 더 적합할 때도 있습니다.
Unity에서는 MonoBehaviour에 억지로 적용하기보다, 데미지 계산이나 스탯 계산 같은 순수 C# 로직에 적용하는 것이 좋습니다.
7. 옵저버 패턴
옵저버 패턴은 어떤 객체의 상태가 변했을 때, 그 변화를 관심 있는 객체들에게 자동으로 알려주는 패턴입니다.
예를 들어 플레이어 HP가 감소했을 때 UI 체력바, 사운드, 이펙트가 각각 반응하도록 만들 수 있습니다.
C++에서는 인터페이스와 포인터 목록을 사용합니다.
class IObserver {
public:
virtual void onNotify(int hp) = 0;
virtual ~IObserver() = default;
};
C#에서는 event와 delegate를 사용하면 더 간단하게 구현할 수 있습니다.
public event Action<int> OnHpChanged;
OnHpChanged?.Invoke(hp);
Unity에서는 이벤트를 등록하고 해제하는 위치가 중요합니다.
private void OnEnable()
{
playerHealth.OnHpChanged += UpdateHpBar;
}
private void OnDisable()
{
playerHealth.OnHpChanged -= UpdateHpBar;
}
이벤트를 해제하지 않으면 비활성화되거나 파괴된 오브젝트가 계속 이벤트를 받아 NullReferenceException이나 MissingReferenceException이 발생할 수 있습니다.
오늘의 핵심 정리
오늘 학습한 내용의 핵심은 다음과 같습니다.
- 템플릿은 타입을 일반화해 코드 재사용성을 높이는 기능입니다.
- STL은 템플릿 기반의 표준 자료구조와 알고리즘 모음입니다.
- sort는 람다식을 활용하면 구조체나 클래스도 원하는 기준으로 정렬할 수 있습니다.
- C++의 class는 기본 접근 제한이 private이므로 public 명시가 중요합니다.
- 싱글톤의 = delete는 함수를 삭제하는 것이 아니라 사용을 금지하는 문법입니다.
- 데코레이터 패턴은 객체를 감싸 기능을 동적으로 추가하는 패턴입니다.
- 옵저버 패턴은 상태 변화와 반응 객체 사이의 의존성을 줄이는 데 사용됩니다.
느낀 점
C++은 C#보다 메모리 관리와 객체 수명, 복사와 이동에 대해 더 명시적으로 다뤄야 한다는 점을 알 수 있었습니다. 같은 디자인 패턴이라도 C++에서는 포인터, 참조, 소멸자, move 같은 요소를 신경 써야 하고, C#과 Unity에서는 이벤트 구독 해제나 MonoBehaviour 생명주기를 주의해야 합니다.
단순히 문법을 외우는 것보다, 어떤 상황에서 어떤 구조를 선택해야 하는지 이해하는 것이 더 중요하다고 느꼈습니다.
'내배캠_Unreal10기' 카테고리의 다른 글
| [TIL] 방의 개수 / 이분 탐색과 탐욕법 (0) | 2026.07.21 |
|---|---|
| [과제 회고] 내일배움캠프 Unreal 10기 CH2 과제 회고 - C++ 텍스트 RPG 구현하기 (0) | 2026.07.08 |
| [TIL] 내일배움캠프 Unreal 10기 7일차 (0) | 2026.07.07 |
| [TIL] 내일배움캠프 Unreal 10기 2일차 (0) | 2026.06.29 |
| [TIL] 내일배움캠프 Unreal 10기 1일차 (0) | 2026.06.26 |