면접 질문실전 질문꼬리 질문

코틀린의 팩토리 패턴 (Factory Pattern)

skydovesJaewoong Eum (skydoves)||7분 소요

코틀린의 팩토리 패턴 (Factory Pattern)

팩토리 패턴(Factory Pattern)은 객체 생성을 전담 메서드나 클래스에 위임하는 생성 디자인 패턴(creational design pattern)입니다. 생성자를 직접 호출하는 대신 팩토리 메서드를 통해 객체를 만들기 때문에, 클라이언트 코드가 구체적인 구현체에 의존하지 않게 됩니다. 코틀린에서는 companion object 팩토리 메서드, sealed class 계층 구조, 최상위(top-level) 팩토리 함수 등 언어 특성을 활용한 관용적인 형태로 구현할 수 있습니다. 이러한 팩토리 패턴을 적절히 활용하면 기존 소비 코드를 수정하지 않고도 새로운 타입을 쉽게 추가할 수 있어 유지보수성이 크게 향상됩니다.

이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.

  • 팩토리 패턴의 목적과, 직접 생성자를 호출하는 방식과의 차이점을 설명할 수 있습니다.
  • 코틀린의 companion objectsealed class를 활용하여 팩토리 메서드를 구현할 수 있습니다.
  • 추상 팩토리(Abstract Factory) 패턴을 적용하여 연관된 객체 그룹을 생성할 수 있습니다.
  • 팩토리 패턴이 실질적으로 도움이 되는 상황과, 직접 생성이 더 간결한 상황을 판단할 수 있습니다.

Companion Object를 활용한 팩토리 메서드

코틀린의 companion object는 팩토리 메서드를 배치하기에 가장 자연스러운 위치입니다. Java에서는 정적(static) 팩토리 메서드를 클래스에 직접 선언하지만, 코틀린에서는 companion object를 활용합니다. companion object는 인터페이스를 구현하거나 상태를 보유할 수 있다는 점에서 Java의 정적 메서드보다 훨씬 유연합니다. invoke 연산자를 오버로드하거나 create(), from() 같은 명명된 팩토리 메서드를 정의하는 것이 일반적인 패턴입니다.

interface Logger {
    fun log(message: String)
}

class ConsoleLogger private constructor() : Logger {
    override fun log(message: String) {
        println("[CONSOLE] $message")
    }

    companion object {
        // 팩토리 메서드를 통해서만 인스턴스 생성 가능
        fun create(): Logger = ConsoleLogger()
    }
}

class FileLogger private constructor(
    private val path: String
) : Logger {
    override fun log(message: String) {
        File(path).appendText("$message\n")
    }

    companion object {
        // 파일 경로를 받아 FileLogger 인스턴스 생성
        fun create(path: String): Logger = FileLogger(path)
    }
}

위 코드에서 생성자는 private으로 선언되어 있으므로, 인스턴스를 얻으려면 반드시 팩토리 메서드를 거쳐야 합니다. 덕분에 각 클래스가 내부적으로 인자 유효성 검증, 인스턴스 캐싱, 서브타입 반환 등의 로직을 수행할 수 있으며, 호출 측에서는 이러한 내부 결정을 전혀 알 필요가 없습니다. 면접에서 이 부분을 설명하실 때는 "생성자를 외부에 노출하지 않음으로써 객체 생성 과정을 캡슐화할 수 있다"는 점을 강조하시면 좋습니다.

Sealed Class 계층 구조를 활용한 팩토리

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기