본문 바로가기

Swift

[Swift] static을 언제 쓰는데?

728x90

Swift는 method와 property에 static 접두사를 사용해서 인스턴스가 아닌 타입(선언된 타입)과 연결할 수 있도록 한다.

 

Static Property

static property의 가장 일반적인 사용 사례는 환경 설정(Configuration)이다.

static 키워드를 사용해서 설정(색상, 폰트)들을 관리하는 이유는 namespace(함수, 변수 등과 같은 내부 식별자에 범위를 제공하는 선언적 영역, 유효 범위를 제공하는 영역)를 제공하기 때문이다. 

 

일반적인 예시는 스타일 가이드로 사용하는 것이다.

만약 특정 색상이나 글꼴을 변경하고 싶을 때 프로젝트를 모두 뜯어봐야 한다면 비효율적이고 정확하지 않을 것이다. (빠지는 부분들이 있기 때문에)

 

따라서, 코드 전체에 값을 분산시키는 것보다 한 곳에서 색상, 글꼴 폰트 및 크기 등을 정의하는 것이 좋다.

 

enum AppStyles {
  enum Colors {
    static let mainColor = UIColor(red: 1, green: 0.2, blue: 0.2, alpha: 1)
    static let darkAccent = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
  }
  enum FontSizes {
    static let small: CGFloat = 12
    static let medium: CGFloat = 14
    static let large: CGFloat = 18
    static let xlarge: CGFloat = 21
  }
}

위와 같이 한 곳에서 관리할 경우, 메인 컬러를 수정해야 하는 상황에서 한 부분만 변경하면 된다.

 

(위의 코드에서 열거형을 통해서 static property를 사용한 이유는 설정 객체를 인스턴스로 만들지 못하도록 하기 위함이다.

구조체에서 private initializer를 사용해도 똑같이 동작하지만, 열거형은 initializer를 갖고 있지 않기 때문에 보다 적합한 방법이라고 할 수 있다.)

 

static property를 통해서 앱에서 사용되는 제한된 문자열 집합을 정의할 수 있고

(ex, UserDefaults의 키 값, Notification Center를 통해 전송되는 알림의 이름 등 .. )

앱 전체에서 일정하게 유지되어야 하는 전역 설정을 configuration object를 전달할 필요 없이 사용할 수 있다. 

 


static property의 또 다른 용도는 그것들을 캐시로 사용할 수 있다는 것이다. 특정 object를 생성하는 것은 많은 비용이 들 수 있다. 

 

예를 들면, dateformatter가 있다.

(글에서는 값 비싼 객체의 좋은 예시로 dateformatter가 있다고 표현)

 

struct Blogpost {
  private static var dateFormatter = ISO8601DateFormatter()

  let publishDate: Date?
  // other properties ...

  init(_ publishDateString: String /* other properties */) {
    self.publishDate = Blogpost.dateFormatter.date(from: publishDateString)
  }
}

Blogpost 인스턴스를 얼마나 만드는 것과 상관없이 string을 변환하는 dateFormatter는 언제나 ISO8601DateFormatter 가 된다.

 

만약, dateFormatter를 static으로 선언하여 type과 연관시키지 않고 인스턴스와 연관시켰다면, (아무런 키워드 없이 작성)

Blogpost 인스턴스가 생성될 때마다 dateFormatter도 같이 생성하게 된다.

 

같은 역할을 하는 dateFormatter에 대해서 인스턴스가 생기는 것과 함께 중복적으로 만들어지는 것은 낭비적인 일이다. 

 

따라서 생성하는데 비용이 많이 들면서 안전하게 재사용 될 수 있는 object에 대해서는 정적으로 정의하는 것이 좋다. 

그러면 한번만 생성하고 사용할 수 있다.

 

 


Static Method

프로그래밍에서 일반적인 패턴은 팩토리 패턴이다. 

 

factory는 대상 object의 초기화에 대한 특정 세부사항을 숨기면서도 간단하게 object를 만들 수 있다.

 

enum BlogpostFactory {
  static func create(withTitle title: String, body: String) -> Blogpost {
    let metadata = Metadata(/* metadata properties */)
    return Blogpost(title: title, body: body, createdAt: Date(), metadata: metadata)
  }
}

위와 같이 코드를 작성했다면,

BlogpostFactory를 통해 Blogpost의 새로운 인스턴스를 간단하게 만들 수 있다는 것이다.

 

class method와 static method의 차이

하위 클래스(상속 받은 클래스)가 클래스 메서드를 재정의 할 수 있다는 점이 주된 차이점이다.

 

class SomeClass {
  class func date(from string: String) -> Date {
    return ISO8601DateFormatter().date(from: string)!
  }
}
class SubClass: SomeClass {
  override class func date(from string: String) -> Date {
    return DateFormatter().date(from: string)!
  }
}

위와 같인 date함수에 대해서 하위 클래스가 재정의 하는 경우, 이러한 작업은 class method에서만 가능하고 static method에서는 불가능하다. 

 


즉, static 키워드를 통해서 

✅ 설정을 관리하거나 

✅ 비싼 object에 static property를 사용해서 보다 효율적으로 코드를 작성할 수 있다는 것과

✅ 간단한 factory 패턴을 구현할 수 있다는 것을 알 수 있다.

 

'Swift' 카테고리의 다른 글

[Swift] 싱글톤 패턴에서 구조체와 클래스의 차이  (0) 2022.10.13
[Swift] Anti Pattern이 뭐고?  (0) 2022.10.13
[Swift] class func VS static func  (0) 2022.10.12
URLSession (개념)  (0) 2022.09.01
Codable  (0) 2022.08.31