티스토리 뷰

728x90
반응형
설계의 완성: 상속이 필요 없다면 final을 붙여라

클래스 설계의 마침표, final

왜 우리는 "더 이상 상속이 필요 없는 클래스"에 명시적으로 final을 붙여야 할까?

본질(Essence): 상속은 객체지향의 강력한 무기이지만, 의도치 않은 상속은 시스템을 복잡하게 만들고 성능을 저하시킵니다. 더 이상의 확장이 필요 없는 클래스라면 final을 붙여 설계의 의도를 명확히 하고 성능 이득을 챙겨야 합니다.

1. 설계의 명확성: "여기서 끝내겠습니다"

코드는 읽는 사람에게 의도를 전달해야 합니다. 클래스에 final이 붙어 있다면, 다른 개발자는 이 클래스의 내부 로직을 분석할 때 '어디선가 이 로직이 오버라이딩되어 다르게 동작할 수 있다'는 걱정을 할 필요가 없습니다.

C++ 예시: 상속을 허용하지 않는 완성된 분석기
// 이 클래스는 B를 상속받아 기능을 구현했지만,
// 본인 스스로는 더 이상 상속을 허용하지 않는 '완성형'입니다.
class PacketAnalyzer final : public BaseProtocol {
public:
    void analyze() override { 
        // 정밀 분석 로직 (수정/확장 금지)
    }
};

2. final을 붙였을 때 얻는 3가지 이득

🚀 성능 최적화 (Devirtualization) 컴파일러는 가상 함수 테이블(vtable)을 거치지 않고 직접 함수를 호출하는 '정적 바인딩'을 수행하여 실행 속도를 높입니다.
🛡️ 보안 및 안정성 중요한 로직이 담긴 클래스를 누군가 상속받아 악의적으로 혹은 실수로 동작을 바꾸는 행위를 원천 차단합니다.
🧹 메모리 절약 상속을 막음으로써 가상 소멸자(virtual destructor)가 필요 없게 되고, 이는 객체의 크기를 줄이는 결과로 이어집니다.
✍️ 유지보수 용이성 클래스 구조가 단순해져서 영향도 분석이 쉬워지고, 리팩토링 시 사이드 이펙트를 최소화할 수 있습니다.

3. 가상 소멸자 고민으로부터의 해방

상속 관계에서 우리를 가장 괴롭히는 것은 "부모 소멸자에 virtual을 붙였나?" 하는 메모리 누수 문제입니다. 하지만 클래스가 final이라면 이 고민이 사라집니다.

일반적인 상속 관계: 부모 소멸자에 virtual이 필수입니다. (안 그러면 자식 소멸자가 안 불림)
final 클래스: 상속 자체가 안 되므로 virtual 소멸자가 없어도 메모리 누수 위험이 전혀 없습니다!
// 안전하고 가벼운 final 클래스 설계
class SecureToken final {
public:
    SecureToken() { /* 자원 할당 */ }
    ~SecureToken() { /* 자원 해제 - virtual이 아니어도 안전! */ }
};

4. 언제 final을 붙여야 할까?

기본적으로 "상속을 염두에 두고 설계한 Base 클래스"가 아니라면 모두 final 후보입니다.

  • 유틸리티 성격의 도우미 클래스
  • 특정 비즈니스 로직의 구현체 (예: 분석기, 암호화 모듈)
  • 데이터를 담기만 하는 단순 객체 (DTO, VO)

요약: 개발자의 약속

1. 상속이 필요한 부모 클래스는 virtual 소멸자를 잊지 말자.

2. 상속이 필요 없는 모든 클래스에는 final을 붙여 문을 닫자.

3. final을 붙이는 순간, 당신의 코드는 더 빠르고, 안전하며, 명확해집니다.

728x90
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
글 보관함