[스터디] 초기화

팔랑이·2025년 2월 9일
0

iOS/Swift

목록 보기
66/71
post-thumbnail

서론

이번 주부터 한 가지 주제를 깊이 공부하고, 토론하는 시간을 갖기로 했다.
첫 번째 주제는 초기화.

초기화란 단순히 변수를 0으로 만드는 것이 아니라, 변수를 선언하고 처음으로 값을 할당하는 과정을 의미한다.

처음엔 저 말이 굉장히 받아들이기 힘들었다... '초기화' 또는 initialize 라는 단어와 저 의미가 개인적으로 매칭이 굉장히 안 됐음...

저 말뜻은 이제 이해는 했는데, 변수에 Default Value를 줘서 직접 초기화 하는 것과 init 생성자에서 초기화하는 것의 차이와 장단점이 궁금해졌다.

본론

Swift에서 클래스를 사용할 때 변수 초기화 방법에는 Default Value를 주는 것생성자(init) 사용 두 가지 방식이 있다.

여러 예시를 통해 차이점을 알아보자.

1) 네트워크 연결 (URLSession)

생성자로 초기화

class NetworkManager {
    let session: URLSession
    let baseURL: String
    
    init(session: URLSession = .shared, baseURL: String) {
        self.session = session
        self.baseURL = baseURL
    }

    func fetchData(endpoint: String, completion: @escaping (Data?) -> Void) {
        guard let url = URL(string: "\(baseURL)\(endpoint)") else { return }
        let task = session.dataTask(with: url) { data, _, _ in
            completion(data)
        }
        task.resume()
    }
}

Default Value로 초기화

class NetworkManager {
    let session = URLSession.shared
    let baseURL = "https://api.example.com"

    func fetchData(endpoint: String, completion: @escaping (Data?) -> Void) {
        guard let url = URL(string: "\(baseURL)\(endpoint)") else { return }
        let task = session.dataTask(with: url) { data, _, _ in
            completion(data)
        }
        task.resume()
    }
}

차이점

init을 사용하면 baseURL을 동적으로 설정할 수 있으며, URLSession을 외부에서 주입할 수 있어 유닛 테스트가 가능하다.
반면, 직접 초기화한 경우 baseURL이 고정되어 있어 변경할 수 없으며, session을 외부에서 조작하기 어려워 테스트가 힘들다.


2) 사용자 세션 관리

생성자로 초기화

class UserSession {
    let userID: String
    var isLoggedIn: Bool
    
    init(userID: String, isLoggedIn: Bool = false) {
        self.userID = userID
        self.isLoggedIn = isLoggedIn
    }
    
    func login() {
        self.isLoggedIn = true
    }
    
    func logout() {
        self.isLoggedIn = false
    }
}

Default Value로 초기화

class UserSession {
    var userID = "guest"
    var isLoggedIn = false
    
    func login() {
        self.isLoggedIn = true
    }
    
    func logout() {
        self.isLoggedIn = false
    }
}

차이점

init을 사용하면 여러 개의 UserSession 객체를 만들 때 각각 다른 userID를 가질 수 있다.
직접 초기화한 경우 userID가 "guest"로 고정되어 있어, 개별 유저별 세션을 관리하기 어렵다.


3) UIViewController 초기화

생성자로 초기화

class LoginViewController: UIViewController {
    let username: String
    
    init(username: String) {
        self.username = username
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("\(username) 님, 로그인 화면입니다!")
    }
}

Default Value로 초기화

class LoginViewController: UIViewController {
    var username = "Guest"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("\(username) 님, 로그인 화면입니다!")
    }
}

차이점

init을 사용하면 LoginViewController(username: "John")과 같이 사용자 이름을 설정할 수 있다.
반면, 직접 초기화한 경우 username이 "Guest"로 고정되어 있어 모든 화면에서 같은 이름을 사용하게 된다.


결론

위 예시들을 보면 생성자를 사용하지 않고 초기화했을 때의 공통적인 문제점을 발견할 수 있다.

  • 객체를 생성할 때 원하는 파라미터를 사용해 바로 설정하기 어려움
  • 객체가 동적으로 변해야 할 때 관리가 어려움
  • 테스팅, 유지보수가 어려워짐

물론 다음과 같이 추가적인 setter 메서드를 사용하면 변경할 수 있지만, 코드가 더 복잡해지고 유지보수성도 떨어진다.

class NetworkManager {
    var baseURL = "https://api.example.com"

    func updateBaseURL(newURL: String) {
        self.baseURL = newURL
    }
}

이렇게 하면 updateBaseURL(newURL:)을 호출해서 변경할 수 있긴 하지만,

  • 객체를 생성한 이후에 별도로 메서드를 호출해야 한다.
  • 객체가 사용되기 전에 URL이 변경되지 않으면, 예상치 못한 URL로 요청이 갈 수 있다.
  • 객체를 생성하는 코드와 설정하는 코드가 분리되어 가독성이 떨어질 수 있다.

짜바리 표

init 사용직접 초기화
객체마다 다른 값 설정 가능?가능불가능
유닛 테스트 가능?가능(의존성 주입)어려움
상속 시 초기화 순서 조절 가능?가능(super.init())불가능
변경 가능한 기본값 제공 가능?가능(기본 매개변수)어려움
초기화 로직 추가 가능?가능불가능
profile
정체되지 않는 성장

0개의 댓글