프로그래밍 언어/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 이후 지역 정적 변수는 안전, 클래스 정적 변수는 주의 필요
테스트 유연성 싱글톤은 의존성 주입과 충돌 → 테스트 어려움
설계 팁 공유/고정 상태가 필요한 경우에만 신중히 사용