Delegation Pattern (보완 예정)

Park Suyong·2022년 2월 22일
0

Study

목록 보기
2/12

Delegation Pattern

정의

먼저 단어의 의미부터 알고 가도록 한다. Delegation이란, 위임을 뜻한다. Delegater는 어떤 행위를 다른 이에게 위임하는 위임자를 말하며, Delegate는 어떤 행위를 위임받아 실제로 수행하는 대리자를 의미한다.

Delegation Pattern이란, 상속과 동일한 코드 재사용을 달성할 수 있도록 하는 객체지향 디자인 패턴이며, 어떤 기능을 자신이 수행하지 않고 다른 객체에 위임하여 해당 객체가 작업을 수행하도록 구성한 디자인 패턴이다. 그리고 kotlin에서는 이를 by 라는 키워드를 통해 boiler plate 코드 없이 네이티브하게 지원한다.

Delegation Pattern을 사용하는 이유

상속(Inheritance)구성(Composition)에 대해 이해해야 한다.

상속은 위험하며, 많은 문제를 발생시킬 수 있다. 그 문제들은 캡슐화 위반, 객체의 유연성 저하 등이 될 것이다. 상속으로 인해 하위 클래스가 상위 클래스의 구성을 알 수 있으며, 부모 클래스가 변경될 경우 하위 클래스 또한 변경되어야 한다. 게다가, 부모 클래스의 의도와는 다르게 자식 클래스가 동작할 수도 있다. 따라서, 객체 지향 원칙에도 위배될 수 있다.

이러한 위험성을 해결하는 방법으로 Kotlin 문서에서는 Composition(혹은 Aggregation) 관계로 구현하는 것을 권장한다. 이는 상속이 아니라, 클래스 내부에서 다른 클래스 의존성을 갖는 것을 말한다. 이를 흔히 Has-A 관계라 한다. (상속은 Is-A 관계일 때 사용하지만, 굳이 상속이 필요하지 않을 경우 Composition을 사용하는 것을 권장한다는 것.)

Delegation Pattern은 이러한 Composition을 사용하는 대표적인 패턴이라고 할 수 있다.

Kotlin - by

Kotlin에는 Delegation Pattern을 boiler plate 코드 없이 쉽게 사용할 수 있도록 by 키워드를 제공한다. 대표적으로 두 가지 사용 방법이 존재한다.

1. Delegated Properties - by 키워드를 활용한 Properties에서의 활용

Kotlin에서는 지연 초기화라는 개념이 존재한다. 대표적으로 lateinit 키워드가 있고, by lazy 키워드가 있는데 이는 다른 게시물에서 살펴보도록 한다.

by lazy 초기화는 호출 시점에 한 번 초기화를 진행하고, 그 이후에는 가져다 쓰기만 한다. by 이후에 오는 lazy에게 프로퍼티 생성을 위임하고, lazy 내부 동작에 따라 코드를 초기화하는 것이다. 즉, by lazy 호출시 lazy에게 위임하여 내부 코드 동작에 따라 delegation 처리를 함께 하는 것이다.

private val viewModel = MainViewModel by lazy {
    MainViewModel()
}
2. Interface/Class delegation - Interface를 class delegation에서의 활용

상속 대신 delegation을 활용한다. by 키워드를 사용한다. 아래와 같은 사용법이 가능하다.

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() {
        print(x)
    }
}

class Derived(base: Base) : Base by base 

fun main() {
    val b = BaseImpl(10)
    Derived(b).print()
}

결론

Delegation Pattern은 상속 대신 Composition을 활용하는 패턴이다.

참고

Effective Java에서는 상속보다는 Composition을 사용하라고 권장하고 있다고 하고, 상속을 고려하여 설계하고 문서화하되 그러지 않았다면 상속을 금지할 것을 권장한다고 한다. 그런데 Kotlin은 클래스를 생성하면 기본적으로 final 이다. 언어 자체가 상속을 기본적으로 금지함으로써 불필요한 상속으로 발생할 수 있는 문제점을 애초에 원천적으로 차단한다. 상속이 필요하다면 open 키워드를 붙여야 한다. 이로써 Kotlin에서 상속의 위험성으로 인해 발생할 수 있는 문제는 해결됐다. 이제, Kotlin by 키워드를 활용하여 Delegation Pattern을 사용하자.

물론, 상속 자체가 위험하므로 반드시 사용하지 말자! 이것은 아니다. 최초에 완성도가 매우 높은 설계 과정을 거쳤다면 상속은 아름다운 도구가 될 것이다. 다만 그렇지 않을 가능성이 높고 시간이 갈수록 개발 규모는 커질 것이며 프로젝트 코드는 점점 많아지며 유지보수가 어려운 코드가 될 가능성이 높다. 선택의 문제이겠으나, 더 좋은 결과를 탄생시킬 수 있는 방법을 선택하도록 한다.

References

[Kotlin] Delegate Pattern 이란? by 키워드 사용하기

위키백과 Delegation pattern

Kotlin Delegation을 알아보고, Delegated Properties와 class에서의 Delegation을 알아본다.

Kotlin Docs

profile
Android Developer

0개의 댓글