Swift 기본 타입
낯선 언어를 매일 학습하며 몰입과 성장을 기록하는 일지
· 7 min read
오늘의 포커스 #
- Swift 공식 문서 중 Type에 대한 이해
The Baiscs #
Naming constatns and Variables #
- 유니코드 문자를 포함한 거의 대부분의 문자가 변수 또는 상수의 이름이 될 수 있음
- 다만 이름에 공백, 수학 기호, 화살표, 사적 유니코드 스칼라 값, 선, 박스 문자는 허용되지 않는다.
- 숫자는 허용되나 시작을 숫자로 할 수는 없다.
- 동일이름, 동일타입으로는 중복 변수 또는 상수를 만들 수 없음
- 또한 변수를 상수로, 상수를 변수로 변경 불가
- 다른 언어와 다르게 스위프트의 예약어를 이름으로 쓰고 싶다면 backticks으로 감싸서 사용해야 한다.
- 하지만 스위프트의 키워드의 경우 예외 없이 사용 불가
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!
Printing Constants and Variables #
- 상수 또는 변수를
print(\_:separator:terminator:)함수로 출력 가능
print(friendlyWelcome)
// prints Bojour
print(\_:separator:terminator:)함수- 전역 함수
- 하나 또는 많은 값들을 적절한 결과로 출랴
separator와terminator인자는 기본값이 존재, 생략 가능terminator의 기본값은 line break- 다른 값을 너어주고 싶으면 해당 인자에 원하는 값을 넣어줄 수 있음
- 문자열 보간(interpolation)을 사용 가능
- interpolation: 긴 문자열의 경우 placeholder에 변수명을 집어 넣어 해당 변수의 값을 문자열 안에 바꾸어 넣는 기능
print("The current value of friendlyWelcome is \(friendlyWelcome)")
Comments #
- Comments는 C, C++, Java와 상동
Semicolosn #
- 다른 언어와 달리 스위프트는 세미콜론을 각 statement 뒤에 붙일 필요가 없음
- 다만 원한다면 사용할 수 있음
- 다중 statement를 한 줄로 쓸 때는 semicolon으로 statement를 구분시켜야함
Integers #
- Integer의 경우 비트 수의 크기를 선택 가능
- unsigned는 앞에 U를 붙여 표현 가능
- UInt8, Int32, Int8
- Swift는 추가적으로 뒤에 숫자가 없는 Int 타입을 제공
- Int 타입은 플랫폼의 native word size에 따라 Int 타입의 크기를 결정
- Int는 32 비트 플랫폼에서는 Int32, 64 비트 플랫폼에서는 Int64가 자동 선택
- UInt도 마찬가지로 적용됨
Floating-Point Numbers #
- 특정 사이즈의 floating-point Numbers가 필요하지 않다면
Double타입을 사용 - 특정 크기는 Float32, Float64처럼 Float 뒤 크기를 지정 가능
- 다만 그래픽 코드의 경우 빠른 GPU 처리에 적합한 Float를 사용
Type Safety And Type Inference #
Numeric Literals #
- 기본은 10진수
- 0b 접두사는 2진수
- 0o 접두사는 8진수
- 0x 접두사는 16진수
- e접두사는 10의 승수를 의미
- p는 2의 승수를 의미
- 가독성을 위해 패딩 또는 언더 대시를 넣을 수 있음
let paddedDouble = 00123.456let oneMillion = 1_000_000let justOverOneMillion = 1_000_000.000_000_1
Numeric Type Conversion #
- Type(variable) 또는 Type(value)의 형태로 타입 변환 가능
- Floating point numbers에서 Integer로의 Conversion은 내림 연산
- Int(-3.9) = -3
Type Aliases #
typealias키워드를 이용해서 type aliases를 선언typealias AudioSample = UInt16- 문맥적으로 더욱 적절한 타입명을 붙여줄 수 있음
Booleans #
- Boolean은 논리값을 가짐
true,false
- 조건문에서 사용 가능
if turnipsAreDelicious {
print("Mmm, tasty tunips!")
} else {
print("Eww, turnips are horrible.")
}
- Swift의 타입 안정성은 다른 타입을 Bool 타입 대신하여 쓸 수 없도록 함
while(1)과 같은 코드 불가
Tuples #
- 튜플은 여러개의 값을 하나의 단일 값으로 묶는 타입
- 튜플 안의 값은 어떤 타입이나 들어 올 수 있고, 다른 값들의 타입들이 동일할 필요도 없음
(404, "Not Found")는 튜플로 생성된 HTTP Status Code- Int와 String을 하나의 튜플로 묶음
- 사용 하지 않을 값에 대해서는 언더스코어(_)를 통해 해당 부분을 무시할 수 있음
let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
print("The status code is \(justTheStatusCode.0)")
print("The status message is \(justTheStatusCode.1)")
- 또한 선언 시 각각의 튜플 요소들에 이름을 지을 수 있음
let http200Status = (statusCode: 200, description: "OK")
- 튜플은 함수의 값을 리턴할 때 매우 유용
- 예제와 같은 웹 페이지 탐색을 시도하는 함수의 경우 (Int, String) 튜플 타입을 페이지 탐색의 성공 또는 실패를 표현하기 위해 리턴하기 때문
- 다만 복잡하게 연관된 값들을 묶기에는 적절하지 않음
- 복잡한 구조의 경우
class또는srtructure를 고려해야 함
Options #
- 값이 없을 수도 있는 상황에서 사용
- optional은 2가지를 의미
- 값이 특정 타입이어서 해당 값에 접근하기 위해 optioanl은 unwrap
- 값이 아예 없는 경우
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is "Optional Int"
- 하지만 이 코드는 실패, possibleNumber가 Optional로 선언되지 않았기 때문
- Optional 타입은 optional을 포함하고 있는 타입의 변수명 뒤에
?를 붙여야함
nil #
- 값없음 상태는 특별한 값인 nil을 할당하여 optional value에 설정
var serverResponseCode: Int? = 404
serverResponseCode = nil
- 처음 Optional 타입 선언 시 값을 정해주지 않으면 기본값으로 nil이 들어감
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
nil과의 비교 조건문을 통해 해당 optional variable이 값을 가지고 있는지 확인- non optional type에서는
nil을 사용 불가
Optional Binding #
- optional 타입이 값을 가지고 있는지 확인할 때 사용
- 사용가능하다면 임시 상수 또는 변수로서 사용 가능한 변수를 만들기 위해 optional binding 사용
- if또는 while문을 옵셔널 안의 값의 확인을 위해 사을
- 이후 single action의 부분으로서 변수 또는 상수값으로 추출
if let actualNumber = Int(possibleNumber) {
print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
print("The string \"\(possibleNumber)\" couldn't be converted to an integer")
}
// Prints "The string "123" has an integer value of 123".
- 위의 코드는 optional type이 unwrap이 되어 정상 할당 되었는지를 조건으로 봄
let myNumber = Int(possibleNumber)
// Here, myNumber is an optional integer
if let myNumber = myNumber {
// Here, myNumber is a non-optional integer
print("My number is \(myNumber)")
}
// Prints "My number is 123".
- 위 코드도 마찬가지로 myNumber라는 상수에 nil이 아니라면 정상 할당될 것이므로 optional 안에 값이 있는지 확인할 수 있음
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100".
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
}
}
// Prints "4 < 42 < 100".
Providing a Fallback Value #
- nil-coalescing operator(
??)를 이용하여 기본 값을 주는 것은 missing value를 다루는 또 다른 방법
let name: String? = nil
let greeting = "Hello, " + (name ?? "friend") + "!"
print(greeting)
// Prints "Hello, friend!"
- name이 nil이 아니라면 name을 선택, name이 nil이라면 firend가 선택됨
Force Unwrapping #
- nil이 corrupted state or programmer error와 같은 unrecoverable failrue를 표헌할 때
!를 optionals 이름의 끝에 추가하여 그 값에 접근 가능 - 이것을 optional value의 force unwrapping라 함
- non-nil 값을 unwrap할 때는 unwrapped된 값이 리턴
- nil값을 force unwrap할 때는 런타임 에러 발생
!는 `fatalError(:file:line:)의 shorter spelling
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let number = convertedNumber!
guard let number = convertedNumber else {
fatalError("The number was invalid")
}
Implicitly Unwrapped Optionals (암시적 추출 옵셔널) #
- 초기 설정 직후, 이후 생애 동안 값이 항상 존재한다고 보장될 때만 사용(
String!). - 사용 시 매번 언래핑 없이 비옵셔널처럼 접근 가능. 단, nil이면 런타임 에러.
- 나중에 nil 가능성이 있으면
String?로 유지하고 바인딩 사용.
let possibleString: String? = "optional"
let forced: String = possibleString! // 명시적 강제 언래핑
let assumed: String! = "implicitly unwrapped"
let auto: String = assumed // 자동 언래핑
let stillOptional = assumed // 타입: String?
if assumed != nil {
print(assumed!) // 안전 확인 후 강제 언래핑
}
if let definite = assumed {
print(definite) // 바인딩으로 안전하게 사용
}
Memory Safety 한눈에 #
- 확정 초기화: 값을 읽기 전에 반드시 초기화.
- 경계 안전: 배열/버퍼는 유효 인덱스만 접근.
- 수명 안전: 값의 생애 동안만 메모리 접근(해제 후 사용 금지).
- 겹치는 접근은 증명 가능한 경우에만 허용(동시성 데이터 레이스 방지).
- 이름에
unsafe,unchecked,unmanaged가 포함된 API 사용 시 안전 책임은 개발자에게 있음.
Error Handling 기초 #
- 실패 원인을 전달·전파하기 위해
throws/try/do-catch사용. - 옵셔널은 “값 유무”만 전달하는 반면, 오류 처리는 “실패 이유”를 표현.
enum SandwichError: Error {
case outOfCleanDishes
case missingIngredients([String])
}
func makeASandwich() throws {
// 상황에 따라 오류를 던질 수 있음
}
do {
try makeASandwich()
// 성공 시 진행
} catch SandwichError.outOfCleanDishes {
// 설거지 실행
} catch SandwichError.missingIngredients(let items) {
// 재료 구매
} catch {
// 기타 오류 처리
}
Assertions와 Preconditions #
- 공통: 런타임 검증. 거짓이면 즉시 종료(복구 불가한 잘못된 상태).
- Assertions: 디버그 빌드에서만 평가 → 개발 중 가정 검증에 적합.
- Preconditions: 디버그/프로덕션 모두 평가 → 반드시 참이어야 하는 전제 확인.
- 최적화
-Ounchecked에선 precondition 미검증.fatalError는 항상 종료.
let age = -3
assert(age >= 0, "나이는 음수가 될 수 없습니다.") // 디버그에서만 평가
if age < 0 {
assertionFailure("잘못된 상태 감지")
}
let index = 1
precondition(index > 0, "Index must be greater than zero.") // 프로덕션에서도 평가
// 미구현 스텁
func todo() -> Never {
fatalError("Unimplemented")
}