추상화
추상화(抽象化, Abstraction)는 복잡한 대상에서 불필요한 세부 사항을 숨기고 핵심 개념·행위·인터페이스만 드러내어 문제를 단순화하는 컴퓨터과학과 소프트웨어공학의 기본 개념이다.
추상화는 컴퓨터 시스템과 소프트웨어를 이해하고 설계하기 위한 핵심 원리이다. 프로그래밍에서 추상화는 복잡한 구현 세부 사항을 단순한 API, 인터페이스, 타입, 함수, 클래스, 계층 구조 뒤에 숨겨 사용자가 필요한 기능에만 집중하게 하는 방식이다.[1]
예를 들어 개발자는 파일을 읽을 때 저장장치의 블록 배치, 파일 시스템 메타데이터, 커널 입출력 처리, 디스크 드라이버 동작을 직접 다루지 않고 open(), read() 같은 추상화된 인터페이스를 사용한다. 마찬가지로 객체지향 프로그래밍에서는 객체가 내부 상태와 구현을 감추고 공개된 메서드나 인터페이스를 통해 외부와 상호작용한다.[2]
추상화는 단순히 정보를 숨기는 것이 아니라, 문제 해결에 필요한 관점과 모델을 선택하는 과정이다. 어떤 세부 사항을 감출지, 어떤 속성과 행위를 드러낼지 결정함으로써 시스템을 더 이해하기 쉽고 재사용 가능하며 변경에 강하게 만든다.
컴퓨터과학에서 추상화는 여러 수준에서 나타난다. 하드웨어 수준에서는 논리 회로와 명령어 집합이 전기적 신호를 추상화하고, 운영체제는 프로세스·파일·네트워크 소켓으로 하드웨어 자원을 추상화한다. 프로그래밍 언어는 기계어와 메모리 관리를 변수, 함수, 객체, 모듈 같은 개념으로 추상화한다. OpenStax의 컴퓨터과학 교재는 컴퓨터 시스템을 서로 겹쳐진 여러 추상화 수준으로 볼 수 있다고 설명한다.[3]
| 구분 | 설명 | 예시 |
|---|---|---|
| 데이터 추상화 | 데이터의 내부 표현을 숨기고, 값과 연산의 의미만 드러내는 방식이다. | 스택, 큐, 리스트, 맵, 집합 |
| 절차 추상화 | 복잡한 처리 과정을 함수나 메서드 이름 뒤에 감추는 방식이다. | sort(), sendEmail(), calculateTax()
|
| 제어 추상화 | 반복, 조건, 예외 처리, 비동기 실행 등 제어 흐름을 더 높은 수준의 문법이나 구조로 표현하는 방식이다. | for, while, try-catch, async/await
|
| 타입 추상화 | 구체적인 구현보다 타입의 계약과 사용법을 중심으로 코드를 작성하는 방식이다. | 인터페이스, 추상 클래스, 제네릭 타입 |
| 계층 추상화 | 시스템을 여러 계층으로 나누어 각 계층이 하위 계층의 복잡성을 감추는 방식이다. | OSI 모델, 운영체제 API, 프레임워크, 클라우드 서비스 |
| 도메인 추상화 | 현실 세계의 업무 개념을 소프트웨어 모델로 표현하는 방식이다. | 주문, 결제, 회원, 상품, 계좌 |
객체지향 프로그래밍(Object-Oriented Programming, OOP)에서 추상화는 객체의 핵심 속성과 행위만 모델링하고, 불필요한 구현 세부 사항은 외부에 노출하지 않는 원리이다. MDN은 객체가 공개 인터페이스를 제공하면서 내부 상태를 유지하고, 다른 코드는 객체 내부에서 어떤 일이 일어나는지 알 필요가 없다고 설명한다.[4]
객체지향에서 추상화는 보통 다음 구조로 구현된다.
- 클래스: 공통 속성과 행위를 묶어 객체의 설계도를 만든다.
- 추상 클래스: 공통 구현 일부를 제공하면서, 하위 클래스가 반드시 구현해야 할 추상 멤버를 정의한다.
- 인터페이스: 구현 없이 외부에 제공해야 하는 기능의 계약을 정의한다.
- 다형성: 동일한 인터페이스를 따르는 여러 구현체를 같은 방식으로 사용할 수 있게 한다.
마이크로소프트의 .NET 설계 지침은 추상화를 “계약을 설명하지만 계약의 전체 구현은 제공하지 않는 타입”으로 설명하며, 일반적으로 추상 클래스나 인터페이스로 구현된다고 안내한다.[5]
추상 클래스와 인터페이스는 모두 추상화를 구현하는 대표적인 수단이지만 목적과 사용 방식이 다르다.
| 구분 | 추상 클래스 | 인터페이스 |
|---|---|---|
| 목적 | 공통 상태와 공통 구현을 일부 제공하면서 하위 클래스의 구현을 강제한다. | 객체가 제공해야 하는 기능의 계약을 정의한다. |
| 인스턴스 생성 | 직접 인스턴스화하지 않는 것이 일반적이다. | 직접 인스턴스화하지 않고 구현 클래스가 필요하다. |
| 구현 포함 | 일부 메서드나 속성은 구현할 수 있고, 일부는 추상 멤버로 둘 수 있다. | 언어에 따라 다르지만, 핵심 목적은 계약 정의이다. |
| 관계 | “A는 B의 한 종류이다”라는 상속 관계에 적합하다. | “A는 B 기능을 제공한다”라는 능력·역할 표현에 적합하다. |
| 예시 | Animal, Vehicle, BaseController
|
Comparable, Serializable, PaymentGateway
|
Java의 공식 튜토리얼은 추상 클래스와 추상 메서드를 통해 공통 동작과 구현 강제 구조를 만들 수 있다고 설명한다.[6] Python도 abc 모듈을 통해 추상 베이스 클래스(Abstract Base Class, ABC)를 정의하는 기반을 제공한다.[7]
다음 예시는 결제 수단의 세부 구현을 PaymentGateway 인터페이스 뒤에 숨기는 추상화이다. 주문 서비스는 신용카드 결제인지, 간편결제인지, 계좌이체인지 알 필요 없이 pay()라는 계약만 사용한다.
interface PaymentGateway {
pay(amount: number): Promise<void>;
}
class CardPaymentGateway implements PaymentGateway {
async pay(amount: number): Promise<void> {
// 카드사 API 호출, 인증, 승인 처리
}
}
class BankTransferGateway implements PaymentGateway {
async pay(amount: number): Promise<void> {
// 은행 API 호출, 계좌 확인, 이체 처리
}
}
class OrderService {
constructor(private paymentGateway: PaymentGateway) {}
async checkout(totalPrice: number): Promise<void> {
await this.paymentGateway.pay(totalPrice);
}
}
이 구조에서 OrderService는 구체적인 결제 구현체에 직접 의존하지 않는다. 따라서 새로운 결제 수단을 추가하더라도 PaymentGateway 계약을 지키는 구현체만 만들면 기존 주문 로직을 크게 바꾸지 않아도 된다.
추상 자료형(Abstract Data Type, ADT)은 데이터의 구체적인 저장 방식보다 값과 연산의 의미를 중심으로 정의한 자료형이다. 예를 들어 스택은 배열로 구현할 수도 있고 연결 리스트로 구현할 수도 있지만, 추상 자료형으로서의 스택은 push, pop, peek 같은 연산과 후입선출(LIFO) 규칙으로 설명된다.
Python의 collections.abc 문서는 컨테이너가 특정 인터페이스를 제공하는지 검사할 수 있는 추상 베이스 클래스를 제공한다고 설명한다. 예를 들어 객체가 해시 가능한지, 매핑인지, 시퀀스인지 등을 추상 인터페이스 관점에서 다룰 수 있다.[8]
- 복잡성 감소: 구현 세부 사항을 감추어 개발자가 현재 문제에 필요한 정보에 집중할 수 있다.
- 재사용성 향상: 공통 개념과 계약을 분리하면 여러 구현체가 같은 추상화를 공유할 수 있다.
- 유지보수성 향상: 내부 구현을 바꾸더라도 외부 인터페이스가 유지되면 영향 범위를 줄일 수 있다.
- 테스트 용이성: 인터페이스나 추상 타입을 기준으로 목 객체, 스텁, 테스트 더블을 만들 수 있다.
- 확장성 향상: 기존 코드를 크게 수정하지 않고 새로운 구현체나 기능을 추가하기 쉽다.
- 의존성 감소: 상위 모듈이 구체 구현보다 추상화에 의존하게 하여 결합도를 낮출 수 있다.
추상화는 강력한 설계 도구이지만 무조건 많을수록 좋은 것은 아니다. 지나치게 많은 추상 계층은 코드 이해를 어렵게 하고, 실제 동작을 파악하기 위해 여러 파일과 계층을 추적해야 하는 문제를 만들 수 있다. 또한 성능, 네트워크 지연, 메모리 사용량, 트랜잭션 경계 같은 하위 구현의 특성이 완전히 숨겨지지 않는 경우가 있다.
조엘 스폴스키가 제시한 “누수 추상화의 법칙”은 모든 중요하고 복잡한 추상화는 어느 정도 하위 구현의 세부 사항을 드러낸다는 관찰이다.[9] 예를 들어 데이터베이스 ORM은 SQL을 감추지만 성능 문제를 해결하려면 결국 쿼리 실행 계획, 인덱스, 조인 구조를 이해해야 할 수 있다.
| 개념 | 추상화와의 관계 |
|---|---|
| 캡슐화 | 내부 상태와 구현을 감추는 기법이다. 추상화가 “무엇을 드러낼 것인가”에 초점을 둔다면, 캡슐화는 “어떻게 감출 것인가”에 더 가깝다. |
| 정보 은닉 | 변경 가능성이 큰 내부 구현 세부 사항을 외부에서 알 수 없게 하는 설계 원칙이다. |
| 모듈화 | 시스템을 독립적인 구성 요소로 나누는 방식이다. 각 모듈은 외부에 추상화된 인터페이스를 제공한다. |
| 다형성 | 같은 추상 타입이나 인터페이스를 따르는 여러 구현체를 동일한 방식으로 사용할 수 있게 한다. |
| 의존성 역전 | 고수준 모듈이 구체 구현이 아니라 추상화에 의존하게 하는 설계 원칙이다. |
| API | 소프트웨어가 외부에 제공하는 추상화된 사용 계약이다. |
좋은 추상화는 단순히 클래스를 많이 만들거나 인터페이스를 분리하는 것이 아니라, 사용자의 관점에서 안정적인 개념과 변할 가능성이 높은 구현을 적절히 나누는 것이다.
- 사용자 관점 우선: 추상화는 구현자의 내부 구조보다 사용하는 코드의 필요를 기준으로 설계해야 한다.
- 변경 가능성 분리: 자주 바뀌는 구현 세부 사항은 인터페이스 뒤에 숨기고, 안정적인 계약은 명확하게 드러낸다.
- 과도한 일반화 회피: 실제 요구가 없는 미래 확장을 위해 불필요한 추상 계층을 만들면 오히려 유지보수성이 떨어질 수 있다.
- 명확한 이름 사용: 추상화의 이름은 숨겨진 구현보다 드러나는 역할과 책임을 설명해야 한다.
- 계약 문서화: 입력, 출력, 예외, 부작용, 성능 특성, 스레드 안전성 같은 사용 조건을 명확히 해야 한다.
추상화는 컴퓨터과학의 거의 모든 영역을 관통하는 기본 개념이다. 하드웨어, 운영체제, 프로그래밍 언어, 라이브러리, 프레임워크, 클라우드 서비스, 인공지능 도구는 모두 하위 복잡성을 더 단순한 개념으로 다루게 하는 추상화 계층을 제공한다.
소프트웨어 개발에서 추상화는 대규모 시스템을 사람이 이해 가능한 단위로 나누고, 변경 가능한 구현을 안정적인 계약 뒤에 숨기며, 여러 구현을 같은 방식으로 사용할 수 있게 한다. 반면 잘못 설계된 추상화는 불필요한 복잡성과 성능 문제, 디버깅 어려움을 만들 수 있으므로, 문제 영역과 사용자의 요구에 맞는 적절한 추상화 수준을 선택하는 것이 중요하다.
- ↑ MDN Web Docs, "Abstraction", https://developer.mozilla.org/en-US/docs/Glossary/Abstraction, 확인한 날짜: 2026년 6월 15일.
- ↑ MDN Web Docs, "Object-oriented programming", https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object-oriented_programming, 확인한 날짜: 2026년 6월 15일.
- ↑ OpenStax, "5.2 Computer Levels of Abstraction", https://openstax.org/books/introduction-computer-science/pages/5-2-computer-levels-of-abstraction, 확인한 날짜: 2026년 6월 15일.
- ↑ MDN Web Docs, "Object-oriented programming", https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object-oriented_programming, 확인한 날짜: 2026년 6월 15일.
- ↑ Microsoft Learn, "Abstractions: Abstract Types and Interfaces", https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/abstractions-abstract-types-and-interfaces, 확인한 날짜: 2026년 6월 15일.
- ↑ Oracle Java Tutorials, "Abstract Methods and Classes", https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html, 확인한 날짜: 2026년 6월 15일.
- ↑ Python Documentation, "abc — Abstract Base Classes", https://docs.python.org/3/library/abc.html, 확인한 날짜: 2026년 6월 15일.
- ↑ Python Documentation, "collections.abc — Abstract Base Classes for Containers", https://docs.python.org/3/library/collections.abc.html, 확인한 날짜: 2026년 6월 15일.
- ↑ Joel Spolsky, "The Law of Leaky Abstractions", https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/, 확인한 날짜: 2026년 6월 15일.
