의존성 주입에 대해

Donghee Lee·2022년 9월 26일
0

iOS-Swift

목록 보기
19/20
post-thumbnail

의존성 주입에 대해


‼️iOS 취준생이 작성한 글이므로 잘못된 정보가 있을 수 있습니다.

최근 프로젝트를 진행하며 생각보다 볼륨이 커져가는 모습을 보며 코드간의 재사용성, 유연성에 대해 흘려듣기만 했던 내용을 정리해보고자 한다.

어떻게 하면 코드의 재사용성을 높이고 가독성, 확장성, 유연성, 종속성을 좋게 할까?

의존성 주입, 이게 왜 필요한지부터 생각해보자...

우선 기존에 사용하던 방식으로 인스턴스 생성의 책임을 객체 스스로 정하도록 하지 않고
생성자, 프로퍼티의 형태로 "던져주는, 넘겨주는" 것 정도로 이해해보자.

예시는 글보다 코드로 설명하기 쉬울 것 같다!

상황을 먼저 설정하자면 자동차 회사인 BMW, HYUNDAI 있고 선택된 자동차를 관리하는 class가 각각 있다고 생각하자.

먼저 BMW, HYUNDAI 클래스를 정의하면

class BMW {}
class HYUNDAI {}

선택된 자동차 객체를 생성할 수 있는 클래스는

class SelectedCar {
    private let car: BMW
    init(car: BMW) {
        self.car = car
    }
}

이렇게 된다.

자 여기서 어떤 문제점이 보이는가?

그렇다. 생성자로 지금 BMW 클래스를 받고 있기 때문에, HYUNDAI 객체를 넣어 사용할 때 코드를 새로 작성해야 하므로 코드의 재사용성이 줄어들게 된다.

만약 여기서 HYUNDAI로 바꾸려고 한다면

class SelectedCar {
    private let car: HYUNDAI
    init(car: HYUNDAI) {
        self.car = car
    }
}

이렇게 코드를 하나하나 수정해줘야 하며, 코드의 확장성도 줄어든 모습을 확인할 수 있다.
여기서 SelectedCar 클래스는 car 인스턴스를 생성하는 책임이 있으며, HYUNDAI나 BMW 클래스에게 의존적이게 된다.

아니 난 SelectedCar에 내가 원하는 인스턴스만 넣어서 필요할 때 사용하고 싶은데 어떡하지?
코드를 더 추가해야 하나? 라는 생각이 떠오른다.

어떤 클래스에도 사용될 수 있는 protocol을 정의해보자.

protocol Driving {
    func canDrive()
    func isDriving() -> Bool
}

protocol로 정의한 행동을 HYUNDAI, BMW 클래스가 상속받게 되어 사용한다면?
또한 protocol 타입으로 SelectedCar의 car 프로퍼티가 지정된다면 어떻게 될까?

그렇다. SelectedCar 클래스에게 HYUNDAI나 BMW 클래스를 의존적으로 만들지 않고 외부에서 직접 "주입시켜" 줄 수 있다.
즉, 어떤 Driving 프로토콜을 채택하는 어떤 객체 타입이든 car 변수로 대체될 수 있다.

그렇다면 HYUNDAI, BMW 클래스 모두 Driving protocol을 상속해보자.

class BMW: Driving {
    func canDrive() {
        print("canDrive")
    }

    func isDriving() -> Bool {
        return true
    }
}
class HYUNDAI: Driving {
    func canDrive() {
        print("canDrive")
    }

    func isDriving() -> Bool {
        return true
    }
}

그리고 SelectedCar 클래스 내부의 car 변수도 같은 프로토콜을 타입으로 갖게 하자.

class SelectedCar {
    private let car: Driving
    init(car: Driving) {
        self.car = car
    }
}
var car = SelectedCar(car: HYUNDAI())
var car2 = SelectedCar(car: BMW())

이렇게 되면 앞서 말한대로, SelectedCar 클래스에게 HYUNDAI나 BMW의 인스턴스를 생성하는 책임(의존)을 없앨 수 있으며 외부에서 주입해주는 대로 사용할 수 있게된다.

또한 SelectedCar의 car 변수도 immutable하게 유지될 수 있으며
BMW, HYUNDAI에 종속적이던 SelectedCar의 유연성도 확장할 수 있게된다.

즉, SelectedCar 객체는 car에 어떤 타입이 들어오는가와 같은 디테일에 대해 전혀 신경쓰지 않을 수 있게된다.


전체 코드

protocol Driving {
    func canDrive()
    func isDriving() -> Bool
}

class BMW: Driving {
    func canDrive() {
        print("canDrive")
    }

    func isDriving() -> Bool {
        return true
    }
}
class HYUNDAI: Driving {
    func canDrive() {
        print("canDrive")
    }

    func isDriving() -> Bool {
        return true
    }
}

class SelectedCar {
    private let car: Driving
    init(car: Driving) {
        self.car = car
    }
}

var car = SelectedCar(car: HYUNDAI())
profile
Better than Yesterday

0개의 댓글