Menu
Coddy logo textTech

C++의 RAII

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 16번째.

RAII (Resource Acquisition Is Initialization)는 리소스 관리가 객체의 수명과 연결되는 기본적인 C++ 관용구입니다. 핵심 아이디어는 간단합니다. 생성자에서 리소스를 획득하고, 소멸자에서 이를 해제하는 것입니다.

객체가 생성될 때, 필요한 모든 리소스를 획득합니다. 객체가 범위를 벗어나면 소멸자가 자동으로 해당 리소스를 해제합니다. 이는 예외가 발생하더라도 리소스 정리를 보장합니다.

class FileHandler {
    std::FILE* file;
public:
    FileHandler(const char* filename) {
        file = std::fopen(filename, "r");  // 리소스 획득
    }
    
    ~FileHandler() {
        if (file) std::fclose(file);       // 리소스 해제
    }
};

RAII를 사용하면 정리를 잊어버릴 일이 없습니다:

void processFile() {
    FileHandler handler("data.txt");  // 리소스 획득
    // 파일 작업 중...
    // 여기서 예외가 발생하더라도 소멸자가 실행됩니다!
}   // 리소스가 자동으로 해제됨

스마트 포인터는 RAII가 실제로 적용된 완벽한 예시입니다. unique_ptr는 생성자에서 힙 메모리의 소유권을 획득하고 소멸자에서 이를 삭제합니다. 여러분은 이미 자신도 모르게 RAII를 사용하고 있었습니다!

RAII는 메모리, 파일 핸들, 네트워크 연결, 뮤텍스 또는 데이터베이스 연결과 같은 모든 리소스에 적용됩니다. 리소스를 객체로 래핑함으로써, C++는 결정론적인 정리를 보장하고 누수 및 댕글링 핸들과 같은 전체 범주의 버그를 제거합니다.

challenge icon

챌린지

쉬움

네트워크와 유사한 연결의 수명 주기를 자동으로 처리하여 RAII를 보여주는 연결 관리자를 만들어 보겠습니다. 연결이 생성되면 "열려야(open)" 하고, 범위를 벗어나면 수동 정리 없이 자동으로 "닫혀야(close)" 합니다!

코드를 구성하기 위해 두 개의 파일을 생성합니다:

  • Connection.h: RAII 원칙을 사용하여 연결 리소스를 관리하는 Connection 클래스를 정의합니다. 클래스에는 다음이 포함되어야 합니다:
    • 연결을 식별하기 위한 프라이빗 connectionId 속성 (string)
    • 연결 상태를 추적하기 위한 프라이빗 isOpen 속성 (bool)
    • 연결 ID를 매개변수로 받아 isOpen을 true로 설정하고, "Opening connection: <id>"를 출력하는 생성자
    • 연결이 열려 있는지 확인하고, isOpen을 false로 설정하여 연결을 닫은 후 "Closing connection: <id>"를 출력하는 소멸자
    • 연결이 열려 있는 경우 "[<id>] Sending: <message>"를 출력하는 send(string message) 메서드
    • 연결 ID를 반환하는 getId() 메서드
  • main.cpp: 입력으로부터 연결 ID와 메시지를 읽어 RAII가 어떻게 자동 정리를 보장하는지 보여줍니다. 그런 다음:
    • 중괄호 { }를 사용하여 범위를 생성합니다
    • 해당 범위 내에서 입력받은 ID를 사용하여 스택에 Connection 객체를 생성합니다
    • 연결을 사용하여 입력받은 메시지를 전송합니다
    • 범위가 끝나도록 합니다 (연결이 자동으로 닫혀야 합니다)
    • 범위가 끝난 후, "Connection out of scope"를 출력합니다

RAII의 장점은 연결을 닫는 것을 기억할 필요가 없다는 것입니다. 객체가 범위를 벗어날 때 소멸자가 이를 자동으로 처리합니다. 이 패턴은 코드에서 예기치 않은 일이 발생하더라도 리소스 누수를 방지합니다.

main.cpp#include "Connection.h"를 사용하여 헤더 파일을 포함하세요.

치트 시트

RAII(Resource Acquisition Is Initialization, 자원 획득은 초기화이다)는 자원 관리를 객체의 수명과 연결하는 C++ 관용구입니다. 자원은 생성자에서 획득되고 소멸자에서 해제됩니다.

객체가 범위를 벗어나면 소멸자가 자동으로 자원을 해제하여, 예외가 발생하더라도 정리를 보장합니다.

class FileHandler {
    std::FILE* file;
public:
    FileHandler(const char* filename) {
        file = std::fopen(filename, "r");  // 자원 획득
    }
    
    ~FileHandler() {
        if (file) std::fclose(file);       // 자원 해제
    }
};

RAII는 자동 정리를 보장합니다:

void processFile() {
    FileHandler handler("data.txt");  // 자원 획득
    // 파일 작업 수행...
    // 예외가 발생하더라도 소멸자는 여전히 실행됩니다!
}   // 자원이 자동으로 해제됨

unique_ptr와 같은 스마트 포인터는 RAII의 대표적인 예입니다. 이들은 생성자에서 힙 메모리를 할당받고 소멸자에서 이를 삭제합니다.

RAII는 메모리, 파일 핸들, 네트워크 연결, 뮤텍스 또는 데이터베이스 연결과 같은 모든 자원에 적용됩니다. 이는 결정론적인 정리를 보장하며 누수(leak)나 매달린 핸들(dangling handles)과 같은 버그를 제거합니다.

직접 해보기

#include <iostream>
#include <string>
#include "Connection.h"

using namespace std;

int main() {
    string connectionId;
    string message;
    
    // 입력 읽기
    cin >> connectionId;
    cin.ignore();
    getline(cin, message);

    // TODO: 중괄호 { }를 사용하여 스코프(scope) 생성
    // 스코프 내부:
    //   - connectionId를 사용하여 스택에 Connection 객체 생성
    //   - connection을 사용하여 message 전송
    // 스코프 종료 (소멸자가 자동으로 호출됨)

    // TODO: 스코프가 종료된 후, "Connection out of scope" 출력

    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨