티스토리 뷰
목차
1. 추상화란?
추상화(Abstraction)는 불필요한 구현 세부사항은 감추고, 핵심적인 개념이나 행위만을 정의하여 표현하는 객체지향 설계 원칙이다.
즉, "무엇을 할 수 있는가"에 집중하고, "어떻게 구현할 것인가"는 감춘다는 철학
📌Java에서의 예시
- List 인터페이스만 알아도 ArrayList나 LinkedList의 구체 구현을 몰라도 사용 할 수 있음
- 이처럼 추상화를 통해 사용과 구현을 분리하고, 유연한 설계를 할 수 있다.
📌 예시로 이해하기
- "TV 리모컨"은 전원을 켜고 채널을 바꿀 수 있음 (기능 = 추상화된 인터페이스)
- 내부적으로 무슨 회로로 동작하는지는 알 필요 없음 (구현 = 캡슐화)
public interface RemoteControl {
void powerOn();
void changeChannel(int channel);
}
- SamsungTV, LGTV는 이 인터페이스를 각자 다르게 구현 가능 (다형성 기반)
2. 추상 클래스 vs 인터페이스
| 항목 | 추상 클래스 | 인터페이스 |
| 키워드 | abstract class | interface |
| 목적 | 공통 로직 + 확장 포인트 제공 | 기능 명세만 제공 |
| 다중 상속 | ❌ (단일 상속만 가능) | ✅ (여러 인터페이스 구현 가능) |
| 접근제어자 | 필드, 생성자, protected등 가능 | public static final, public abstarct가 기본 |
| 사용 예 | 상위 클래스에 기본 동작을 제공하고 싶을 때 | 설계 중심 역할 분리, 전략/역할 분할 등 |
📍 추상 클래스 예제
public abstract class Animal {
public void eat() {
System.out.println("먹는다");
}
public abstract void sound(); // 구현은 하위 클래스에서
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("멍멍");
}
}
📍 인터페이스 예제
public interface Payment {
void pay(int amount);
}
public class CreditCardPayment implements Payment {
public void pay(int amount) {
System.out.println("카드로 " + amount + "원 결제합니다");
}
}
3. 실무에서 추상화가 중요한 이유
✅ 변경에 강한 설계
- 구체 구현이 바뀌더라도 추상 타입(인터페이스, 추상 클래스)은 그대로 -> 클라이언트 코드 영향 없음
✅ 테스트와 유연성
- 인터페이스 기반 -> Mock 객체 주입 가능 -> 테스트 용이
✅ 레이어 분리 & 아키텍처 기반 설계
- Controller -> Service -> Repository 구조에서, Repository는 보통 인터페이스로 추상화
- 구현체는 JDBC, JPA, MyBatis등 자유롭게 변경 가능
public interface UserRepository {
Optional<User> findById(Long id);
}
4. 추상화가 부족한 나쁜 설계 예시
public class OrderService {
private KakaoPayService kakaoPayService;
public void pay() {
kakaoPayService.requestPayment();
}
}
- KakaoParService에 직접 의존
- TossPayService, CardPayService를 쓰려면 기존 코드 수정 필요
✅ 개선 후
public interface PaymentStrategy {
void requestPayment();
}
public class OrderService {
private final PaymentStrategy strategy;
public OrderService(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void pay() {
strategy.requestPayment();
}
}
- 추상화가 안되어 있으면 구체 클래스에 직접 의존하게 되어, 새로운 요구사항이 생길 때마다 기존 코드를 수정해야 한다.
- 이는 변경에 취약한 구조가 되고, 서비스 로직과 인프라 로직이 뒤섞여 테스트도 어렵고 재사용도 힘들어 진다.
5. 실무에서 추상화가 자주 등장하는 예
| 분야 | 추상화 대상 | 설명 |
| Spring Data JPA | JpaRepository<T, ID> | 구현체 없어도 기본 메서드 제공 |
| DI/IoC | 인터페이스 기반 주입 | 구현 클래스는 외부에서 결정 |
| 전략 패턴 | Strategy 인터페이스 | 정책을 런타임에 교체 가능 |
| 서비스 계층 분리 | Service 인터페이스 | 테스트, 모듈화에 유리 |
✅ 마무리 요약
- 추상화는 불필요한 정보는 숨기고 핵심 인터페이스만 제공하는 객체지향의 핵심 원칙
- 추상 클래스는 공통 구현 포함, 인터페이스는 역할 분리와 유연성 확보에 강점
- 실무에서는 역할 기반 설계, DI 컨테이너 기반 설계, 테스트 전략에 필수
- 추상화가 잘 된 구조는 변경에 강하고, 테스트가 쉬우며, 유지보수성이 높다
🔜 다음 포스팅 주제는 "SRP - 단일 책임 원칙 : 클래스는 하나의 책임만 가져야 한다" 주제로 포스팅 해보려고 한다. 객체 지향의 설계 원칙과 SOLID의 각 특성들은 연결되는 내용들이 많기 때문에 각 요소마다 이해를 하기보다는 전체적으로 연결지으며 이해하고 내것으로 만드는 것이 좋다.
'IT > OOP' 카테고리의 다른 글
| 🌀다형성(Polymorphism) - 한 인터페이스, 여러 구현의 힘 (0) | 2025.04.15 |
|---|---|
| 상속(Inheritance) - 코드 재사용의 유혹, 그러나 신중해야 할 이유 (0) | 2025.04.15 |
| 🔒 캡슐화(Encapsulation) - 객체지향의 시작점, 복잡성의 종착역 (0) | 2025.04.14 |
| 객체지향 프로그래밍(OOP) (0) | 2025.03.11 |