← 블로그 목록

상속을 줄이고 델리게이트와 시그널로 푸는 이유

상속은 ‘무엇의 하위 타입인가’를 표현하는 데 강하지만, UI 이벤트나 객체 간 통신처럼 호출 관계가 자주 바뀌는 영역에서는 델리게이트나 시그널과 슬롯 같은 느슨한 연결이 더 잘 맞는다. C# 델리게이트와 Qt 시그널의 사례를 빌려, 좋은 설계는 상속을 줄이는 신념이 아니라 ‘타입 관계’와 ‘실행 시 연결 관계’를 분리해 보는 습관에서 나온다는 점을 정리한다.

상속을 줄이고 델리게이트와 시그널로 푸는 이유

상속을 줄이고 델리게이트와 시그널로 푸는 이유

객체지향 프로그래밍에서 상속은 여전히 중요한 도구다. 공통 인터페이스를 만들고, 안정적인 기반 동작을 재사용하는 데는 실제로 도움이 된다. 하지만 이벤트 처리나 UI 연결처럼 누가 누구를 호출할지 자주 바뀌는 문제에서는 상속이 금방 무거워질 수 있다.

그래서 많은 프레임워크는 상속 하나로 모든 연결을 해결하려 하지 않는다. 대신 델리게이트(delegate)시그널과 슬롯(signals and slots)처럼, 호출 관계를 더 느슨하게 연결하는 메커니즘을 함께 제공한다.


델리게이트는 “나중에 호출할 함수를 값처럼 들고 다니는 방식”이다

델리게이트는 호출 대상을 값처럼 전달하는 메커니즘이다. 마이크로소프트의 C# delegates 가이드는 델리게이트를 메서드에 대한 참조를 담는 형식으로 설명한다.

이 방식이 유용한 이유는 간단하다.

이런 문제를 굳이 버튼 클래스를 상속해서 해결하지 않아도 되기 때문이다. 필요한 동작만 연결해 두고, 나중에 교체할 수도 있다.

즉 델리게이트는 동작을 붙이는 일타입 계층을 설계하는 일을 분리해 준다.


Qt의 시그널과 슬롯은 느슨한 연결이 왜 중요한지 잘 보여 준다

Qt 문서의 Signals & Slots는 한 객체가 상태 변화를 알리고, 다른 객체가 그 알림을 받아 반응하는 구조를 설명한다. 여기서 핵심은 두 객체가 서로를 강하게 알 필요가 없다는 점이다.

Qt는 이 구조의 장점을 아주 명확하게 적는다.

이건 상속과 다른 종류의 힘이다. 상속은 무엇의 하위 타입인가를 표현하는 데 강하고, 시그널과 슬롯은 누가 누구의 변화에 반응하는가를 표현하는 데 강하다.


상속이 문제라기보다, 상속으로 이벤트를 전부 해결하려 할 때 문제가 커진다

예를 들어 버튼을 눌렀을 때 메시지를 띄우고 싶다고 해 보자. 이때 매번 새 버튼 클래스를 상속받아 MyButton, SaveButton, CancelButton을 만드는 방식도 가능하다. 하지만 UI가 커질수록 이런 구조는 금방 퍼진다.

로버트 나이스트롬의 Subclass Sandbox는 상속이 유용할 때도 있지만, 기반 클래스가 지나치게 많은 책임을 끌어안으면 결합이 커지고 바꾸기 어려워진다고 설명한다. 즉 상속은 통제된 범위에서는 좋지만, 모든 변화를 받아내는 그릇이 되면 부담이 커진다.


그래서 실무에서는 “상속할 것”과 “연결할 것”을 나눠 본다

상속이 잘 맞는 경우는 여전히 분명하다.

반대로 델리게이트나 시그널이 잘 맞는 경우도 뚜렷하다.

결국 중요한 것은 상속을 버리는 신념이 아니라, 타입 관계실행 시 연결 관계를 구분하는 습관이다.


핵심 정리

상속은 여전히 유용한 도구지만, 이벤트 처리와 느슨한 협력이 중요한 영역에서는 델리게이트와 시그널 같은 방식이 더 잘 맞는 경우가 많다. 델리게이트는 호출 대상을 값처럼 다루게 해 주고, 시그널과 슬롯은 송신자와 수신자를 느슨하게 연결해 준다.

그래서 좋은 설계는 상속을 무조건 줄이는 데 있지 않다. 무엇을 타입 계층으로 표현할지, 무엇을 연결 메커니즘으로 풀지를 분리해 보는 데 더 가깝다.

참고 자료

← 목록으로
Related

함께 읽으면 좋은 글

소프트웨어 설계입문객체지향
소프트웨어 설계가 처음이라면 이 5가지 질문부터 던지는 편이 낫다

처음 설계를 시작할 때는 클래스 수를 늘리는 것보다, 무엇이 책임이고 무엇이 자주 바뀌는지 먼저 묻는 편이 훨씬 안전하다. 입문자가 바로 적용할 수 있는 5가지 질문으로 정리한다.

게임 개발객체지향조합
게임 개발에서 상속보다 조합이 자주 선택되는 이유

게임 객체는 이동·물리·AI·네트워크처럼 여러 시스템의 교차점에 놓이기 때문에 깊은 상속 계층은 금방 무거워진다. 그래서 컴포넌트 중심 조합이 자주 선택되는 것이지, 상속이 틀려서가 아니다. 안정적인 공통 규약에는 상속이 여전히 유용하며, 핵심은 ‘상속이냐 조합이냐’의 신념 싸움이 아니라 변경 비용이 가장 낮아지는 지점을 보는 일이라는 점을 정리한다.

프로그래밍참조 무결성수명 관리
참조 무결성은 데이터베이스 규칙이면서 동시에 런타임 안전 규칙이기도 하다

참조 무결성은 외래 키 규칙으로만 생각하기 쉽지만, 런타임에서 포인터·핸들·식별자가 가리키는 대상의 수명을 관리하는 문제에도 거의 같은 구조가 깔려 있다. 데이터베이스가 ‘존재하는 행만 가리키게 하라’고 한다면 런타임은 ‘살아 있는 객체만 가리키게 하라’를 요구한다. 결국 핵심은 소유권과 수명, 유효성 확인을 함께 설계하는 일이다.