Summary: 프레임워크는 특정 종류의 애플리케이션에 공통으로 쓰이는 구조와 실행 흐름을 미리 구현해 둔 골격이다. 개발자는 정해진 확장 지점에 필요한 동작을 추가하며, 전체 흐름은 프레임워크가 관리한다. 이 제어 방식은 구조까지 재사용하게 해 주지만 학습과 디버깅, 다른 시스템과의 통합 비용을 동반한다.
프레임워크의 정의
프레임워크는 특정 종류의 애플리케이션이나 하위 시스템을 만들기 위한 재사용 가능한 설계이자 부분 구현이다. 그 자체가 완성된 프로그램은 아니다. 개발자가 정해진 확장 지점에 필요한 동작을 채워 넣어야 하나의 애플리케이션이 되기 때문에 반완성 애플리케이션이라고 부른다.
재사용 범위는 함수나 클래스에서 끝나지 않는다. 컴포넌트가 협력하는 방식, 공통 처리 순서와 제어 흐름, 반복되는 정책도 프레임워크에 포함된다. 같은 종류의 애플리케이션에서 반복되는 부분은 프레임워크가 맡고, 프로젝트마다 달라지는 동작은 개발자가 인터페이스와 규약에 맞춰 구현한다.
프레임워크를 도입하면 코드뿐 아니라 프레임워크가 정한 구조와 실행 규칙도 함께 들어온다. 넓은 범위를 재사용하는 대신 애플리케이션 구조가 프레임워크의 규약에 영향을 받는 이유다.
프레임워크의 핵심 구성
| 구성 | 역할 |
| 안정된 골격 | 공통 처리 순서와 컴포넌트 협력 구조 정의 |
| 공통 구현·서비스 | 여러 애플리케이션에서 반복되는 기능 제공 |
| 확장 지점(Extension Point) | 애플리케이션별 동작을 연결하는 훅, 콜백, 인터페이스 |
| 제어 메커니즘 | 생명주기, 이벤트 루프, 디스패처, 컨테이너 등을 통해 호출 시점 결정 |
| 애플리케이션별 코드 | 확장 지점의 계약에 맞춰 구체적인 동작 제공 |
| 설정·등록 정보 | 사용할 컴포넌트와 구현을 프레임워크에 연결 |
안정된 골격과 공통 구현은 프레임워크가 맡고, 애플리케이션마다 달라지는 동작은 개발자가 확장 지점에 제공한다. 이 확장 지점에는 호출 시점, 입력과 반환 값, 다른 컴포넌트와 협력하는 방법까지 규약으로 정해져 있다.
생명주기나 이벤트 루프, 디스패처, 컨테이너는 어느 시점에 어떤 코드를 호출할지 결정한다. 개발자가 만든 구현은 설정·등록·조합·상속 가운데 프레임워크가 요구하는 방식으로 이 흐름에 연결된다.
제어의 역전
제어의 역전(Inversion of Control, IoC)은 애플리케이션이 전체 실행 순서를 직접 주도하지 않는 구조를 말한다. 프레임워크가 흐름을 관리하다가 필요한 시점에 등록된 애플리케이션 코드를 호출한다.
일반적인 라이브러리 사용
애플리케이션의 메인 흐름 → 라이브러리 호출 → 결과 반환 → 애플리케이션 흐름 계속
프레임워크 사용
프레임워크가 생명주기 관리 → 이벤트·단계 감지 → 등록된 애플리케이션 코드 호출 → 프레임워크 흐름으로 복귀
프레임워크는 언제 어떤 단계를 실행할지 정하고, 애플리케이션 코드는 그 단계에서 수행할 일을 제공한다. GUI 프레임워크라면 메인 이벤트 루프는 프레임워크가 관리하고, 애플리케이션은 각 이벤트에 대응할 핸들러를 등록한다. 실제 이벤트가 발생했을 때 핸들러를 호출하는 쪽도 프레임워크다.
의존성 주입(Dependency Injection, DI)은 IoC와 관련되지만 같은 개념은 아니다. 클래스가 필요한 객체를 직접 만들거나 찾지 않고 외부에서 받도록 하는 것이 DI다. 이는 클래스와 의존성 사이에서 IoC를 구현하는 한 가지 방법이다. 프레임워크의 IoC는 더 넓게 실행 흐름, 이벤트 처리, 객체 생성과 연결까지 다룰 수 있다.
라이브러리와 프레임워크의 차이
| 구분 | 라이브러리(Library) | 프레임워크(Framework) |
| 주된 재사용 단위 | 독립 기능을 제공하는 함수·클래스·컴포넌트 | 애플리케이션 골격, 컴포넌트 관계, 공통 구현 |
| 전체 흐름의 주도권 | 애플리케이션 코드 | 프레임워크 |
| 대표 호출 방향 | 애플리케이션 → 라이브러리 | 프레임워크 → 애플리케이션 콜백·훅 |
| 사용 방식 | 필요한 기능을 애플리케이션이 선택해 직접 호출 | 정해진 확장 계약에 맞춘 코드를 등록·상속·구성 |
| 구조에 미치는 범위 | 호출한 기능 중심 | 애플리케이션 구조와 생명주기에 영향 |
라이브러리는 애플리케이션이 실행 흐름을 유지하면서 필요한 기능을 직접 호출한다. 프레임워크는 애플리케이션의 골격을 제공하고, 확장 규약에 맞는 코드를 받아 전체 실행을 조직한다. 코드 크기나 기능 수보다 제어권과 재사용 범위가 더 분명한 구분 기준이다.
그렇다고 모든 개별 호출이 한 방향으로만 흐르는 것은 아니다. 프레임워크도 애플리케이션이 직접 호출할 메서드를 제공하고, 내부에서 여러 라이브러리를 사용한다. 표에서 말하는 호출 방향은 전체 실행과 컴포넌트 관계를 어느 쪽이 조직하는지를 뜻한다.
프레임워크 동작 흐름
먼저 프레임워크가 제공하는 콜백, 훅 메서드, 인터페이스, 기반 클래스 가운데 어디를 확장해야 하는지 확인한다. 그 규약에 맞춰 애플리케이션 코드를 구현한 뒤 설정이나 등록, 객체 조합 또는 상속으로 프레임워크에 연결한다.
실행이 시작되면 프레임워크 런타임이 메인 흐름과 생명주기를 관리한다. 이벤트 루프나 디스패처, 컨테이너가 처리 시점을 판단해 연결된 핸들러·훅·컴포넌트를 호출한다. 해당 처리가 끝나면 제어는 다시 프레임워크로 돌아간다.
[애플리케이션 코드 구현·등록]
↓
[프레임워크 시작 및 공통 흐름 관리]
↓
[이벤트 또는 생명주기 단계 발생]
↓
[등록된 콜백·훅 호출]
↓
[프레임워크 공통 흐름으로 복귀]
애플리케이션 코드는 독립적인 메인 흐름을 갖기보다 프레임워크가 마련한 처리 단계에 참여한다. 무엇을 구현할지만큼 언제, 어떤 상태와 입력으로 호출되는지를 나타내는 확장 규약이 중요하다.
확장 방식: 화이트박스와 블랙박스
| 구분 | 화이트박스 프레임워크 | 블랙박스 프레임워크 |
| 주요 확장 방식 | 상속, 동적 바인딩, 훅 메서드 재정의 | 인터페이스·규약 구현, 객체 조합, 위임 |
| 필요한 이해 | 내부 구조와 상속 계층에 대한 지식 | 외부 인터페이스와 컴포넌트 계약 중심 |
| 결합 지점 | 프레임워크 기반 클래스의 내부 설계 | 교체 가능한 컴포넌트 인터페이스 |
| 사용 측면 | 내부 구현 의존과 학습 부담 증가 가능 | 일반적으로 사용·확장하기 쉬움 |
| 설계 측면 | 상속과 재정의를 통해 확장 골격 제공 | 다양한 사용 사례를 수용할 인터페이스·훅의 선행 설계 필요 |
화이트박스 프레임워크는 기반 클래스를 상속하고 정해진 메서드를 재정의해 동작을 바꾼다. 어느 메서드를 어떤 규칙으로 재정의할지 판단하려면 상속 계층과 내부 구조를 알아야 한다. 그만큼 사용 코드가 프레임워크 내부 설계에 강하게 결합될 수 있다.
블랙박스 프레임워크는 정해진 인터페이스를 구현한 컴포넌트를 조합하거나 위임하는 방식으로 확장한다. 내부 구현보다 외부 인터페이스와 컴포넌트 간 계약을 알면 되므로 일반적으로 사용하기 쉽다. 대신 프레임워크를 설계하는 쪽에서는 여러 사용 사례의 변화 지점을 미리 찾아 인터페이스와 훅으로 만들어야 한다.
두 방식의 경계가 항상 선명한 것은 아니다. 하나의 프레임워크 안에서도 어떤 부분은 상속으로, 다른 부분은 컴포넌트 조합으로 확장할 수 있다.
장점
변하기 쉬운 구현을 안정된 인터페이스 뒤로 숨기면 변경의 영향을 해당 컴포넌트와 확장 지점 주변으로 제한할 수 있다. 프레임워크가 제공하는 모듈성은 이 경계에서 나온다.
재사용 범위도 개별 함수나 컴포넌트보다 넓다. 이들을 연결하는 애플리케이션 구조와 도메인 설계까지 다시 쓸 수 있다. 훅·콜백·인터페이스는 공통 골격을 바꾸지 않고 애플리케이션별 동작을 넣을 자리를 제공한다.
생명주기와 외부 이벤트의 전달은 프레임워크가 맡고, 애플리케이션 코드는 구체적인 처리에 집중한다. 여러 애플리케이션이 같은 처리 순서를 공유할 수 있는 이유다.
비용과 제약
프레임워크를 사용하려면 확장 지점뿐 아니라 생명주기, 컴포넌트 관계와 호출 규약까지 익혀야 한다. 라이브러리의 기능 하나를 호출할 때보다 이해해야 할 범위가 넓다. 어느 정도 학습하고 직접 적용해 보기 전에는 현재 문제에 맞는지 판단하기 어려울 수도 있다.
제어가 프레임워크와 애플리케이션 콜백 사이를 오가기 때문에 실행 경로가 코드에 명확하게 드러나지 않을 수 있다. 디버거로 흐름을 따라가면 프레임워크 내부와 애플리케이션 코드를 계속 넘나들게 되고, 결함이 어느 쪽에서 발생했는지 구분하기도 어렵다. 범용 컴포넌트와 애플리케이션별 확장을 결합한 상태로 검증해야 한다는 문제도 남는다.
서로 다른 이벤트 루프나 전달 방식, 컴포넌트 규약을 가진 프레임워크끼리는 통합하기 어렵다. 프레임워크의 요구사항이나 인터페이스가 바뀌면 그 확장 규약을 따르는 애플리케이션도 수정해야 한다. 공통 구조를 넓게 재사용하는 만큼 특정 프레임워크 구조에 대한 종속성도 커진다.
선택 기준
| 확인 항목 | 판단 질문 |
| 문제 영역 | 프레임워크의 공통 골격이 현재 애플리케이션 종류·도메인과 일치하는가 |
| 확장 지점 | 필요한 변화를 훅·콜백·인터페이스로 표현할 수 있는가 |
| 제어 흐름 | 프레임워크의 생명주기·이벤트 처리 방식이 애플리케이션 요구와 맞는가 |
| 통합성 | 기존 라이브러리·컴포넌트·다른 프레임워크의 이벤트 처리 방식과 결합할 수 있는가 |
| 학습 투자 | 규약과 내부 동작을 익히는 비용을 여러 기능·프로젝트에서 회수할 수 있는가 |
| 변경 대응 | 프레임워크의 버전·인터페이스 변화에 맞춰 애플리케이션을 유지할 수 있는가 |
| 검증·디버깅 | 프레임워크와 애플리케이션 콜백을 함께 추적할 문서·테스트·진단 수단이 있는가 |
기능 목록만 비교해서는 프레임워크의 적합성을 판단하기 어렵다. 현재 문제와 공통 골격이 맞는지, 필요한 변화를 제공된 확장 지점으로 표현할 수 있는지, 프레임워크의 생명주기와 이벤트 처리 방식이 요구사항과 충돌하지 않는지 확인해야 한다. 기존 라이브러리나 다른 프레임워크를 함께 사용한다면 제어 메커니즘과 컴포넌트 규약도 비교 대상이다.
학습과 유지 비용은 재사용 범위와 함께 봐야 한다. 독립된 기능 몇 개만 필요하고 실행 흐름을 직접 관리해야 한다면 라이브러리가 더 적합할 수 있다. 반대로 여러 기능이나 프로젝트에서 같은 구조와 생명주기가 반복된다면 프레임워크의 골격을 재사용할 여지가 있다. 버전 변화에 대응할 수 있는지, 콜백 흐름을 추적할 문서와 테스트·진단 수단이 있는지도 도입 전에 확인할 항목이다.
'WiSoft' 카테고리의 다른 글
| 노트북과 Raspberry Pi의 TCP Client-Server 구성 (0) | 2026.07.14 |
|---|---|
| C++ TCP Socket Programming (0) | 2026.07.14 |
| Socket의 개념과 Client-Server 구조 (0) | 2026.07.14 |
| Raspberry Pi에 Ubuntu Server 설치와 네트워크 설정 (0) | 2026.07.01 |
| UART와 RS-232·RS-422·RS-485의 동작과 차이 (1) | 2026.06.28 |

































