티스토리 뷰

IT/OOP

🌀다형성(Polymorphism) - 한 인터페이스, 여러 구현의 힘

Stv 2025. 4. 15. 18:48

목차


    1. 다형성이란?

    다형성(Polymorphism)은 하나의 인터페이스(또는 부모 타입)를 통해 다양한 구현(자식 클래스)의 동작을 수행할 수 있는 객체지향의 핵심 원칙이다.

     

    간단히 말하면 : "같은 메시지를 보냈을 때, 객체가 각자 다른 방식으로 응답하는 능력"

     

    2. 왜 다형성이 중요한가?

     

    📌 유지보수성과 확장성 향상

    • 새로운 기능 추가 시 기존 코드 수정 없이 확장 가능 (OCP 원칙 실현)
    • 고수준 모듈이 저수준 구현이 아닌 인터페잇에 의존하게 된다 (DIP 원칙 실현)
    • 다양한 객체를 하나의 타입으로 다룰 수 있음

    📌 의존성 분리 (Decoupling)

    • 클라이언트 코드는 인터페이스만 알고 구체 구현은 모름 -> 유연한 설계 가능

    📌 테스트 용이성

    • 인터페이스 덕분에 Mock 객체를 쉽게 주입하여 단위 테스트가 가능하다.

     

    3. 정적 다형성 vs 동적 다형성

    구분 설명 대표 방식
    정적 다형성 컴파일 타임에 결정됨 메서드 오버로딩
    동적 다형성 런타임에 결정됨 메서드 오버라이딩

     

    4. 메서드 오버로딩 vs 오버라이딩 차이

     

    ▶ 오버로딩 (Overloading)

    • 같은 이름의 메서드지만 매개변수 타입/개수/순서가 다름
    • 컴파일 시점에 결정됨
    public class Printer {
        public void print(String s) { ... }
        public void print(int i) { ... }
    }

     

    ▶ 오버라이딩 (Overriding)

    • 상속된 메서드를 재정의하는 것
    • 런타임 시점에 어떤 메서드가 실행될지 결정됨
    class Animal {
        public void sound() {
            System.out.println("동물 소리");
        }
    }
    
    class Dog extends Animal {
        @Override
        public void sound() {
            System.out.println("멍멍");
        }
    }
    Animal a = new Dog();
    a.sound(); // "멍멍" 출력 → 런타임 다형성

     

    5. 실무 설계에서 다형성의 적용 예

     

    🎯 서비스 계층에서 인터페이스를 사용하는 이유

    public interface PaymentStrategy {
        void pay(int amount);
    }
    
    public class KakaoPay implements PaymentStrategy {
        public void pay(int amount) {
            System.out.println("카카오페이 결제: " + amount);
        }
    }
    
    public class TossPay implements PaymentStrategy {
        public void pay(int amount) {
            System.out.println("토스페이 결제: " + amount);
        }
    }
    public class PaymentService {
        private final PaymentStrategy strategy;
    
        public PaymentService(PaymentStrategy strategy) {
            this.strategy = strategy;
        }
    
        public void processPayment(int amount) {
            strategy.pay(amount); // 다형성의 핵심
        }
    }
    새로운 결제 수단 추가해도 기존 코드는 전혀 수정할 필요 없음
    (OCP 원칙 충족)

     

    6. 다형성을 사용하지 않은 나쁜 코드

    public class PaymentService {
        public void pay(String type, int amount) {
            if ("kakao".equals(type)) {
                // kakao pay logic
            } else if ("toss".equals(type)) {
                // toss pay logic
            }
        }
    }
    • if-else가 늘어날수록 유지보수 어려움 + 테스트 복잡도 증가 + OCP 위반

    7. 다형성과 SOLID 연계

    • OCP(개방-폐쇄 원칙) : 구현 클래스 확장 시 기존 코드 변경 없음
    • DIP(의존성 역전 원칙) : 추상화(인터페이스)에 의존함으로써 구체 클래스에 의존하지 않음

    8. 다향성 + 전략 패턴(Strategy Pattern)

    • 다형성은 대표적인 디자인 패턴에서 많이 사용된다. 그 중 하나가 바로 전략 패턴(Strategy Pattern)
    같은 작업을 여러 알고리즘(전략)으로 처리할 수 있게 만든 구조
    실행 시점에 객체의 행위를 바꾸고 싶을 때 사용

     

    ✅ 마무리 요약

    • 다형성은 "같은 타입(인터페이스)으로 다양한 객체를 처리할 수 있는 능력"
    • 오버로딩은 컴파일 타임, 오버라이딩은 런타임에 결정됨
    • 실무에서는 인터페이스 + DI -> 다형성 기반 유연한 설계가 기본
    • if-else를 줄이고, 새로운 요구사항 추가에 강한 구조를 만들 수 있음

    🔜 다음 포스팅에서는 "추상화 (Abstraction) - 복잡함을 감추고 본질만 드러내다" 라는 주제로 포스팅 할 예정이다.