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

안드로이드에서의 빌더 패턴(Builder Pattern)

skydovesJaewoong Eum (skydoves)||8분 소요

안드로이드에서의 빌더 패턴(Builder Pattern)

빌더 패턴(Builder Pattern)은 복잡한 객체를 단계별로 생성하기 위해 널리 사용되는 생성 디자인 패턴(creational design pattern)입니다. 여러 개의 생성자를 다양한 매개변수 조합으로 오버로딩하는 대신, 빌더 객체가 메서드 호출을 통해 설정 값을 하나씩 축적한 뒤 최종적으로 build() 한 번의 호출로 완성된 객체를 생성합니다. 이 패턴은 안드로이드 SDK 곳곳에서 활용되고 있으며, 선택적 프로퍼티가 많은 객체를 애플리케이션 코드에서 직접 생성할 때에도 매우 유용합니다. 실무에서는 AlertDialog, Notification, OkHttpClient 등을 구성할 때 자연스럽게 접하게 되므로, 면접에서도 단골로 등장하는 주제입니다.

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

  • 빌더 패턴이 객체의 생성과 표현을 어떻게 분리하는지 설명할 수 있습니다.
  • 안드로이드 SDK에서 빌더 패턴을 사용하는 대표적인 클래스를 식별할 수 있습니다.
  • 코틀린에서 전통적인 방식과 DSL 방식을 모두 활용하여 커스텀 빌더를 구현할 수 있습니다.
  • 코틀린의 언어 기능이 명시적 빌더의 필요성을 어떻게 줄여 주는지 설명할 수 있습니다.
  • 빌더 패턴과 기본값이 있는 네임드 인자(named arguments with defaults) 중 어떤 방식이 더 적합한지 판단할 수 있습니다.
  • 빌더의 build() 메서드에서 유효성 검증을 적용하여 생성 불변조건(construction invariants)을 보장하는 방법을 이해할 수 있습니다.

빌더 패턴의 동작 원리

빌더 패턴은 두 가지 역할로 구성됩니다. 빌더(Builder) 클래스는 개별 프로퍼티를 설정하는 setter 메서드를 노출하며, 각 호출에서 자기 자신을 반환하여 메서드 체이닝(method chaining)을 지원합니다. build() 메서드는 생성 과정을 마무리하고 완성된 대상 객체를 반환합니다. 대상 클래스의 생성자는 일반적으로 private으로 선언하여, 오직 빌더를 통해서만 인스턴스를 생성할 수 있도록 제한합니다.

빌더 패턴은 GoF(Gang of Four) 카탈로그에 정의된 생성 패턴 계열에 속합니다. 생성되는 구체적인 타입을 숨기는 팩토리 메서드 패턴과 달리, 빌더 패턴은 선택적 필드가 많거나 다단계 초기화가 필요한 객체의 생성 과정 자체를 단순화하는 데 초점을 맞추고 있습니다. 면접에서 빌더 패턴을 설명하실 때 이 차이점을 함께 언급하시면 디자인 패턴에 대한 깊은 이해를 보여줄 수 있습니다.

이러한 분리가 중요한 이유는 클래스에 선택적 매개변수가 여러 개 존재하는 경우에 잘 드러납니다. 빌더가 없다면 텔레스코핑 생성자(telescoping constructor, 매개변수를 하나씩 추가하는 생성자 체인)를 만들거나, 많은 nullable 기본값을 가진 단일 생성자를 사용해야 합니다. 텔레스코핑 생성자는 호출자가 레이블 없이 위치 기반 인자를 전달해야 하므로 가독성이 떨어집니다. 코틀린에서는 네임드 인자 덕분에 기본값이 있는 단일 생성자도 잘 동작하지만, 빌더 패턴에는 한 가지 추가적인 이점이 있습니다. 바로 build() 호출 시점까지 유효성 검증을 지연시킬 수 있다는 것입니다. 이를 통해 객체가 생성되기 전에 완전히 설정되었음을 보장할 수 있으며, 호출 지점에서 의도가 명확해지고 우발적인 설정 오류를 방지할 수 있습니다.

안드로이드 SDK에서의 빌더 패턴

안드로이드에서는 여러 핵심 API에서 빌더 방식을 채택하고 있습니다. AlertDialog.Builder는 제목, 메시지, 버튼, 콜백을 설정한 후 create()를 호출하여 다이얼로그를 생성합니다.

val dialog = AlertDialog.Builder(context)
    .setTitle("Confirmation")
    .setMessage("Are you sure?")
    .setPositiveButton("Yes") { d, _ -> d.dismiss() }
    .setNegativeButton("No") { d, _ -> d.dismiss() }
    .create()
dialog.show()

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

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

구독하기