프로그래밍 언어/C++
C++ static - 5. 객체지향 설계에서의 static 활용
개발_노트
2025. 3. 25. 21:26
5. 객체지향 설계에서의 static 활용
🔹 개요
C++의 static 키워드는 객체 없이도 클래스 수준에서 상태나 기능을 공유할 수 있게 해주며,
객체지향 설계에서도 다음과 같은 용도로 매우 널리 사용됩니다:
- 싱글톤(Singleton) 패턴 구현
- 공통 상태 공유 (객체 간 공유 변수)
- 정적 유틸리티 클래스
- 함수 내 상태 유지
하지만 동시에 테스트, 유연성, 스레드 안전성과 같은 측면에서도 고려할 점이 많습니다.
✅ 1. 싱글톤 패턴: 정적 인스턴스를 통한 전역 접근
static 멤버 변수를 사용하면 클래스 인스턴스를 단 하나만 생성하고 공유할 수 있습니다.
class Singleton {
private:
Singleton() = default;
inline static Singleton instance; // C++17 이상
public:
static Singleton& getInstance() {
return instance;
}
void sayHello() {
std::cout << "Hello from Singleton\n";
}
};
int main() {
Singleton::getInstance().sayHello();
}
📌 특징:
- 인스턴스 생성 제어 (private 생성자)
- 전역에서 동일한 객체 접근
- 정적 멤버 변수로 전역 상태 유지
✅ 2. 클래스 간 데이터 공유 설계
static 멤버 변수는 모든 객체가 동일한 데이터를 공유할 때 사용됩니다.
class UserSession {
public:
static int activeUsers;
UserSession() { activeUsers++; }
~UserSession() { activeUsers--; }
};
int UserSession::activeUsers = 0;
📌 모든 인스턴스가 하나의 activeUsers 변수를 공유
→ 상태 동기화, 리소스 카운팅 등에 유용
✅ 3. 정적 유틸리티 클래스 설계
static 함수만으로 구성된 클래스는 객체 생성 없이 기능만 제공하는 유틸리티로 활용됩니다.
class MathUtil {
public:
static int max(int a, int b) {
return (a > b) ? a : b;
}
};
📌 상태를 가지지 않고, 재사용 가능한 기능을 묶어 관리
→ 전역 함수보다 네임스페이스적 구조와 가독성 확보
✅ 4. 함수 내 상태 유지 (정적 지역 변수)
static 지역 변수는 함수 호출 이후에도 값을 유지할 수 있어, 상태를 기억하는 함수 구현이 가능합니다.
class Logger {
public:
static void log(const std::string& msg) {
static int count = 0;
std::cout << "[" << ++count << "] " << msg << "\n";
}
};
📌 로그 호출 횟수처럼 누적 상태 관리가 필요한 경우 유용
✅ 5. 스레드 안전성 고려사항
📌 C++11 이후: 지역 static 변수 초기화는 스레드 안전
static Singleton& getInstance() {
static Singleton instance; // C++11 이후 안전하게 초기화됨
return instance;
}
✔️ C++11부터는 보장됨:
- 첫 진입 시 단 한 번만 초기화됨
- 이후 동시 접근은 안전
❗ 클래스 정적 멤버 변수는 주의 필요
// 초기화에 동시 접근하면 문제 발생 가능
static Singleton instance;
✔️ 대책:
- std::mutex 사용
- 지역 정적 변수로 구조 전환
✅ 6. 의존성 주입(Dependency Injection)과의 관계
❗ 문제점: 싱글톤은 의존성 주입을 어렵게 함
- static 기반 싱글톤은 내부에 전역 의존성을 고정
- 테스트 시 Mock 대체, 의존성 변경이 불가능하거나 매우 어렵다
class Service {
public:
static Service& getInstance(); // 교체 불가, 강한 결합
};
✅ 현대적 설계 방향
- 인터페이스 기반 DI와 팩토리 패턴으로 전환
- static 사용 최소화 + 테스트 가능성 향상
✅ 요약
항목 | 설명 |
싱글톤 패턴 | 정적 인스턴스를 통해 객체 하나만 유지 |
공유 상태 | 모든 객체가 동일한 정적 멤버 변수 참조 |
유틸리티 클래스 | 정적 함수로 기능만 제공, 객체 생성 없음 |
상태 유지 | 함수 내 정적 변수로 호출 간 상태 기억 |
스레드 안전성 | C++11 이후 지역 정적 변수는 안전, 클래스 정적 변수는 주의 필요 |
테스트 유연성 | 싱글톤은 의존성 주입과 충돌 → 테스트 어려움 |
설계 팁 | 공유/고정 상태가 필요한 경우에만 신중히 사용 |