코딩 · 프로그래밍 언어
스위프트 기초 입문 튜토리얼
핵심 답변
스위프트는 Apple이 iPhone, iPad, Mac, Apple Watch, Apple TV 앱을 위해 만든 빠르고 안전한 컴파일 언어이며 Linux와 Windows에서도 실행됩니다. print("Hello, world")를 hello.swift로 저장하고 swift hello.swift로 실행하세요. 핵심 개념은 let 상수와 var 변수, 타입 추론, 값이 없을 수 있는 경우를 위한 옵셔널, 값 의미론을 가진 구조체와 열거형, 프로토콜, do/try/catch로 처리하는 오류입니다.
스위프트란 무엇이고 어디에 쓰이는가
스위프트는 Apple이 2014년에 Objective-C를 대체할 현대적인 언어로 발표했고 2015년에 오픈 소스로 공개했으며, 프로젝트는 swift.org에 있습니다. Apple 플랫폼 앱을 만드는 주력 언어이며 보통 SwiftUI나 UIKit 프레임워크와 함께 씁니다. 서버 사이드 코드(예: Vapor 프레임워크)와 명령줄 도구에도 쓰입니다. 변수는 반드시 초기화해야 하고, 배열은 범위를 검사하며, nil은 명시적으로 처리해야 하는 등 흔한 버그를 막도록 설계되었습니다.
스위프트 설치와 Hello, world 실행
Mac에서는 App Store에서 Xcode를 설치하거나 Xcode 명령줄 도구를 설치하세요. Linux와 Windows에서는 swift.org에서 툴체인을 내려받습니다. swift --version으로 확인합니다.
print("Hello, world")swift hello.swift
# Hello, world
swiftc hello.swift -o hello # compile to a binary
./hello더 큰 프로젝트는 swift package init --type executable을 실행한 뒤 swift run을 사용하세요. Xcode 플레이그라운드도 쉽게 실험할 수 있는 방법입니다.
상수, 변수, 기본 자료형
상수에는 let, 변수에는 var를 사용하세요. let을 우선하세요. var를 한 번도 바꾸지 않으면 컴파일러가 경고합니다. 타입은 추론되며, 스위프트는 숫자 타입 사이를 암묵적으로 변환하지 않습니다.
| 타입 | 예시 | 설명 |
|---|---|---|
Int | let n = 42 | 최신 플랫폼에서 64비트 |
Double | let x = 3.14 | 기본 부동소수점 타입 |
Bool | let ok = true | true 또는 false |
String | let s = "hi \(name)" | 유니코드 텍스트, 값 타입 |
Character | let c: Character = "é" | 사용자가 인식하는 문자 하나 |
[Int], [String: Int] | [1, 2], ["a": 1] | 배열과 딕셔너리 |
let name = "Ada"
var count = 7
count += 1
let avg = Double(count) / 2 // explicit conversion
print("\(name) has \(count) items, avg \(avg)") // Ada has 8 items, avg 4.0
print(7 / 2, 7 % 2) // 3 1문자열 리터럴 안의 \(expression)은 값을 끼워 넣습니다(문자열 보간).
제어 흐름
let score = 72
if score >= 90 {
print("A")
} else if score >= 70 {
print("B") // B
} else {
print("C")
}
for i in 0..<3 {
print(i, terminator: " ") // 0 1 2
}
print()
var n = 10
while n > 1 { n /= 2 }
print(n) // 1
let day = "SAT"
switch day {
case "SAT", "SUN":
print("weekend") // weekend
default:
print("weekday")
}switch는 모든 경우를 다뤄야 하고, 기본적으로 다음 case로 넘어가지 않으며, 범위(case 90...100:), 튜플, 열거형 case를 매칭할 수 있습니다.
함수와 클로저
매개변수에는 호출하는 쪽이 쓰는 인수 레이블이 있어 호출이 문장처럼 읽힙니다. 레이블을 생략하려면 _를 사용합니다. 클로저는 중괄호로 쓰는 이름 없는 함수입니다.
func greet(_ name: String, with greeting: String = "Hello") -> String {
return "\(greeting), \(name)!"
}
print(greet("Lin")) // Hello, Lin!
print(greet("Lin", with: "Hi")) // Hi, Lin!
let nums = [3, 1, 2, 5]
let squares = nums.map { $0 * $0 }
let evens = nums.filter { $0 % 2 == 0 }
let sorted = nums.sorted(by: >)
print(squares, evens, sorted) // [9, 1, 4, 25] [2] [5, 3, 2, 1]$0은 클로저의 첫 번째 인수를 가리킵니다. 클로저가 마지막 인수일 때는 괄호 뒤에 쓸 수 있습니다(후행 클로저 문법).
배열, 딕셔너리, 집합
var fruits = ["apple", "pear"]
fruits.append("fig")
print(fruits.count, fruits[0], fruits.contains("fig")) // 3 apple true
var ages: [String: Int] = ["ann": 31, "bob": 25]
ages["cy"] = 40
for (person, age) in ages.sorted(by: { $0.key < $1.key }) {
print(person, age) // ann 31, bob 25, cy 40
}
print(ages["zed", default: 0]) // 0
let tags: Set = ["b", "a", "b"]
print(tags.count) // 2컬렉션은 값 타입입니다. 배열을 다른 변수에 대입하면 독립된 복사본이 만들어집니다(둘 중 하나가 바뀔 때만 지연 복사됩니다). let 배열은 전혀 수정할 수 없습니다.
대표 기능: 옵셔널
값이 없을 수 있으면 String?처럼 쓰는 옵셔널 타입을 가집니다. 언래핑하기 전에는 String으로 사용할 수 없으므로 컴파일러가 nil 경우를 처리하도록 강제합니다.
let input = "42"
let number: Int? = Int(input) // nil if input is not a number
if let number { // unwrap: runs only when not nil
print("got \(number)") // got 42
}
func firstWord(_ text: String) -> String? {
text.split(separator: " ").first.map(String.init)
}
guard let word = firstWord("hello world") else {
fatalError("no words")
}
print(word) // hello
print(firstWord("")?.uppercased() ?? "none") // noneif let과 guard let은 안전하게 언래핑하고, ?.(옵셔널 체이닝)는 값이 있을 때만 메서드를 호출하며, ??는 기본값을 제공합니다. 강제 언래핑 value!는 값이 nil이면 크래시하므로 드물게 사용하세요. 짧은 형태 if let number는 Swift 5.7 이상이 필요합니다.
구조체, 클래스, 열거형, 프로토콜
구조체와 열거형은 값 타입이고, 클래스는 상속이 가능한 참조 타입입니다. 스위프트 코드는 클래스 계층보다 구조체와 프로토콜(인터페이스)을 선호합니다.
protocol Shape {
func area() -> Double
}
struct Rect: Shape {
var width: Double
var height: Double
func area() -> Double { width * height }
}
enum Circle: Shape {
case unit
case radius(Double)
func area() -> Double {
switch self {
case .unit: return Double.pi
case .radius(let r): return Double.pi * r * r
}
}
}
let shapes: [any Shape] = [Rect(width: 2, height: 3), Circle.radius(1)]
let total = shapes.reduce(0) { $0 + $1.area() }
print((total * 100).rounded() / 100) // 9.14구조체는 멤버와이즈 이니셜라이저(Rect(width:height:))를 자동으로 얻습니다. 열거형 case는 .radius(Double)처럼 연관 값을 가질 수 있습니다.
오류 처리
실패할 수 있는 함수에는 throws를 붙입니다. 호출하는 쪽은 do/catch 블록 안에서 try를 쓰거나, try?로 오류를 nil로 바꿀 수 있습니다.
enum AgeError: Error {
case notANumber(String)
case negative
}
func parseAge(_ text: String) throws -> Int {
guard let age = Int(text) else { throw AgeError.notANumber(text) }
guard age >= 0 else { throw AgeError.negative }
return age
}
do {
print(try parseAge("41")) // 41
print(try parseAge("abc"))
} catch AgeError.notANumber(let text) {
print("not a number: \(text)") // not a number: abc
} catch {
print("other error: \(error)")
}
let maybe = try? parseAge("-3") // nil
print(maybe as Any) // nil작은 완성 프로그램: 단어 빈도 세기
import Foundation
let args = CommandLine.arguments
guard args.count == 2 else {
print("usage: swift words.swift FILE")
exit(1)
}
do {
let text = try String(contentsOfFile: args[1], encoding: .utf8).lowercased()
let words = text.split { !$0.isLetter && $0 != "'" }
var counts: [Substring: Int] = [:]
for word in words {
counts[word, default: 0] += 1
}
for (word, n) in counts.sorted(by: { $0.value > $1.value }).prefix(5) {
print(String(n).padding(toLength: 6, withPad: " ", startingAt: 0) + word)
}
} catch {
print("cannot read \(args[1]): \(error.localizedDescription)")
exit(1)
}swift words.swift notes.txt로 실행합니다. Foundation은 파일 읽기와 문자열 도우미를 제공하며, Apple 플랫폼과 Linux, Windows 툴체인에서 사용할 수 있습니다.
초보자가 자주 하는 실수
let상수나let구조체의 속성을 바꾸려는 경우. 값이 바뀌어야 하면var를 사용하세요.- 구조체가 객체처럼 공유되기를 기대하는 경우. 복사본을 바꿔도 원본은 바뀌지 않습니다. 동일성을 공유해야 하면 클래스를 사용하세요.
s[0]처럼 정수로String을 인덱싱하는 경우.s.first,s.prefix(3),String.Index값을 사용하세요.- 변환 없이
Int와Double을 연산에 섞어 쓰는 경우. 컴파일 오류가 됩니다. - 오류를 던지는 호출 앞의
try를 빠뜨리거나, 오류 시 크래시하는try!를 쓰는 경우.
다음 학습 단계
공식 가이드이자 레퍼런스인 docs.swift.org의 "The Swift Programming Language"와 swift.org의 문서 허브를 읽으세요. 앱을 만들려면 Xcode에서 Apple의 SwiftUI 튜토리얼을 따라 하세요. 그다음 스위프트 동시성(async/await과 액터), 제네릭, 의존성을 위한 Swift Package Manager를 익히세요.
자주 묻는 질문
스위프트는 Apple 플랫폼 전용인가요?
아닙니다. 스위프트는 오픈 소스이고 Linux와 Windows에서도 실행되며 서버 사이드 코드와 도구에 쓰입니다. 다만 SwiftUI, UIKit 같은 앱 프레임워크는 Apple 전용입니다.
스위프트와 Objective-C 중 무엇을 배워야 하나요?
스위프트를 배우세요. 새 앱에는 Apple이 권장하는 언어이며, 필요하면 기존 Objective-C 코드를 호출할 수 있습니다.
스위프트에서 구조체와 클래스는 무엇이 다른가요?
구조체는 대입하거나 전달할 때 복사되는 값 타입이고, 클래스는 모든 변수가 하나의 인스턴스를 공유하는 참조 타입입니다. 클래스는 상속과 디이니셜라이저도 지원합니다.
타입 뒤의 물음표는 무슨 뜻인가요?
Int?는 옵셔널로, Int 또는 nil을 담습니다. 값을 사용하기 전에 if let 등으로 언래핑해야 합니다.