1. 사이드 이펙트 (Side Effect)
함수가 자신의 반환값 외에 외부의 상태를 변경하거나 관찰 가능한 변화를 일으키는 행위입니다.
📋 주요 사이드 이펙트의 예시
- 외부 변수 수정: 전역 변수나 멤버 변수 값을 변경하는 경우
- I/O 작업: 로그 출력(printf, UE_LOG)이나 파일 저장
- 객체 상태 변경: 인자로 받은 객체의 내부 값을 수정
- 예외 발생: 프로그램의 실행 흐름을 갑작스럽게 중단
💡 왜 사이드 이펙트를 경계해야 하는가?
- 디버깅의 난해함: 상태를 읽기만 할 것 같은 함수(Get...)가 내부에서 상태를 바꾸고 있다면 버그 추적이 매우 힘듭니다.
- 멀티스레드 위험: 여러 스레드가 동시에 외부 변수를 건드리는 경합 조건(Race Condition)을 유발합니다.
- 최적화 제한: 컴파일러는 사이드 이펙트가 없는 순수 함수(Pure Function)를 훨씬 더 공격적으로 최적화할 수 있습니다.
2. Android Vulkan: 차세대 그래픽 API
하드웨어(GPU)를 더 직접적으로 제어하여 CPU 오버헤드를 줄이는 저수준(Low-level) API입니다.
⚙️ OpenGL ES vs Vulkan
| 구분 | OpenGL ES (Implicit) | Vulkan (Explicit) |
| 제어 방식 | 드라이버가 많은 부분을 자동 관리 | 개발자가 직접 메모리/명령 관리 |
| CPU 부하 | 드라이버 오버헤드가 높음 | 오버헤드가 매우 낮음 |
| 멀티코어 | 싱글 스레드에 최적화 | 멀티스레드 병렬 명령 생성 가능 |
| 예측 가능성 | 드라이버 판단에 따라 성능 요동 | 개발자가 제어하므로 스터터링 감소 |
🛠️ 실무 적용 전략
- RHI 인터페이스 활용: C++에서 직접 Vulkan 함수를 부르기보다 엔진의 RHI(Render Hardware Interface) 레이어를 통해 명령을 내립니다.
- 드로우 콜 최적화: Vulkan은 CPU 오버헤드가 낮지만, 여전히 인스턴싱(Instancing) 등을 통해 명령 횟수 자체를 관리하는 것이 중요합니다.
- 데이터 정렬: GPU로 보내는 구조체는 반드시 16바이트 정렬이 되어 있어야 Vulkan 환경에서 크래시를 방지할 수 있습니다.
3. 바이너리(Binary)와 리터럴 최적화
프로그램이 최종적으로 기계어로 변환되는 과정과 메모리 절약 기술입니다.
- 바이너리 최적화: 불필요한 심볼 제거 및 인라이닝을 통해 실행 파일 크기를 줄이면 명령어 캐시 히트율이 올라갑니다.
- 리터럴 풀링: 동일한 문자열이나 상수를 읽기 전용 영역에 딱 한 번만 저장하고 재사용하여 메모리 점유율을 낮춥니다.
4. 현대적 C++ 상수 시스템 (const / constexpr / consteval)
상수를 언제 결정하느냐에 따라 성능 최적화의 깊이가 달라집니다.
🔍 상수 키워드 비교
| 키워드 | 결정 시점 | 특징 |
| const | 런타임 | "읽기 전용"임을 보장. 함수 뒤에 붙어 멤버 변수 수정 방지. |
| constexpr | 컴파일 타임 | 가능하면 빌드 시 계산 끝냄. 런타임 오버헤드 0(Zero). |
| consteval | 컴파일 타임 | 무조건 빌드 시 계산. 런타임 변수 대입 시 빌드 에러 발생. |
💡 시니어의 조언: static constexpr의 활용
변수 앞에 static constexpr을 붙이면 해당 변수는 스택이 아닌 데이터 영역의 읽기 전용 구간에 딱 하나만 존재하게 됩니다. 모든 인스턴스가 이를 공유하므로 메모리 낭비를 줄이고 캐시 효율을 극대화하는 리터럴 최적화의 핵심이 됩니다.
5. 방어적 프로그래밍과 설계 원칙
- CQS (Command-Query Separation): 상태를 읽는 함수(Getter)와 상태를 바꾸는 함수(Command)를 엄격히 분리하여 사이드 이펙트를 관리합니다.
- 상수 멤버 함수: 객체의 상태를 건드리지 않는 모든 함수는 뒤에 const를 붙여 설계적 신뢰도를 높입니다.
- 컴파일 타임 에러 지향: 버그는 실행 중(Runtime)에 터지는 것보다 빌드 중(Compile time)에 발견되는 것이 훨씬 저렴합니다. consteval과 constexpr은 이를 강제하는 강력한 도구입니다.
'C++ 공부' 카테고리의 다른 글
| [C++ Study] 키워드와 메모리 구조를 통한 안전한 코드 설계 (explicit, 형변환연산자, cast, mutable, 메모리영역) (0) | 2026.04.17 |
|---|---|
| [C++ Study] friend, 상속의 경계, 그리고 static의 메모리 전략 (0) | 2026.04.10 |
| [C++ Study] 열거형, 복사 생성자, 그리고 메모리 관리 전략 (0) | 2026.04.08 |
| 소수 판별하기 (0) | 2025.10.31 |
| N번째 큰 수 찾기 (std::nth_element) (0) | 2025.10.24 |