iOS & Swift

Swift 빌더 패턴(Builder Pattern)으로 매개변수 8개 초기화 지옥 탈출하기

Swift로 앱을 만들다 보면 어느 순간 초기화 코드가 이렇게 변해 있습니다.

이석우iOS Developer5분 읽기
Swift 빌더 패턴(Builder Pattern)으로 매개변수 8개 초기화 지옥 탈출하기 대표 이미지

Swift로 앱을 만들다 보면 어느 순간 초기화 코드가 이렇게 변해 있습니다.

User(name:age:email:phone:address:isVerified:profileURL:createdAt:)

괄호 안에 매개변수가 여덟 개.

호출하는 쪽 코드를 보면 어떤 값이 email이고 어떤 게 phone인지 눈으로 하나씩 세게 되죠.

사이드 프로젝트에서도 흔히 만나는 상황인데, Swift 빌더 패턴으로 정리하면 깔끔하게 풀립니다.

결론부터 말하면, 매개변수가 많은 초기화는 빌더 패턴으로 “한 줄에 하나씩” 설정하도록 바꾸면 훨씬 읽기 쉬워집니다. 순서를 외울 필요도, 안 쓰는 값에 nil을 억지로 채워 넣을 필요도 없어지거든요.

Swift 빌더 패턴 쓰기 전과 후, 초기화 코드가 이렇게 갈립니다
Swift 빌더 패턴 쓰기 전과 후, 초기화 코드가 이렇게 갈립니다

오늘 이 글에서 얻어가실 내용을 먼저 정리해둘게요.

  1. 매개변수 8개짜리 init이 왜 실수를 부르는지
  2. 빌더 패턴이 이걸 어떻게 해결하는지
  3. Swift에서 실제로 쓰는 코드 형태
  4. 이 패턴을 언제 쓰고 언제 피해야 하는지

매개변수 8개짜리 init, 왜 지옥일까?

매개변수가 서너 개일 때는 사실 별문제가 없어요.

문제는 개수가 늘어나면서 시작됩니다.

첫째, 순서 실수가 납니다. email 자리에 phone을 넣어도 둘 다 String이면 컴파일러가 안 잡아줘요.

둘째, 선택값 처리가 지저분해집니다. 지금 당장 안 쓰는 값까지 nil, nil, nil로 채워야 하죠.

셋째, 호출부가 길어져서 무슨 객체를 만드는 건지 한눈에 안 들어옵니다.

매개변수가 많을수록 init은 “채워야 할 빈칸 시험지”가 되고, 빈칸이 많아질수록 실수도 같이 늘어납니다.

phone과 profileURL 자리를 바꿔 넣는 버그는 하루 넘게 잡아먹기도 합니다. 타입이 같으면 이런 실수는 정말 티가 안 납니다.


빌더 패턴이 뭔가요?

빌더 패턴은 복잡한 객체를 한 번에 만들지 않고, 값을 하나씩 채워 넣은 다음 마지막에 완성하는 방식이에요.

초기화 시점에 모든 값을 넘기는 대신, 필요한 값만 골라서 설정하고 build() 같은 메서드로 최종 객체를 받는 구조라고 보시면 됩니다.

식당에서 주문할 때를 떠올리면 쉬워요. 재료를 한꺼번에 외쳐 부르는 게 아니라, “빵은 통밀, 치즈는 추가, 소스는 빼고” 이렇게 항목별로 말하는 거죠.

핵심 값을 설정하는 메서드가 자기 자신을 돌려주면, 점을 이어 붙이듯 체이닝으로 쓸 수 있습니다. 아래는 가장 단순한 형태의 빌더예요.

final class UserBuilder {
    private var name = ""
    private var email: String?
    // 값을 설정하고 self를 반환해 체이닝을 가능하게 함
    func setName(_ v: String) -> Self { name = v; return self }
    func setEmail(_ v: String) -> Self { email = v; return self }
    func build() -> User { User(name: name, email: email) }
}

설정 메서드가 Self를 반환하니까 .setName(...).setEmail(...)처럼 이어 붙일 수 있습니다.

체이닝 호출이 실제로는 이렇게 흘러가요
체이닝 호출이 실제로는 이렇게 흘러가요
빌더 하나 붙여놓고 커피 마시면서 정리했더니 마음이 편하더라고요
빌더 하나 붙여놓고 커피 마시면서 정리했더니 마음이 편하더라고요

Swift에서 빌더 패턴 어떻게 쓰나요?

실제 호출부가 어떻게 달라지는지가 제일 궁금하실 텐데요.

앞에서 만든 빌더를 쓰면 객체 생성 코드가 이렇게 바뀝니다.

// 필요한 값만, 이름표를 붙여 순서 걱정 없이 설정
let user = UserBuilder()
    .setName("이석우")
    .setEmail("hello@example.com")
    .build()
// 안 쓰는 값에 nil을 채워 넣지 않아도 됨

보시면 순서를 신경 쓸 일이 없어요. 메서드 이름이 곧 이름표라서 email 자리에 phone을 넣는 실수가 구조적으로 막힙니다.

안 쓰는 값은 그냥 호출하지 않으면 그만이고요.

Swift에서는 클래스 대신 구조체(struct)로 빌더를 만들기도 하고, 클로저를 넘겨 한 블록 안에서 설정하는 방식도 많이 씁니다. 프로젝트 스타일에 맞춰 고르시면 됩니다.

이름표 붙은 메서드로 이어 쓰니 순서 걱정이 사라졌어요
이름표 붙은 메서드로 이어 쓰니 순서 걱정이 사라졌어요

빌더 패턴, 언제 쓰고 언제 피할까

좋아 보인다고 모든 곳에 넣으면 오히려 코드만 늘어납니다.

제 기준을 표로 정리해봤어요 (2026년 기준 제 개인 프로젝트 경험).

상황 추천
매개변수 5개 이상, 선택값 많음 빌더 패턴
같은 타입 매개변수가 여러 개 빌더 패턴
매개변수 2~3개, 전부 필수 일반 init
값이 단순하고 고정적 일반 init

정리하면, 매개변수가 적고 전부 필수면 굳이 빌더를 만들 이유가 없습니다.

반대로 선택값이 뒤섞인 큰 객체라면 빌더 쪽이 확실히 편해요.

Q. 빌더를 만들면 코드가 더 늘어나지 않나요?

맞아요. 빌더 클래스 자체는 코드가 늘어납니다. 대신 그 객체를 만드는 호출부가 여러 군데라면, 호출부가 깔끔해지는 이득이 더 큽니다.

Q. Swift에는 기본값 매개변수가 있는데 그걸로 안 되나요?

매개변수가 서너 개면 기본값(default parameter)만으로 충분합니다. 개수가 많고 조합이 다양할 때 빌더의 장점이 살아나요.


매개변수 8개짜리 init 때문에 스트레스받고 계셨다면, 딱 그 지점에만 빌더 패턴을 한번 적용해보세요. 전부 갈아엎을 필요 없이 제일 복잡한 객체 하나부터 시작하면 부담이 적습니다. 오늘도 즐거운 코딩 되세요!

함께 보면 좋은 글