- Q. Swift의 접근제어자(Access Control)는 어떤게 있나요?
- Q. defer 구문이 무엇인가요?
- Q. Struct와 Class의 차이는 무엇이고 어떤 때에 사용하나요?
- Q. Optional은 무엇이고, 왜 사용하나요?
- Q. method vs static method vs class method
- Q. 상속(inheritance)과 확장(extension)의 차이는 무엇일까요?
- Q. swift의 고차함수에는 무엇이 있나요?
- Q. Array, Dictionary, Set을 차이점에 기반하여 설명해 주세요.
안녕하세요! caution입니다. 오늘은 Swift 관련 면접 질문과 답을 대략적으로 정리해보고자 합니다. 간략하게 Q - A 정도로 작성할게요!
Q. Swift의 접근제어자(Access Control)는 어떤게 있나요?
키워드 | 범위 |
---|---|
open | 모듈 외부에서도 접근 가능 |
public | 모듈 외부에서도 접근 가능 |
internal | 하나의 모듈 내부에서 접근 가능 |
fileprivate | 하나의 파일 내에서 접근 가능 |
private | 정의 블록 내부에서 접근 가능 |
open과 public의 차이
open
접근 수준을 가지는 클래스만이 모듈 밖의 다른 모듈에서 상속하고 멤버를 override할 수 있습니다.
외부 프레임워크에서 모듈로 클래스를 가져와서써야되는데 접근제어자를 뭘 써야하나요?
가져올 수 있는 접근제어자에는 open과 public이 있습니다. 필요한 범위에 따라 불러오는 블록의 접근제어자를 지정해주면 됩니다. 단 public 으로 선언된 클래스 내부에서 open을 멤버로 선언할 수는 없습니다.
정리
- 바깥 요소의 접근제어 수준보다 높은 수준의 내부 요소는 있을 수 없다.
- 특정 접근제어 수준의 타입이 함수의 매개변수나 반환되는 타입일 경우 함수는 해당 값의 접근제어보다 높을 수 없다.
Q. defer 구문이 무엇인가요?
선언된 블럭의 코드 동작이 모두 수행되고 난 다음 블럭을 빠져나가기 전 마지막으로 불리는 영역입니다.
- defer 구문을 여러 개 선언하게 되면 선언된 역순으로 호출됩니다.
- 중첩해서 사용하면 바깥쪽 구문을 완료하고 내부의 defer 구문을 호출합니다.
func sample() {
defer {
print("1 start")
defer {
print("1-1 start")
defer { print("1-1-1") }
defer { print("1-1-2") }
print("1-1 end")
}
print("1 end")
}
defer {
print("2 start")
defer { print("2-1") }
defer { print("2-2") }
print("2 end")
}
}
sample()
Q. Struct와 Class의 차이는 무엇이고 어떤 때에 사용하나요?
- struct는 값 타입, class는 참조 타입입니다.
- Reference Count를 높이지 않고, init/deinit 시 RC를 세지 않는다는 점. 즉 RC를 세는것도 하나의 작업이니깐 이 작업을 안하기 때문에 class에 비해 빠르다.
- 값 타입은 멀티스레딩에 안전하다.
- class보다 struct가 접근과 사용이 빠릅니다.
- struct는 Stack에, class는 Heap 영역에 저장됩니다.
- Stack 메모리 영역은 프로그램이 실행될 때 미리 영역을 확보해놓기 때문에 빈 공간을 확보할 필요 없이 데이터를 저장할 수 있습니다.
- 반면 Heap 영역은 필요할 때마다 동적으로 메모리를 할당해야하기 때문에 새로 들어올 데이터가 들어갈 수 있는 빈 공간이 있는지 탐색하고 없다면 공간을 할당해야한다.
- 하지만 인스턴스의 규모가 크면 struct보다는 class를 지향합니다.
- struct는 값 복사가 일어나기 때문에 데이터 양이 많다면 시간이 오래걸리기 때문입니다. 그에 비해 class는 참조 메모리 주소값만 복사하면 되서 다소 빠릅니다.
- struct는 상속을 받을 수 없지만 protocol은 채택가능하다.
Array와 Dictionary는 값 타입? 참조 타입?
Swift의 String과 Array, Set 등은 값 타입으로 되어있지만 내부는 참조 타입으로 되어있습니다. 그렇기 때문에 많은 양의 문자열을 복사해도 그 속도가 매우 빠릅니다.
Copy-on-write : 실제로 데이터가 수정(write)될 때 새로 메모리를 할당합니다. 값 타입 생성 속도 저하를 보완합니다.
Q. Optional은 무엇이고, 왜 사용하나요?
Optional은 nil을 넣을 수 있는 타입입니다.
Swift는 안정성을 매우 중요시합니다. Optional을 사용하면 개발자가 놓칠 수 있는 부분을 보완할 수 있습니다. 특정 변수가 nil로 변환될 가능성이 있다면 Optional을 사용해서 옵셔널 바인딩을 통해 nil
case를 처리할 수 있습니다.
Q. method vs static method vs class method
method는 class, struct, enum 등에 포함되어 있는 function을 말합니다. 우리가 일반적으로 말하는 class의 method에도 여러 종류가 있습니다.
class SuperClass {
func instanceMehtod() {}
static func staticMethod() {}
class func classMethod() {}
}
class SubClass: SuperClass {
override func staticMethod() {}
override class func classMethod() {}
}
- instance method : class나 struct의 인스턴스를 통해서만 접근 가능한 method
- static method : 인스턴스 없이 직접 Class.Method 로 접근 가능한 method
- class method : static method와 동일하게 인스턴스 없이 접근 가능한 method이지만, class에서만 사용할 수 있으며 struct와 enum에서는 선언할 수 없습니다. 또한 static method와 달리 override가 가능합니다.
- protocol에서 class func 을 정의했다면 해당 프로토콜은 class만 채택가능하겠죠?
Q. 상속(inheritance)과 확장(extension)의 차이는 무엇일까요?
상속은 Swift에서 클래스를 다른 타입과 차별화 하는 기본 동작으로, 상속하는 클래스를 하위클래스, 상속 받은 클래스를 슈퍼클래스라고 합니다. 하위클래스는 슈퍼클래스에 속한 메소드, 프로퍼티 및 하위 스크립트들을 호출하고 접근할 수 있으며, 이를 재정의할 수 있습니다.
확장은 class, struct, enum 모두 사용할 수 있습니다. final로 선언된 class의 경우 상속이 불가능하지만 extension은 가능합니다. 상속은 수직계층적으로 범위를 넓히는 거라면 extension은 수평적으로 범위를 넓힌다고 볼 수 있습니다.
Q. swift의 고차함수에는 무엇이 있나요?
고차함수(Higher-order function)은 ‘다른 함수를 전달인자로 받거나 함수실행의 결과를 함수로 반환하는 함수’를 뜻합니다.
스위프트의 함수(클로저)는 일급시민이기 때문에 함수의 전달인자로 전달할 수 있으며, 함수의 결과값으로 반환할 수 있습니다.
map, filter, reduce
map함수는 컨테이너 내부의 기존 데이터를 변형(transform)하여 새로운 컨테이너를 생성합니다. filter함수는 컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출합니다. reduce함수는 컨테이너 내부의 콘텐츠를 하나로 통합합니다.
Q. Array, Dictionary, Set을 차이점에 기반하여 설명해 주세요.
세 개 모두 Swift에서 제공하는 컬렉션 타입입니다. Generic으로 특정 타입에 대한 컬렉션을 만들게 됩니다. Array는 순서가 있고 Dictionary와 Set은 순서가 없으며, Dictionary는 Hash 키-값을 연결한 Hash Table이고 Set은 중복값을 허용하지 않습니다. 중복값을 허용하지 않기 위해서 Set에 들어갈 수 있는 값들은 Hashable 자료형입니다.
Hash Table에서 Hash는 왜 사용하나요? Hash 함수의 성능이 떨어진다면 어떤 문제가 발생할 수 있나요?
Hash를 사용하는 이유는 데이터를 접근할 때 O(1)으로 한 번에 접근하기 위해서입니다. 이 Hash 값을 만들어 내는 함수를 Hash 함수라고 하는데 이 함수는 같은 입력값에는 같은 출력값을 나타내고, 출력값으로는 입력값을 유추할 수 없는 특징을 가집니다. 하지만 Hash 함수를 사용하더라도 충돌이 발생하게 됩니다. 서로 다른 입력값에 같은 키를 만들어 내게 된다면 어떻게 될까요? 해시 테이블에서는 키에 해당하는 공간을 연결 리스트로 만들어 넣게 됩니다. 만약 최악의 경우 이렇게 항목들이 연결 리스트로 들어가 있다면 데이터를 가져오기 위해 O(n)의 시간이 걸리게 됩니다.
case | Hash Table 평균 | Hash Table 최악 | 배열 | Linked List |
---|---|---|---|---|
탐색 | O(1) | O(n) | O(1) | O(n) |
삽입 | O(1) | O(n) | O(n) | O(1) |
삭제 | O(1) | O(n) | O(n) | O(1) |