내일배움캠프(Spring 7기)/특강

Java 객체 간의 결합도 세션

가지코딩 2025. 5. 2. 12:01
  • 일시 : 05/02(월) 11:00
  • 장소 : zoom
  • 진행 : 김기용 튜터님

0. OCP(Open-Close-Principle)

확장에는 열려 있고 변경에는 닫혀 있어야한다는 설계원칙(solid 중 하나)


1. 객체 간의 결합도

한 객체가 다른 객체와 상호작용할 때 얼마나 강하게 의존하고 있는지를 나타내는 정도

 

 

강한 결합

  • 한 객체가 다른 객체의 구현에 깊게 의존
  • 한 객체가 변경되면 다른 객체도 영향을 받음 → 변경에 취약
class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    Engine engine = new Engine();  // 직접 생성 (강한 결합)

    void drive() {
        engine.start();
    }
}

 

 

느슨한 결합

  • 인터페이스나 추상 클래스에 의존
  • 의존성 주입(Dependency Injection)을 통해 외부에서 객체를 주입
  • 변경에 유연하고 확장 가능
interface Engine {
    void start();
}

class GasEngine implements Engine {
    public void start() {
        System.out.println("Gas engine started");
    }
}

class Car {
    private Engine engine;

    // 의존성 주입
    Car(Engine engine) {
        this.engine = engine;
    }

    void drive() {
        engine.start();
    }
}

 

 

강한 결합 vs 느슨한 결합

  • 일반적으로 느슨한 결합이 좋다.
    • 변경에 강하고 유연한 설계 가능
    • 유지보수/확장/테스트가 쉬움
    • SOLID 원칙(특히 DIP: 의존 역전 원칙)에 부합
  • 객체 간 관계가 변경될 가능성이 없는 경우, 추상화나 느슨한 결합은 오히려 불필요한 복잡성을 초래할 수 있다.
    • ex. Scanner, Integer, String 등

2. 의존성 주입(DI)

객체가 필요로 하는 의존 객체를 직접 생성하지 않고 외부에서 주입받는 방식

 

public class MessageService {
    private Skt skt;
    private Scanner scanner = new Scanner(System.in);

    public MessageService(Skt skt) {
        this.skt = skt; // ✅ 주입 받음
    }

    public void sendMessage() {
        System.out.print("메시지: ");
        String message = scanner.nextLine();
        skt.send(message);
    }
}
public class Main {
    public static void main(String[] args) {
        Skt skt1 = new Skt("Seoul");
        Skt skt2 = new Skt("SeongNam");
        MessageService messageService = new MessageService(skt2); // ✅ 주입
        messageService.sendMessage();
    }
}

3. 제어의 역전(IoC)

  • 의존성 주입(DI) 을 통해 구현된다.
  • 자신이 사용할 객체를 직접 생성하거나 결정하지 않고 외부로 부터 주입받아 활용만한다. → IoC
public class Main {
    public static void main(String[] args) {
        Skt skt = new Skt("SeongNam");
        Kt kt = new Kt("SeongNam");
        MessageService messageService = new MessageService(skt);
        messageService.sendMessage();
    }
}

4. 객체 지향의 특징과 결합도

객체 지향의 4가지 특징

  • 캡슐화 - 접근제어를 통해 객체 내부의 정보를 외부로부터 은닉
  • 다형성 - 한가지 타입으로 다양한 구현체들을 다룰 수 있는 성질
  • 상속 - 부모의 요소를 물려받는 것(재활용성)
  • 추상화 - 중요한 본질만 남기는 것

 

 

다형성(Polymorphism)

  • 하나의 형태(자료형/데이터타입) 으로 여러가지 형태(구현체)를 다룰 수 있는 성질
  • 다형성은 IoC 설계를 유연하게 만들어준다.

 

상속(Inheritance)

  • 부모의 요소를 자식이 물려받는 것 → 재활용성

 

 

추상화(Abstraction)

  • 중요한 본질만 남기는 것

 

  • 인터페이스의 추상화
    • MessageService 는 구현체(KT, SKT, etc)에 의존하지 않고 인터페이스(기능 중심)에 의존하게 된다.
    • MessageSerivce 는 통신사가 어떻게 구현되었는지 알지 못해도 메시지를 전송할 수 있다.

 

  • 상속의 추상화
    • 거대한 전체 흐름(검수 등)을 감추고 확장 가능한 부분만 노출