Merge changes from master into FlashMaestro

FlashMaestro authored
revision 70331896e40b3209b9359450c7d4ed20f5feb31f
About
# Apple Swift Programming Language translation for KOREAN
This is a [The Swift Programming Language](https://developer.apple.com/swift/) guide documentation translation project.

**Disclaimer : It is not an official translation project, and it is an independent translation project; our activities and the opinions expressed on this WebSite should in no way be linked to Apple, the corporation.**

_This project **never be used for commercial purposes**.
By translating "The Swift Programming Language" we want to help a lot of korean learners who may otherwise struggle to understand it._

현재 1차 초벌 번역이 끝난 상태며, 퍼블리싱 준비중입니다. 기다려주세요!!!!.

>이 프로젝트는 애플의 새로운 프로그래밍 언어인 Swift 문서 번역 프로젝트 입니다. 이 프로젝트는 공식적인 번역 프로젝트가 아니며, 이 곳에서 나오는 의견 및 번역은 애플사의 입장과 전혀 무관합니다.
**이 번역 프로젝트는 절대로 상업적인 목적으로 사용되지 않습니다.으며, 사용할 수도 없습니다. 번역물의 이용에 대한 자세한 사항은 [링크](https://www.penflip.com/jjuakim/swift-korean/discussions/39)를 참조하세요. **

## Original Contents
- [Download “The Swift Programming Language” from the iBooks Store](https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11)
- [The Swift Programming Language 웹 사이트](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/)

## Let's translate it!
- 누가 어떤 챕터를 번역하고 있을까..? 저도 참여할 수 있을까요? - [번역작업 할당 현황](https://www.penflip.com/jjuakim/swift-korean/discussions/35)
- 번역을 시작하기전에 그리고 submit 하기 전에 꼭 읽어주세요! - [번역 가이드](https://www.penflip.com/jjuakim/swift-korean/discussions/36)
- 이러한 단어는 어떻게 번역해야 할까요? - [Dictionary](https://www.penflip.com/jjuakim/swift-korean/discussions/27)
chapter11
# 11 클래스와 구조체 (Classes and Structures)
> Translator : 문대선(daeseonmoon@gmail.com)

클래스와 구조체는 프로그램의 코드블럭을 정의할때 사용됩니다. 여러분은 프로퍼티를 정의할수 있고당신의 클래스와 구조체에 기능을 추가하기 위해 상수, 변수, 그리고 함수를 정의할때와 동일한 문법적 표기로으로 프로퍼티와드를 정의하실 있습니다.

다른 프로그래밍 언어와는 달리 스위프트, Swift는 사용자 클래스와 구조체를 위해서 헤더(custom classes and structures)를 위해서 인터페이스 파일과 구현 파일을 나누어서 만들 필요가 없습니다. 단일파일에 선언과 구현을 Swift에서는 한 파일에서 클래스나 구조체를 정의하며, 다른 코드에서 사용하기 위한 그 클래스와 구조체의 외부 인터페이스는 자동적으로 생성됩니다.

>NOTE
클래스의 인스턴스는 전통적으로 오브젝트라 표기하기도 합로 알려져 있습니다. 하지만 스위프트Swifit의 클래스와 구조체는 다른 언어보다도 기능적인(functionality) 측면에 중점을 두고 이 챕터에서도 클래스나 구조체의 인스턴스에 적용가능한 기능적인 면을 설명할것이기 때문에 더 일반적인 인스턴스라는 용어를 사용할것입니다(#이게 먼말이여 리뷰좀 해주세요).

## 클래스와 구조체의 비교
스위프트에서 클래스와 구조체는 여러 공통점을 가지고 있습니다. 공통점으로는
* 프로퍼티를 정의하고 값을 할당할수 있습니다.
* 메소드를 정의하고 메소드의 기능(역할)을 정의할수 있습니다.
* 접근자 문법을 통해서 할당된 값에 사용할수 있는 접근자를 정의할수 있습니다.
* 초기화를 위해 초기자(Initializer)를 정의할수 있습니다.
* 기본 구현에 확장가능(상속)
* 특정 종류의 표즌 기능을 제공하는 프로토콜을 준수할수 있습니다.

더 많은 정보를 원하신다면 Properties, Methods, Subscripts, Initialization, Extensions 그리고 Protocols 항목을 참조하십시오.

클래스는 구조체를 통해서는 할수없는 아래와 같은 추가적인 기능들을 지원합니다.
* 상속은 다른 클래스의 특성을 상속받는 클래스의 생성을 가능케합니다.
* 형변환은 여러분이 런타임시에 클래스의 형을 확인하고 변환을 가능케합니다.
* 해제(Deinitializer)는 클래스 인스턴스에 할당된 자원을 환원 가능케합니다.
* 참조카운팅은 하나의 클래스 인스턴스에 하나 이상의 참조를 가능케합니다.

더 많은 정보를 원하신다면 Inheritance, Type Casting, Initialization 그리고 Automatic Reference Counting 항목을 참조하십시오.

>NOTE
여러분의 코드에서 구조체는 언제나 복사가 될뿐 참조카운팅을 사용하지 않습니다.

## 정의문법
클래스와 구조체는 유사한 문법적 구조를 가지고 있습니다. 클래스는 `class` 키워드를 구조체는 `struct` 키워드를 사용합니다. 둘다 그들의 정의를 중괄호({})내에 위치시킵니다.
```
class SomeClass {
// 이곳에 클래스를 정의하십시오
에 가깝고, 이 챕터의 대부분은 클래스나 스트럭쳐 타입의 인스턴스에 적용 가능한 기능을 설명할 것입니다. 이런 이유때문에 일반적인 용어로서의 인스턴스가 사용될 것입니다.

## 클래스와 구조체의 비교 (Comparing Classes and Structures)
Swift에서 클래스와 구조체는 여러 공통점을 가지고 있습니다. 공통적으로 가능한 것으로는:
* 값을 저장하기 위한 프로퍼티를 정의할 수 있습니다.
* 기능을 제공하기 위한 메서드를 정의할 수 있습니다.
* 서브스크립트 문법을 사용하여 그들의 값에 접근하는 것을 제공하는 서브스크립트들을 정의 할 수 있습니다.
* 그들의 초기 상태를 설정하기 위한 Initializer를 정의할 수 있습니다.
* 기본적인 구현을 넘어서 그들의 기능을 확장시키기 위한 확장(expand)이 가능합니다.
* 특정 종류의 표준 기능을 제공하는 것으로 프로토콜을 따를 수 있습니다.

더 많은 정보를 원하신다면 [Properties](), [Methods](), [Subscripts](), [Initialization](), [Extensions]() 그리고 [Protocols]() 항목을 참조하십시오.

클래스는 구조체는 할 수 없는 다음과 같은 추가적인 기능들을 지원합니다 :
* 상속은 어느 클래스가 다른 클래스의 특성을 상속받을 수 있게합니다.
* 타입 변환(TypeCasting)은 여러분이 작동시(runtime)에 클래스의 타입을 확인하고 변환을 가능하게합니다.
* 해제(Deinitializer)는 클래스의 인스턴스가 할당된 자원을 환원 가능케합니다.
* 참조카운팅(Reference counting)은 하나의 클래스 인스턴스를 한번 이상 참조하는 것을 가능하게 합니다.

더 많은 정보를 원하신다면 [Inheritance](), [Type Casting](), [Initialization]() 그리고 [Automatic Reference Counting]() 항목을 참조하십시오.

>NOTE
여러분의 코드에서 구조체를 전달할때, 구조체는 언제나 복사가 될뿐, 참조카운팅을 사용하지 못합니다.

### 정의 문법 (Definition Syntax)
클래스와 구조체는 유사한 문법적 구조를 가지고 있습니다. 클래스는 `class` 키워드를 구조체는 `struct` 키워드를 사용합니다. 구조체와 클래스 모두 그들의 모든 정의는 중괄호({})내에 위치시킵니다.
```
class SomeClass {
// class definition goes here

}

struct SomeStructure {
// 이곳에 구조체를 정의하십시오
}
```
>NOTE
>새로운 클래스나 구조체를 정의할때 유용한 형이름을 주십시오. 일괄성을 스위프트 타입 표준인 UpperCamelCase를 사용하십시오(ex: SomeClass, SomeStruture).
>프로퍼티나 메소드를 정의할때는 형이름과 차별화를 주기위해 lowerCamelCase를 사용하십시오(ex: frameRate, incrementCount)

클래스와 구조체 정의문의 예:
```
struct Resolution {
var width = 0
var height = 0
}

class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
```
위의 예제는 픽셀기반 해상도를 정의하기 위한 `Resolution`이란 새로운 구조체를 정의합니다. 이 구조체는 `width`와 `height`라는 두개의 프로퍼티를 가지고 있습니다. 저장된 프로퍼티는 변수나 상수로서 이 클래스나 구조체의 속하며 구조체의 부분으로서 존재합니다.
이 두 프로퍼티는 정수값 0으로 초기화됨으로써 정수형입니다.

위의 예제는 또한 특정 비디오 모드를 정의하는 VideoMode라 불리는 클래스를 정의합니다. 이 클래스는 네개의 변수 저장 프로퍼티를 가지고 있습니다. 첫번째 변수인 resolution은 새로운 Resolution 구조체의 인스턴스로 초기화됩니다. 새로 생성되는 VideoMode 인스턴스는 interlaced변수는 false로 플레이 프레임 레이트는 0.0로, name은 옵션널(?) String으로 초기화합니다. name 프로퍼티는 옵셔널이기 때문에 자동적으로 기본값 nil이나 "no name value" 값을 가지게 됩니다.

## 클래스와 구조체 인스턴스
Resolution 구조체와 VideoMode 클래스는 Resolution또는 VideoMode가 어떻게 보일지를 정의할뿐 특정 해상도나 비디오모드를 정의하진 않습니다. 그렇게학 위해서 여러분은 이 구조체나 클래스의 인스턴스를 생성해야 합니다.
구조체나 클래스 인스턴스를 생성하기 위한 문법적 구조는 유사합니다.
```
let someResolution = Resolution()
let someVideoMode = VideoMode()
```
구조체와 클래스는 새 인스턴스를 생성하기위해 초기화 문법을 사용합니다. 가장 간단한 초기화 문법은 Resolution()이나 VideoMode()와 같이 클래스나 구조체의 형 이름에 괄호(())를 덧붙여주는것 입니다. 이 구문은 프로퍼티의 기본값을 갖는 새 인스턴스를 생성합니다. 자세한 클래스와 구조체의 초기화는 Initialization 항목을 참조하십시오.

## 프로퍼티 접근하기
dot(.) 문법을 사용해서 여러분은 인스턴스의 프로퍼티에 접근할수 있습니다. dot 문법은 인스턴스 이름 뒤에 공백문자 없이 dot(.)과 프로퍼티 네임을 적는것입니다.
```
println("The width of someResolution is \
(someResolution.width)")
// "The width of soneResolution is 0" 출력
```
이 예제에서 `someResolution.width`는 `someResolution`의 `width` 프로퍼티를 참조하고 기본 초기값 0를 반환합니다.
여러분은 섭(sub)프로퍼티를 통해 `VideoMode`에 속한 `resolution` 프로퍼티의 `width` 프로퍼티에도 접근할수 있습니다.
```
println("The width of someVideoMode is \
(someVideoMode.resolution.width)")
// "The width of someVideoMode is 0" 출력
```
dot 문법을 통해 변수 프로퍼티에 새로운 값을 할당하는것도 가능합니다.
```
someVideoMode.resolution.width = 1280
println("The width of someVideoMode is now \
(someVideoMode.resolution.width)")
// "The width of someVideoMode is now 1280" 출력
```
> NOTE
Objective-C와는 달리 Swift는 구조체의 프로퍼티도 섭프로퍼티를 통해 직접적으로 설정할수 있습니다. 위의 마지막 예제에서 someVideoMode에 속한 resulotion 프로퍼티의 width 프로퍼티의 값을 resolution 프로퍼티를 새로설정할 필요없이 직접적으로 할당했습니다.

## 구조체형의 멤버 초기화
모든 구조체는 여러분이 새로은 구조체 인스턴스의 멤버 프로퍼티들을 초기화 할수있는 자동 생성된 멤버초기자(*member initializer*)를 제공합니다. 새로운 구조체 프로퍼티의 기본 초기화 값은 각 변수의 이름으로 멤버초기자에 넘겨줄수 있습니다.
```
let vga = Resolution(width: 640, height: 480)
```
구조체완 달리 클래스 인스턴스의 경우에는 기본 멤버초기자를 받지 않습니다. 초기자의 자세한 사항은 `Initialization`을 참조해주십시오.

## 구조체와 열거형은 값형식
갑형식(*value type*)은 함수에 매개변수로 넘겨지거나 변수나 상수에 할당될때 값을 복사하는 형입니다.

사실 여러분은 지금까지 전 챕터에서 값형식을 광범위하게 사용했습니다. 사실 스위프트에서 기본 형- 정수, 실수, 불리언, 문자열, 배열과 딕셔너리-은 전부 값형식이고 구조체로 구현되어있습니다.

Swift에서 모든 구조체와 열거형은 값형식입니다. 즉 여러분이 생성하는 모든 구조체와 열거형 인스턴스들-그리고 그들에 속한 모든 값형식 프로퍼티-은 언제나 여러분의 코드내에서 그들이 함수의 인자로 전달되거나 새로운 변수나 상수에 할당될때 복사가 됩니다.

전 챕터에서 사용된 `Resolution` 구조체의 사용예를 한번보죠
```
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
```
이 예제는 `hd` 상수를 선언하고 full HD video(1920 픽셀 넓이에 1080 픽셀 높이)의 넓이와 높이로 초기화된 Resolution 인스턴스를 할당했습니다.

그리고 `cinema` 변수를 선언하고 `hd` 상수의 값을 할당했습니다. `Resolution`이 구조체이기 때문에 존재하는 인스턴스의 복사가 이루어지고 이 새로 복사된 값이 `cinema`에 할당됩니다. `hd`와 `cinema`가 현재 같은 넓이와 높이 값을 가지고 있지만 그들은 완전히 다른 인스턴스입니다.

다음의 코드를 통해 `cinema`의 `width` 프로퍼티에 디지털 시네마 프로젝션(2048 픽셀 넓이와 1080 픽셀 높이)의 넓이를 새로 할당하도록 하겠습니다.
```
cinema.width = 2048
```
`cinema` 인스턴스의 `width`를 출력해봄으로써 이 값이 2048로 변했음을 확인할수 있습니다.
```
println("cinema is now \(cinema.width) pixels wide")
// "cinema is now 2048 pixels wide" 출력
```
하지만 아래의 코드를 통해 `hd` 인스턴스에 속한 `width` 프로퍼티의 값은 여전히 1920임을 확인할수 있습니다.
```
println("hd is still \(hd.width) pixels wide")
// "hd is still 1920 pixels wide" 출력
```
`cinema`에 `hd` 인스턴스를 할당할때 `hd`에 저장되어있던 프로퍼티의 값들이 새로 생성된 `cinema` 인스턴스로 복사가 이루어졌음을 알수 있습니다. 결과를 보면 동일한 값을 가지고 있는 완전히 분리된 인스턴스임을 알수 있습니다.
두 인스턴스는 서로 다른 인스턴스이기 때문에 `cinema`의 `width`를 2048로 할당하더라도 `hd` 인스턴스에 저장되어있는 width 값에는 어떠한 영향도 미치지 않습니다.

열거형에도 동일한 법칙이 적용됩니다
```
enum CompassPoint {
case North, South, East, West
}
var currentDirection = CompassPoint.West
let rememberedDirection = currentDirection
currentDirection = .East
if rememberedDirection == .West {
println("The remembered direction is still .West")
}
// "The remembered direction is still .West" 출력
```
`rememberedDirection`에 `currentDirection`의 값이 할당될때 실제적으로는 값의 복사가 이루어집니다. 그러므로 `currentDirection`의 값이 변경된후에도 `rememberedDirection`에 복사되어서 저장된 원래 값에는 어떠한 영향도 미치지 않습니다.

## 클래스는 참조형식
값형식과는 달리 참조형식(*reference type*)은 함수에 인자로 전달되때나 상수나 변수에 할당될때 복사가 이루어지지 않습니다. 동일한 인스턴스의 레퍼런스(reference)가 복사대신 사용됩니다.

위에서 정의한 `VideoMode` 클래스의 사용을 통한 예제를 살펴보도록 하겠습니다.
```
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
```
이 예제에서 우리는 `tenEighty`라는 상수를 선언하고 새로 생성된 `VideoMode` 클래스의 인스턴스를 할당했습니다. 비디오 모드는 전에 설정했던 1920 x 1080의 HD 해상도의 복사된 값을 할당했습니다. 또한 interlaced를 설정하고 name에 "1080i"를 주었습니다. 그리고 마지막으로 프레임 레이트를 초당 25.0로 설정했습니다.

다음으로 `tenEighty`를 `alsoTenEighty'라는 새로운 상수에 할당하고 `alsoTenEighty`의 프레임 레이트의 값을 수정하겠습니다.
```
let alsoTenEighty = tenEighty
asloTenEighty.frameRate = 30.0
```
클래스는 참조형식이기때문에 `tenEighty`와 `alsoTenEighty`는 실제적으로 동일한 `VideoMode` 인스턴스를 참조하고 있습니다. 그들은 단지 동일한 인스턴스를 참조하는 서로 다른 이름일뿐입니다.

아래의 예제코드를 통해 `tenEighty`의 `framerate` 프로퍼티가 새로운 프레임 레이트 값인 30.0임을 확인할수 있습니다.
```
println("The frameRate property of tenEighty is now
\(tenEighty.frameRate)")
// "The frameRate property of tenEighty is now 30.0" 출력
```
`tenEighty`와 `alsoTenEighty`가 변수가 아니라 상수로 선언되었음을 주의깊게 보십시오. `tenEighty`와 `alsoTenEighty` 상수의 그자체는 실제적으로 바뀌지 않기때문에 여러분은 여전히 tenEighty.frameRate과 alsoTenEighty.frameRate의 값을 바꿀수 있습니다.
`tenEighty`와 `alsoTenEighty` 자체는 `VideoMode` 인스턴스를 "저장"하지 않고
// structure definition goes here
}
```
>NOTE
새로운 클래스나 구조체를 정의할때마다 새로운 Swift의 타입을 효과적으로 정의 할 수있다. `String`, `Int`, 그리고 `Bool`와 같은 표준의 Swift타입과 동일한 대문자 사용법과 맞도록 타입들에게 `SomeClass`나 `SomeStructure`와 같은 `UserCamelCase`에 따른 이름을 주십시오. 역으로 프로퍼티와 메서드는 이들과 타입이름으로 구분이 되도록 `frameRate`나 `incrementCount`와 같은 `lowerCamelCase`에 따른 이름을 주십시오.

클래스와 구조체 정의문의 예:
```
struct Resolution {
var width = 0
var height = 0
}

class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
```
위의 예제는 픽셀기반 해상도를 표현하기 위한 `Resolution`이란 새로운 구조체를 정의합니다. 이 구조체는 `width`와 `height`라는 두개의 저장된 프로퍼티(stored property)를 가지고 있습니다. 저장된 프로퍼티는 클래스의 변수나 상수로서 구성되고 저장된 변수나 상수입니다. 이 두 프로퍼티는 정수값 0으로 초기화된 `int`타입으로 표현됩니다.

위의 예제는 또한 비디오 화면을 위한 특정 비디오 모드를 정의하는 `VideoMode`라는 클래스를 정의합니다. 이 클래스는 네개의 변수인 저장된 프로퍼티를 가지고 있습니다. 첫번째로 `resolution`은 새로운 `Resolution`구조체의 인스턴스로 초기화됩니다. 즉 `Resolution`의 프로퍼티 타입으로 표현됩니다. 나머지 세개의 프로퍼티들은, 새로운 `VideoMode`인스턴스들은 각각
`interanced`는 non-interlaced 비디오라는 의미의 `false`로 초기화 되고, 재생시 frame Rate는 0.0으로 초기화 된다. 그리고 `name`이라 불리는 옵셔널 `String`값이 있다. `name` 프로퍼티는 옵셔널 타입이기 때문에 자동적으로 "`name` 프로퍼티에 값이 없다"는 의미인 `nil`로 기본값이 주어집니다.

### 클래스와 구조체 인스턴스 (Class and Structure Instances)
`Resolution` 구조체와 `VideoMode` 클래스는 오직 `Resolution`또는 `VideoMode`가 어떻게 보일지를 정의할뿐, 특정한 해상도나 비디오 모드를 표현하지는 않습니다. 그러기에, 여러분은 구조체나 클래스의 인스턴스를 만들 필요가 있습니다.

구조체나 클래스 인스턴스를 생성하기 위한 문법은 매우 유사합니다:
```
let someResolution = Resolution()
let someVideoMode = VideoMode()
```
구조체와 클래스는 둘 다 새 인스턴스를 생성하기위해 Initializer 문법을 사용합니다. 가장 간단한 형태의 Initializer 문법은 `Resolution()`이나 `VideoMode()`와 같이 클래스나 구조체의 타입 이름에 빈 괄호(())를 덧붙인 것을 사용하는 것입니다. 이는 각 프로퍼티가 기본값으로 초기화 되어 있는 클래스나 구조체의 새 인스턴스를 생성합니다. 자세한 클래스와 구조체의 초기화는 [Initialization]() 항목을 참조하십시오.

### 프로퍼티 접근 (Accessing Properties)
dot(.) 문법을 사용해서 인스턴스의 프로퍼티에 접근할 수 있습니다. dot 문법에서, 인스턴스 이름 뒤에 아무런 공간 없이 바로 dot(.)과 프로퍼티 네임을 적는것입니다.
```
println("The width of someResolution is \(someResolution.width)")
// prints "The width of someResolution is 0"
```
이 예제에서 `someResolution.width`는 `someResolution`의 `width` 프로퍼티를 참조하고 기본 초기값인 0를 반환합니다.

여러분은 원하는 정보를 찾기 위해 내부 프로퍼티로 계속 들어갈 수 있습니다. 예를 들면 `VideoMode`에 속한 `resolution` 프로퍼티내의 `width` 프로퍼티와 같이 말입니다.
```
println("The width of someVideoMode is \(someVideoMode.resolution.width)")
// prints "The width of someVideoMode is 0"
```
dot 문법을 통해 변수 프로퍼티로서 새로운 값을 할당하는것도 가능합니다.
```
someVideoMode.resolution.width = 1280
println("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// prints "The width of someVideoMode is now 1280"
```
> NOTE
Objective-C와는 달리 Swift는 구조체 프로퍼티의 내부프로퍼티들을 직접적으로 설정하는 것이 가능합니다. 위의 마지막 예제를 보면, `someVideoMode`의 `resulotion` 프로퍼티내의 `width` 프로퍼티의 값을 `resolution` 프로퍼티의 전체를 새로운 값으로 설정 할 필요없이 직접적으로 설정하고 있습니다.

### 구조체 타입을 위한 멤버들의 초기화 (Memberwise Initializers for Structure Types)
모든 구조체는 여러분이 새로은 구조체 인스턴스의 멤버 프로퍼티들을 초기화 할수있는 자동 생성된 멤버들의 initializer(memberwise initializer) 가지고 있습니다. 새로운 인스턴스의 프로퍼티들을 위한 초기값들은 이름을 통해서 멤버들의 initializer에게 전달 될 수 있습니다.
```
let vga = Resolution(width: 640, height: 480)
```
구조체와 다르게, 클래스 인스턴스는 기본 멤버들의 initializer를 받지 않습니다. Initializer의 자세한 사항은 [Initialization]()을 참조해주십시오.

## 구조체와 열거형은 값 타입 (Structures and Enumerations Are Value Types)
값 타입(value type)은 변수나 상수에게 할당될 때나 함수에게 값이 전달될 때, 복사되는 타입입니다.

여러분은 지금까지 전 챕터까지 내내 값 타입을 광범위하게 사용했습니다. 사실 Swift에서 기본 형- 정수, 부동 소숫점수, 이진형, 문자열, 배열과 딕셔너리-은 전부 값형식이고 보이지 않는 곳에서 구조체로 구현되어 있습니다.

Swift에서 모든 구조체와 열거형은 값 타입입니다. 즉 여러분이 생성하는 모든 구조체와 열거형 인스턴스들, -그리고 프로퍼티로서 그들이 가지고 있는 모든 값 타입-은 여러분의 코드내에서 전달되는 경우에는 언제나 복사됩니다.

앞의 예제에서 사용된 예제에서 `Resolution` 구조체의 사용에 대해서 더 생각해보자:
```
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
```
이 예제는 `hd`라는 상수를 선언하고 full HD video(1920 픽셀 넓이에 1080 픽셀 높이)의 넓이와 높이로 초기화된 `Resolution` 인스턴스로 설정하였습니다.

그리고 `cinema`라는 변수를 선언하고 `hd` 상수의 현재 값으로 설정했습니다. `Resolution`이 구조체이기 때문에 존재하는 인스턴스의 복사본이 만들어지고, 이 새로운 복사본이 `cinema`에 할당됩니다. `hd`와 `cinema`가 현재 같은 넓이와 높이 값을 가지고 있다하더라도, 그들은 보이지 않는 곳에서는 완전히 다른 두 개의 인스턴스들입니다.

다음은 `cinema`의 `width` 프로퍼티에 디지털 시네마 프로젝션을 위해 사용되는 slightly-wider 2K 표준값의(2048 픽셀 넓이와 1080 픽셀 높이)의 넓이로 수정합니다.
```
cinema.width = 2048
```
`cinema` 인스턴스의 `width` 프로퍼티를 체크하는 것으로 이 값이 정말로 2048로 변했음을 볼 수 있습니다.
```
println("cinema is now \(cinema.width) pixels wide")
// prints "cinema is now 2048 pixels wide"
```
하지만 `hd` 인스턴스의 `width` 프로퍼티는 여전히 예전 값인 1920를 가지고 있습니다.
```
println("hd is still \(hd.width) pixels wide")
// prints "hd is still 1920 pixels wide"
```
`cinema`에 `hd` 인스턴스를 할당할때 `hd`에 저장되어있던 프로퍼티의 값들이 새로 생성된 `cinema` 인스턴스로 복사가 이루어졌음을 알수 있습니다. 결과를 보면 동일한 값을 가지고 있는 완전히 분리된 인스턴스임을 알수 있습니다. 두 인스턴스는 서로 다른 인스턴스이기 때문에 `cinema`의 `width`를 2048로 할당하더라도 `hd` 인스턴스에 저장되어있는 width 값에는 어떠한 영향도 미치지 않습니다.

열거형에도 동일한 법칙이 적용됩니다
```
enum CompassPoint {
case North, South, East, West
}
var currentDirection = CompassPoint.West
let rememberedDirection = currentDirection
currentDirection = .East
if rememberedDirection == .West {
println("The remembered direction is still .West")
}
// "The remembered direction is still .West" 출력
```
`rememberedDirection`에 `currentDirection`의 값이 할당될때 그 값의 복사본이 실제로 설정됩니다. 그러므로 `currentDirection`의 값이 변경된후에도 `rememberedDirection`에 저장된 원래 값에 복사본에는 어떠한 영향도 미치지 않습니다.

## 클래스는 참조 타입 (Classes Are Reference Types)
값 타입과 달리 참조 타입(reference type)은 함수로 전달되때나 상수나 변수에 할당될때 복사가 이루어지지 않습니다. 복사본 대신, 동일한 인스턴스의 레퍼런스(reference)가 사용됩니다.

위에서 정의한 `VideoMode` 클래스의 사용을 통한 예제가 있습니다:
```
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
```
이 예제에서 우리는 `tenEighty`라는 상수를 선언하고 새로 생성된 `VideoMode` 클래스의 인스턴스를 할당합니다. 비디오 모드는 전에 설정했던 1920 x 1080의 HD 해상도의 복사본을 할당했습니다. 또한 interlaced를 설정하고 "1080i"라는 이름을 주었습니다. 마지막으로 frame rate는 프레임 레이트를 초당 25.0 프레임으로 설정했습니다.

다음으로 `tenEighty`를 `alsoTenEighty`라는 새로운 상수에 할당하고, `alsoTenEighty`의 프레임 레이트의 값을 수정하겠습니다.
```
let alsoTenEighty = tenEighty
asloTenEighty.frameRate = 30.0
```
클래스는 참조 타입이기때문에 `tenEighty`와 `alsoTenEighty`는 사실 동일한 `VideoMode` 인스턴스를 참조하고 있습니다. 실제적으로 그들은 단지 동일한 인스턴스를 참조하는 서로 다른 이름일뿐입니다.

아래의 예제코드를 통해 `tenEighty`의 `framerate` 프로퍼티가 새로운 프레임 레이트 값인 30.0임을 확인할수 있습니다.
```
println("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// prints "The frameRate property of tenEighty is now 30.0"
```
`tenEighty`와 `alsoTenEighty`가 변수가 아니라 상수로 선언되었음을 주의깊게 보십시오. `tenEighty`와 `alsoTenEighty` 상수의 그자체는 실제적으로 바뀌지 않기때문에 여러분은 여전히 `tenEighty.frameRate`과 `alsoTenEighty.frameRate`의 값을 바꿀수 있습니다.
`tenEighty`와 `alsoTenEighty` 자체는 `VideoMode` 인스턴스를 "저장"하지 않고 보이지 않는 곳에서
`VideoMode` 인스턴스를 참조만 합니다. 바뀌는것은 참조되고 있는 `VideoMode`의 `frameRate`프로퍼티이지 `VideoMode`를 참조하고 있는 상수의 값은 변하지 않습니다.

## 식별연산자(Identity Operators)
클래스는 참조타입이기때문에 여러 상수나 변수가 동일한 클래스의 인스턴스를 참조하는게 가능합니다.(구조체와 열거형은 할당되거나 함수에 매개변수로 전달될때 복사가 이루어지기때문에 동일한 인스턴스의 참조는 불가능합니다.)

이러한 이유로 두 상수나 변수가 정확하게 동일한 클래스의 인스턴스를 참조하고 있는지 알아내는것은 종종 유용하게 사용됩니다. 그러한 경우를 알아내기 위해서 Swift는 아래의 두가지 식별연산자를 제공합니다
* 동일한(Identical to) (===)
* 동일하지 않은(Not identical to) (!==)

두 상수나 변수가 동일한 인스턴스를 가리키는지 검사하기 위해 위의 두 연산자를 사용하십시오.
```
if tenEighty === alsoTenEighty {
println("tenEighty and alsoTenEighty refer to the same Resolution instance.")
}
// "tenEighty and alsoTenEighty refer to the same Resolution instance." 출력
```
"동일한(identical to)"("==="로 표현된)과 "같은(equal to)"("=="로 표현된)가 같지 않다라것에 주의하십시오.
* "동일한"은 클래스 형의 두 상수나 변수가 정확하게 동일한 클래스 인스턴스를 참조하고 있음을 뜻합니다.
* "같은"은 두 인스턴스가 같은 값을 가지고 있는지를 검사합니다.

여러분이 사용자 클래스나 구조체를 정의할때 두 인스턴스가 "같은"조건을 결정하는것은 여러분의 결정입니다.
여러분만의 "같은"과 "같지않은(not equal to)"연사자를 구현하는 과정에 대한 자세한 사항은 `Equivalence Operators`를 참조하십시오.

## 포인터 (Pointers)
만약 여러분이 C나 C++ 또는 Objective-C를 사용해본 경험이 있으시다면 이 언어들이 메모리주소를 참조하기 위해 포인터를 사용한다는 것을 아실겁니다. 어떤 참조형식 인스턴스를 참조하는 Swift 상수나 변수는 C에서의 포인터와 유사합니다. 하지만 이것은 메모리상의 주소를 직접적으로 가르키는 것은 아니고 또한 여러분이 생성한 인스턴스를 가르키기 위해 asterisk(*)를 필요로 하지도 않습니다. 대신 Swift에서는 이러한 레퍼런스들은 다른 상수나 변수처럼 정의할수 있습니다.

## 클래스와 구조체중에 선택하기 (Choosing Between Classes and Structures)
여러분 프로그램 코드의 특정 분리된 블록을 사용자 데이터 형으로 정의하기위해 여러분은 클래스나 구조체를 사용할수 있습니다.

하지만 구조체 인스턴스는 언제나 값을 전달하고 클래스 인스턴스는 참조변수를 전달합니다. 즉 이것은 이들이 서로 다른 종류의 작업에 적합하다는것을 뜻합니다. 여러분은 프로젝트에 필요한 데이터 집합이나 기능을 정의할때 그것들이 클래스로 정의되어야 할지 구조체로 정의되어야 할지 결정해야 한다는걸 생각하십시오.

일반적인 가이드로는 아래의 조건중에 한가지또는 그 이상일 경우에는 구조체를 생각하십시오.
* 구조체의 주목적이 몇몇 연관성있는 간단한 데이터 값의 캡슐화일 경우
* 캡술화된 값들이 그 구조체의 인스턴스가 할당될때나 전달될때 참조보다는 복사가 예상될 경우
* 구조체에 저장되는 모든 프로퍼티들이 참조보다는 복사가 예상되는 값형식일 경우
* 구조체가 다른 형(type)에서부터 프로퍼티나 기능이 상속될 필요가 없을 경우

구조체를 사용하는 좋은 예:
* `Double`형을 갖는 width와 height 프로퍼티의 캡슐화를 하는 기하학적 모형의 사이즈.
* `Int`형을 갖는 start와 length 프로퍼티의 캡슐화를 하는 시리즈의 범위에 접근하는 방법.
* `Double`형을 갖는 x,y와 z 프로퍼티의 캡슈화를 하는 3차원 좌표시스템의 포인터.

이외의 경우에는 클래스로 정의하고 레퍼런스로 전달되고 관리되는 클래스의 인스턴스를 생성하십시오. 실질적으로는 대부분의 사용자 데이터 형은 구조체가 아닌 클래스로 정의되어야 합니다.

## 컬렉션 형의 할당과 복사 (Assignment and Copy Behavior for Collection Types)
Swift의 `Array`와 `Dictionary` 형은 구조체로 구현되어 있습니다. 하지만 배열의 경우에는 다른 구조체가 함수나 메소드에 전달될때나 상수나 변수에 할당될때와는 약간 다르게 복사가 작동합니다.

이후에 설명할 `Array`와 `Dictionary`의 복사는 구조체가 아닌 클래스로 구현된 `NSArray`와 `NSDictionary`의 복사와도 또한 다르게 작동합니다. `NSArray`와 `NSDictionary`인스턴스는 언제나 복사가 아니라 인스턴스의 레퍼런스가 전달되거나 할당됩니다.

> NOTE
밑에 설명은 배열, 딕셔너리, 문자열 그리고 다른 값의 "복제"를 설명합니다. 복제가 언급된곳에서 여러분은 여러분의 코드가 언제나 복사처럼 작동하는것을 보게 될것입니다. 하지만 Swift는 절대적으로 필요할 경우에만 실제 값의 복사가 일어납니다. Swift는 추가적인 성능적 향상을 위해서 모든 값의 복사를 관리합니다. 그리고 이러한 최적화를 선점하기위해서 대체적인 할당문의 사용을 해서는 안됩니다.

## 딕셔너리의 할당과 복사
여러분이 `Dictionary` 인스턴스를 상수또는 변수에 할당할때나 함수또는 메소드에 매개변수로 전달할때 딕셔너리는 할당이되거나 함수가 호츨되는 그 시점에 복제가 됩니다. 이 과정의 자세한 사항은 `Structures and Enumerations Are Value Types`
(Assignment and Copy Behavior for Dictionaries)
여러분이 `Dictionary` 인스턴스를 상수 또는 변수에 할당할때나 함수또는 메서드에 매개변수로 전달할때 딕셔너리는 할당이되거나 함수가 호츨되는 그 시점에 복제가 됩니다. 이 과정의 자세한 사항은 [Structures and Enumerations Are Value Types]()
항목을 참조하십시오.

만약 딕셔너리 인스턴스에 저장되어있는 키 또는 값이 값형식(구조체이거나 열거형)일 경우 그들 역시 할당될시나 함수의 호출시에 복제가 일어납니다. 이와는 다르게 만약 키 또는 값이 참조형식(클래스이거나 함수)일 경우에는 레퍼런스의 복제가 일어납니다. 하지만 이것은 그들이 참조하고 있는 클래스 인스턴스나 함수가 아닙니다. 이러한 딕셔너리의 키또는 값의 복제 방식은 구조체가 복사될때 구조체의 저장속성의 복제방식과 같습니다.

밑의 예제에서는 네 사람의 이름과 나이를 갖는 `ages`라는 딕셔너리를 정의합니다. `copiedAges`라 명명된 새로운 변수에 이 `ages` 딕셔너리를 할당합니다. 할당후에 `ages`와 `copiedAges`는 서로 다른 딕셔너리입니다.
```
var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19]
var copiedAges = ages
```
이 딕셔너리의 키는 `String`타입이고 값은 `Int`형입니다. 두 형은 Swift에서 값형식입니다. 그러므로 딕셔너리의 복제가 일어날때 키와 값들 또한 복제됩니다.

여러분은 두 딕셔너리중에 하나의 age값을 바꾸고 확인함으로써 `ages` 딕셔너리가 복제되었음을 증명할수 있습니다. 여러분이 `copiedAges` 딕셔너리의 "Peter"의 값을 24로 바꿔도 `ages` 딕셔너리의 반환값은 복제가 일어나기전과 동일한 23을 반환함을 알수 있습니다.
```
copiedAges["Peter"] = 24
println(ages["Peter"])
// "23" 출력
```
## 배열의 할당과 복제
Swift의 배열형의 할당과 복제방식은 딕셔너리 형보다 더 복잡합니다. `Array`는 여러분이 배열의 요소들을 다룰때와 복제할때 반드시 필요할 경우에만 복제를 행함으로써 C와 비슷한 성능을 제공합니다. 만약 여러분이 `Array` 인스턴스를 상수또는 변수에 할당하거나 함수 또는 메소드의 매개변수로 전달할때 배열의 요소들은 할당이 될때나 함수가 호츨될때 복제되지 않습니다. 대신 두 배열은 동일하게 정렬된 요소들의 값을 공유합니다. 여러분은 한 배열에서 요소의 값을 수정할때 다른 또 하나의 배열을 통해서 그 결과를 관찰하실 수 있습니다.

배열에서 복제는 여러분이 배열의 길이를 수정할 가능성이 있는 코드를 실행할때 일어납니다. 이것은 요소의 추가, 삽입, 삭제 또는 배열요소들의 범위를 바꾸기 위해 사용되어지는 범위지정된 subscript들을 포함합니다. 배열의 복제가 일어날때의 배열 요소들의 복제 작동방식은 `Assignment and Copy Behavior for Dictionaries`
타입입니다. 두 형은 Swift에서 값 타입입니다. 그러므로 딕셔너리의 복제가 일어날때 키와 값들 또한 복제됩니다.

여러분은 두 딕셔너리중에 하나의 age값을 바꾸고 확인함으로써 `ages` 딕셔너리가 복제되었음을 증명할수 있습니다. 여러분이 `copiedAges` 딕셔너리의 `"Peter"`의 값을 24로 바꿔도 `ages` 딕셔너리의 반환값은 복제가 일어나기전과 동일한 23을 반환함을 알수 있습니다.
```
copiedAges["Peter"] = 24
println(ages["Peter"])
// "23" 출력
```
## 배열의 할당과 복제 (Assignment and Copy Behavior for Arrays)
Swift의 배열 타입의 할당과 복제방식은 딕셔너리 타입보다 더 복잡합니다. `Array`는 여러분이 배열의 요소들을 다룰때와 복제할때 반드시 필요할 경우에만 복제를 행함으로써 C와 비슷한 성능을 제공합니다. 만약 여러분이 `Array` 인스턴스를 상수또는 변수에 할당하거나 함수 또는 메서드의 파라미터로 전달할때 배열의 요소들은 할당이 될때나 함수가 호츨될때 복제되지 않습니다. 대신 두 배열은 동일하게 정렬된 요소들의 값을 공유합니다. 여러분은 한 배열에서 요소의 값을 수정할때 다른 또 하나의 배열을 통해서 그 결과를 관찰하실 수 있습니다.

배열에서 복제는 여러분이 배열의 길이를 수정할 가능성이 있는 코드를 실행할때 일어납니다. 이것은 요소의 추가, 삽입, 삭제 또는 배열요소들의 범위를 바꾸기 위해 사용되어지는 범위지정된 subscript들을 포함합니다. 배열의 복제가 일어날때의 배열 요소들의 복제 작동방식은 [Assignment and Copy Behavior for Dictionaries]()
에 설명된 딕셔너리의 키, 값의 복제와 동일합니다.

아래 예제는 `a`라 명명된 변수에 `Int`값들을 갖는 새로운 배열을 할당합니다. 그리고 이 배열은 또다시 `b`와 `c`로 명명된 두 변수에 할당됩니다.
```
var a = [1, 2, 3]
var b = a
var c = a
```
여러분은 supscript 문법을 통해 a 또는 b 또는 c 배열의 첫번째 값을 구할수 있습니다.
```
println(a[0])
// 1
println(b[0])
// 1
println(c[0])
// 1
```
만약 여러분이 supscript 문법을 통해 배열에 새로운 값을 할당하면 `a`, `b`, `c` 세개의 배열은 새로 할당된 값을 반환할것입니다. supcript 문법을 통한 단일 값의 수정은 배열의 길이를 변화시키지 않기때문에 배열의 요소에 새로운 값을 할당할때에는 복제가 일어나지 않습니다.
```
a[0] = 42
println(a[0])
// 42
println(b[0])
// 42
println(c[0])
// 42
```
하지만 만약 여러분이 `a`배열에 새로운 요소를 추가한다면 여러분은 배열의 길이를 수정하게 됩니다. 이것은 Swift로 하여금 요소가 추가될시에 새로운 배열의 복제를 생성하게 합니다. 더욱이 `a`는 별도의 독립적인 원배열의 복제된 배열입니다.

만약 여러분이 복제가 된후에 `a`배열의 요소를 수정하면 `a`는 여전히 원배열 요소를 참조하고 있는 `b`나 `c`와는 다른 값을 반환할것입니다.
```
a.append(4)
a[0] = 777
println(a[0])
// 777
println(b[0])
// 42
println(c[0])
// 42
```
## 배열 유니크 확인 (Ensuring That an Array Is Unique)
배열을 함수나 메소드에 전달하거나 배열의 요소들을 조작하기전에 그 배열이 유니크한지 확인하는것은 유용합니다. 배열형 변수의 메소드인 `unshare`를 호출함으로써 여러분은 배열의 유니크함을 확인하실 수 있습니다. (`unshare` 메소드는 상수 배열로는 호출할수 없습니다.)

만약 여러 변수들이 동일한 배열을 참조하고 있고 여러분이 그중에 하나의 변수를 이용해서 `unshare`메소드를 호출했다면 그 배열은 복제가 됨으로써 그 변수가 그 변수만의 독립적인 배열의 복사를 가지게 됩니다. 하지만 그 변수가 그 배열에 대한 유일한 참조변수라면 복제가 일어나지 않습니다.

위 예제코드의 마지막에 `b`와 `c`는 동일한 배열을 참조하고 있습니다 `b`배열 `unshare` 메소드를 호출해서 유니크한 배열을 만들도록 하겠습니다.
```
b.unshare()
```
만약 여러분이 `unshare` 메소드를 호출한뒤에 `b` 배열의 첫번째 요소의 값을 수정한다면 세 배열은 모두 다른 값을 보여줄겁니다.
```
b[0] = -105
println(a[0])
// 777
println(b[0])
// -105
println(c[0])
// 42
```
## 복수의 배열이 동일한 요소들을 공유하는지 검사 (Checking Whether Two Arrays Share the Same Elements)
식별 연산자(===와 !===)를 통해 하나 이상의 배열 또는 subarray들이 동일한 저장소와 요소들을 공유하는지를 확인할수 있습니다.

아래 예제에서는 "동일한(identical to)" 연산자(===)를 사용해서 배열 `b`와 `c`가 여전히 배열요소들을 공유하는지 확인합니다.
```
if b === c {
println("b and c still share the same array elements.")
} else {
println("b and c now refer to two independent sets of array elements.")
}
// "b and c now refer to two independent sets of array elements." 출력
```
또한 식별연산자를 사용해 subarray들이 동일한 요소를 공유하는지도 검사할수 있습니다. 아래 예제는 `b`의 동일한 subarray를 비교함으로써 그 둘이 동일한 요소를 참조하고 있음을 확인합니다.
```
if b[0...1] === b[0...1] {
printls("These two subarrays share the same elements.")
} else {
println("These two subarrays do not share the same elements.")
}
// "These two subarrays share the same elements." 출력
```
## 강제로 배열 복제하기
배열의 `copy` 메소드를 호출함으로 강제적으로 배열의 복제를 할수 있습니다. 이 메소
println("b and c still share the same array elements.")
} else {
println("b and c now refer to two independent sets of array elements.")
}
// prints "b and c now refer to two independent sets of array elements."
```
또한 식별연산자를 사용해 subarray들이 동일한 요소를 공유하는지도 검사할수 있습니다. 아래 예제는 `b`의 동일한 subarray를 비교함으로써 그 둘이 동일한 요소를 참조하고 있음을 확인합니다.
```
if b[0...1] === b[0...1] {
println("These two subarrays share the same elements.")
} else {
println("These two subarrays do not share the same elements.")
}
// prints "These two subarrays share the same elements."
```
## 강제로 배열 복제하기 (Forcing a Copy of an Array)
배열의 `copy` 메서드를 호출함으로 강제적으로 배열의 복제를 할수 있습니다. 이 메서
드는 얕은복제(shallow copy)를 행하며 복사된 요소들을 갖는 새로운 배열을 반환합니다.
아래 예제에서 우리는 `names`라는 배열을 정의하고 7명의 이름을 저장합니다. `copiedNames`로 명명된 새로운 변수에 `names`배열의 `copy`메소드를 호출하고 결과값을 할당합니다.
```
var names = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"]
var copiedNames = names.copy()
```
여러분은 둘중 하나의 배열 요소의 값을 수정하고 다른 배열에서의 요소값을 확인함으로써 `names` 배열의 복제가 제대로 이루어졌는지 확인하실수 있습니다.
만약 여러분이 `copiedNames` 배열의 첫번째 요소의 값을 `Mohsen`에서 `"Mo"`로 수정해도 `names`배열은 여전히 복제가 일어나기전의 원래 값인 `"Mohsen"`을 반환합니다.
```
copiedNames[0] = "Mo"
println(names[0])
// "Mohsen" 출력
```
> NOTE
여러분이 단지 특정배열이 존재하는 유일한 레퍼런스임을 확실시 하시고 싶으시다면 `copy`가 아닌 `unshare`메소드를 호출하십시오. `unshare`메소드는 필요한 경우가 아닐경우 배열의 복제를 생성하지 않습니다. 반면 `copy` 메소드는 그 배열이 다른 배열과 공유하고 있지 않더라도 언제나 복제 배열을 생성합니다.
chapter12

No preview for this file type

chapter14
# 14 서브스크립트 (Subscripts)
> Translator : Snowcat8436 (snowcat8436@gmail.com)

클래스, 구조체 그리고 열거형은 collection, list, sequence의 member element에 접근하기 위한 축약형인 _서브스크립트_로 정의할 수 있습니다. 또한 값의 설정이나 검색을 위한 별도의 메서드(seperate method)없이 index를 통해서 값을 설정하거나 검색하기 위해 서브스크립트를 사용할 수있습니다. 예를 들어서 `someArray[index]`와 같이 `배열`의 내부값(element)에 접근하거나 `someDictionary[key]`와 같이 사용하여 `딕셔너리`의 내부값(element)에 접근할 수 있습니다.

한 타입을 위해서 여러개의 서브스크립트를 정의 할 수도 있고, 또한
서브스크립트로 넘기는 index값의 타입을 기초로하여 사용하기 적절한 서브스크립트 overload(중복)를 선택할수 있다. 서브스크립트는 당신이 원하는 타입에 맞게 여러개의 입력 파라미터(input parameter)를 가지도록 정의할 수도 있다.

## 서브스크립트 문법(Subscript Syntax)

서브스크립트는 인스턴스의 이름 뒤에 있는 '[]'안에 한개 이상의 값을 적는 것으로 당신이 인스턴스들의 타입(instances of a type)를 요구할 수 있다. 그들의 문법은 인스턴스의 메서드나 computed property의 문법과 유사합니다. 인스턴스의 메서드들과 동일한 방식으로 `subscript`키워드와 함께 특정한 하나 이상의 입력 파라미터와 와 리턴타입을 통해서 서브스크립트를 정의할 수 있다. 다만 인스턴스의 메서드들과는 달리 서브스크립트는 읽고 쓰는 권한만 있거나 읽는 권한만을 가질 수 있다. 다음 코드는 서브스크립트가 computed property들과 동일한 방식으로 getter와 setter를 통해 작업하는 것을 보여줍니다
```
subscript(index: Int) -> Int {
get {
// return an appropriate subscript value here
}
set(newValue) {
// perform a suitable setting action here
}
}
```
`newValue`의 type은 해당 subscript의 리턴값과 동일합니다.
computed properties와 같이 당신은 setter의 파라미터인 `(newValue)`를 특정하게 선택할수 없습니다. 만일 당신이 setter를 위한 타입을 아무것도 제공하지 않는다면, 그제서야 기본 parameter인 `newValue`가 setter를 위해 제공될 것입니다.

읽기 전용의 computed properties와 같이 `get` 키워드를 없애서 읽기 전용의 서브스크립트를 만들 수 있다.:
```
subscript(index: Int) -> Int {
// return an appropriate subscript value here
}
```
이곳에 정수를 n배 한 결과를 표시하는 `TimesTable structure`를 선언하기 을 위한 읽기 전용의 서브스크립트를 구현하는 예제가 하나 있습니다.
```
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
println("six times three is \(threeTimesTable[6])")
// prints "six times three is 18"
```
이 예제에서 새로운 `TimesTable`의 인스턴스는 3의 배수를 출력을 하도록 생성되고.
이것은 넘겨준 값인 3을 구조체의 `initializer`가 인스턴스의 `multiplier` 파라미터로 사용한 것을 의미합니다.
해당 서브스크립트를 부르는 것으로 `threeTimesTable`의 인스턴스에게 요청할 수 있다. 보는 바와같이 `threeTimesTable[6]`과 같이 부르는 것으로 `threeTimesTable` 인스턴스의 서브스크립트를 부를 수 있다. 해당 요청은 6의 3배 테이블을 요청했으며 그 값은 18=6*3 이 된다.

>NOTE
n배 테이블은 고정된 숫자값을 출력하는 규칙에 기반합니다. 따라서 **newValue**등을 통하여 **treeTimesTable[someindex]**를 따로 설정하는 것은 적절하지 않으며 그러기에 위의 **TimesTable**을 위한 서브스크립트는 읽기전용의 서브스크립트로 선언되었습니다.

## 서브스크립트 사용(Subscript Usage)

아주 정확한 의미의 "subscript"는 그것이 사용되는 문맥에 따라 결정된다. 서브스크립트는 일반적으로 collection, list, 또는 sequence에 특정 member elements에 접근하기 위한 단축형이라는 의미로 사용되며, 당신은 특별한 클래스나 구조체의 기능을 위해 적절한 방식으로 자유롭게 대부분의 서브스크립트를 구현할 수있다.
예를 들어서 Swift의 딕셔너리 타입은 딕셔너리`Dictionary` 타입은 `Dictionary` 인스턴스에 저장된 값들을 설정하고 검색하기 위한 하나의 서브스크립트로 구현했다.
당신은 딕셔너리 안에 딕셔너리의 키의 타입의 키값을 서브스크립트의 '[]'안에 넣는 것으로 값을 세팅할 수 있으며 딕셔너리 안에 들어갈 값을 서브스크립트에 할당할 수도 있다:
```
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
```
위 예제는 `numberOfLegs`라는 변수를 선언하고 이를 3가지 key-value 쌍을 가진 딕셔너리 literal로 초기화 하고있다.
`numberOfLegs` 딕셔너리의 타입은 **`Dictionary<\String, Int>**` 를 뜻하며. 딕셔너리가 생성이 된 후, 이 예제는 서브스크립트 assignment을 사용하여 `String` 키인 `"bird"`와 `Int` 값인 2를 딕셔너리에 추가하는 것을 볼 수있다.
딕셔너리 서브스크립트에 관한 보다 많은 정보를 원한다면, [Accessing and Modifying a Dicionary](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_142)를 참고하기 바란다.

>NOTE
Swift의 딕셔너리 타입은 내부적인 key-value 서브스크립트가 요구하고 반환하는 타입이 옵셔널 타입인 서브스크립트로 구현하였습니다. 위에서 **numberOfLegs** 딕셔너리를 보면, key-value 서브스크립트를 요구하고 반환하는 타입이 `Int`일까요?, 그렇지 않으면 옵셔널 `Int`일까요? 딕셔너리 타입은 '모든 키가 값을 가지는 것은 아니다'라는 사실을 위한 모델을 지원하기 위해 옵셔널 서브스크립트 타입을 사용합니다. 그리고 어떤 키에 값을 삭제하는 방법을 제공하는데, 이 경우 해당 키값의 값는 `nil`로 할당된다.

## 서브스크립트 옵션(Subscript Options)

서브스크립트는 어떠한 숫자의 입력 파라미터들도 처리가 가능하다.그리고 그리고 이 입력 파라미터들은 어떠한 타입도 가능하다. 서브스크립트는 또한 어떠한 타입으로도 리턴이 가능하다. 서브스크립트는 변수 파라미터와 variadic parameters도 가능하지만, in-out parameters 나 default parameter 값은 지원하지 않습니다.
클래스나 구조체는 필요한 만큼의 서브스크립트를 구현하는 것이 가능하며, 적절한 서브스크립트는 보통 각각의 서브스크립트가 사용되는 요소요소에서 서브스크립트에 포함되어 서로 대비하도록 한 값이나 값들의 타입이 기초라고 생각할 수 있습니다.
이러한 다수의 서브스크립트에 관한 정의는 _서브스크립트 overloading_으로도 알려져 있습니다.
대부분의 한개의 파라미터만을 요구하는 서브스크립트와는 다르게, 만일 네가당신이 만들 것에 필요하다면, 다수의 파라미터를 요구하는 서브스크립트를 선언할 수도 있습니다.
다음 예제는 `Double`값을 가지는 2차원 행렬을 표현하는 **`Matrix**`라는 구조체를 선언하고 있습니다. **`Matrix**` 구조체의 서브스크립트는 두개의 정수형 파라미터를 요구 하고 있습니다:
```c
struct Matrix {
let rows: Int, columns: Int
var grid: Double[]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: 0.0)
}
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValidForRow(row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValidForRow(row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
```
**`Matrix**는 **rows**와 **`는 `rows`와 `columns**`이라는 두개의 파라미터를 요구하는 initializer 를 제공하며, `Double` 타입으로 **`rows * columns**`를 충분히 저장할 수 있을만큼 큰 배열을 생성합니다. 각 **`Matrix**`의 위치의 초기값은 `0.0`으로 주어지며. 이러한 작업이 모두 이루어 진 다음에는 만들어진 배열을 배열의 initializer로 보내서 올바른 크기의 배열을 만듭니다. 이 initializer에 다한 자세한 사항은 [Creating and Initializing an Array](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_142)를 참고하세요.

이제 다음과 같은 방식으로 적절한 **row**와 **column**을 initializer에 넘기는 것으로 새로운 **`Matrix**` 인스턴스를 생성할 수 있습니다.
```c
var matrix = Matrix(rows: 2, columns: 2)
```
아래의 예제는 2x2의 크기를 가진 새로운 **`Matrix**` 인스턴스를 생성하는 예제입니다. **`Matrix**` 인스턴스를 효과적이도록 평평하게 펴서 보여주기 위한 **`grid**` 배열을 참고하면 왼쪽위에서부터 오른쪽 아래로 읽어 나가는 것을 볼 수 있습니다.

![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/subscriptMatrix01_2x.png)

**`matrix**`에 값을 넣을때는 **,**row,column를 이용해서 서브스크립트에 맞는 형태로 값을 넘겨주면 설정할 수 있습니다:
```c
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
```
이 두 문장은 우측 상단의 값([0, 1])을 `1.5`로, 좌측 하단의 값([1, 0])을 `3.2`로 설정합니다:

![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/subscriptMatrix02_2x.png)

**`Matrix**`의 서브스크립트의 getter와 setter는 모두 올바른 **`row**와 **`와 `column**`값이 들어오는지 체크하는 assertion을 포함하고 있습니다. 이 assertion들을 돕기 위하여 **`Matrix**`는 자체적으로 **`indexIsValid**`라는 convenience method를 가지고 있으며 이는 주어진 값이 **`matrix**`의 범위를 넘어가는지 아닌지를 체크합니다:
```c
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
```
만일 **`matrix**`의 경계를 넘어가는 값이 서브스크립트로 들어오게 된다면 assertion이 발생합니다:
```c
let someValue = matrix[2, 2]
// this triggers an assert, because [2, 2] is outside of the matrix bounds
```


chapter26
# 26 언어 레퍼런스에 대하여 (About the Language Reference)
> Translator : 이름 (메일주소)

준비중
chapter27
# 27 언어 구조 (Lexcial Structure)
> Translator : 이름 (메일주소)

준비중
chapter28
# 28 타입 (Types)
> Translator : 이름 (메일주소)

준비중
chapter29
# 29 표현 (Expressions)
> Translator : 이름 (메일주소)

준비중
chapter3
# 03 기초 다지기 (The Basics)
> Translator : FlashMaestro (masterofflash@nate.com)
> Translator : Snowcat8436 (snowcat8436@gmail.com)

Swift는 iOS와 OS X 앱을 개발하기 위한 새로운 프로그래밍 언어 입니다. 그러나 C나 Objective-C로 개발하면서 얻었던 경험들과 많은 부분이 유사할 것입니다.

Swift는 정수형을 위한 `Int`, 부동소숫점 값을 위한 `Double`과 `Float`, 불리언값을 위한 `Bool`, 문자열 데이터를 위한 `String`을 포함해 C와 Objective-C의 기본적인 데이터 타입에서 약간 변형된 형태로 제공합니다. 또한 `컬랙션 타입`으로 통칭되는 `Array`와 `Dictionary` 이 두가지 주요한 컬랙션 타입 또한 강력한 형태로 제공합니다.

Swift도 C처럼 식별 가능한 이름을 가지고 값을 참조하거나 저장하기 위한 변수를 사용합니다. 또한 변경 불가능한 값들 또한 폭넓게 사용되도록 했습니다. 보통 상수라고 알려져 있는데, 이것은 C에서의 상수보다 훨씬 강력합니다. 상수는 변경될 필요가 없는 값을 가지고 작업하려고 할 때 코드를 조금 더 안전하고 깔끔하게 만들 수 있도록 Swift 전반에 걸쳐 쓰이게 됩니다.

Swift는 잘 알려진 타입들 뿐 아니라 Objective-C에는 없었던 고급 타입들도 선보이고 있습니다. 값들의 묶음을 만들고 전달할 수 있도록 하는 튜플도 이 고급 타입들 중에 하나입니다. 튜플은 함수의 반환값으로 여러개의 값을 하나로 결합해 돌려줄 수 있도록 합니다.

Swift는 어떤 값의 부재를 다룰 수 있는 선택형 타입도 제공 합니다. 이 선택형은 "값이 존재하고, 그 값은 x입니다." 혹은 "값이 존재 하지 않습니다."라고 할 수 있습니다. 선택형은 Objective-C의 포인터에서 `nil`을 사용하는 것과 비슷합니다. 하지만 클래스 뿐만 아니라 어떤 타입에도 사용할 수 있습니다. 선택형은 Objective-C의 `nil` 포인터보다 훨씬 안전하고 쓰임새 있습니다. 또 Swift의 강력한 기능들중 핵심적인 기능입니다.

선택형은 Swift가 `type safe`하다는 예시 입니다. Swift는 당신이 코드를 통해 다루는 값들의 타입을 확실히 하는 것을 돕습니다. 당신이 만든 코드중에 일부가 `String` 타입을 사용해야 할 때 타입 세이프는 `Int`같은 값을 전달하는 실수를 막아줍니다. 이를 통해 개발하는 동안 가능한한 빨리 에러는 인지하고 고치는 것이 가능합니다.

## 상수(Constants)와 변수(Variables)
상수와 변수는 어떤 이름(`maximumNumberOfLoginAttempts`나 `welcomeMessage`)과 특정한 형태의 값(숫자 `10`이나 문자열 `Hello`)의 결합으로 구성됩니다. 상수의 값은 한번 지정되고 난 후에는 변경될 수 없고 변수는 값이 지정되고 난 이후에도 변경될 수 있습니다.


### 상수와 변수의 선언
상수와 변수는 사용되기 전에 선언되어야 합니다. 상수는 let키워드, 변수는 var 키워드를 가지고 정의할 수 있습니다. 여기 사용자가 로그인을 시도한 횟수를 추적하는데 사용되는 변수와 상수를 만드는 예제가 있습니다.

```
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
```

이 코드는 다음과 같이 해석할 수 있습니다.

"`maxiumNumberOfLoginAttempts`라는 새로운 상수를 선언하고 값은 10으로 할당한다. 그리고 `currentLoginAttemp`라는 변수를 선언하고 0이라는 초기값을 할당한다."

예제에서 보면 최대값은 변하지 않기 때문에 로그인을 시도할 수 있는 최대 횟수가 상수에 정의되어 있습니다. 그리고 매번 로그인을 실패할 때마다 숫자가 증가해야 하기 때문에 현재 로그인 시도 횟수는 변수로 정의되어 있습니다.

콤마로 구분해서 한줄에 여러개의 상수나 변수를 선언하는 것도 가능합니다.
```
var x = 0.0, y = 0.0, z = 0.0
```

>노트
코드를 작성할 때 변경할 필요가 없는 값을 저장하는 경우 항상 `let` 키워드를 사용해 상수로 선언하라. 그리고 변경할 필요가 있을 경우에만 변수로 선언하라.

### 타입 명시(Type Annotations)
상수나 변수를 만들 때 어떤 형태의 값이 저장될 지 명확하게 하기 위해 타입을 명시할 수 있습니다. 상수나 변수의 이름뒤에 콜론을 쓰고 한칸을 띄우고 사용하고 싶은 타입의 이름을 써서 타입을 명시할 수 있습니다.

다음 예시는 `welcomeMessage`라는 변수에 `String`값이 저장될 수 잇다는 것을 표시하기 위해 타입 명시를 하는 것입니다.

var welcomeMessage: String

콜론은 "~타입 의"라는 의미를 가집니다. 따라서 위의 코드는 다음과 같이 해석할 수 있습니다.

"`String`타입의 변수 `welcomeMessage`를 선언한다."

"`String`타입의" 라는 말은 "어떤 `String`값이든 저장할 수 있다."라는 의미 입니다. "어떤타입의"(혹은 "어떤 종류의") 라는 것은 그것이 저장될 수 있다 라는 의미로 생각하면 됩니다.

이제 `welcomeMessage`변수에는 오류없이 어떤 문자열 값이든 저장할 수 있습니다.

welcomeMessage = "Hello"

>노트
연습중에 타입 명시를 해야하는 경우는 드물다. 만약 상수나 변수를 정의하는 지점에 초기값을 지정한다면, Swift는 그 상수나 변수를 위해 사용할 타입을 추측한다. 이것이 바로 `타입 세이프`와 `타입 추정`이다. 위의 예제에서 `welcomeMessage`에 초기값을 지정하지 않았다. 그래서 초기값으로 부터 타입을 추정하기 힘들기 때문에 타입을 명시해준 것이다.

### 상수와 변수 이름 짓기
상수와 변수의 이름을 지정하기 위해서 유니코드를 포함한 어떤 문자든지 사용할 수 있습니다.

```
let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"
```

상수와 변수의 이름에는 수학기호, 화살표, 개인용(혹은 유효하지 않은) 유니코드, -선, 상자 그리기용 문자 등을 사용할 수 없다. 또 숫자로 시작해서도 안되고 이름 중간에 숫자가 들어가서도 안됩니다.

특정 타입의 상수나 변수를 한번 선언 했다면, 같은 이름으로 다시 선언하는 것이나 다른 형태의 값을을 저장하도록 하는 것은 불가능 합니다. 또 변수에 상수를 저장하거나 상수에 변수를 저장하는 것 또한 불가능 합니다.

>노트
만약 Swift 예약어로 상수나 변수명을 만들고 싶다면 변수명을 ```표시로 묶어서 쓸 수 있다. 그러나 정말 다른 대안이 없는 경우가 아니면 사용하지 않는 것이 좋다.

기존 변수의 값을 호환 가능한 다른 값으로 변경할 수 있습니다. 예를 들면 `friendlyWelcome`의 값은 `"Hello!"`에서 `"Bonjour!"`로 변경됩니다.

```
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome is now "Bonjour!
```

변수와는 다르게 상수는 한번 값이 정해지면 변경할 수 없습니다. 컴파일할 때 에러가 발생하도록 시도해 봅시다.

```
let languageName = "Swift"
languageName = "Swift++"
// this is a compile-time error - languageName cannot be changed
```


### 상수와 변수의 출력
`println` 함수를 사용하면 상수와 변수의 현재 값을 출력할 수 있습니다.

```
println(friendlyWelcome)
// prints "Bonjour!
```

`println`은 출력하기 적절하게 줄단위로 끊어서 값을 출력해주는 전역 함수 입니다. Xcode에서 작업을 하고 있다면 `println`을 사용하면 Xcode의 "console"창에 결과가 나옵니다. (다음으로 `print` 함수는 `println`함수와 동일한 기능을 수행하지만 값을 출력하기 위해 한줄의 끝을 표시해줄 필요가 없습니다.)

`println`함수는 전달된 어떤 `String`값이든 출력해줍니다.

```
println("This is a string")
// prints "This is a string
```

`println`함수는 코코아의 `NSLog`함수와 비슷한 방식으로 복잡한 로그 메시지를 출력하는 것도 가능합니다. 메시지에는 상수와 변수의 현재값을 포함할 수 있습니다.

Swift는 긴 문자열에서 상수나 변수명을 대체문자로 사용해 Swift가 상수나 변수의 현재 값으로 즉시 대체할 수 있도록 문자열 해석 방식을 사용합니다. 다음과 같이 이름을 괄호로 감싸고 이스케이프 시키기 위해 여는 괄호 앞에 백슬래시를 써주면 됩니다.

```
println("The current value of friendlyWelcome is \(friendlyWelcome)")
// prints "The current value of friendlyWelcome is Bonjour!
```

>노트
문자열 해석에 관한 모든 옵션은 `문자열 해석` 부분에 설명되어 있습니다.

## 주석(Comments)

스스로 상기하기 위해서 혹은 메모하기 위해 코드내에 실행되지 않는 글을 쓰려고 할 때 주석을 사용할 수 있습니다. 작성한 코드를 컴파일 할 때 Swift의 컴파일러는 주석을 무시합니다.

Swift의 주석은 C의 주석과 흡사합니다. 한줄 주석은 /`/`(슬래시)를 두번 연속해서 쓰면 시작됩니다.
```
// this is a comment
```
또 여러줄 주석도 쓸 수 있습니다. 여러줄 주석은 슬래시와 별표를 쓰고(`/*`) 끝에는 별표와 슬래시(`*/`)를 순서대로 써주면 됩니다.

```c
/* this is also a comment,
but written over multiple lines */
```

C의 여러줄 주석과는 다르게 Swift에서는 여러줄 주석 안에 다른 여러줄 주석을 쓸 수 있습니다. 내부 여러줄 주석을 쓰려면 첫번째 여러줄 주석 부분을 시작하고 두번째 여러줄 주석을 첫번째 주석 안에서 시작합니다. 그리고 두번째 주석을 닫아준 후 첫번째 주석을 닫아주면 됩니다.

```
/* this is the start of the first multiline comment
/* this is the second, nested multiline comment */
this is the end of the first multiline comment */
```

내부 여러줄 주석은 이미 코드에 여러줄 주석을 포함하고 있더라도 넓은 범위의 코드를 빠르고 쉽게 주석처리 할 수 있게해줍니다.

## 세미콜론(Semicolons)
많은 다른 언어들과는 다르게 Swift는 코드의 각 문장 끝마다 세미콜론(`;`)이 꼭 필요하지는 않습니다. 하지만 쓰고 싶다면 써도 됩니다. 하지만 한줄에 여러 문장을 처리하려고 한다면 세미콜론이 꼭 필요 합니다.

```c
let cat = "🐱"; println(cat)
// prints "🐱"
```

## 정수(Integers)
정수는 `42`나 `-23`같이 소수점 단위가 없는 숫자들 전체 입니다. 정수는 부호가 있는 것(양수,0, 음수)와 부호가 없는 것(양수, 0) 모두를 포함합니다.

Swift는 8, 16, 32, 64 비트 형태로 부호있는 정수와 부호없는 정수를 지원합니다. 정수형은 부호 없는 8비트 정수형 `UInt8`, 부호있는 32비트 정수형 `Int32` 처럼 C와 비슷한 관습을 따른 이름을 갖고 있습니다. Swift의 다른 모든 타입과 마찬가지고 정수형 타입명 역시 대문자로 시작합니다.

### 정수범위
각 정수형 타입에 최대값과 최소값은 `min`과 `max` 속성을 가지고 접근할 수 있습니다.

```
let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
```

이런 속성값들은 예제에서 볼 수 있는 `Uint8`과 같은 타입들의 적정 범위를 나타내는 값이기 때문에 다른 타입들에도 동일 표현으로 사용할 수 있습니다.

### Int
대부분의 경우 코드 내에서 사용하기 위해 특정 크기를 지정할 필요가 없습니다. Swift가 현재의 플랫폼에 해당하는 워드(word) 크기를 갖는 `Int`라는 추가 타입을 지원하기 때문입니다.

- 32비트 플랫폼에서 `Int`는 `Int32`와 동일한 크기를 갖습니다.
- 64비트 플랫폼에서 `Int`는 `Int64`와 동일한 크기를 갖습니다.

정수형의 특정 크기가 필요한 것이 아니라면 코드 내에서 항상 `Int`를 사용하면 됩니다. 이것은 코드가 일관성을 갖고 상호처리가 가능하도록 합니다. 32비트 플랫폼에서 조차 `Int`는 넓은 범위의 정수를 포함하기에 충분할 만한 `-2,147,483,648` ~ `2,147,483,647`의 범위를 갖습니다.

### UInt
Swift는 `UInt`라는 부호없는 정수 타입도 지원합니다. 이것 또한 현재 플랫폼에 해당하는 워드 크기를 갖습니다.

- 32비트 플랫폼에서 `UInt`는 `UInt32`와 동일한 크기를 갖습니다.
- 64비트 플랫폼에서 `UInt`는 `UInt64`와 동일한 크기를 갖습니다.

>노트
특별히 현재 플랫폼 해당 워드 크기의 부호없는 정수형이 필요할 때만 `UInt`를 사용하라. 그런 경우가 아니라면 양수만 저장하는 경우일지라도 `Int`가 더 적절하다. 정수형을 위한 `Int`의 일관성이 코드가 `타입 세이프`와 `타입 추정`으로 묘사되는 다른 숫자 형태로의 변환또는 정수의 추정 타입일치가 필요한 경우를 피해 상호처리가 가능하도록 합니다.

## 부동 소수점 수
부동 소수점 수란 `3.14159`, `0.1`, `-273.15` 처럼 소수 부분을 갖는 숫자를 말합니다.

부동 소수점 타입은 `Int` 타입에 저장될 수 있는 것보다 훨씬 크거나 작은 숫자를 저장하거나 더 넓은 범위의 숫자를 표현할 수 있습니다. Swift는 두가지의 부동 소수점 타입을 제공합니다.

- `Double`은 64비트 부동 소수점 수를 표현합니다. 매우 크거나 특별히 정밀한 부동 소수점 값을 원할 경우 사용합니다.
- `Float`은 32비트 부동 소수점 수를 표현합니다. 64비트의 정밀함이 필요하지 않은 경우 사용합시다.

>노트
`Float`이 6자리의 소수를 표현할 수 있는 것에 비해 `Double`은 최소 15자리의 소수를 표현할 수 있는 정도의 정밀도를 갖습니다. 코드에서 다루는데 필요한 속성이나 값의 범위에 따라 적절히 부동 소수점 타입을 골라서 사용합니다.

## 타입 세이프와 타입 추정(Type Safty and Type Inference)
Swift는 타입 세이프 언어입니다. 타입 세이프 언어들은 코드 내에서 다루는 값들의 타입이 명확하도록 만듭니다. 코드의 어떤 부분에서 `String`타입이 기대된다면 실수로 `Int`타입을 전달하는 것은 불가능합니다.

Swift가 타입 세이프이기 때문에 컴파일을 할 때 타입 검사를 수행하고 일치하지 않는 타입들에 대해서 에러로 표시합니다. 이를 통해 개발을 진행하면서 가능한 일찍 오류를 인지하고 고칠 수 있도록 합니다.

타입 검사는 다른 형태의 값들을 가지고 일을할 때 에러를 피할 수 있도록 해줍니다. 그러나 이것이 항상 상수나 변수를 선언할 때 타입을 명시해줘야 한다는 것을 의미하지는 않습니다. 필요로 하는 값의 타입을 명시해야 하지 않는 경우 Swift는 적절한 타입을 찾기 위해 타입 추정을 수행합니다. 타입 추정은 코드를 컴파일할 때 프로그래머가 공급한 값을 가지고 컴파일러가 자동적으로 특정 표현식의 타입을 알아내도록 합니다.

Swift는 타입 추정 때문에 C나 Objective-C에 비해 타입을 지정해줘야 하는 경우가 적습니다. 상수나 변수는 여전히 명시적으로 타입이 지정되지만 그 타입을 특정하는 많은 일들이 대신 수행됩니다.(\*역자주: 상수나 변수는 타입 추정을 통해 타입을 확실하게 가지게 되기 때문에 타입을 지정해주기 위해 프로그래머가 해야할 일들이 줄었다는 것입니다.)

타입 추정은 상수나 변수를 초기값과 함께 선언할 때 특히 유용합니다. 종종 타입 추정은 상수나 변수가 선언되는 지점에서 문자 그대로의 값을 할당하는 것을 통해 이뤄집니다.(문자 그대로의 값이란 아래쪽 예시에서 볼 수 있는 `42`나 `3.14159`와 같은 소스코드에 직접적으로 쓰여져 있는 값을 말합니다.)

예를 들면, 타입을 명시하지 않고 새로운 상수를 선언할 때 `42`라는 문자그대로의 값을 할당하면 Swift는 정수형처럼 보이는 숫자를 가지고 초기화를 했기 때문에 상수가 `Int`값을 갖기를 원한다고 추정합니다.

```
let meaningOfLife = 42
// meaningOfLife is inferred to be of type Int
```

이와 비슷하게 부동 소수점 수를 위한 타입을 특정하지 않으면 Swift는 `Double`형 타입을 생성하길 원하다고 추정합니다.

```
let pi = 3.14159
// pi is inferred to be of type Double
```

Swift는 부동 소수점 수를 위한 타입을 추정할 때 `Float`보다는 항상 `Double`을 선택합니다.

만약 한 표현식 안에 정수와 부동 소수점 수를 결합해서 사용하면 문맥으로부터 `Double` 타입이라고 추정될 것입니다.

```
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double
```

문자 그대로의 `3`은 스스로 어떤 타입인지 명시되어 있지 않습니다. 또 덧셈 부분에 부동 소수점 수가 존재하기 때문에 `Double`이 출력 지정 타입으로 추정됩니다.

## 숫자의 문자표현
정수 문자표현은 다음과 같이 쓸 수 있습니다.
- 10진수는 아무런 접두어 없이
- 2진수는 접두어 `0b`를 붙여서
- 8진수는 접두어 `0o`를 붙여서
- 16진수는 접두어 `0x`를 붙여서

다음 정수 문자 표현들은 모두 십진수 `17`을 나타냅니다.

```
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
```

부동 소수점 수의 문자 표현은 10진수(접두어 없이) 혹은 16진수(접두어 `0x`를 붙여서)가 될 수 있습니다. 이런 문자표현은 소수점 앞뒤로 항상 숫자(혹은 16진수 숫자)를 갖습니다. 또 이것은 10진수의 소수점을 나타내기 위한 대소문자 `e` 혹은 16진수의 소수점을 나타내기 위한 `p`로 표현되는 *지수*를 가지고 있을 수도 있습니다.

`exp` 지수를 가지고 있는 10진수는 기수에 10의 exp승을 곱해 얻을 수 있습니다.

- `1.25e2 means` 는 1.25 × 10^2, or 나 `125.0`을 뜻합니다.
- `1.25e-2 means` 는 1.25 × 10^-2, or 나 `0.0125`를 뜻합니다.

`exp` 지수를 가지고 있는 16진수는 기수에 2의 exp승을 곱해 얻을 수 있습니다.

- `0xFp2 means` 는 15 × 2^2, or 나 `60.0`을 뜻합니다.
-` 0xFp-2 means` 는 15 × 2^-2, or 나 `3.75`를 뜻합니다.

다음 부동 소수점 수의 문자표현은 모두 10진수 `12.1875`의 값을 갖습니다.

```
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
```

숫자의 문자표현은 좀 더 쉽게 읽을 수 있도록 추가 형식을 포함하기도 합니다. 정수나 소수 모두 좀 더 읽기 쉽도록 여분의 0이나 \_(underscores)를 포함할 수 있습니다. 두 양식 모두 문자표현의 실제 값에는 영향을 주지 않습니다.

```c
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
```

## 숫자의 타입 변환(Numeric Type Conversion)

당신의 코드에서 모든 일반적인 목적으로 사용되는 정수형 상수나 변수가 모두 양수임을 알고 있더라도, 이를 위해 `int`타입을 사용 할 수 있다. 하지만 위와 같은 모든 상황에서 기본적인 정수형 타입을 사용하는 것은 당신의 코드에서 정수형 상수들이나 변수들이 당신에 코드내에서 즉시 서로 정보를 교환한다는 것을 의미한다. 그리고 이는 문자 그대로의 정수형을 의미하는데 적절하다.

다른 정수형 타입들은 오직 외부의 소스로 부터오거나, 성능혹은 메모리와 같은 최적화가 필요하여 명확한 크기의 데이터를사용하는 작업이 필요한 경우에만 사용한다.
이런 상황에서 명확한 크기의 타입들을 사용하는 것은 어떠한 돌발적인 오버플로우나 사용되는 데이터의 종류를 기록하는데 도움이 된다.

### 정수형 변환(Integer Conversion)

정수형의 상수나 변수에 저장 가능한 숫자의 범위는 각 숫자의 타입에 따라 다르다. `Int8`타입의 상수나 변수의 경우 `-128~`~`127`의 값을 저장할 수 있으며, 반면 `UInt8`타입의 상수나 변수는 0~`0`~`255`의 값을 저장할 수있다. 지정된 크기의 정수형 타입에 맞지않는 숫자는 컴파일시 에러를 출력한다:
```c
let cannotBeNegative: UInt8 = -1
// UInt8 cannot store negative numbers, and so this will report an error
let tooBig: Int8 = Int8.max + 1
// Int8 cannot store a number larger than its maximum value,
// and so this will also report an error
```
각 숫자 타입은 각각 저장할 수있는 값의 범위가 다르기 때문에, 숫자의 형 변환은 경우에 따라 맞는 경우로 선택하여야 한다. 이러한 접근은 숨겨진 변환 에러들을 방지해주고 코드에서 타입을 변환하고 있다고 명시적으로 이야기하는것을 도와준다.

특별한 숫자 타입에서 다른 타입으로 변환하기 위해서, 존재하는 값을 원하는 타입의 숫자를 초기화 한다. 아래의 예시에서, 상수 **`twoThousand**`는 `UInt16`이고, 반면에 상수 **`one**`은 `UInt8`이다. 이 두값은 서로 같은 타입이 아니기 때문에 이대로 서로 더하는 것은 불가능 하다. 대신에 이 예제에서 처럼 **`UInt16(one)**`를 이용하여 `one`의 값을 가진 `UInt16`타입을 새로 만들 수 있다. 그리고 이는 원래 값이 있었던 것처럼 사용할 수있다.
```c
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
```
이제는 덧셈의 양쪽 값이 `UInt16`이기 때문에, 덧셈이 가능하다. 그 결과값(**`twoThousandAndOne**`)는 두 `UInt16`의 덧셈이기 때문에 `Uint16`타입을 가진다.

**`SomeType(fInitialValue)**`는 Swift타입의 기본적인 초기화 방법이자 초기화 값을 전달하는 방법입니다. 보이지 않는 곳에서, `UInt16`은 `UInt8`값을 변화하는 initializer를 가지고 있고, 이 initializer는 존재하는 `UInt8`에서 새로운 `UInt16`를 만드는데 사용된다. 그러나 어떠한 값도 넘길수 없다면, 그 타입이You can’t pass in any type here, however—it has to be a type for which UInt16 provides an initializer. Extending existing types to provide initializers that accept new types (including your own type definitions) is covered in 하지만 어느 타입이나 넘길 수 있는 것은 아닙니다. 이는 `UInt16`만을 initializer는 받아들이게 되어있습니다. 존재하는 타입을 확장하여 initializer에게 자신만이 정의한 타입을 포함해서 새 타입을 받아들이게 하고 싶다면 [Extensions]()를 보세요.

### 정수와 실수 변환(Integer and Floating-Point Conversion)

실수와 정수사이의 변환은 분명하게 만들어야 한다:
```
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi equals 3.14159, and is inferred to be of type Double
```
위 예제에서 덧셈을 위해서 양쪽의 타입이 동일하도록 상수값 3을 `Double`타입의 값으로 바꾸는 것을 볼 수있다. 만일 이러한 변환이 없다면, 덧셈은 가능하지 않을 것이다.

또한 반대로 실수를 정수로 바꾸어 계사나는 것도 가능하다, 다만 이 경우 `Double`이나 `Float`값을 정수로 초기화하는 과정이 필요하다.
```
let integerPi = Int(pi)
// integerPi equals 3, and is inferred to be of type Int
```
실수형 값은 위와 같은 방식으로 새로운 정수형 값으로 변환시에 항상 소숫점 이하의 값을 버림한다. 예를들면 4.75는 4가되고 -3.9는 -3이 된다.

>NOTE
숫자 상수나 변수를 결합하기위한 규칙은 numeric literals의 규칙과는 다릅니다. numeric literals는 그 스스로가 명시적인 타입을 가지고 있지 않기 때문에 literal value 3은 literal value `0.14159`와 바로 더할 수 있습니다. 이는 그들의 타입은 오직 컴파일로 체크한다는 것을 의미합니다.

## 타입 알리아스(Type Aliases)

_타입알리아스_는 이미 존재하는 타입을 또다른 이름으로 정의하는것을 이야기합니다. `typealias`라는 키워드로 타입 알리아스를 정의할 수 있습니다.

타입 알리아스는 외부의 소스에서온 특정한 사이즈를 가진 데이터로 작업하는 경우 처럼 이미 존재하는 타입을 보다 문맥에 맞는 이름으로 알아보고 싶을때 유용하다:
```
typealias AudioSample = UInt16
```
당신이 타입알리아스를 정의하는 즉시, 당신은 그 타입알리아스를 원래의 이름대신 사용할 수있습니다:
```
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound is now 0
```
위에서 `UInt16`을 위한 **`AudioSample**`알리아스를 볼 수 있다. 이것이 알리아스이기 때문에 **`maxAmplitudeFound**`를 위한 변수인 **`AudioSample.min**`은 실제로는 **`UInt16.min**`의 값인 0`0`을 의미한다.

## 이진형(Booleans)

Swift는 `Bool`이라는 기본적인 이진형 타입을 가진다. 이진형 값은 논리적으로 취급되며, 그때문에 그들은 오직 참과 거짓의 두가지 값을 가진다. Swift는 이를 위해 `true`와 `false`라는 두가지의 상수값을 제공한다:
```
let orangesAreOrange = true
let turnipsAreDelicious = false
```
**`orangesAreOrange**와 **`와 `turnipsAreDelicious**`의 타입은 이진형의 문자 그대로의 값으로 초기화가 가능한 `Bool`타입을 가지고 있습니다. 위에서의 `Int`와 `Double`처럼, 만일 당신이 `true`나 `false`로 값을 설정한다면 자동으로 형태가 결정될 것이기 때문에 `Bool`로서 상수나 변수를 선언할 필요가 없다.
타입 추론(Type inference)은 상수나 Swift의 코드를 더욱 간결하고 읽기 쉽게 하는데 도움을 준다.

이진형 값은 다음과 같은 if문처럼 조건문으로 작업하는 경우에 특히 유용하다:
```
if turnipsAreDelicious {
println("Mmm, tasty turnips!")
} else {
println("Eww, turnips are horrible.")
}
// prints "Eww, turnips are horrible."
```
위의 if문과 같은 조건문에 대한 것은 [Control Flow]()에서 조금 더 자세히 다룰것이다.

다음 예제는 컴파일 타임의 에러를 보여준다:
```
let i = 1
if i {
// this example will not compile, and will report an error
}
```
그러나 다음의 예제는 올바르게 처리되는 것을 보여준다:
```
let i = 1
if i == 1 {
// this example will compile successfully
}
```
**`i ==1** 1`의 비교 결과는 `Bool`타입이고, 그때문에 두번째 예제는 타입 체크를 통과할수 있다. **`i ==1** 1`과 같은 비교구문은 [기본연산자]()에서 다룰 것입니다.

다른 Swift의 타입 세이프예제와 마찬가지로, 이러한 접근은 돌발적인 에러를 피할 수 있게 해주고, 을 코드의 특정한 부분에서의 의도를 항상 분명하게 하는 것을 보장한다.

## 튜플(Tuples)

튜플은 여러 값들을 하나의 값으로 묶어준다. 튜플안의 여러 값들은 어느 타입도 가능하고, 각각 동일한 타입일 필요도 없다.

아래의 예시에서 **`(404, "Not Found")**`는 HTTP의 상태코드를 묘사하는 튜플이다. HTTP상태 코드는 당신이 웹페이지에 요청을 할때 웹서버의 상태를 알려주는 특별한 코드이다. 요청한 페이지가 존재하지 않는다면 404 Not Found라는 상태 코드가 반환된다.
```c
let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")
```
(404, "Not Found") 튜플은 HTTP 상태코드를 두개의 나누어진 값으로 표현하기 위한 `Int`값 하나와`String`값 하나를 서로 묶은 것이다. 이것은 " `(Int, String)`타입의 튜플"이라고 말할 수있다.

당신은 어떠한 순서를 가진타입들로부터도 튜블들을 만들 수 있습니다. 그리고 그 튜블들은 당신이 원하는 만큼 서로 다른 타입들을 가질 수 있습니다. 튜플 (Int, Int, Int)나 튜플(String, Bool) 혹은 당신이 필요한 어떠한 순서를 가진 튜플이라면 어떠한 것도 당신을 막을 수 없습니다. (모두 생성 가능하단의미)

당신은 튜플의 각 내용들을 분리된 상수나 변수로 분해할수 있고 이는 평상시처럼 접근도 가능합니다.
```
let (statusCode, statusMessage) = http404Error
println("The status code is \(statusCode)")
// prints "The status code is 404"
println("The status message is \(statusMessage)")
// prints "The status message is Not Found"
```
만일 당신이 튜플의 값들중 오직 몇몇개만 필요하다면, 튜플을 분리할때 튜플에서 무시할 부분을 언더바 "\_" 로 처리하면 된다:
```c
let (justTheStatusCode, _) = http404Error
println("The status code is \(justTheStatusCode)")
// prints "The status code is 404"
```
또다른 방식으로는 0부터 시작하는 index number를 통하여 각각의 element value에 접근합니다:
```
println("The status code is \(http404Error.0)")
// prints "The status code is 404"
println("The status message is \(http404Error.1)")
// prints "The status message is Not Found"
```
튜플을 정의할때 튜플의 각 element들에 이름을 지어줄 수도 있습니다:
```
let http200Status = (statusCode: 200, description: "OK")
```
만일 튜플의 각 element에 이름을 지어줬다면, 각 element에 값에 접근하기 위해서 element의 이름을 사용할 수 있습니다:
```
println("The status code is \(http200Status.statusCode)")
// prints "The status code is 200"
println("The status message is \(http200Status.description)")
// prints "The status message is OK"
```
튜플들은 함수들의 리턴값으로써 특히 유용합니다.
웹페이지를 검색하기위한 함수는 보통 페이지 검색을 성공여부를 표현하기 위해서 `(Int, String)` 튜플을 리턴합니다.두 개의 서로 다른 타입의 구분되는 값을 가진 튜플을 리턴하는 것으로 그 함수는 단순히 오직 하나의 타입을 가진 하나의 값을 리턴하는 것보다 결과에 대한 보다 유용한 정보를 제공할 수 있습니다.
보다 자세한 정보는 [Functions with Multiple Return Values]()를 참고하기 바란다.

>NOTE
튜플은 연관성있는 값들을 임시로 묶는데도 유용하다. 그들은 복잡한 자료구조를 생성하기에는 알맞지 않다. 만일 당신의 자료구조가 임시적이지 않고 계속해서 사용될 것으로 생각된다면, 튜플보다는 클래스나 자료구조로 만드는 것이 나을 것이다. 보다 많은 정보가 필요하다면 [Classes and Structures]()를 참조하기 바란다.

## 옵셔널(Optionals)

옵셔널은 어떠한 값이 부재인지를 체크할때 사용한다.
옵셔널이란 다음을 이야기한다:

- 그곳에는 값이 "있다", 그리고 그것은 x와 동일하다.
혹은
- 그곳에는 값이 전혀 "없다"

>NOTE
옵셔널에 대한 개념은 C나 Objective-C에는 존재하지 않는다. Objective-C에서 그나마 가장 가까운 개념은 메서드에서 object값을 리턴하는 대신 올바른 오브젝트가 존재하지 않는다 라는 의미로 `nil`을 리턴하는 것이다. 그러나 이는 오직 오브젝트에만 적용할 수있고 구조체, 기본적인 C언어 타입들, 열거형에 대해서는 적용할 수 없다. 이런 타입들을 위해서 Objective-C 메서들은 보통 값의 부재를 의미하는 `NSNotFound`와 같은 특수한 값을 리턴합니다. 이러한 접근은 메서드를 부르는 쪽에서 체크나 테스트를 위한 특수한 값을 잘 알고 있다고 가정하고 있습니다. Swift의 옵셔널은 특별한 용도의 상수가 필요 없이 어떠한 타입의 값의 부재를 바로 알아낼수 있도록 만들어줍니다.

이곳에 한가지 예제가 있다. Swift의 `String`타입은 `String`타입을 `Int`타입으로 변환하기 위한 `toInt`라는 메서드를 가집니다. 그러나 모든 문자형이 정수형으로 변환 가능한것은 아닙니다. "123"이라는 문자형은 123이라는 숫자값으로 변환이 가능하지만, `"hellow, world"`라는 값은 분명한 숫자값으로 변환할 수 없습니다.

아래의 예제는 `String`을 `Int`로 변환하기 위해 `toInt`메서드를 사용하고 있다:
```
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
// convertedNumber is inferred to be of type "Int?", or "optional Int"
```
Because the `toInt`메서드가 실패하는 것으로 보아, 이는 `int`가 아닌 optional Int값을 리턴하고있다. optional Int는 `Int`가 아닌 `Int?`로 쓴다. 물음표는 그 값이 optional하다는 것을 의미한다. 이는 그 값이 어떠한 `Int`값을 가지거나 아예 전혀 값을 가지지 않는다는 것을 의미한다. (이는 `Bool`이나 `String`과 같은 다른 값은 가질 수 없다. 이는 오직 `Int`값을 가지거나 아무값도 없을 뿐이다.)

### If문과 강제 언랩핑(If Statements and Forced Unwrapping)

어떠한 옵셔널이 값을 가지고있나 찾기위해서 `if`문을 사용할 수 있다. 이 경우 만일 옵셔널이 값을 가지고 있다면 그 결과는 `true`일 것이고 전혀 값을 가지지 않는다면 `false`일 것이다.

옵셔널이 값을 가진다는 것을 확실히 알때, 옵셔널의 이름의 맨 마지막에 느낌표를 붙이는 것으로 그 근원 값에 접근할 수 있다. 여기서 물음표는 "내가 이 옵셔널은 확실히 값을 가지고 있고 이를 사용하라"라는 효과적인 말이다. 이것을 옵셔널 값의 강제 언랩핑이라고 한다:
```
if convertedNumber {
println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
// prints "123 has an integer value of 123"
```
`if`문에 대한 보다 많은 것을 원한다면 [Control Flow]()를 참조하기 바란다.

>NOTE
느낌표를 사용하여 값이 존재하지 않는 옵셔널 값에 접근하려 시도하면 런타임 에러가 발생한다. 느낌표를 사용하여 강제 언랩핑을 하기 전에는 항상 옵셔널 값이 `nil`이 아니라는 것을 확실히 해야 한다.

### 옵셔널 바인딩(Optional Binding)

당신은 옵셔널이 값을 가지고 있는지를 찾고 만일 그렇다면 값을 임시로 상수나 변수로 사용하도록 만들기 위해 옵셔널 바인딩을 사용할 수 있습니다. 옵셔널 바인딩은 `if`문이나 `while`문에서 옵셔널 안에 값이 있는지 체크하고 이를 상수나 변수로 추출하는 것을 한번에 하기 위해 사용할 수 있다. `if`문이나 `while`문에 대해서 더욱 자세한 설명이 필요하다면 [Control Flow]페이지를 참고하시기 바랍니다.

`if`문을 위해서 옵셔널 바인딩을 하는 경우 다음과 같이 쓸 수 있습니다:
```
if let constantName = someOptional {
statements
}
```
위 예시를 보면 당신은 **`possibleNumber**`예제를 강제 언랩핑하는 대신 옵셔널 바인딩을 사용하는 방식으로 다시 쓸 수 있습니다:
```c
if let actualNumber = possibleNumber.toInt() {
println("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
// prints "123 has an integer value of 123"
```
이는 다음을 의미합니다:

“만일 **`possibleNumber.toInt**`가 리턴한 옵셔널 `int`값이 값을 가지고 있을 경우, 새로운 상수인 **`actualNumber**`를 그 옵셔널이 가지는 값으로 설정한다.”

만일 변환이 성공적이라면, 상수 **`actualNumber**`는 `if`문의 첫번째 부분에서 사용하는 것이 가능하다. 이는 옵셔널이 가지는 값으로 이미 초기화 되어있고, !를 뒤에 붙여서 그 값을 가져오는 것이 필요하지 않다. 예제에서 **`actualNumber**`는 단순히 변환의 결과를 출력하기위해 사용한다.

옵셔널 바인딩은 변수와 상수 모두에 사용할 수 있다. 만일 `if`문의 첫번째 문장에서 **`actualNumber**`의 값을 조종하는 것을 원한다면, **`actualNumber**`를 변수로 사용할 수 있다. 그러면 옵셔널을 가지는 그 값을 상수대신 변수로서 만들 수 있다.

### nil

네가 값이 없는 상태의 옵셔널 변수를 원한다면 특별한 값인 `nil`로 옵셔널 변수를 설정하면 된다:
```
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
```
>NOTE
`nil`은 옵셔널이 아닌 상수나 변수와 사용할 수 없다. 만일 네 코드에 있는 상수나 변수가 명확한 조건하에서 값의 부재에 대응하기를 원한다면, 항상 적절한 타입의 옵셔널 값으로 그것을 선언하여야 한다.

만일 네가 값을 제공하지 않고 옵셔널 상수나 변수를 정의한다면, 그 상수나 변수는 당신을 위해 자동적으로 `nil`로 설정할 것이다:
```
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
```
>NOTE
Swift의 `nil` 은 Objective-C에서의 `nil`과 같지 않다. Objective-C에서 `nil`은 존재하지 않는 오브젝트를 위한 포인터라면, Swift에서 `nil`은 포인터가 아니고 명확한 값의 부재를 이야기할 뿐이다. 따라서 오브젝트 타입들뿐만 아니라 어떠한 타입의 옵셔널들이라도 `nil`로 설정하는 것이 가능하다.

### 무조건적으로 언랩핑된 옵셔널(Implicitly Unwrapped Optionals)

위에서 이야기한 것과 같이 옵셔널들은 상수나 변수가 **"값을 가지지 않는 것**"을 허용한다는 것을 나타낸다. 옵셔널은 값이 있는지 없는지를 보기 위해 `if`문을 이용하여 체크할 수 있고, 값이 존재하는 옵셔널의 값에 접근하기 위해 옵셔널 바인딩을 통한 조건부 언랩핑이 가능하다.

때때로 옵셔널은 처음으로 값을 설정한 이후에는 값을 가지고 있다는 것은 프로그램 구조적으로 명확하다. 이러한 경우 위 사항들은 옵셔널의 값에 접근할때마다 체크하고 언랩핑해야하는 과정을 없애는데 유용하다. 이런 이유때문에 안전하게 항상 값을 가진다고 가정할 수 있다.

이러한 종류의 옵셔널들은 Implicitly Unwrapped Optionals로 정의되었다고 할 수 있다. 당신은 옵셔널로 만들기 원하는 타입 뒤에 물음표보다 느낌표를 붙이는 것으로 Implicitly Unwrapped Optional을 만들 수 있다.

Implicitly Unwrapped Optional은 옵셔널이 첫번째로 정의되고 옵셔널들이 각 포인트에서 확실하게 존재한다고 가정한 뒤에 옵셔널의 값이 존재하는지 즉시 확인할때 유용하다.
Swift에서 Implicitly Unwrapped Optional의 최우선 용도는 클래스의 초기화 과정에서 소유자가 없는 참조나 무조건적인 언랩핑된 옵셔널 속성들을 설명하는 것이다.

Implicitly Unwrapped Optional은 보이지 않는 곳에서는 일반적인 옵셔널과 같다. 그러나 접근할때마다 옵셔널 값의 언랩핑이 필요 없이 옵셔널 값이 아닌 것 처럼 사용할 수도 있다. 아래의 예시는 옵셔널 `String`과 무조건적인 언랩핑 옵셔널 `String`의 behavior에서의 차이점을 보여준다:
```
let possibleString: String? = "An optional string."
println(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
println(assumedString) // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."
```

Implicitly Unwrapped Optional을 그것이 사용될때마다 자동적으로 언랩핑을 하기 위한 권한이 주어진 옵셔널으로 생각 할 수 있다. 그것을 사용할때마다 느낌표를 옵셔널의 이름뒤에 붙이는 것 보다는 네가 옵셔널을 선언할때 옵셔널의 타입 뒤에 느낌표를 붙이는 것이 낫다.

>NOTE
만일 네가 명확하지 않은 값에 Implicitly Unwrapped Optional로 접근을 시도할 경우, 런타임 에러가 발생한다. 그 결과는 마치 값이 명확하지 않은 일반적인 옵셔널 뒤에 느낌표를 붙인 결과와 정확히 같다.

만일 Implicitly Unwrapped Optional이 값을 가졌는지를 체크하기 위해서는 여전히 일반적인 옵셔널 처럼 다룰 수 있다:
```
if assumedString {
println(assumedString)
}
// prints "An implicitly unwrapped optional string."
```
또한 한 문장으로 옵셔널의 값을 체크하고 언랩핑하기 위한 Implicitly Unwrapped Optionals의 옵셔널 바인딩도 사용가능하다:
```
if let definiteString = assumedString {
println(definiteString)
}
// prints "An implicitly unwrapped optional string."
```
>NOTE
Implicitly Unwrapped Optional은 나중에 값이 `nil`이 가능성이 있는 경우에는 사용할 수 없다. 어떠한 변수가 `nil` 값을 가지는지 체크할 필요가 있는 경우에는 항상 일반적인 옵셔널 타입을 사용한다.

## Assertions

옵셔널은 값이 있는지 있지 않은지 체크를 할수 있게 해주고, 값이 부재한지 우아하게 대처하는 코드를 작성합니다. 그러나 이것으로는 값이 없거나 명확한 조건을 만족하지 않은 값을 제공하는 경우에 코드를 계속 실행하게 하는 것은 불가능합니다. 이러한 상황에서 당신은 코드상에서 값이 없거나 올바르지 않은 경우를 디버그하기 위한 기회를 제공하고 종료 코드를 실행하기 위해 Assertion을 발생시킬수 있습니다.

### Assertions을 통한 디버그(Debugging with Assertions)

assertion은 논리적 조건이 항상 `true`인지를 런타임에 체크한다. 문자 그대로, assertion은 조건이 항상 `true`인 것을 “주장한다”. 더 이상의 코드를 실행시키기 전에 필수적인 조건을 만족하는 지를 확실히 하기 위해서 assertion을 사용한다. 만일 그 조건이 `true`라면, 보통 코드는 계속하여 실행된다. 그러나 만일 그 조건이 `false`라면 코드는 종료되고, 너의 앱도 종료될 것이다.

만일 Xcode에서 앱을 빌드하고 실행할때와 같이 당신의 코드가 디버깅 환경에서 돌아가고 있을때 assertion이 발생한다면, 어디서 올바르지 않은 상태가 발생했는지 볼 수 있고, assertion이 발생한 시점에서의 앱의 상태를 요구할 수있다. assertion은 또한 당신에게 assert가 발생한 원인에 대한 명확한 디버그 메시지도 제공한다.

당신는 전역적인 assert함수로서 assertion을 작성할 수도 있고, assert함수에게 `true`와 `false`를 체크할 조건과 조건이 `false`일때 출력할 메시지를 넘겨줄 수 있다:
```
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not >= 0
```
이 예제에서 코드는 오직 **`age >= 0**`이 `true`일때(**`age**`가 음수가 아닐때)만 실행됩니다. 만일 **`age**`의 값이 음수라면 위와 같이 **`age >= 0**`의 결과는 `false`가 되고 assertion이 발생하며 그 앱은 종료됩니다.

Assertion 메시지는 문자어구를 사용해야하는 것은 아닙니다. assertion 메시지는 다음과 같이 원하는 경우에는 생략도 가능합니다:
```
assert(age >= 0)
```
### Assertion을 사용할 때(When to Use Assertions)

어떠한 조건이 `false`가 될수 있지만 코드 실행을 계속하기 위해서는 반드시 `true`이여만 하는 곳에 assertion을 사용한다. asertion 체크를 포함하는 올바른 경우들은 다음과 같다:

- 어떠한 정수의 서브스크립트 인덱스가 커스텀 서브스크립트 구현을 위해 제공되었으나, 그 서브스크립트 인덱스의 값이 너무 크거나 작을 수 있을때.
- 함수로 넘긴 어떤 값이 함수에서 작업을 진행하는데 적합하지 않은 값일때.
- 옵셔널 값이 현재 `nil`인데 추후의 코드 실행을 위해서 `nil`이 아닌 값이 필요할때.

이에 관해서는 [Subscripts]()와 [Functions]()을 참고하시기 바랍니다.

>NOTE
Assertions는 당신의 앱이 종료하는 원인이고, 당신의 코드를 부적절한 조건이라도 곤란한 상황이 발생하지 않도록 디자인 하기 위한 대체물이 없다. 그렇기는 하지만 올바르지 않은 조건이 발생할 수 있는 상황에서, assertion은 어떠한 조건을 앱의 출시 전에 개발에서 강조하고 주목시키기 위한 매우 효과적인 방법이다.





chapter30
# 30 스테이트먼트 (Statements)
> Translator : 이름 (메일주소)

준비중
chapter31
# 31 선언 (Declarations)
> Translator : 이름 (메일주소)

준비중
chapter32
# 32 속성 (Attributes)
> Translator : 이름 (메일주소)

준비중
chapter33
# 33 패턴 (Patterns)
> Translator : 이름 (메일주소)

준비중
chapter34
# 34 제너릭 매개변수와 인자 (Generic Parameters and Arguments)
> Translator : 이름 (메일주소)

준비중
chapter35
# 35 문법 요약(Summary of the Grammar)
> Translator : 이름 (메일주소)

준비중
chapter4
# 04 기본 연산자 (Basic Operators)
> Translator : 해탈 (kimqqyun@gmail.com)

_연산자_는 값을 확인 변경 합치기 위해 사용하는 특수 기호나 문구입니다. 예를 들어 더하기 연산자(`+`)는 두 숫자를 더합니다. (`let i = 1 + 2` 과 같이)
더 복잡한 예는 논리 AND 연산자 (`&&`) 를 포함하는것 (`
에서 쓰이는것 같이) 두 숫자를 더합니다.
더 복잡한 연산자에 대해 예를 들자면, (`if
enteredDoorCode && passedRetinaScan`)그리고 증가에서와 같이) 논리 AND 연산자 `++i`는&&`가 있고, `i`의 값 `1`만큼 증가시키는 축약 연산자입것을 축약해서 표현한 `++i` 증가 연산자가 있습니다.

Swift 는 대부분의 표준 C 연산자를 지원하며 일반적인 코딩 오류를 제거하는 몇가지 기능을 향상 시켰습니다. 할당연산자 (`=`)대신 항등 연산자(`==`)로 대신 사용할때하는 실수를 방지하기 위해 값을 반환하지 않습니다.
산술연산자(`+` ,` -` ,`*`,`/` ,`%` 등)가 오버플로우를 감지하고 그들을 저장하는 유형의 허용된 값의 범위보다 크거나 작아 숫자로 작업할때서 발생하는 예기치 않은 결과를 방지 할 수 있습니다.
당신은 오버 플로우 연산자에 설명된대로 Swift의 오버플로우 연산자를 사용하여 오버플로 값을 선택할수 있습니다. 이것은 [Overflow Operaters]() 에 설명되어 있습니다. // 링크

C 와 달리, Swift는 부동 소수점 숫자에 나머지 (`%`) 계산을 수행 할 수 있습니다. 또한 Swift는 또한 2개의 범위 연산자를 제공합니다.C언어에는 없는 (`A..B`) 그리고 (`A...B`) 이며의 2가지의 범위 연산자를 제공합니다. 이 연산자들은 값의 범위를 표현하기 위한 연산자입니다. 이것은 C 에서 찾을 수 없습니다.

이 장에서는 Swift의 일반적인 연산자를 설명합니다. 고급 연산자는 [고급 연산자(Advanced Operator)]() 장에 있습니다, 그리고 사용자 정의 연산자를 정의하고 사용자 정의 형식에 대한 표준 연산자를 구현하는 방법에 대해 설명합니다. // 링크

## 용어 (Teminology)
연산자는 단항, 이진, 그리고 삼항이 있습니다.

- _단항_ 연산자는 단일 대상에서 작동합니다. (예 `-a`) 단항 _전위_ 연산자를 바로 앞에 나타내고, (예 `!b`) 단항 _후위_ 연산자는 타겟이후에 즉시 나타납니다. (예 `i++`)
- 이항 연산자는 두 가지의 대상에 작동합니다. 이항연산자는 중위연산자이며 두 대상 사이에 나타납니다. (예 `2 + 3`)
- 삼항 연산자는 세 가지 대상에 작동합니다. C 처럼 , Swift는 하나의 삼항연산자를 가지고 있습니다. 삼항 조건 연산자는 (`a ? b : c`) 입니다.

연산자에 영향을 주는 값은 피연산자입니다. 식 `1 + 2`에을 보면 `+` 기호는 이항 연산자이며 두가지의 피연산자 값인 `1` 과 `2`입니다.

## 할당 연산자
할당 연산자는 `(`a = b)`) 초기화자(initializes) 또는 `b` 의 값을 `a` 에 할당하는것입니다.
```
let b = 100
var a = 5
a = b
// a 는 이제 10 과 같습니다.
```

만약 오른쪽이 같은 여러 값을 가진 튜플의 경우에 그 요소는 한번에 여러개의 상수 또는 변수로 분해 될수있습니다.
```
let (x, y) = (1, 2)
// x 는 1 과 같고 y 는 2 와 같다.
```

C 와 Objective-C의 대입 연산자와는 달리, Swift의 대입 연산자 자체가 값을 반환하지 않습니다. 다음 구문은 유효하지 않습니다.
```
if x = y {
// x = y가 값을 반환하지 않기 때문에 이것은 유효하지 않다,
}
```

이 기능은위 구문이 유효하지 않은 이유는, 실수로 (`==`) 연산자를 사용하여 막는것은대신 (`==`)를 대신 연산자를 사용하는것을 방지하기 떄문위해서입니다. `if x = y` 가 유효하지 않게 함으로써 Swift 코드에서 이러한 종류의 오류를 방지하는데 도움이 됩니다.

## 산술 연산자
Swift 는 4가지의 산술연산자가 모든 숫자 타입을 지원합니다.

- 덧셈 (`+`)
- 뺼셈 (`-`)
- 곱셈 (`*`)
- 나눗셈 (`/`)

```
1 + 2 // 3 과 같다
5 - 3 // 2 와 같다
2 * 3 // 6 과 같다
10.0 / 2.5 // 4.0 과 같다
```
C 및 Objective-C의 산술 연산자와는 달리 Swift 산술 연산자는 값이 기본적으로 오버플로우하는것을 허용하지 않는다. Swift 오버플로우 연산자(`a &+ b`와 같은)를 사용하여 값 오버플로 동작을 선택할 수있습니다. [Overflow Operators]()를 참조하십시오. // 링크

또한 덧셈 연산자는 문자열을 지원합니다.
```
"hello, " + "world" // "hello, world" 와 같다
```

두 개의 문자 값이거나 하나는 문자`Character` 값이거나 하나는 `Character` 값 그리고 하나는 문자열`String` 값일때 두 개를 함께 더해서 새로운 문자열`String` 값을 만들 수 있습니다.

```
let dog: Character = "🐶🐶
let cow: Character = "🐮"
let dogCow = dog + cow
// dogCow is equal to "🐶🐮"
```
이것에 대해선 [문자열과 문자(Concatenating Strings and Characters)]()를 참조 바랍니다. // 링크

## 나머지 연산자
나머지 연산자는 (`a % b`) `b` 의 많은 배수가 `a`에 맞게 곱해지며 그리고 남아 있는 값을 반환합니다. (이는 _나머지_ 라고 불립니다.)

> NOTE

> 나머지 연산자는 (%`%`) 또한 _모듈로(modulo) 연산_으로 다른 언어에 알려져있다. 그러나 Swift에서의 동작은 음수를 의미한다. 엄격히 말하면, 모듈로 연산보다는 나머지 연산이다.

여기에 나머지 연산의 동작이 어떻게 되는지 나와있습니다. ` 9 % 4 ` `을 계산해보면, 당신은 첫번째로 `4`들을 곱하여 `9`에 맞게 할9`안에 몇 개의 `4`가 들어갈 수 있는지 알아낼 것이다.
![remainderinteger_2x.png](images/remainderinteger_2x.png)

당신은 `4`들을 `9`에 맞추었고 그리고 나머지는 `1`이다. (오렌지 색깔을 보라)

Swift에서는 이렇게 쓰여집니다.

`
```
9 % 4 // 1과 같다
``
`

`a % b` 의 답을 측정해보면, `%` 연산자는 나머지 출력과 `=` 연산자를아래의 방정식을 계산하고, `remainder`를 반환합니다.

`a` = (b`b` x `배수`) + `나머지`

`배수`는 `a` 에 들어갈 `b`의 최대의 숫자입니다.

`9` 와 `4`를 식에 대입 할경우

` 9` = (4 × 2`4` × `2`) + `1 `

`a` 의 값이 음수 일때도 같은 메소드가 지원되며 나머지 값이 음수가 나옵니다.

```
-9 % 4 // -1과 같다
``
`

`-9` 와 `4` 를 넣으면 다음과 같은 식이 나옵니다.

`-9` = (4`4` × `-2`) + `-1`

나머지 값이 `-1`이 주어집니다.

`b`가 음수일때 부호는 무시됩니다. 이 뜻은 `a % b` 와 `a % -b`는 항상 같은 대답을 주고 있다는 것을 의미합니다.

## 부동 소수점 나머지 연산
C 와 Objective-C의 나머지 연산과는 달리, Swift의 나머지 연산은 부동 소수점 연산 또한 지원합니다.

````
8 % 2.5 // 2.5와 같음
``
`

예를 들어 `8`을 `2.5`로 나누었을때 `3`과 같으며 나머지는 `0.5`와 같습니다. 그리고 나머지 연산이 반환하는 값은 `Double` 타입의 `0.5` 입니다.
![remainderfloat_2x.png](images/remainderfloat_2x.png)


## 증가연산자와 감소 연산자
C와 같이, Swift는 증가 연산자(`++`)와 감소 연산자(`--`)를 제공한다. 이것은 숫자 변수 `1`를 증가시키거나 감소시키는 축약형입니다. 정수형과 부동소수점형을 연산자와 같이 사용 가능합니다.
```
var i = 0
++i // i 는 이제 1과 같다
```

만약 `++i` 호출마다 `i`의 값은 `1` 씩 증가됩니다. 기본적으로 `++i` 는 `i = i + 1` 의 약어입니다. 마찬가지로 `--i`를 `i = i - 1` 의 약어로 사용할 수 있습니다.

`++` 와 `--` 기호는 전위연산자 또는 후위연산자로 사용이 가능합니다. `++i` 와 `++i`는 둘다` i`의 값을` 1` 증가시키는 방법입니다. 비슷하게, `--i` 와 `i--`는 `i`의 값을 `1` 감소시키는 방법입니다.

이러한 수정연산자는 `i` 와 그리고 반환값 까지 변화시킵니다. 만약 `i`에 저장된 값을 증가 또는 감소 시킬 경우 반환값을 무시 할 수도 있습니다. 그러나 반환된 값을 사용할 경우, 당신은 다음과 같은 규칙에 따라 연산자의 전위연산자나 후위연산자를 사용하는지 여부에 따라 달라집니다.

- 만약 변수 앞에 쓰여질 경우, 값이 증가한 후에 반환된다.
- 반약 변수 뒤에 쓰여질 경우, 값이 반환된 뒤에 증가된다.

예제 코드 (For example:)
```
var a = 0
let b = ++a
// a 와 b 둘다 1과 같다.
let c = a++
// a 는 지금 2 입니다. 그러나 c는 이전의 값인 1이 이미 설정되어있습니다.
```

위의 예제코드에서 `let b = ++a` 는 `a`를 반환하기 전에 `a`를 증가시킨다. 이 방법은 `a` 와 `b` 의 새로운 값이 동등한 이유이다.

그러나, `let c = a++` 는 `a`를 후에 반환한 뒤 `a`를 증가시킨다. 이 뜻은 `c`가 없은 값은 예전의 값인 `1`이며 `a`에게는 업데이트 된 `2`와 같습니다.

`i++`의 특정동작을 필요로 하지 않는한, `++i` 나 `--i`를 사용하는것이 좋습니다. 왜냐하면 그것은 모든 경우에 `i`를 결과를 반환하고 수정하는 예상된 동작을 가지기 때문입니다.

## 단항 마이너스 연산자
숫자 값의 부호는 전위연산자 `-`를 사용하여 전환할 수 있다. 이것은 단항 마이너스 연산자로 알려진것입니다.

```
let three = 3
let minusThree = -three // minusThree equal -3
let plusThree = -minusThree // plus equal 3, or "minus minus three"
```

단항 마이너스 연산자는 공백없이 값 바로 앞에 추가됩니다.

## 단항 플러스 연산자
단항 플러스 연산자(`+`)는 간단하게 값 앞에 추가되며 값을 변경하지 않고 값을 반환합니다.

```
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix equals -6
```

플러스 연산자가 있음에도 불구하고 실제로 아무것도 하지 않지만, 당신은 또한 단항 마이너스 연산자를 사용하는 경우에 양수에 대한 코드대칭에 사용할 수 있습니다.

## 복합 할당 연산자
C와 같이 Swift는 다른 작업에 할당(`=`)을 결합하는 복합 할당 연산자를 제공합니다. 한 예를 들어 덧셈 할당 연산자입니다 (`+=`):
```
var a = 1
a += 2
// a 는 3과 같다
```

표현식 `a += 2` 는 `a = a + 2` 의 축약형입니다. 효과적으로 한 연산자가 가산 및 할당이 동시에 결합과 작업이 됩니다.

>NOTE
>
>
복합 할당 연산자는 값을 반환하지 않습니다. 당신은 `let b = a += 2` 이러한 코드를 작성할수 없습니다. 예를 들어 이러한 코드는 위의 증가 및 감소 연산자와는 다릅니다.

복합 할당 연산자의 전체 목록은 [Expressions]() 에서 찾을 수 있습니다. // 링크

## 비교 연산자
Swift는 C의 표준 비교연산자를 지원합니다.

- 같음 연산자 (`a == b`)
- 같지 않음 연산자 (`a != b`)
- 보다 큰 (`a > b`)
- 보다 작은(`a < b`)
- 보다 크거나 같은 (`a >= b`)
- 보다 작거나 같은 (`a <= b`)

>NOTE
Swift는 또한 두 개체 참조가 동일한 인스턴스 객체를 참조하고 있는지 여부를 테스트 하는 연산자를 지원합니다. (`===` 와 `!==`) 자세한 내용은 [Classes and Structures]()를 참조하십시오 // 링크 .

비교 연산자의 각 문장이 참인지 여부를 나타내는 `Bool` 값을 반환합니다 :

```
1 == 1 // true, because 1 is equal to 1
2 != 1 //
2 > 1 // 참
true, because 2 is not equal to 1
2 > 1 // true, because 2 is greater than 1

1 < 2 // true, because 1 is less than 2
1 >= 1 // true, because 1 is greater than or equal to 1
2 <= 1 // 거짓
false, because 2 is not less than or equal to 1
```

비교 연산자는 종종 `if`문 같은 조건문에 사용됩니다 :

```
let name == "world"
if name == "world" {
println("hello, world")
} else {
println("I'm sorry \(name), but I don't recognize you")
}
// prints "hello, world", because name is indeed equal to "world”
```
`if`에 대한 더 많은 정보는 [Control Flow]()를 참조하기 바랍니다. // 링크

## 삼항 조건 연산자
삼항 조건 연산자는 특별한 연산자와 세개의 파트로 이루어져있습니다.
식은 이러합니다. (`question ? answer1 : answer2`)
이 `question`을 기초로하여 참인지 거짓인지에 따라 두 식중 하나를 평가하기 위한 축약어입니다. 만약 `question` 이 참이면 `answer1`을 계산하고 값을 반환합니다; 그렇지 않으면 `answer2`를 계산하고 값을 반환합니다.

삼항 조건 연산자는 아래의 코드에 대한 속기단축 표현입니다.

```
if question {
answer1
} else {
answer2
}
```

이것은 테이블 행의 픽셀 높이를 계산하는 예제입니다. 행의 헤더가 있다면 컨텐츠의 높이가 50 픽셀이상이고 행의 헤더가 없다면 20픽셀 보다 큰것입니다.:

```
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight 는 90과 같다
```

위의 예제코드는 아래 코드의 속기입니다.

```
let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
rowHeight = rowHeight + 50
} else {
rowHeight = rowHeight + 20
}

```

첫번째 예제의 삼항 조건 연산자의 사용은 `rowheight`에 단 한줄의 코드를 이용하여 올바른 값으로 설정될 수 있음을 의미합니다. 이것은 두 번째 예제코드보다 간결하고 그 값이 `if` 문 내에서 수정될 필요가 없기 떄문에 이것은 `rowheight`가 변수가 될 필요성이 없어집니다.

삼항 조건 연산자는 두 식의 어떤 결정을 고려하는것을 위해 효율적인 속기를 제공합니다. 그러나 삼항 조건 연산자는 주의해서 다뤄야 합니다. 남용하면 그 간결함은 읽기 어려운 코드로 이어질 수 있습니다. 하나의 복합 구문에 삼항 조건 연산자와 다중 인스턴스를 결합하는것을 피하십시오.

## 범위 연산자
Swift는 두 개의 범위연산자를 지원하며 이 축약어는 값의 범위를 표현합니다.

### 폐쇄 범위 연산자
폐쇄 범위 연산자(`a...b`)는 `a`에서 `b` 까지의 범위를 정의합니다. 그리고 `a`와 `b`의 값을 포함합니다.

폐쇄 범위 연산자는 `for-in` 루프와 같이 사용하고자 하는 값 범위에서 반복할때 폐쇄 범위 연산자는 유용합니다.

```
for index in 1...5 {
println("\(index) time 5 is \(index * 5)")
}
// 1번쨰 반복 5 is 5
// 2번쨰 반복 5 is 10
// 3번쨰 반복 5 is 15
// 4번쨰 반복 5 is 20
// 5번쨰 반복 5 is 25
```
`for-in` 루프에 대해서는 [Control Flow]() 항목을 참조하십시오 // 링크

### 반 폐쇄 범위 연산자
반 폐쇄 범위 연산자 (`a..b`)는 `a` 에서 `b` 로 실행되는 범위를 정의하지만 `b`가 포함되어 있지 않습니다. 처음 값은 포함하고 있지만 최종값은 아니기 때문에 반폐쇄라고 합니다.

반 폐쇄 범위는 특히 0을 기반으로한 리스트 또는 배열로 작업할때 유용합니다. 그것은 리스트의 길이(포함안되는)까지 계산하는데 유용합니다.
```
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = name.count
for i in 0.count {
println("Person \(i + 1) is called \(names[i]")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack
```
배열에는 4개의 항목이 포함되어있습니다. 하지만 반 폐쇄 범위기 때문에 `0..count` 는 단지 3까지만 카운트 합니다. (배열의 마지막 항목의 인덱스)
배열에 대해 더 참조하고 싶다면 [Arrays(배열)]()을 참조하세요. // 링크

## 논리 연산자
논리 연산자는 `true`와 `false` 불리언 논리 값을 수정하거나 결합합니다. Swift는 C 기반 언어의 세 가지 표준 논리 연산자를 지원합니다.

- NOT (`!a`)
- AND (`a && b`)
- OR (`a || b`)

## 논리 NOT 연산자
논리 NOT 연산자(`!a`)는 불리언 논리 값인 `true` 값을 반전시키고 `false` 값은 `true` 가 됩니다.

논리 NOT 연산자는 전위 연산자입니다. 값 앞에 연산을 공백없이 즉시 표현 할 수 있습니다. 이것은 "`not` a`"로 바로 읽을 수 있으며 다음의 예제에서 볼 수 있습니다.

```
let allowedEntry = false
if !allowedEnrty {
println("ACCESS DENIED")
}
// prints "ACCESS DENIED"
```

`if !allowedEntry` 는 "if not allowed entry" 로 읽을 수 있습니다.
즉 `allowedEntry`이 `false`인 경우 라인 이후의 `not allowed entry` 가 `true`인 경우에 해당할 경우로 실행됩니다.
이 예제에서와 같이 불리언 상수와 변수 이름의 주의 깊은 선택은 이중 부정 또는 혼란한 논리구문을 피하면서 읽기 쉽고 간결한 코드를 유지하는데 도움이 될 수 있습니다.

## 논리 AND 연산자

논리 AND 연산자(`a && b`)의 전체 표현식은 두 값이 모두 `true`이어야 `true`가 됩니다.

반대로 두 값이 `false` 이면 전체 표현식 또한 `false` 입니다. 사실 첫번째 값이 `false` 인 경우 두번째 값이 평가되지 않습니다. 그것을 가능할수 없기 때문에 전체표현식이 `true`와 같게 됩니다. 이는 _short-circuit evaluation_ 로 불립니다.

이 예제에서는 두 개의 `Bool`값을 고려하여 만약 두 값이 `true` 에만 접근할 수 있습니다.

```
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
println("Welcome!")
} else {
println("ACCEssSS DENIED")
}
// prints "ACCESS DENIED"
```

## 논리 OR 연산자
논리 OR 연산자(`a || b`)는 인접한 파이프 문자로 만든 중위연산자 입니다. 전체표현식이 `true`가 될 때 까지 두 개의 값 중 하나만이 참이어야 하는 논리식을 만드는데 사용합니다.

위의 논리 AND 연산자처럼 논리 OR 연산자는 식을 고려할떄 short-circuit evaluation을 사용합니다. 논리 OR식의 좌측에 `true`가 해당하는 경우는 전체 표현식의 결과를 변경 할수 있기 때문에 우측은 계산되지 않습니다.

아래의 예제에서 첫 번째 `Bool` 값(`hasDoorKey`)은 `false`이지만 두 번째 값(`knowsOverridePassword`)는 `true`이다. 하나의 값 이`true`이기 떄문 전체표현식은 `true`로 평가하고 접근이 허용됩니다.

```
let hasDoorKey = false
let knowOverridePassword = true
if hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```

## 복합 논리 연산자

당신은 여러 논리 연산자를 결합하여 복합 논리 연산자를 만들 수 있습니다.

```
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```

이 예제는 `&&` 및 `||` 연산자를 여러개 사용하여 긴 복합 표현식을 만들었습니다. 그러나 `&&` 와 `||` 연산자는 여전히 두 개의 값에 대해 작동하므로 이는 실제로 서로 세개가 연결된 작은 표현입니다.

만약 우리가 문의 코드를 입력하고 망막 검사를 통과한경우; 우리가 유효한 도어 키가 있는 경우이거나 긴급 재정의 암호를 알고있는 다음에 접근할 수 있습니다.

`enteredDoorCode` 와 `passedRetinaScan` 그리고 `hasDoorKey` 의 값에 기초하여 처음 두 개의 작은 표현식은 `false` 입니다. 그러나 긴급 재정의 암호가 `true`로 알려져있습니다 ,그래서 전체 복합 표현식은 여전히 `true`로 평가됩니다.

## 괄호 명시
괄호가 엄격히 필요하지 않은경우, 읽기 복잡한 표현의 의도록 쉽게 만들수 있는 경우에 괄호가 포함되는것이 유용한 경우가 종종 있다.

위의 door access 예제 코드에서 그것의 의도를 명시적으로 확인하기 위해 복합 표현식의 첫번째 부분을 괄호를 추가하는데에 유용합니다.

```
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
```

괄호는 처음 두 값을 전체 논리에서 별도의 가능한 상태의 일부로 분명히 간주되게 만듭니다. 복합식의 출력이 변하지는 않지만 전체적인 목적이 독자에게 명확해집니다. 가독성은 항상 간결함을 선호합니다; 괄호의 사용은 당신의 의도를 확실히 파악하는데 도움이 됩니다.

chapter5
# 05 문자열과 문자 (Strings and Characters)
> Translator : 해탈 (kimqqyun@gmail.com)

_문자열_은 `"hello, world"` 또는 `"albatross"` 와 같은 문자의 컬렉션입니다. Swift 문자열은 문자열`String` 타입으로 표시되며 이는 문자 타입의 컬렉션 값 표현입니다.

Swift 문자열 및 문자`String` 및 `Character` 타입은 코드와 함께 텍스트 작업에서 유니코드호환을 완벽호환하며 빠릅니다. 문자 생성 및 조작을 위한 구문은 C 문자열과 유사한 구문을 사용하여 가볍게 읽을 수 있습니다. 문자열 연결은 두 문자열을 추가할 때 `+` 연산자를 추가하는 것만큼 간단하며 문자열의 가변성은 Swift의 다른 값과 상수나 변수 그리고 다른 값들의 선택으로 관리됩니다.

Swift의 문자열`String` 유형은 빠르고 현대적인 구현에도 불구하고 문법이 단순합니다. 모든 문자열 인코딩이 독립적인 유니코드 문자로 구성, 다양한 유니코드 표현에 접근하기 위한 지원을 제공합니다.

문자열 삽입 과정에서 상수, 변수, 리터럴 및 긴 문자열을 삽입할 수 있습니다. 이것은 사용자 정의 문자열 값을 만들어서 보여주거나 저장을 쉽게 할 수 있습니다.


> NOTE
Swift의 문자열`String` 타입은 Foundation의 `NSString` 클래스에 연결됩니다. 당신은 Cocoa 또는 Cocoa Touch의 Foundation 프레임워크로 작업하는 경우 `NSString`의 API를 이용하여 문자열`String` 값 호출을 만드는 것이 가능하며 또한 이 장에서 설명한 문자열`String` 기능도 사용 가능합니다. 또한, `NSString`의 API 인스턴스를 필요로 하는 문자열`String` 값도 사용 가능합니다.
Foundation 과 Cocoa 에 대한 자세한 정보는 _[Using Swift With Cocoa and Objective-C_]() 를 참조하십시오.

## 문자열 리터럴

코드 내에서 미리 정의된 문자열`String` 값인 리터럴등을 포함할 수 있습니다. 문자열 리터럴이란 큰따옴표로 둘러싸인 텍스트 문자의 고정된 순서입니다.

문자열 리터럴은 상수나 변수의 초기값을 제공하는것에 사용될 수 있습니다.
```
let someString = "Some string literal value"
```

Swift는 초기화된 문자열 리터럴 값으로 `someString` 상수에 대한 문자열`String`의 형식을 유추합니다.

문자열 리터럴은 다음과 같은 특수 문자를 포함할 수 있습니다.

- 이스케이프 특별 문자 `\0` (null 문자), `\\` (백슬래시), `\t` (수평 탭), `¶
` (줄 바꿈), `\r` (캐리지 리턴), `\"` (큰따옴표), `\'` (작은따옴표)
- 1바이트 유니코드 스칼라는 `\xnn` 이며 `nn`은 두개의 16진수 숫자입니다.
- 2바이트 유니코드 스칼라는 `\unnnn` 이며 `nnnn`은 4개의 16진수 숫자입니다.
- 4바이트 유니코드 스칼라는 `\Unnnnnnnn` 이며 `nnnnnnnn`은 8개의 16진수 숫자입니다.

아래의 코드는 여러 종류의 특수문자의 예를 나타냅니다.
`wiseWords` 상수는 두 개의 이스케이프 문자가 포함되어 있습니다. `dollarSign` 과 `blackHeart` 및 `sparklingHeart` 상수는 세 가지 다른 유니코드 스칼라 문자 형식을 보여줍니다.

```
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\x24" // $, Unicode scalar U+0024
let blackHeart = "\u2665" // ♥, Unicode scalar U+2665
let sparklingHeart = "\U0001F496" // 💖, Unicode scalar U+1F496
```

## 빈 문자의 초기화 (Initializing an Empty String)

긴 문자열을 만들기 위한 포인트를 위해 빈 문자열`String` 값을 만들려면 빈 문자열 리터럴을 변수에 할당하거나 초기화 문법을 사용하여 새 문자열`String` 인스턴스를 초기화합니다.

```
var emptyString = "" // 빈 문자열 리터럴
var anotherEmptyString = String() // 초기화 문법
// 두 문자열 모두 비어있으며 서로 똑같다.

```

`isEmpty`의 불리언 속성을 체크하여 문자열 값이 비어있는지 여부를 확인할 수 있습니다.
```
if emptyString.isEmpty {
println("여기엔 아무것도 보이지 않습니다.")
}
// prints 여긴 아무것도 보이지 않습니다."
```

## 문자열 가변성

특정 문자열`String`을 변수에 할당하여(수정될 수 있는 경우) 수정(또는 변경)할 수 있는지를 나타내거나 상수(수정될 수 없는 경우)를 말합니다.
```
var variableString = "Horse"
variableString += " and carriage"
// variableString 은 "Horse and carriage" 입니다.

let constantString = "Highlander"
constantString += " and another Highlander"
// 컴파일 에러 - 상수 문자열은 변경될 수 없습니다.
```

> NOTE
> 이 방법은 Objective-C 또는 Cocoa에서 다른 방법으로 접근합니다. 문자열이 변경될 수 있는지를 나타내기 위해 두 개의 클래스 (`NSString` 또는 `NSMutableString`) 사이에서 선택할 수 있습니다.

## 문자열 값 타입 (Strings Are Value Types)

Swift의 문자열`String` 타입은 값 타입입니다. 새 문자열`String` 값을 만드는 경우에 상수 또는 변수에 할당되면 그 문자열 값이 함수나 메소드에 전달 될 때 복사됩니다. 각각의 경우에 기존의 문자열`String` 값의 새 복사본이 전달되거나 복사되며 이는 원래의 버전이 아닙니다. 값 타입은 [Structurs and Enumerations Are Value Types]()를 참조하십시오. // 링크

>NOTE
>
>
이 동작은 Cocoa에 있는 `NSString` 과는 다릅니다. Cocoa에 있는 `NSString` 인스턴스를 생성할 때와 함수나 메소드에 전달하거나 변수에 할당 및 전달될 때 같은 단일 `NSString`에 대한 참조를 할당합니다. 특별히 요청하지 않는 한 문자열에 대해 어떠한 복사는 수행되지 않습니다.

Swift의 문자열`String` 기본 복사 동작(copy-by-default)은 문자열 값이 함수나 메소드에의해 수행될 때 어디에서 오는지 상관없이 정확한 문자열`String` 값을 소유하고 깨끗한지 확인합니다. 스스로 수정하지 않는 한 전달된 문자열이 수정되지 않는다는 것을 보장합니다.

내부적으로 Swift의 컴파일러는 실제 복사가 반드시 필요한 경우에만 발생하도록 최적화하고 있습니다. 이 뜻은 문자열로 작업할 때 항상 좋은 성능을 의미합니다.

## 문자와 작업하기 (Working with Charaters)

Swift의 문자열`String` 타입은 지정된 순서로 문자`Character` 값의 컬렉션을 나타냅니다. 각 문자`Character`의 값은 하나의 유니코드 문자를 나타냅니다. 각 문자`Character`에 대해 `for-in` 루프의 문자 반복을 사용하여 각각의 문자의 값에 접근할 수 있습니다.

```
for character in "Dog!🐶"{
println(character)
}
// D
// o
// g
// !
// 🐶
```

`for-in` 루프에 대해서는 For Loops 를 참조하십시오 // 링크

또한, 문자`Character` 타입 주석을표시를 제공하여 단일 문자열 리터럴에서 독립(stand-alone) 문자`Character` 상수나 변수를 만들 수 있습니다.

```
let yenSign: Character = "¥"
```

## 문자 세기 (Counting Characters)
문자열의 문자의 수를 검색하려면 전역 함수인 `countElements`를 호출하여 함수의 유일한 매개변수인 문자열을 전달합니다.

```
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")
// prints "unusualMenagerie has 40 characters"
```

> NOTE
>
>
다른 유니코드 문자와 같은 유니코드 문자의 다른 표현은 메모리의 저장된 다른 양을 필요로 할 수 있습니다. 이 때문에 Swift의 문자는 각 문자의 표현에서 동일한 양의 메모리를 차지하지 않습니다. 결과에 따라 문자열의 길이는 차례로 그 문자의 각각 반복하지 않고는 계산될 수 없다. 당신이 특히 긴 문자열 값으로 작업하는 경우 `CountElements` 기능이 해당 문자열에 대한 정확한 글자수를 계산하기 위해 문자열에서 문자 세기를 반복해야 한다는 것을 인식해야 합니다.
>
>
또한 `countElements`에 의해 반환된 문자 수는 항상 같은 문자가 포함되어있는 `NSSString`의 길이 속성과 동일하지 않습니다. 길이는 `NSString`을 기초로 한 문자열 UTF-16 표현 내의 16bit 유닛 숫자에 기반을 두고 문자열에서 유니코드 문자의 수에 기반을 두지는 않습니다.
이 사실을 반영하기 위해 길이 속성은 Swift가 `NSString` 문자열 값에 접근할 때 `utf16count`라고 합니다.

## 문자열 및 문자 합치기(Concatenating Strings and Characters)

문자열 및 문자`String` 및 `Character`를 덧셈 연산자(`+`)와 함께 추가하여 새로운 문자열(또는 연결된) 값을 만들 수 있습니다.

```
let string1 = "hello"
let string2 = "there"
let character1: Character = "!"
let character2: Character = "?"

let stringPlusCharacter = string1 + character1 // equals "hello!"
let stringPlusString = string1 + string2 // equals "hello there"
let characterPlusString = character1 + string1 // equals "!hello"
let characterPlusCharacter = character1 + character2 // equals "!?"
```
또한 덧셈 할당연산자(+=)로 기존의 문자열 변수에 문자열이나 문자`String` 변수에 `String`이나 `Character` 값을 추가할 수 있습니다.
```
var instruction = "look over"
instruction += sting2
// instriction 은 "look over there" 와 같습니다.

var welcome = "good mornig"
welcome += character1
// welcome 은 "good morning!" 과 같습니다.
```

> NOTE
>
> 문자
`Character` 값은 하나의 문자만을 포함해야만 하기 때문에 기존의 문자변수에 문자열이나 문자`Character` 변수에 `String`이나 `Character`를 추가할 수 없습니다.

## 문자열 삽입

문자열 삽입은 상수, 변수, 리터럴 그리고 표현식을 혼합하여 이용 및 문자열 안에 문자 값을 포함하여 새로운 문자열`String` 값을 만드는 방법입니다. 문자열 리터럴에 삽입된 각 항목은 백슬래시가 앞에 있으며 한 쌍의 괄호로 싸여있습니다.
```
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
```
위의 예에서 `multiplier`의 값은 `\(multiplier)` 문자열 리터럴로 삽입됩니다. 이 플레이스홀더는 실제 문자열 삽입이 평가될 때 `multiplier`의 실제 값으로 치환됩니다.

`multiplier`의 값은 큰 문자열 표현식 나중의 일부입니다. 이 표현식은 `Double(mutiplier) * 2.5` 의 값을 계산하고 문자열로 결과 (`7.5`)를 삽입됩니다. 이 경우에 문자열 리터럴 내부에 포함된 경우 표현은 `\(Double(multiplier) * 2.5)`로 기록됩니다.


> NOTE
>
>
문자열에 삽입된 괄호안에 쓰는 표현으로 이스케이프 큰 따옴표 (`"`) 또는 백 슬래시(`\`)와 캐리지 리턴 및 줄바꿈을 포함할 수 없습니다.

## 문자열 비교
Swift는 문자열`String` 값을 비교하는 세가지 방법을 제공합니다 : 문자열 같음, 전위 같음, 후위 같음 // 디스커션에 올림

### String Equality
두개의 문자열`String` 값이 동일한 순서로 포함되어 있는 경우 두개의 문자열 값이 동일한 것으로 간주됩니다.

```
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
pinrtln("These two strings are considered equal")
}
// prints "These two strings are considered equal"
```


### Prefix and Suffix Equality

문자열이 특정 문자열의 전위 또는 후위가 있는지를 확인하여 문자열의 `hasPrefix``hasSuffix` 메서드를 호출, `String` 타입의 단일 인수인 부울값을 각각 반환합니다. 두 가지 방법은 기본 문자열과 전위나 문자열 사이에 문자별 비교를 수행합니다. 두 가지 방법은 기본 문자열과 전위나 후위 및 문자열 사이의 문자별 비교를 수행합니다.


아래의 예는 _셰익스피어의 로미오와 줄리엣_ 의 처음 두 액트인 장면의 위치를 나타내는 문자열의 배열을 고려하였습니다.

```
let romeoAndJuliet = [
"Act 1 Scene 1: Verona, A public place",
"Act 1 Scene 2: Capulet's mansion",
"Act 1 Scene 3: A room in Capulet's mansion",
"Act 1 Scene 4: A street outside Capulet's mansion",
"Act 1 Scene 5: The Great Hall in Capulet's mansion",
"Act 2 Scene 1: Outside Capulet's mansion",
"Act 2 Scene 2: Capulet's orchard",
"Act 2 Scene 3: Outside Friar Lawrence's cell",
"Act 2 Scene 4: A street in Verona",
"Act 2 Scene 5: Capulet's mansion",
"Act 2 Scene 6: Friar Lawrence's cell"
]
```
Act 1의 장면의 수를 `romeoAndJuliet` 배열에 `hasPrefix`를 사용하여 계산할 수 있습니다.


```
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
++act1SceneCount
}
}
println("There are \(act1SceneCount) scenes in Act 1")
// prints "There are 5 scenes in Act 1"
```

마찬가지로 `hasSiffix` 메소드를 사용하여 Capulet's mansion and Friar Lawrence's cell의 장면의 수를 계산합니다.

```
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
if scene.hasSuffix("Capulet's mansion") {
++mansionCount
} else if scene.hasSuffix("Friar Lawrence's cell") {
++cellCount
}
}
println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// prints "6 mansion scenes; 2 cell scenes"
```

## 대문자와 소문자 문자열
`uppercaseString``lowercaseString` 속성을 가진 문자열에 대문자와 소문자 버전에 접근할 수 있습니다.

```
let normal = "Could you help me, please?"
let shouty = normal.uppercaseString
// shouty is equal to "COULD YOU HELP ME, PLEASE?"
let whispered = normal.lowercaseString
// whispered is equal to "could you help me, please?"
```

## 유니코드
유니코드는 국제 표준 인코딩 및 텍스트를 나타내는 것입니다. 유니코드는 표준화된 형태로 거의 모든 문자를 표시하고 텍스트 파일 또는 웹페이지와 같은 외부 소스로부터 해당 문자를 읽고 쓸 수 있습니다.

Swift의 문자열 및 문자`String` 및 `Character` 유형은 유니코드를 완벽하게 준수합니다. 아래에 설명으로 그들은 서로 다른 유니코드 인코딩의 숫자를 지원합니다.

### 유니코드 용어

유니코드의 모든 문자는 하나 이상의 유니코드 스칼라로 표현될 수 있습니다. 유니코드 스칼라는 문자 또는 수정에 대한 고유한 21bit(그리고 이름) 입니다, 이러한 `U+0061`나 `LOWERCASE LATINLETTER A("a")` 과 같이 `U+1F425`와 `FRONT-FACING BABY CHICK("🐥")` 같은 경우입니다.

유니코드 문자열이 텍스트 파일이나 다른 저장소에 기록될 때 이러한 유니코드 스칼라는 여러 유니코드 정의 중 하나의 형식으로 인코딩됩니다. 각 형식은 코드 단위로 알려진 작은 덩어리의 문자열을 인코딩합니다. 이들은 UTF-8 (8bit 코드 단위로 문자열을 인코딩) 형식과 UTF-16 (16bit 코드 단위로 문자열을 인코딩) 형식을 포함하고 있습니다.

### 문자열의 유니코드 표현

Swift는 문자열의 유니코드 표현에 접근할 수 있는 여러 가지 방법을 제공합니다.

유니코드 문자로 개별 문자`Character` 값에 접근을 `for-in` 구문으로 반복할 수 있습니다. 이 과정은 [문자와 작업하기]()에 설명되어있습니다.

또한, 유니코드 호환 표현 중 하나의 문자열`String` 값에 접근:

- UTF-8 코드단위의 컬렉션(문자열의 `UTF-8` 속성에 접근)
- UTF-16 코드단위의 컬렉션 (문자열의 `UTF-16` 속성에 접근)
- UTF-21bit 유니코드 스칼라값의 컬렉션 (문자열의 `unicodeScalars` 속성에 접근)

아래의 각 예제에서는 D,O,G,! 및 (DOG FACE) 문자로 구성되어 있으며 문자열은 다른 표현을 보여줍니다. (`DOG FACE` 또는 `유니코드 스칼라 U+1F436)

```
let dogString = "Dog!🐶"
```

#### UTF-8

문자열의 UTF-8 속성을 반복하여 문자열`String`의 `UTF-8` 표현에 접근할 수 있습니다.
`UTF8View`의 속성은 부호 없는 8 bit(`UInt8`) 값의 모음이며 문자열의 UTF-8 의 각 바이트 문자열 표현입니다.:

```
for codeUnit in dogString.utf8 {
print("\(codeUnit) ")
}
print("¶
")
// 68 111 103 33 240 159 144 182
```

위의 예에서 첫 번째 네개의 십진수 `codeUnit` 값(`68`,`111`,`103`,`33`)은 그 문자 UTF-8로 표현과 동일한 D,o,g`D`,`o`,`g` 그리고 !`!`를 나타내며 이것들은 ASCII의 표현과 동일합니다. 마지막 네개의 `codeUnit`의 값(`240`,`159`,`144`,`182`)은 `DOG FACE`의 4바이트 UTF-8 표현입니다.

#### UTF-16

UTF-16 속성에 반복하여 UTF-16 표현에 접근할수 있습니다. `UTF816View` 타입의 속성은 부호 없는 16 bit(`UInt16`)값의 모음이며 문자열의 UTF-16의 각 바이트 문자열 표현입니다.:

```
for codeUnit in dogString.utf16 {
print("\(codeUnit) ")
}
print("¶
")
// 68 111 103 33 55357 56374

```

다시 처음 4가지 `codeUnit`의 값(`68`,`111`, `103`, `33`)은 UTF-16 코드 단위의 값은 UTF-8의 문자열 표현과 같은 값을 가지며 D,o,g`D`,`o`,`g` 그리고 !`!`의 문자를 표현합니다.

다섯 번째와 여섯 번째 `codeUnit`의 값(`55357` 과 `56374`)는 `DOG FACE` 문자를 UTF-16을 써로게이트 페어로 표현한것이다. 이 값은 `U+D83D`(십진수 값 `55357`)의 lead 써로게이트 값과 `U+DC36`(십진수 값 `56374`)의 trail 써로게이트 값입니다.

#### 유니코드 스칼라

`unicodeScalars` 속성을 반복하여 문자열`String` 값의 유니코드 스칼라 표현에 접근할 수 있습니다. 이 속성타입은 `UnicodeScalarView` 이며 `UnicodeScalar` 값 타입의 컬렉션입니다. 유니코드 스칼라 21bit 코드 포인트는 lead 써로게이트나 trail 써로게이트가 아닙니다.

각 `UnicodeScalar`는 값 속성(value property)이 있으며 이것은 스칼라의 21bit 값을 반환합니다. `UInt32` 안의 값을 표현한 것입니다.:

```
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ")
}
print("¶
")
// 68 111 103 33 128054
```

`Value` 속성들은 처음 4개의 유니코드스칼라`UnicodeScalar` 값(`68`, `11`, `103`, `33`)을 다시 문자 `D`, `o`, `g` 와 `!`를 표현합니다.
다섯 번째이면서 마지막인 유니코드스칼라 값`UnicodeScalar`의 `Value` 속성은 십진법의 `12804`이며 16진법 `1F436`과 같습니다. 이는 `DOG FACE` 문자인 유니코드 스칼라 `U+1F436`과 같습니다.

`Value` 속성들을 쿼리하는 대신 각 `UnicodeScalar` 값은 또한 문자열 삽입으로 새로운 문자열`String` 값을 생성하는데 사용될 수 있습니다.

```
for scalar in dogString.unicodeScalars {
println("\(scalar) ")
}
// D
// o
// g
// !
// 🐶
```



chapter6
# 06 컬렉션 타입 (Collection Types)

> Translator : 유정협 (justin.yoo@aliencube.com)

스위프트는 여러 값들을 한꺼번에 저장하기 위해 배열과 딕셔너리로 알려진 두가지 *_컬렉션 타입*_을 제공한다. 배열은 동일한 타입을 가진 값을 순서대로 저장한다. 딕셔너리는 동일한 타입을 가진 값을 순서와 상관 없이 저장한다. 따라서, 딕셔너리는 유일한 식별자인 키를 통해 값을 찾고 참조하게 된다.

스위프트에서 배열과 딕셔너리는 항상 자신이 저장하고자 하는 키와 값의 타입을 확인한다. 이것은 다른 타입을 가진 값을 배열이나 딕셔너리에 실수로라도 저장하지 못한다는 것을 의미한다. 이는 또한 배열과 딕셔너리에서 값을 가져올 때 어떤 타입의 값을 가져올 수 있는지 확신할 수 있다는 의미이기도 하다. 스위프트에서 이렇게 명시적인 타입 컬렉션을 사용하는 것은 당신의 코드가 명확한 밸류 타입을 가져야 하게끔 하는 것이며 개발시 타입이 맞는지 아닌지를 바로바로 잡아낼 수 있게끔 해준다는 것이다.

> **참고:**
>
NOTE
스위프트의 `Array` 타입은 상수나 변수에 지정될 때, 혹은 함수나 메소드에서 사용될 때 다른 타입들과 다른 행동을 보여준다. 더 자세한 내용은 "[컬렉션의 변경 가능성"\*링크필요\*(Mutability of Collections)]() 섹션과 "[컬렉션 타입에서 할당과 복사 형태"\*링크필요\*(Assignment and Copy Behavior for Collection Types]() 섹션을 참고하도록 하자.


## 배열 (Arrays ##
)
배열은 같은 타입을 가진 여러개의 값을 순서대로 저장한다. 한 배열 안에서는 같은 값이 여러 다른 위치에서 나타날 수 있다.

스위프트에서 배열은 특정한 종류들의 값들을 저장할 수 있다. 이것은 Objective-C의 `NSArray`와 `NSMutableArray` 클라스와는 다르다. `NSArray`와 `NSMutableArray` 클라스는 어느 종류의 객체든 저장할 수 있고, 반환하는 객체의 속성에 대한 어떠한 정보도 제공하지 않는다. 반면에 스위프트에서는 특정 배열에 저장할 수 있는 밸류 타입은 항상 명시적인 타입 선언을 통하거나 타입 추정을 통해 확인한다. 굳이 클라스 타입이 될 필요는 없다. 예를 들어 만약 당신이 `Int` 타입 배열을 하나 생성한다고 하면, `Int` 값이 아닌 어떤 값도 이 배열에 대입할 수 없다. 스위프트는 타입 지정에 대해 안전하고, 배열 안에 무슨 타입이 들어있는지를 혹은 들어갈지를 항상 확인한다.


### 배열 타입 축약 문법 (Array Type Shorthand Syntax ###)

스위프트 배열 타입을 정확하게 쓰려면 `Array` 형태로 해야 한다. 여기서 `SomeType`은 배열에 저장할 타입을 의미한다. 또한 축약 형태인 `SomeType[]`으로도 배열을 사용할 수 있다. 이 두 가지 형태가 기능적으로는 동일할지라도, 축약 형태를 사용하는 것을 권장한다. 이 축약 형태의 배열이 이 가이드 문서에서도 계속 쓰일 것이다.


### 배열 표현식 (Array Literals ###)

배열은 배열 표현식을 통해서 초기화를 시킬 수 있다. 배열 표현식은 하나 또는 그 이상의 값들을 배열 컬렉션에 담는 축약 형태를 가리킨다. 배열 표현식은 대괄호로 둘러싸고, 콤마로 값들을 구분하는 형태로 하여 여러개의 값들을 표현한다.

```
[value1, value2, value3]
```

아래는 `String` 타입의 값들을 저장하는 `shoppingList`라는 배열을 생성하는 예제이다.

```
var shoppingList: String[] = ["Eggs", "Mink"]

// shoppingList has been initialized with two initial items
```

`shoppingList` 변수는 "`String` 타입의 값들을 갖는 배열"로 정의했기 때문에 `String[]` 타입으로 배열 타입을 지정했다. 이렇게 `Strigng` 타입을 갖는 것으로 배열 타입을 지정했기 때문에 이 배열은 오직 `String` 값들만을 저장할 수 있다. 여기서 `shoppingList` 배열은 두 "`Eggs`", "`Mink`" `String` 값을 배열 표현식으로 지정하여 초기화를 시켰다.

> **참고:**
>
NOTE
이 `shoppingList` 배열은 다음에 나올 예제에서 더 많은 쇼핑 목록을 추가하기 때문에 상수를 위한 `let` introducer가 아닌 `var` introducer를 통해 변수로 지정했다.

이 경우에 배열 표현식은 두 `String` 값 이외에는 다른 것을 포함하지 않는다. 이것은 `shoppingList` 변수의 타입 정의 – 오직 `String` 타입의 값들만 저장할 수 있는 배열 – 와 일치한다. 따라서, 배열 표현식을 이용하여 `shoppingList` 변수를 초기화 하는 것이 허용된다.

스위프트의 타입 추정 덕분에 당신은 배열 표현식을 이용하여 같은 타입을 갖는 변수를 초기화 시킨다면 배열 타입을 쓸 필요가 없다. 따라서, `shoppingList` 변수의 초기화는 아래와 같이 좀 더 간결한 형태로도 가능하다.

```
var shoppingList = ["Eggs", "Mink"]
```

배열 표현식의 모든 값들이 모두 같은 타입이기 때문에 스위프트는 `String[]`이 `shoppingList` 변수의 사용에 맞는 타입이라고 추정할 수 있다.


### 배열의 접근 및 수정 Accessing and Modifying an Array

배열은 메소드와 프로퍼티를 통해 접근과 수정이 가능하다. 혹은 subscript 문법을 사용할 수도 있다.

배열 안에 값이 몇 개나 있는지를 확인하기 위해 읽기 전용 속성인 `count` 프로퍼티를 사용한다:

```
println("The shopping list contains \(shoppingList.count) items.")

// prints "The shopping list contains 2 items."
```

불리언 값을 반환하는 `isEmpty` 프로퍼티를 이용하면 `count` 프로퍼티 값이 `0`인지 아닌지 곧바로 확인할 수 있다:

```
if shoppingList.isEmpty {
println("The shopping list is empty.")
} else {
println("The shopping list is not empty.")
}

// prints "The shopping list is not empty."
```

새로운 값을 배열의 마지막에 추가하는 것은 `append` 메소드를 이용하면 된다:

```
shoppingList.append("Flour")

// shoppingList now contains 3 items, and someone is making pancakes
```

추가 할당 연산자인 `+=`를 이용하여 배열의 마지막에 새로운 값을 추가할 수도 있다.

```
shoppingList += "Baking Powder"

// shoppingList now contains 4 items
```

같은 타입을 갖는 배열 표현식을 이용하여 한꺼번에 추가시킬 수도 있다:

```
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]

// shoppingList now contains 7 items
```

배열로부터 값을 찾는 것은 배열 변수 바로 뒤에 대괄호를 사용해서 찾고자 하는 값의 인덱스값을 이용하면 된다:

```
var firstItem = shoppingList[0]

// firstItem is equal to "Eggs"
```

배열의 첫번째 값이 갖는 인덱스는 `0`이다. `1`이 아님을 명심하자. 스위프트에서 배열의 인덱스는 항상 0부터 시작한다.

Subscript 문법을 사용하면 지정한 인덱스에 이미 존재하는 값을 바꿀 수도 있다:

```
shoppingList[0] = "Six eggs"

// the first item in the list is now equal to "Six eggs" rather than "Eggs"
```

Subscript 문법을 이용하면 범위를 줘서 한꺼번에 값을 바꿀 수도 있다. 심지어는 바꾸려고 하는 범위가 실제 값의 크기와 달라도 그게 가능하다. 아래 예제는 `shoppingList` 배열에 있는 "`Chocolate Spread`", "`Cheese`", "`Butter`" 값을 "`Bananas`", "`Apples`"으로 바꾸어 버린다:

```
shoppingList[4...6] = ["Bananas", "Apples"]

// shoppingList now contains 6 items
```

> **참고:**
>
NOTE
Subscript 문법을 사용해서 새 값을 배열의 마지막에 추가하는 것은 안된다. 만약에 배열의 크기보다 큰 인덱스 값을 사용해서 배열에 접근하려 한다면 런타임 에러를 확인할 수 있을 것이다. 하지만 유효한 인덱스 값은 사용 전에 배열의 `count` 프로퍼티를 이용하여 확인이 가능하다. `count` 프로퍼티 값이 `0`인 경우 – 빈 배열인 경우 – 를 제외하면 배열에서 가장 큰 인덱스 값은 항상 `count - 1`이 될 것이다. 인덱스는 항상 `0`에서 시작하기 때문이다.

특정한 인덱스에 배열 값을 넣고 싶다면 배열의 `insert(atIndex:)` 메소드를 이용한다:

```
shoppingList.insert("Maple Syrup", atIndex: 0)

// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list
```

이것은 `insert` 메소드를 이용하여 "`Mayple Syrup`"이란 새로운 값을 `shoppingList` 배열의 가장 앞 `0` 인덱스 값을 가진 곳에 넣는 것이다.

비슷한 방식으로 배열에서 값을 지울 수도 있다. `removeAtIndex` 메소드를 이용하면 되는데, 이 메소드는 배열내 주어진 인덱스에서 특정 값을 지우고 난 후 그 지워진 값을 반환한다. 이 지워진 값은 필요하지 않다면 무시해도 좋다.

```
let mapleSyrup = shoppingList.removeAtIndex(0)

// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string
```

배열에서 값을 지우고난 다음에 생기는 공백은 자동으로 지워진다. 따라서, `0` 인덱스에 해당하는 값은 이제 "`Six eggs`"이다:

```
firstItem = shoppingList[0]

// firstItem is now equal to "Six eggs"
```

만약 배열의 마지막 값을 지우고 싶다면 `removeLast` 메소드를 이용한다. 이 메소드를 이용하면 `removeAtIndex` 메소드를 `count` 프로퍼티와 함께 사용하는 불필요한 수고를 피할 수 있다. `removeAtIndex` 메소드와 마찬가지로 `removeLast` 메소드 역시 지워진 값을 반환한다:

```
let apples = shoppingList.removeLast()

// the last item in the array has just been removed
// shoppingList now contains 5 items, and no cheese
// the apples constant is now equal to the removed "Apples" string
```

### 배열에서 반복문 사용하기 Iterating Over an Array

`for-in` 반복문을 사용하면 배열 안의 모든 값들에 접근할 수 있다:

```
for item in shoppingList {
println(item)
}

// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
```

만약 배열 안의 개별적인 값들과 그에 해당하는 인덱스가 함께 필요하다면 전역 함수인 `enumerate`를 사용해서 배열을 돌릴 수 있다. `enumerate` 함수는 배열내 각각의 값에 대해 인덱스와 결합한 튜플 값을 반환한다. 반복문을 돌리는 도중 이 튜플을 변수나 상수로 분리하여 사용할 수 있다:

```
for (index, value) in enumerate(shoppingList) {
println("Item \(index + 1): \(value)")
}

// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
```

`for-in` 반복문에 대해서는 "[For 반복문"\*링크필요\*]() 항목을 참고하도록 하자.


### 배열의 생성과 초기화 Creating and Initializing an Array ###

배열의 초기화 문법을 이용하면 초기값 할당 없이 특정 타입을 가진 빈 배열을 만들 수 있다:

```
var someInts = Int[]()
println("someInts is of type Int[] with \(someInts.count) items.")

// prints "someInts is of type Int[] with 0 items."
```

`someInts` 변수의 타입은 `Int[]`로 추정 가능한데, 이것은 `Int[]`로 초기화를 했기 때문이다.

또한 만약 컨텍스트 상에서 함수의 인자라든가 이미 타입 선언이 된 변수 혹은 상수라든가 하는 식으로 해서 이미 타입 정보를 갖고 있다면, 빈 배열을 곧바로 빈 배열 표현식을 이용하여 만들 수 있다. 빈 배열 표현식은 `[]`와 같이 대괄호만을 이용한다:

```
someInts.append(3)

// someInts now contains 1 value of type Int

someInts = []

// someInts is now an empty array, but is still of type Int[]
```

스위프트의 `Array` 타입도 특정 크기와 기본 값을 갖는 배열을 만들 수 있는 생성자를 제공한다. 배열에 들어갈 수 있는 값의 갯수(`count` 인자)와 기본 값(`repeatedValue` 인자)을 생성자에 제공하여 배열을 만들 수 있다:

```
var threeDoubles = Double[](count: 3, repeatedValue: 0.0)

// threeDoubles is of type Double[], and equals [0.0, 0.0, 0.0]
```

생성자를 사용할 때 기본 값에서 타입을 추정하기 때문에 배열 생성시 굳이 타입 지정을 할 필요가 없다:

```
var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)

// anotherThreeDoubles is inferred as Double[], and equals [2.5, 2.5, 2.5]
```

마지막으로 이미 존재하는 같은 타입의 두 배열을 `+` 연산자를 통해 합치는 것만으로 새로운 배열을 생성할 수도 있다. 이렇게 만들어진 새로운 배열의 타입은 합치기 전 두 배열의 타입으로부터 추정 가능하다:

```
var sixDoubles = threeDoubles + anotherThreeDoubles

// sixDoubles is inferred as Double[], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
```


## 딕셔너리 Dictionaries ##

_딕셔너리_는 같은 타입을 가진 여러개의 값을 저장하는 하나의 컨테이너이다. 각각의 값은 유일한 키 값에 물려 있으며, 이 키 값은 딕셔너리 안에서 해당 값을 찾기 위한 식별자의 역할을 한다. 배열의 값들과 달리 딕셔너리 안에 저장된 값은 어떤 순서가 정해져 있지 않다. 실제로 사전에서 어떤 단어의 정의를 찾는 것과 매우 같은 방식으로 딕셔너리 안에 정의된 식별자를 이용해서 값을 찾는다.

스위프트의 딕셔너리는 특정한 타입의 키와 그에 따른 값을 저장한다. 이는 Objective-C에서 제공하는 `NSDictionary`와 `NSMutableDictionary` 클라스와는 다르다. `NSDictionary`와 `NSMutableDictionary` 클라스는 어느 종류의 객체든 키와 값으로 저장이 가능한 반면 그 저장된 객체의 속성에 대한 어떠한 정보도 제공하지 않는다. 스위프트에서는 특정 딕셔너리에 저장할 수 있는 키 타입과 밸류 타입은 항상 명시적인 타입 선언을 하거나 타입 추정을 통해 확인한다.

스위프트의 딕셔너리 타입은 `Dictionary` 형태로 쓰인다. 여기서 `KeyType`은 딕셔너리의 키 값으로 쓰이는 값에 대한 타입이고, `ValueType`은 딕셔너리의 키 값에 맞추어 저장하고자 하는 밸류의 타입을 정의하는 것이다.

딕셔너리가 갖고 있는 유일한 제약사항은 반드시 `KeyType`은 해시 가능한 타입이어야 한다. 즉, 그 자체로 유일하게 표현이 가능한 방법을 제공해야 한다는 것이다. 스위프트의 모든 기본 타입들 (`String`, `Int`, `Double`, `Bool`)은 기본적으로 해시 가능한 것들이므로 딕셔너리의 키 타입으로 사용 가능하다. 연관된 값이 없는 열거형의 멤버 값들 역시도 기본적으로 해시 가능한 타입이다. ("[Enumerations"\*링크필요\*]() 참조)


### 딕셔너리 표현식 Dictionary Literals ###

딕셔너리는 딕셔너리 표현식을 통해서 초기화를 시킬 수 있다. 딕셔너리 표현식은 앞에서 살펴봤던 배열 표현식과 비슷한 문법을 갖는다. 딕셔너리 표현식은 하나 또는 그 이상의 키/밸류 쌍을 딕셔너리 컬렉션에 담는 축약 형태를 가리킨다.

키/밸류 쌍은 키와 밸류의 조합이다. 딕셔너리 표현식에서 각각의 키/밸류 쌍 안에서 키와 밸류는 콜론으로 나뉜다. 키/밸류 쌍은 리스트로써, 콤마로 나뉘고 대괄호로 감싼다:

```
[ key 1 : value 1 , key 2 : value 2 , key 3 : value 3 ]
```

아래 예제는 국제공항들의 이름들을 저장하는 딕셔너리를 생성한다. 이 딕셔너리에서 키 값은 국제공항 코드 (IATA 코드)를 나타내는 세글자 코드이며 밸류는 공항의 이름이다:

```
var airports: Dictionary = ["TYO": "Tokyo", "DUB": "Dublin"]
```

`airports` 딕셔너리는 `Dictionary` 타입을 갖게끔 정의했으며 이것은 "`Dictionary` 타입으로서 `String` 타입의 키, `String` 타입의 밸류를 갖는다"는 것을 의미한다.

> **참고:**
>
NOTE
`airports` 딕셔너리는 `let` introducer를 이용한 상수형 대신 `var` introducer를 이용하여 변수로 정의하였다. 이는 아래 예제들에서 이 딕셔너리에 계속해서 공항들을 추가할 것이기 때문이다.

`airports` 딕셔너리는 두 개의 키/밸류 쌍을 포함하는 딕셔너리 표현식을 통해 초기화를 시켰다. 첫번째 쌍은 "`TYO`" 라는 키에 "`Tokyo`" 라는 밸류를 갖는다. 두번째 쌍은 "`DUB`" 라는 키에 "`Dublin`" 이라는 밸류를 갖는다.

이 딕셔너리 표현식은 두개의 `String:String` 쌍을 포함한다. 이것은 `airports` 타입의 정의인 `String` 타입의 키와 `String` 타입의 밸류를 갖는 딕셔너리와 일치한다. 따라서 딕셔너리 표현식을 이용해서 `airpots` 딕셔너리 변수를 두개의 초기값으로 초기화 시킬 수 있다.

As with arrays, you don’t have to write the type of the dictionary if you’re initializing it
with a dictionary literal whose keys and values have consistent types. The initialization of
airports could have been be written in a shorter form instead:
배열과 같이 딕셔너리 표현식의 키/밸류 쌍이 갖는 타입이 일정하다면 딕셔너리 타입을 정의할 필요가 없다. `aiports`의 초기화는 아래와 같은 축약 형태로 표현할 수 있다:

```
var airports = ["TYO": "Tokyo", "DUB": "Dublin"]
```

딕셔너리 표현식 안의 모든 키 값의 타입이 서로 같고, 마찬가지로 모든 밸류 타입이 서로 같기 때문에, 스위프트는 `Dictionary` 타입이 `airports` 딕셔너리에 적용 가능하다고 추정할 수 있다.


### 딕셔너리의 접근 및 수정 Accessing and Modifying a Dictionary

딕셔너리는 메소드와 프로퍼티를 통해 접근과 수정이 가능하다. 혹은 subscript 문법을 사용할 수도 있다. 배열과 같이 딕셔너리 안에 값이 몇 개나 있는지를 확인하기 위해 읽기 전용 속성인 `count` 프로퍼티를 사용한다:

```
println("The dictionary of airports contains \(airports.count) items.")

// prints "The dictionary of airports contains 2 items."
```

딕셔너리에 새 아이템을 추가하기 위해 subscript 문법을 사용할 수 있다. 같은 타입의 새 키를 subscript 인덱스로 사용하여 같은 타입의 새로운 밸류를 할당한다:

```
airports["LHR"] = "London"

// the airports dictionary now contains 3 items
```

You can also use subscript syntax to change the value associated with a particular key:
Subscript 문법을 사용하여 특정 키에 물려 있는 값을 변경시킬 수도 있다:

```
airports["LHR"] = "London Heathrow"

// the value for "LHR" has been changed to "London Heathrow"
```

또다른 subscripting 방법으로써, 딕셔너리의 `updateValue(forKey:)` 메소드를 사용하여 특정 키에 해당하는 값을 설정하거나 변경할 수 있다. 위의 Subscript 예제와 같이 `updateValue(forKey:)` 메소드는 만약 키가 존재하지 않을 경우에는 값을 새로 설정하거나 키가 이미 존재한다면 기존의 값을 수정한다. 하지만 subscript와는 달리 `updateValue(forKey:)` 메소드는 업데이트를 하고난 뒤 이전 값을 반환한다. 이렇게 함으로써 실제로 업데이트가 일어났는지 아닌지를 확인할 수 있게 된다.

`updateValue(forKey:)` 메소드는 딕셔너리의 밸류 타입에 해당하는 `Optional` 값을 반환한다. 예를 들어 어떤 딕셔너리가 `String` 밸류를 저장한다면 이 메소드는 `String?` 타입 또는 "Optional `String`" 타입의 밸류를 반환한다. 이 Optional 밸류는 만약 키가 이미 있었다면 수정하기 이전 밸류를, 아니라면 `nil`을 갖는다:

```
if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") {
println("The old value for DUB was \(oldValue).")
}

// prints "The old value for DUB was Dublin."
```

Subscript 문법을 이용하면 특정 키 값에 대응하는 밸류를 딕셔너리에서 찾을 수 있다. 값이 존재하지 않는 키를 요청할 수 있기 때문에 딕셔너리는 딕셔너리의 밸류 타입에 해당하는 Optional 밸류를 반환한다. 만약 딕셔너리가 요청한 키에 대응하는 밸류를 갖고 있다면, Subscript 는 그 키에 대응하는 밸류를 Optional 밸류를 반환한다. 아니라면 Subscript는 `nil`을 반환한다:

```
if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}

// prints "The name of the airport is Dublin International."
```

Subscript 문법을 이용해 `nil` 값을 특정 키에 할당하는 것으로 딕셔너리에서 키/밸류 쌍을 삭제할 수 있다:

```
airports["APL"] = "Apple International"

// "Apple International" is not the real airport for APL, so delete it

airports["APL"] = nil

// APL has now been removed from the dictionary
```

또는 키/밸류 쌍을 딕셔너리에서 삭제할 때 `removeValueForKey` 메소드를 이용할 수 있다. 이 메소드는 키/밸류 쌍을 삭제하고 삭제된 값을 반환하거나 값이 없다면 `nil`을 반환한다:

```
if let removedValue = airports.removeValueForKey("DUB") {
println("The removed airport's name is \(removedValue).")
} else {
println("The airports dictionary does not contain a value for DUB.")
}

// prints "The removed airport's name is Dublin International."
```


### 딕셔너리에서 반복문 사용하기 Iterating Over a Dictionary ###

`for-in` 반복문을 사용하면 딕셔너리 안의 모든 키/밸류 쌍에 접근할 수 있다. 딕셔너리 각각의 아이템은 `(key, value)` 튜플을 반환하고, 반복문을 돌리는 도중 이 튜플의 멤버들을 분리하여 임시 상수 혹은 변수에 할당하여 사용할 수 있다:


```
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}

// TYO: Tokyo
// LHR: London Heathrow
```

`for-in` 반복문에 대한 자세한 내용은 "For 반복문"\*링크필요\* 섹션을 참고하도록 하자.

또한 딕셔너리의 `keys`, `values` 프로퍼티를 이용하면 키 또는 밸류 컬렉션을 반복문으로 돌릴 수 있다:

```
for airportCode in airports.keys {
println("Airport code: \(airportCode)")
}

// Airport code: TYO
// Airport code: LHR

for airportName in airports.values {
println("Airport name: \(airportName)")
}

// Airport name: Tokyo
// Airport name: London Heathrow
```

만약 딕셔너리의 키 콜렉션, 밸류 콜렉션을 `Array` 인스턴스를 이용하고 싶다면, 딕셔너리의 `keys`, `values` 프로퍼티를 배열로 초기화하여 사용할 수 있다:

```
let airportCodes = Array(airports.keys)

// airportCodes is ["TYO", "LHR"]

let airportNames = Array(airports.values)

// airportNames is ["Tokyo", "London Heathrow"]
```

> **참고:**
>
NOTE
스위프트의 `Dictionary` 타입은 순서를 정하지 않는 컬렉션이다. 키, 밸류, 키/밸류 쌍의 순서는 반복문을 돌릴때 정해지지 않는다.


### 빈 딕셔너리 만들기 Creating an Empty Dictionary ###

배열과 마찬가지로 초기화 문법을 이용하여 비어있는 딕셔너리 타입을 만들 수 있다:

```
var namesOfIntegers = Dictionary()

// namesOfIntegers is an empty Dictionary
```

이 예제는 `Int, String` 타입을 갖는 빈 딕셔너리를 만든다. 키는 `Int` 타입, 밸류는 `String` 타입이다.

만약 컨텍스트에서 이미 해당 타입에 대한 정보를 제공한다면 빈 딕셔너리 표현식을 이용하여 딕셔너리를 초기화하여 만들 수 있다. 빈 딕셔너리 표현식은 `[:]` 으로 나타낼 수 있다:

```
namesOfIntegers[16] = "sixteen"

// namesOfIntegers now contains 1 key-value pair

namesOfIntegers = [:]

// namesOfIntegers is once again an empty dictionary of type Int, String
```

> **참고:**
>
NOTE
스위프트의 배열과 딕셔너리 타입은 제너릭 컬렉션을 구현한다. 제너릭 타입과 컬렉션에 대한 더 자세한 내용은 "[제너릭"\*링크필요\*]() 섹션을 참고하도록 하자.


## 컬렉션의 변경 가능성 Mutability of Collections ##

배열과 딕셔너리는 하나의 컬렉션 안에 여러개의 값을 저장한다. 만약 어떤 변수를 배열이나 딕셔너리 형태로 만든다면 이 컬렉션은 변경이 가능하다. 이는 컬렉션이 초기화된 후에도 여기에 아이템을 더 추가한다거나 뺀다거나 하는 식으로 컬렉션의 크기를 변경시킬 수 있다는 것을 의미한다. 반면에 배열이나 딕셔너리를 상수에 할당한다면 이때에는 컬렉션의 값도, 크기도 바꿀 수 없다.

이러한 불변성 딕셔너리는 기존의 키에 대응하는 값을 바꿀 수 없다는 것을 의미한다. 다시 말해서 불변성 딕셔너리라면 한 번 값이 설정된 후에는 절대로 바꿀 수 없다.

그러나 배열에서 이러한 불변성은 살짝 다른 의미를 갖는다. 불변성 배열의 크기를 바꿀 가능성이 있는 어떤 것도 할 수 없지만, 기존의 배열 인덱스에 새로운 값을 설정하는 것은 가능하다. 이것은 배열의 크기가 고정될 경우, 스위프트의 `Array` 타입에 배열 연산과 관련하여 최적의 성능을 제공한다.

스위프트가 제공하는 `Array` 타입의 변경 가능성은 또한 어떻게 배열 인스턴스가 생성되고 변경되는지에 대해서도 영향을 미친다. 더 자세한 내용은 "[컬렉션 타입에서 할당과 복사 형태"\*링크필요\*]() 섹션을 참조하도록 하자.

> **참고:**
>
NOTE
컬렉션의 크기를 변경시킬 필요가 없는 경우에는 불변성 컬렉션을 만드는 것이 좋다. 이렇게 함으로써 스위프트 컴파일러가 컬렉션의 퍼포먼스에 최적화를 시킬 수 있다.

chapter7
# 07 흐름 제어 (Control Flow)
> Translator : 김나솔(nasol.kim@gmail.com)

Swift 언어에서는 C언어 같은 프로그래밍 언어에서 제공하는 것과 비슷한 제어문 관련 constructs구조를 제공합니다. 이러한 constructs구조에는 `for`나 `while`이 있으며, 이러한 키워드는 어떤 과제작업(task) 여러 번 수행합니다. `if`와 `switch`문은 특정 조건이 충족되는지에 따라서 분기시켜서 코드 블럭을 실행시킵니다. 또한 `break`나 `continue` 같은 구문은 실행의 흐름을 코드 상의 다른 곳으로 이동시킵니다.

C언어에서는 `for`-조건부-증가(increment) 순환문(loop) 이런 방식을 전통적으로 사용하는데, Swfit에서는 `for-in` 순환문(loop)이라는 것이 있어서 배열이나 사전(dictionaries), ranges, 문자열(strings)등 sequence에 대해서iteration하기가 쉽습니다.

C언어의 `switch`문과 비교했을 때, Swift의 `switch`문은 훨씬 더 강력합니다. Swift에서는 `switch`문이 "fall through" 하지 않습니다(역자주: fall through란, switch문에서 한 case에 대해서 처리하고 난 후 다음 case로 넘어가는 것). C언어에서는 실수로 `break`문을 써주지 않아서 에러가 생기는 경우가 있는데 Swift에서는 fall through 하지 않기 때문에 이런 에러를 방지할 수 있습니다. `swich`내의 case에 대해서 여러 종류의 pattern-maching을 사용할 수 있습니다. 수의 범위 match, 투플 match, casts to a specific type. `switch case`에서 match된 값을 임시 상수나 변수에 binding할 수도 있습니다. 이렇게 binding해두면 case의 본문(body) 내에서 이 상수나 변수를 사용할 수 있습니다. 또한 매칭 조건(matching condition)이 복잡한 경우에는, 각 case에 대해서 where절(where clause)을 사용해서 표현할 수 있습니다.

## For 순환문(For Loops)

`for` 순환문(for loop) 사용하면 코드 블럭을 특정 횟수 만큼 수행할 수 있습니다. Swift에는 두 종류의 for 순환문이 있습니다:

* `for-in` : 어떤 범위나 sequence, collection, progression에 대해서, 이 안에 있는 각 항목(item)에 대해서 코드(a set of statement)를 실행합니다.

* `for-condition-increment` : 특정 조건부가 참이 될 때까지 코드를 실행합니다. 보통 루프를 한 번 도는 것이 끝날 때마다 counter를 1씩 증가시킵니다.

### For-In

여러 항목이 들어 있는 컬렉션(collection)이나, 어떤 범위, 배열 안에 들어 있는 항목(item)에 대해서, 또는 문자열에 들어 있는 각 문자에 대해서 iteration을 할 때 `for-in` loop를 사용합니다.

다음의 예는 구구단의 5단에서 처음 몇 개를 출력해 줍니다:
```
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
```

위 예에서는 범위가 1부터 5까지로 정해져 있고(closed range of numbers), 이의 폐쇄 영역이며, 범위에 대해서 컬렉션(collection)안에 들어 있는 각 항목(item)에 대해 이터레이션을 돌고 있습니다. 단, 1...5라고 표현했을 때, `...`(closed range operator)를 보면 알 수 있듯이, 이 범위에는 1과 5가 포함됩니다. 인덱스(`index)`의 값은 범위 내의 첫번째 수, 즉 1이 되며, 루프 내에 있는 구문이 실행됩니다. 위 예에서 루프 안에는 구문이 하나만 있습니다. 인덱스`index`의 현재 값에 대해서 5단의 첫번째를 출력해주는 것입니다. 이 구문이 실행된 다음에 인덱스의 값은 범위 내의 두번째 값, 즉 2가 되도록 업데이트 됩니다. 그리고 `printLnln` 함수가 다시 호출됩니다. 이 작업은 인덱스가 범위의 끝에 이를 때까지 계속됩니다.

위 예에서 인덱스`index`는 상수(constant)이며, 이 상수의 값은 루프를 돌 때마다, 초반에 자동으로 값이 지정됩니다. 따라서 이 상수를 사용하기 전에 선언할 필요가 없습니다. 루프를 선언할 때 포함시키기만 해도 암묵적으로 선언한 셈이 됩니다. 즉 `let` 선언 키워드(declaration keyword)를 써줄 필요가 없습니다.

> NOTE - 인덱스
`index`
상수는 루프의 스코프(scope)안에서만 존재합니다. 루프문이 끝난 다음에 이 인덱스`index`의 값을 확인하고 싶거나, 이 값을 상수가 아니라 변수로 사용하고 싶으면, 루프 안에서 변수로 직접 선언해 주어야 합니다.


범위 내에 있는 값이 필요 없다면, 변수명 대신에 언더바(`_`, underscore)를 써주면 됩니다:

```
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
println("\(base) to the power of \(power) is \(answer)")
println("\(base)를 \(power)번 곱한 것은 \(answer)이다")


// prints "3 to the power of 10 is 59049"
// prints “3의 10승은 59049입니다.”
```

위 예는 어떤 수의 몇 승을 계산해 줍니다(이 예에서는 3`3``10`승을 계산했습니다). 시작하는 값은 1`1`인데(이는 3의 0`3`의 `0`승입니다), 이 시작하는 값에 다시 3을 곱해줍니다. 이 때 0에서 시작해서 9에서 끝나는 half-closed loop를 사용하였습니다. 이 계산을 수행할 때, 루프를 도는 동안 counter의 값은 필요 없습니다. 정확한 횟수만큼 루프를 도는 것만이 중요합니다. 밑줄(`_`, underscore)은 위 예에서 루프 변수 자리에 쓰였는데요, 그 결과 루프를 돌 때의 counter 현재값에 접근할 수 없게 됩니다.

> 리뷰어 주: 10이 포함되는 것을 보면 반개구간이 아니라 폐쇄구간인 1~10인데, 말이 잘못쓰여있는듯. 이건 원문도 그렇네요.

배열 안에 들어 있는 항목(item)에 대해서 이터레이션(iteration)을 할 때에, `for-in` 루프를 사용하세요.

```
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
println("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex !
// Hello, Brian!
// Hello, Jack!
```


딕셔너리(dictionary)에 대해서도 이터레이션(iteration)을 해서 키-값 쌍(key-value pairs)에 접근할 수 있습니다. 딕셔너리에 대해서 이터레이션을 하면, 딕셔너리의 각 항목이 `(key, value)` 투플의 형태로 반환됩니다. 그리고 이 키-값`(key, value)` 쌍은 쪼개어져서 두 개의 상수의 값으로 들어갑니다. 이 값은 `for-in` 루프 내의 본문(body)내에서 사용할 수 있습니다. 아래의 예에서 딕셔너리의 **키**`animalName`이라는 상수에, 딕셔너리의 **값**`legCount`라는 상수에 값으로 들어갑니다:

```
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
println("\(animalName)s have \(legCount) legs")
}
// spiders have 8 legs
// ants have 6 legs
// cats have 4 legs
```
딕셔너리 `Dictionary`안에 있는 항목이 이터레이션 될 때, 딕셔너리 안에 들어 있는 순서대로 되지는 않습니다. 딕셔너리 `Doctionary`안에 들어 있는 데이터는 원래 정의상 순서가 없으며, 이터레이션을 돌 때에도, 어느 항목에 대해서 돌지 확신할 수 없습니다. 배열과 딕셔너리에 대해서 더 자세히 보시려면 [컬렉션 형(Collection Types)]() 장을 참조하세요.


이 이터레이션 되는 순서는 고정되어 있지 않습니다. 딕셔너리 안에 들어 있는 순서대로
배열과 딕셔너리 외에도, 문자열 내의 각 문자에 대해 이터레이션을 돌 때, `for-in` 루프를 사용할 수 있습니다:

```
for character in "Hello" {
println(character)
}
// H
// e
// l
// l
// o
```

### For-조건부-증가부 (For-Condition-Increment )

Swift는 `for-in`루프 말고도 C언어에서 쓰는, 조건부와 증가부가 들어 있는 `for` 루프를 지원합니다:

```
for var index = 0; index < 3; ++index {
println("index is \(index)")
}
// index is 0
// index is 1
// index is 2
```
다음은 이번에 다루는 루프 형식을 일반화해서 나타낸 것입니다.

```
for initialization ; condition ; increment {
statements
}
```

루프의 정의부는 세 부분으로 구성되는데, C언어에서처럼 각 부분을 세미콜론`;`으로 구분하고 있습니다. C언어와는 다르게 Swift에서는 "초기화;조건부;증가부" 부분을 괄호로 감싸주지 않아도 됩니다.

다음은 루프가 실행되는 단계를 나타냅니다:

1. 처음 루프에 들어가면, 초기화 표현식(initialization expression)이 검토되고 루프를 도는 데 필요한 변수나 상수의 값을 지정합니다.
2. 조건 표현식(condition expression)을 검토합니다. 조건부가 거짓(`false)`이면, 루프는 종료하고, 코드 실행(code execution)은 `for` 루프를 닫는 중괄호(})다음 부분에서 계속됩니다. 조건부가 참(`true)`이면, 코드 실행은 루프를 여는 괄호({) 안에서 구문들을 실행합니다.
3. 모든 구문이 실행된 후에는 증가부 표현식(increment expression)이 검토됩니다. 검토 결과 카운터의 값이 증가할 수도 있고 감소할 수도 있습니다. 또는 초기화되었던 변수의 값이 실행된 구문의 결과값에 근거하여 새로운 값으로 대체될 수도 있습니다. 증가부 부분이 검토된 후, 코드 실행은 2단계로 돌아가며, 조건 표현식이 다시 검토됩니다.

위에서 설명한 루프문의 형식(format)과 코드 실행 절차를 개요로 나타내면 다음과 같습니다:
```
initialization
while condition {
statements
increment
}
```
초기화 부분에서 선언된 상수와 변수(예를 들면 var index=0)는 `for` 루프 스코프 내에서만 사용할 수 있습니다. 루프가 끝난 후에도 index의 마지막 값에 접근할 수 있으려면, 루프 스코프가 시작하는 지점 이전에 index를 선언해주어야 합니다 (즉 루프 스코프의 바깥에서 선언해 주어야 합니다):

```
var index : Int // <= 이 부분에서 선언해 주어야..
for index = 0; index < 3; ++index {
println("index is \(index)")
}
// index is 0
// index is 1
// index is 2
println("The loop statements were executed \(index) times")
// prints "The loop statements were executed 3 times"
```

위 예에서 한 가지 주의할 점이 있습니다. 루프가 끝났을 때 `index`의 마지막 값은 2`2`가 아니라 3`3`입니다. 마지막으로 증가부(increment)인 `++index`가 실행되었을 때, `index`의 값은 3`3`이 됩니다. `index`3`3`이 되니, `index < 3` 조건부 `false`가 되서 루프가 끝난 것입니다.

## While 루프 (While Loops)

`while` 루프는 조건부가 거짓이 될 때까지 코드 블럭을 실행시킵니다. 이런 종류의 루프는 보통, 이터레이션이 시작하기 전에 이터레이션이 몇 번이나 돌 지 알지 못할 때 자주 사용합니다. Swift는 두 종류의 `while`루프를 지원합니다. 하나는 `while`인데, 이 루프는 루프를 돌기 시작할 때 조건부를 검토합니다. 다른 하나는 `do-while`인데, 이 루프는 루프를 돌고 나서 조건부를 검토합니다.

### While

`while` 루프는 한 개의 조건부를 검토하는 것에서 시작합니다. 조건부가 참이`true`면, 코드가 실행되며, 조건부가 거짓이`false`가 될 때까지 반복해서 실행됩니다.
다음은 `while`루프를 일반화해서 나타낸 것입니다:

```
while condition {
statements
}
```

이번에 사용할 예제는 뱀과 사다리 게임입니다.

![뱀과 사다리 게임](images/image__255.png)

게임의 규칙은 다음과 같습니다:

* 게임판에는 25개의 칸이 있으며, 목표는 25번 칸에 도달하거나 이를 넘는 것입니다.
* 자기 차례가 오면, 참가자는 6면 주사위를 던지고 나온 수 만큼 점선으로 표시된 경로를 따라서 이동합니다.
* 이동했을 때, 사다리의 아랫 부분에 도달하면, 사다리를 타고 올라갑니다.
* 이동했을 때 뱀의 머리에 도달하면, 뱀을 타고 내려갑니다.

게임판은 정수값 (Int values)으`Int` 값들로 나타냅니다. 게임판의 크기는 `finalSquare` 상수로 정합니다. finalSquare는 배열을 초기화할 때 사용하며, 나중에 게임에 이겼는지 여부를 판별할 때도 사용합니다. 배열 board는 26개의 정수`Int`값 0으로 초기화됩니다. 25개가 아닙니다. (0`0`부터 `25`까지, 26개입니다.)

```
let finalSquare = 25
var board = Int[](count : finalSquare + 1, repeatedValue: 0)
```

몇몇 칸에는 0이 아니라 특정한 값이 지정됩니다. 이 값은 뱀과 사다리 때문에 필요한 값입니다. 사다리의 밑부분이 들어 있는 칸은 게임판에서 앞으로 이동시키는 만큼의 양수(positive number)를 포함하고, 뱀 머리가 들어 있는 칸은 게임판에서 뒤로 이동시키는 만큼의 음수(negative number)를 포함합니다:

```
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
```

3번 칸은 사다리의 밑 부분을 포함합니다. 여기에 가면 참가자는 11번 칸으로 이동합니다. 이것을 나타내기 위해서 `board[03]``+08` 값을 지정합니다. 이는 정수값 8`8`과 동일합니다(`11`3`3`간의 차이). 단항 연산자인 plus operator(`+i`)는 단항 연산자 minus operator(`-i`)와 균형을 이룹니다. 또한 `10`보다 작은 수에는 10자리에 0을 넣어서(예: 8 -> 08) 줄이 맞추어져 가지런하게 보이도록 했습니다.

(이처럼 0을 넣는 등 스타일에 변화를 주는 것은 꼭 필요한 것은 아닙니다만, 이렇게 하면 코드가 더 깔끔하게 보입니다.)


게임 참가자가 시작하는 칸은 "0번 칸"이며, 이 칸은 게임판의 좌측 하단 바깥에 있습니다. 주사위를 처음 던지면, 참가자는 항상 게임판 위로 이동하게 됩니다:

```
var square = 0
var diceRoll = 0
while square < finalSquare {
// 주사위를 던진다
if ++diceRoll == 7 { diceRoll = 1 }
// 주사위를 던져 나온 수 만큼 이동한다
square += diceRoll
if square < board.count {
// 아직 게임판에 있다면, 뱀을 타고 내려가거나 사다리를 타고 올라간다
//if we're still on the board, move up or down for a snake or a ladder
square += board[square]
("Game over!")
```

이 예제에서는 주사위를 던지는 부분을 간단하게 처리했습니다. 난수를 발생시키지 않고, `diceRoll`의 값을 0에서 시작하게 하고, 루프를 돌 때마다, diceRoll 값이 1씩 증가하도록 했습니다. `++i` (prefix increment operator)를 사용해서 말이죠. 그런 다음에 `diceRoll`의 값이 너무 크지 않은지 확인했습니다. `++diceRoll` 값은 `diceRoll`이 1만큼 증가한 값과 같습니다. ++`diceRoll` 값이 7`7`과 같아지면, 값이 너무 커진 것이며, 이 때 `diceRoll` 값을 1로 해줍니다. 이렇게 하면 `diceRoll`의 값은 항상 1,2,3,4,5,6,1,2`1`,`2`,`3`,`4`,`5`,`6`,`1`,`2`, 등등의 값을 가지게 됩니다.

주사위를 던진 후에, 게임 참가자는 `diceRoll` 값 만큼 칸을 이동합니다. 주사위에서 나온 수만큼 이동했는데, 참가자가 25번 칸을 넘어가는 경우가 생길 수 있습니다. 이 경우에는 게임이 끝납니다. 이 시나리오를 따르기 위해서, 코드는 현재의 칸 번호(`square)` 값에다 `board[squre]`에 저장된 값을 더해서 참가자를 이동시키기 전에, 칸 번호`square``board` 배열의 `count` 값보다 작은지 확인합니다.

이렇게 확인작업을 해주지 않으면, `board[squre]`라고 썼을 때 `board 배열의 범위를 넘어서는 값을 접근하려고 시도하게 됩니다.


이렇게 확인작업을 해주지 않으면, board[squre]라고 썼을 때 board
` 배열의 범위를 넘어서는 값을 접근하려고 시도하게 되고, 에러가 날 것입니다. 예를 들어 칸 번호(`square)``26`과 같아지면, 코드는 `board[26]`의 값을 확인하려 할 것이고, 26은 배열의 수보다 큽니다.
이 `while` 루프 실행은 끝납니다. 그리고 루프의 조건부를 확인하고, 루프가 다시 실행되어야 하는지 확인합니다. 게임참가자가 25번 칸이나 25를 넘어서는 칸으로 이동했다면, 루프의 조건부는 거짓이 될 것이고 게임은 끝납니다.
위 예제의 경우에는 `while`루프를 사용하는 것이 적절합니다. 왜냐하면 `while` 루프가 시작되기 전에 게임가 얼마나 계속되어야 하는지 알지 못하기 때문입니다. `while` 루프를 쓰면 특정 조건이 충족될 때까지 계속해서 실행됩니다.

### Do-While

`while`루프와 비슷하지만 약간 다른 루프도 있습니다. 이름은 `do-while`루프이며, 이 루프에서는 루프의 조건부가 검토되기 전에 루프 블록이 한 번 실행됩니다. 그런 다음 조건부가 거짓이 될 때까지 루프를 반복합니다.

다음은 `do-while`문을 간단하게 일반화하여 나타낸 것입니다:

```
do {
statements
} while condition
```
이번에도 뱀과 사다리 게임 예제를 사용하겠습니다. 다만 이번에는 `while` 루프 가 아니라 `do-while` 루프를 사용합니다. `finalSquare`, `board`, `square`, `diceRoll` 변수의 값은 앞에서 `while`루프를 사용했을 때와 동일한 값로 초기화했습니다.

```
let finalSquare = 25
var board = Int[](count : finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
```

이번 예제에서, 루프 내에서 처음으로 하는 작업은 사다리나 뱀이 들어 있는 지 확인하는 것입니다. 사다리를 타고 올라갔을 때 게임 참가자가 바로 25번 칸으로 이동하는 것은 불가능합니다. 즉 사다리를 타는 방법으로는 게임에서 이길 수 없습니다. 따라서 루프 안에서 칸에 뱀이나 사다리가 있는 지 여부를 확인하면 안전합니다.

게임을 시작할 때, 참가자는 “0번 칸”에 있습니다. `board[0]`의 값은 항상 0이며, 이 값이 가지는 효과는 없습니다:

```
do {
// move up or down for a snake or ladder square += board[square]
// 주사위를 던진다
if ++diceRoll == 7 { diceRoll = 1 }
// 주사위를 던져서 나온 수만큼 이동한다
square += diceRoll
} while square < finalSquare
println("Game over!")
```

칸에 뱀이나 사다리가 있는지 프로그램이 확인한 후에, 주사위가 던져집니다. 게임 참가자는 `diceRoll` 값 만큼 칸을 움직입니다. 그런 다음 이번 루프 실행은 끝납니다.

루프의 조건부의 내용(` while square < finalSquare`)은 이전 예제에서와 같지만, 이번에는 루프를 한 번 돈 다음에 이 조건부가 검토됩니다. 이 게임에는 `while`루프보다 `do-while` 루프의 구조가 더 적절합니다. 이번에 사용한 `do-while` 루프에서, `square += board[quare]` 이 부분은 루프의 `while` 조건부에서 `square`가 아직 `board` 상에 있다고 확인한 후에 항상 즉시 실행됩니다. 이렇게 하면 이전 예제에서 한 것처럼 배열의 범위를 확인할 필요가 없어집니다.

## 조건문 (Conditionals Statements)

특정 조건이 충족하는지에 따라 각각 다른 코드를 실행하는 것이 유용한 경우가 많습니다. 어떤 에러가 발생했을 때 특정 코드를 실행시키고 싶을 수도 있습니다. 또는 어떤 값이 너무 높거나 너무 낮을 때 메시지를 보여주고 싶을 수도 있습니다. 이렇게 하려면 코드를 조건문으로 쓰면 됩니다.

Swift에서 코드에 조건문을 추가하는 방법은 두 가지가 있습니다. 바로 `if`문과 `switch`문입니다. 보통 조건의 수가 많지 않을 때에는 보통 `if`문을 사용합니다. 한편 조건의 종류가 다양하고 복잡할 때에는 `switch`문이 더욱 적합하니다. 실행시킬 코드 브랜치를 선택하는데 패턴-매칭이 도움이 되는 경우에도 `switch`문을 사용합니다.

### If

`if`문을 아주 단순하게 표현하면, 하나의 `if` 조건이 있습니다. 그럼 그 조건이 참인 경우에만 코드구문들이 실행됩니다.

```
var temperatureInFahrenheit = 30 if temperatureInFahrenheit <= 32 {
println("It's very cold. Consider wearing a scarf.")
}
// prints "It's very cold. Consider wearing a scarf."
```

위 예제에서는 온도가 화씨 32도(물이 어는 온도)보다 낮은지 같은지 여부를 확인합니다. 온도가 화씨 32도 이하이면, 메시지가 출력됩니다. 그 외의 경우에는 아무런 메시지도 나오지 않으며 코드 실행은 `if`문을 닫는 중괄호(}) 다음으로 이동하여 계속됩니다.

`if`문을 사용할 때에는 `else` 절도 사용할 수 있는데, 여기에는 `if` 조건이 거짓일 때 실행되는 코드가 들어갑니다. `else` 키워드를 사용하여 나타냅니다:

```
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
println("It's very cold. Consider wearing a scarf.")
} else {
println("It's not that cold. Wear a t-shirt.")
}
// prints "It's not that cold. Wear a t-shirt."
```

위에서 두 개의 브랜치 중에서 하나는 항상 실행됩니다. 온도가 화씨 `40`도로 올라갔기 때문에, 스카프를 매라고 조언할 정도로 춥지 않습니다. 따라서 `else` 브랜치가 대신에 실행됩니다.

추가적인 경우를 고려할 때에는 여러 개의 `if`문을 쓸 수도 있습니다:

```
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
println("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
println("It's really warm. Don't forget to wear sunscreen.")
} else {
println("It's not that cold. Wear a t-shirt.")
}
// prints "It's really warm. Don't forget to wear sunscreen."
```

위 예에서, 추가적인 `if` 문이 들어갔습니다. 이 부분은 온도가 특별히 높을 때의 경우에 대한 것입니다.

마지막에 쓴 `else` 절이 있습니다. 이 부분은 온도가 너무 높지도 낮지도 않은 경우에 보여주는 메시지를 출력합니다.

하지만 마지막에 쓴 `else` 절은 선택적입니다. 조건들이 모든 경우를 다뤄야 하지 않는다면, `else`절을 안 써줘도 됩니다:

```
temperatureInFahrenheit = 72
if temperatureInFahrenheit <= 32 {
println("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
println("It's really warm. Don't forget to wear sunscreen.")
}
```

이번 예제에서 온도는 너무 낮지도 너무 높지도 않았습니다. 그래서 `if`나 `else if`조건부에 들어 있는 코드는 실행되지 않았습니다. 그리고 아무 메시지도 출력되지 않았습니다:


### Switch

`switch`문은 값을 검토해서 몇 가지 패턴과 비교합니다. 그런 다음, 처음 매칭되는 패턴이 있는 코드 블록을 실행시킵니다. `if`문을 사용할 때보다 `switch`문을 사용했을 때의 장점은, 여러 가지 경우에 대해서 처리할 수 있게 된다는 점입니다.

`switch`문에서는 어떤 값과 한 개 이상의 동일한 타입(type)의 값을 비교합니다:

```
switch some value to consider {
//switch 고려하려는 값
case value 1 :
respond to value 1
case value 2 ,
value 3 :
respond to value 2 or 3
default :
otherwise, do something else
}
```

`switch`문은 여러 가지 가능한 경우(case)로 구성되어 있습니다. 각 경우는 `case`라는 키워드로 시작됩니다. 특정 값과 비교할 수도 있지만, Swift에서는 더욱 복잡한 패턴과 비교하는(complex pattern matching) 여러 가지 방법이 있습니다. 이에 대해서는 이번 섹션의 뒷부분에 나옵니다.

경우(switch case)의 본문 각각은 서로 독립된 코드실행 브랜치입니다(separate branch of code execution). 이는 `if` 문과 비슷합니다. `switch`문은 어느 브랜치를 선택할지 결정합니다. 이는 비교하려는 값에 대해서 스위치한다고 합니다.

`switch`문 안에는 가능한 경우(case)가 모두 고려되어야 합니다. 즉, 비교하려는 값이 가질 수 있는 모든 값이 해당하는 경우(case)가 반드시 있어야 합니다. 명시적으로 다루지 않는 값에 대해서는 디폴트 경우를 정의해서 처리할 수도 있습니다. 이렇게 할 때에는 키워드 `default`를 사용하며, 이 경우는 `switch`문 안에서 제일 마지막에 위치해야 합니다.

다음의 예에서는 `switch`문을 사용해서 someCharacter 변수에 들어 있는 하나의 소문자를 검토합니다:

```
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
println("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
println("\(someCharacter) is a consonant")
default :
println("\(someCharacter) is not a vowel or a consonant")
}
// prints "e is a vowel "

```
위 예에서 `switch`문 안의 첫번째 경우(case)는 영어의 다섯 개 모음과 매치됩니다. 마찬가지로, 두번째 경우는 영어의 자음 소문자와 매치됩니다.

자음과 모음 이외의 나머지 문자와 매치하는 경우(case)를 만들기 위해, 이 문자들을 다 써주려면 번거롭니다. 그래서 위 예제에서는 디폴트 경우(default case)를 사용하여, 자음과 모음 이외의 문자가 매치되는 경우를 처리했습니다. 이렇게 디폴트 경우를 써줌으로써 이 switch문은 빼먹은 경우(case)가 없는, 포괄적인 switch문이 됩니다.

#### 디폴트로 다음 경우(case)로 넘어가지 않음! (No Implicit Fallthrough)

C언어나 Objective-C의 `switch`문과는 다르게, Swift에서는 디폴트로 다음 경우로 넘어가지 않습니다. 대신에, 한 경우와 매치되면, 그 경우에 해당하는 코드 블록이 실행된 후에, 전체 `switch`문이 종료됩니다. 이 때 명시적으로 `break`문을 써주지 않아도 됩니다. 이렇게 함으로써 C언어에서 보다 실수를 할 위험이 줄어듭니다. C언어에서는 실수로 `break`문을 빠뜨리면 의도하지 않게, 한 개 이상의 경우에 해당하는 코드블럭을 실행시킬 수도 있습니다.

> NOTE
필요하면, 매치된 경우 내의 코드블럭을 다 실행시키기 전에 빠져나올 수도 있습니다. 이에 대해서는 **[Break in a Switch Statement**]() 부분을 참고하세요.

각 경우의 본문은 적어도 한 개 이상의 실행가능한 구문을 포함해야 합니다. 다음의 예제코드처럼 쓰면 안됩니다. 왜냐하면 첫번째 경우의 본문이 비어 있기 때문입니다:

```
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a":
case "A":
println("T he letter A")
default :
println("Not the letter A")
}
// 컴파일 에러가 납니다.
```

C언어의 `switch`문에서는 anotherCharacter가 `“a”``“A”` 경우 둘 다하고 매치되는 반면에, 위 예제의 `switch`문은 그렇지 않습니다. 위 예제에서는 컴파일 에러가 납니다. 왜냐하면 `“a”` 경우의 본문에 실행가능한 코드가 없기 때문입니다.

이런 방식 덕분에, 의도하지 않았는데 다음 경우로 넘어가는 실수를 방지할 수 있으며 의도가 더욱 명확하게 드러납니다.

한 경우에 해당하는 매치를 여러 개 쓸 때에는 콤마`,`로 구분합니다. 그리고 길어지면 줄을 바꾸어 써도 됩니다:

```
switch some value to consider {
case value 1 ,
value 2 :
statements
}
```
> NOTE
특정 경우의 본문이 실행된 후에, 다음 경우로 자동으로 넘어가게 하려면, 키워드 `fallthrough`를 사용하면 됩니다. 자세한 사용방법은 **[Fallthrough**]를 참고하세요.

#### 범위로 매치하기(Range Matching )

스위치`switch` 경우 안에 있는 값에 대해서 어떤 범위 안에 들어있는지 여부를 확인할 수 있습니다. 아래의 예제는 수 범위를 사용하여, 수의 크기에 관계 없이, 어떤 수를 대략적으로 문자로 표현한 결과를 제공합니다:

```
let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount : String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...99:
naturalCount = "tens of"
case 100...999:
naturalCount = "hundreds of"
case 1000...999_999:
naturalCount = "thousands of"
default:
naturalCount = "millions and millions of"
println("There are \(naturalCount) \(countedThings).")
// prints "There are millions and millions of stars in the Milky Way ."
```

#### 튜플 (Tuples)

하나의 `switch`문 안에서 여러 개의 값을 사용할 때에는 튜플을 사용하면 됩니다. 튜플의 각 요소는 특정 값이나 값의 범위와 비교할 수 있습니다. 특정 값을 지정하지 않고 임의의 값을 나타내려면 밑줄 `_`을 사용하세요.

아래의 예제에서는 (x, y)로 표현된 점을 취합니다. 이 점은 `(Int, Int)` 타입의 튜플로 나타내며, 이 점이 그래프 상에서 어느 구역에 위치하는지 분류합니다.

```
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
println("(0, 0) 은 원점에 있습니다")
case (_, 0):
println("(\(somePoint.0), 0)은 x축 상에 있습니다. ")
case (0, _):
println("(0, \(somePoint.1))은 y축 상에 있습니다.")
case (-2...2, -2...2):
println("(\(somePoint.0), \(somePoint.1))은 상자 안에 있습니다.")
default :
println("(\(somePoint.0), \(somePoint.1))은 상자 밖에 있습니다.")
}
//prints "(1, 1) is inside the box"
```
![그래프](images/image__256.png)

`switch`문은 점이 원점(0,0)에 있는지, 빨간선으로 표현된 x축 상에 있는지, 주황색으로 표현된 y축 상에 있는지, 그래프의 중앙에 파란색으로 칠한 4x4 상자 안에 있는지, 그 상자의 밖에 있는지를 판단합니다.

C언어와는 다르게, Swift에서는 하나의 값이나 값 묶음을 여러 개의 경우(case)와 비교할 수 있습니다. 사실 위 예제에서 점(0, 0)은 4개의 경우에 모두 해당됩니다. 하지만 여러 경우와 매치하는 경우에는, 첫번째 경우만 사용됩니다. 따라서 점(0,0)은 `case (0,0)` 하고만 매치하며, 다른 경우 안에 있는 코드는 실행되지 않습니다.

#### 값을 상수와 묶기, 상수에 바인딩하기 (Value Bindings)

`switch`문에서 경우는 매치된 값이나 값들을 임시 상수나 변수에 바인딩할 수 있습니다. 이렇게 바인딩한 상수나 변수는 그 경우의 본문에서 사용할 수 있습니다. 이렇게 하는 것을 보고 값을 묶는다, 바인딩(value binding)한다고 합니다. 왜냐하면 해당 경우의 본문 내에서 값이 특정 상수나 변수에 “묶여” 있기 때문입니다.

아래의 예제는 `(x, y)` 점을 취합니다. 이 점은 (Int, Int) 튜플로 표현되며, 예제는 이 점을 그래프상의 어느 구역에 위치하는지 분류합니다:

```
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
println("x축 상에 있으며 x의 값은 \(x)값입니다.")
case (0, let y):
println("y축 상에 있으며 y의 값은 \(y)입니다.")
case let (x, y):
println("(\(x), \(y))에 있습니다.")
}

// 다음을 출력합니다: "x축 상에 있으며 x의 값은 2입니다"
```
![그래프](images/image__257.png)

`switch`문은 이 점이 빨간색선인 x축 상에 있는지, 주황색선인 y축 상에 있는지, 또는 그 이외의 구역에 있는지를 판단합니다.

위 예제에서 세 개의 `switch` case에서는 플레이스홀더인 상수 x와 상수 y를 선언하였습니다. 이 둘은 `anotherPoint`로부터 튜플 값을 취합니다. 첫번째 case에서 `case (let x, 0)`y값이 0`y`값이 `0`이면 모두 매치합니다. 이 때 점의 x`x`값은 임시 상수인 x`x`에 들어갑니다. 마찬가지로, 두번째 case인 `case(0, let y)`x`x` 값이 0`0`이면 모두 매치합니다. 그리고 이 때 점의 y값은 임시 상수인 y에 들어갑니다.

일단 임시 상수가 선언되면, case의 코드 블록 내에서 사용될 수 있습니다. 위 예제에서는 `println` 함수에서 값을 출력할 때 점의 좌표값을 빠르게 표현하기 위해서 이 상수를 사용하였습니다.

위 예제에는 디폴트 경우(default case)가 없다는 점에 유의하세요. 마지막 경우인 `case let (x, y)`에서는 두 개의 플레이스 홀더 상수로 이루어진 튜플을 선언하는데, 이는 모든 점과 매치합니다. 결국, 남아있는 모든 가능한 값은 이 경우와 매치한다는 의미이며, 스위치 문에서 가능한 모든 경우를 다 포괄하고 있으므로 이 때에는 디폴트 경우를 쓸 필요가 없습니다.

위 예제에서는 x와 y`x`와 `y`의 값이 경우의 본문에서 바뀔 필요가 없습니다. 그래서 키워드 `let`을 사용해서 상수로 선언하였습니다. 값이 바뀔 필요가 있다면 키워드 `var`를 사용해서 변수로 선언하면 됩니다. 이렇게 하면 임시 변수가 만들어지고, 적절한 값으로 초기화됩니다. 이 변수 값의 변화는, 해당 경우 내의 본문 내에서만 영향을 미칩니다.

#### 키워드 `Where`

`switch`의 case에는 `where`절을 사용해서 조건부를 작성할 수도 있습니다.

아래의 예제는 어떤 점 (x, y)과 그래프의 어느 구역에 위치하는지를 분류합니다:

```
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y :
println("(\(x), \(y)) 는 x==y인 곳에 있습니다.")
case let (x, y) where x == -y :
println("(\(x), \(y)) 는 x==-y인 곳에 있습니다.")
case let (x, y):
println("(\(x), \(y)) 는 기타 구역에 있습니다.")
}
// prints "(1, -1) 은 x==-y인 곳에 있습니다."

```
![image__258.png](images/image__258.png)

위 예제의 `switch`문은 이 점이 `x == y`인 녹색사선 상에 있는지, `x==-y`인 보라색 사선 상에 있는지, 그 이외의 지점에 있는지 판단합니다.

위 예제에서 세 개의 case는 플레이스홀더 상수 x와 상수 y를 선언하였으며, 이 둘은 점의 좌표값을 받아서 튜플로 가지고 있습니다. 이 상수는 `where`절에서 사용되어, 동적인 필터를 만들었습니다. 어떤 경우의 `where`절 내의 조건이 참이 되어야 어떤 값이 그 경우와 매치합니다.
이전 예제에서와 마찬가지로, 위 예제의 마지막에 나오는 경우는 나머지 모든 가능한 값과 매치합니다. 따라서 디폴트 경우는 쓸 필요가 없습니다.

## 흐름제어 이동문(Control Transfer Statements)

Control Transfer Statements 는 control을 특정 코드로부터 다른 코드로 이동시키는 방법으로 코드가 실행되는 순서를 바꿉니다. Swift에는 네 가지 흐름제어 이동문이 있습니다:

* continue
* break
* fallthrough
* return

`control`, `break`, `fallthrough`문에 대해서는 여기서 자세히 다루고, `return`문은 **[함수(Functions)**]() 부분에서 다룹니다.

### Continue

`continue`문은 루프에게 현재 하고 있는 것을 멈추고, 루프의 다음번 이터레이션을 시작하라고 명령합니다. 즉 루프를 빠져나가지 않고 “루프의 현재 이터레이션에 대해서는 끝났다”다고 말하는 셈입니다.

> NOTE
`for-조건부-증가부` 루프에서 `continue` 문을 호출한 이후에도, 증가자(incrementer)의 참 거짓 여부를 검토합니다. 루프 자체는 계속됩니다. 다만 루프 내 본문에 있는 코드가 건너뛰어질 뿐입니다.

다음의 예제는 소문자로 된 문자열에서 모든 모음과 빈 칸을 제거하여 암호 같은 문구를 만들어냅니다:

```
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput {
switch character {
case "a", "e", "i", "o", "u", " ":
continue
default :
puzzleOutput += character
}
println(puzzleOutput)
}
// prints "grtmndsthnklk"
```

위 예제코드에서는 모음이나 빈 칸을 만났들 때 `continue` 키워드를 호출합니다. 그러면 그 때 돌던 이터레이션은 즉시 종료하고 다음번 이터레이션의 시작 지점으로 이동합니다. 이렇게 하면 `switch` 블록이 모음과 빈 칸일 때만 매치하도록 할 수 있습니다. 출력해야 하는 모든 문자를 다 case로 검토할 필요가 없죠.

### Break

`break`문은 흐름제어문 전체를 즉시 종료시킵니다. `break`문은 `switch`문이나 루프문 안에서 사용할 수 있는데요, `switch`문이나 루프문을 일찍 종료시키고 싶을 때 사용합니다.

#### 루프문 안에서 쓴 break

`break`는 루프문 안에서 쓰이면, 루프의 실행을 즉시 종료시키고, 루프를 닫는 중괄호(}`}`) 뒤에 나오는 코드로 코드 실행을 이동시킵니다. `break` 뒤에 있는 나머지 코드부분은 이터레이션을 돌지 않습니다. 그리고 그 다음 이터레이션은 시작되지 않습니다.

#### Switch 문 안에서 쓴 break

`break`를 `switch`문 안에서 사용하면, `switch`문 전체를 즉시 종료시킵니다. 그리고 코드 실행을 `switch`문이 끝나는 부분(}) 이후로 이동시킵니다.
`switch`문에서 한 가지 이상의 경우(case)에 매치하는 경우를 무시해야 할 때, 사용할 수 있습니다.

Swift에서 `switch`문은 가능한 모든 경우를 다루어야 하며, 각 경우는 모두 실행가능한 코드를 포함해야 합니다. 하지만 때로는 어떤 case에 해당하면 그 경우에는 아무것도 하지 않고 넘어가야 할 수도 있습니다. 이렇게 할 때 아무것도 하지 않고 넘어가야 하는 case의 본문에 `break`문을 사용하면 됩니다. 그 case가 매치되는 경우, 본문에 있는 `break`문이 `switch`문의 시행을 즉시 종료시킵니다.

> NOTE
case 본문에 주석만 있는 경우에도 컴파일 에러가 납니다. 주석은 실행문이 아니므로, 그 case를 실행하지 않고 넘어가려면 `break`문을 써야 합니다.

다음의 예제는 `Character`변수의 값(Character value)이 무엇인가에 따라서, 이 값이 네 개 언어 중 하나에서 숫자를 나타내는지 여부를 판단합니다. 과감하게 몇 가지 값은 하나의 case와 매치되도록 했습니다:

```
let numberSymbol: Character = "三" // Simplified Chinese for the number 3


var possibleIntegerValue: Int?

switch numberSymbol {

case "1", "?١", "一", "?":

possibleIntegerValue = 1
1
case "2", "?٢", "二", "?":

possibleIntegerValue = 2

case "3", "?٣", "三", "?":

possibleIntegerValue = 3

case "4", "?٤", "四", "?":
possibleIntegerValue = 4
default :
:
break
}
((코드 확인 필요해요.. 본문에 언급된 if let 부분이 안 보여서요.))

if let integerValue = possibleIntegerValue {
println("The integer value of \(numberSymbol) is \(integerValue).")
{

} else {
println("An integer value could not be found for \(numberSymbol).")
}
// prints "The integer value of 三 is 3."
```

위 예제는 `numberSymbol`이 라틴어, 아랍어, 중국어, 태국어의 숫자 1에서 4에 해당하는지 판단합니다. 매치하는 경우가 나타나면, `switch`문은 `possibleIntegerValue`에 해당하는 정수값을 넣습니다. 이때 `possibleIntegerValue`는 선택적입니다. 즉 필수로 선언해야 하는게 아니라 case 본문 내에서 사용할 때에 선언하는 것이죠.

`switch`문이 다 실행된 후에, 원하는 값을 찾았는지 판단하기 위해 바인딩을 사용합니다. 이 바인딩도 선택적으로 사용하는 것입니다. 변수 `possibleIntegerValue`는 선택적 자료형이기 때문에 초기값으로 nil을 갖고 있습니다. `nil`값을 명시적으로 넣어주지 않아도 암묵적으로 `nil` 값을 갖습니다. 따라서 `possibleIntegerValue`가, 네 개 case중 어느 하나와 매치가 되어서, 어떤 실제 값을 갖게 되었을 때에야 바인딩이 일어날 것입니다.

위 예제에서 매치가 가능한 모든 문자를 case로 만드는 것은 너무 일이 많습니다. 그래서 default case를 두어서 매치되지 않은 문자에 대해서 다루도록 했습니다. 이 default case는 아무 작업도 하지 않아도 됩니다. 그래서 본문에 `break`문만 두었습니다.
`default` case와 매치한 경우에, `break`문은 `switch`문의 실행을 종료시키고, 코드 실행은 if let문으로 이동합니다.

### Fallthrough

Swift에서 `switch`문은 한 case와 매치한 후에, 다음 case로 넘어가지 않습니다(fallthrough). 대신헤 한 case와 매치하고 그 본문에 있는 코드가 실행된 후에, `switch`문 전체가 종료됩니다. 이와 달리 C언어에서는 fallthrough가 일어나지 않게 하려면 명시적으로 각 case 본문 끝부분에 `break`를 써주어야 합니다. 이 점을 보면 C언어보다 Swift에서 `switch`구문이 더욱 예측가능하다고 할 수 있습니다. 즉 실수로 의도하지 않았는데 case를 여러 개 실행시키는 것을 방지할 수 있습니다.

C언어에서 일어나는 fallthrough를 꼭 사용해야 한다면, `fallthrough` 키워드를 사용해서 필요할 때 사용할 수도 있습니다. 다음 예제는 어떤 수를 묘사하는 데에 `fallthrough`를 사용합니다.

```
let integerToDescribe = 5
var description = "수 \(integerToDescribe) 는"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += "소수이며, 또한"
fallthrough
default :
description += " 정수입니다."
}
println (description)
//prints "수 5는 소수이며, 또한 정수입니다."
```

위 예제에서는 이름이 `description``String` 변수를 하나 만들어서 초기값을 넣습니다. 그런 다음 이 함수는 `switch`문을 사용해서 `integerToDescribe`의 값이 어느 경우에 해당하는지 검토합니다. `integerToDescribe`의 값이 목록에 있는 소수에 해당하면, 함수는, ‘소수이며 또한’이라는 묘사부분을 `description` 변수의 끝에다가 붙입니다. 그런 다음 키워드 `fallthrough`를 사용해서 `default` case의 경우에 해당하는지도 봅니다. `default` case는 추가적인 텍스트를 `description` 변수의 끝에 붙입니다. 이제 `switch`문 실행이 완료되었습니다.

`integerToDescribe`의 값이 목록 안에 있는 소수에 해당하지 않으면, 첫번째 case와는 매치하지 않습니다. 그런 다음 `integerToDescribe`는 어떤 값이더라도 매치하는 `default` case와 매치합니다.

`switch`문 실행이 완료한 후에, 수에 대해 기술한 `description``println` 함수를 사용하여 출력됩니다. 위 예제에서 수 5`5`는 소수라고 확인되었습니다.

> NOTE
키워드 `fallthrough`를 사용할 때, 조건을 걸어서 다음으로 넘어갈 case를 지정할 수는 없습니다. C언어에서 처럼, `fallthrough` 키워드를 사용하면 단지, 다음에 나오는 case로 넘어갈 수 있을 뿐입니다.

### 이름표가 붙은 구문 (Labeled Statements)

Swift에서는 루프문이나 `switch`문 안에서 루프문이나 `switch`문을 중첩해서 사용함으로써 복잡한 흐름 제어구조를 만들 수도 있습니다. 그리고 루프문과 `switch`문 안에서 `break`문을 사용해서 이들을 바로 종료시킬 수도 있습니다. 이런 경우에 `break`로 종료시키려는 것이 어느 루프문 또는 switch문인지 명시적으로 표시해주면 좋습니다. 마찬가지로, 여러 개의 루프문을 중첩했을 때 `continue`문이 어느 루프문에 영향을 미치는지 명시적으로 표시해주면 좋습니다.

영향을 미칠 대상을 명시적으로 표시하기 위해서는, 루프문이나 `switch`문에다가 구문 이름표(statement label)를 붙일 수 있습니다. 그리고 `break`문이나 `continue`문을 사용할 때 어느 것을 종료시킬지 구문 이름표를 붙임으로써 명시적으로 표시할 수 있습니다.

구문에다가 구문 이름표를 붙이는 방법은 구문의 introducer 키워드 앞에다가 이름을 쓰고 그 뒤에 콜론`:`을 찍는 것입니다. 다음은 `while` 루프 안에서 구문 이름표를 사용한 예입니다. 이 사용방법은 다른 루프문이나 `switch`문의 경우에도 동일합니다:

```
label name : while condition {
statements
}

```

다음 예제에서는 앞에서 다루었던 뱀과 사다리 게임을 약간 변형시킨 것인데, `break`문과 `continue`문을 사용할 때 구문 이름표가 붙은 `while`루프를 사용합니다.
이번에는 게임 규칙이 하나 추가됩니다:

* 게임에서 이기려면, 정확하게 25번 칸 위에 위치해야 합니다.

주사위를 던졌더니, 25번 칸 보다 넘어가는 경우에는, 25번 칸으로 이동할 수 있는 수가 나올 때까지 주사위를 다시 던져야 합니다.

게임판은 이전에 사용한 것과 동일합니다:
![뱀과 사다리 - 게임판](images/image__260.png)


변수 `finalSquare`, `board`, `square`, `diceRoll`은 이전 예제에서와 동일한 값으로 초기화합니다:

```
let finalSquare = 25
var board = Int[](count : finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

```

이번 게임에서는 `while`루프와 `switch`문을 사용해서 게임을 구현합니다. `while` 루프의 구문 이름표는 `gameLoop`라고 붙여서, 이 루프가 뱀과 사다리 게임 전체에 대한 주요 루프임을 나타냅니다.

`while` 루프의 조건부는 `while squre != finalSquare`라고 하여 25번 칸에 정확하게 위치해야 한다는 규칙을 반영합니다:

```
gameLoop: while square != finalSquare {
if ++diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// 주사위에서 나온 수만 큼 이동해서 마지막 칸에 도달하면, 게임이 끝납니다.
break gameLoop
case let newSquare where newSquare > finalSquare:
// 주사위에서 나온 수만 큼 이동했을 때 마지막 칸을 넘어가면, 게임이 계속되고 주사위를 다시 던집니다.
continue gameLoop
default :
// 주사위에서 나온 수 만큼 이동합니다.
square += diceRoll
square += board[square]
}
println("Game over!")
```

루프가 돌 때마다 초반에 주사위가 던져집니다. 이 때 게이머를 바로 이동시키지 않고 `switch`문을 사용해서 이동시켰을 때의 결과를 검토해서 이동시킬지 여부를 판단합니다:

- 주사위에서 나온 수가 게이머를 마지막 칸으로 이동시키면 게임은 끝납니다. `break gameLoop`라고 쓴 부분은 코드 실행을 `while` 루프문 바깥에 있는 줄로 이동시키며, 게임을 끝냅니다.
- 주사위에서 나온 수가 게이머를 마지막 칸을 넘어간 칸으로 이동시키면, 게이머는 이동할 수 없고, 다시 주사위를 던져야 합니다. `continue gameLoop`라고 쓴 부분은 현재의 while loop 이터레이션을 종료시키며, 루프의 다음번 이터레이션을 돌게 합니다.
- 이 외의 나머지 경우에 대해서는, 게이머는 주사위에서 나온 만큼 이동할 수 있습니다. 게이머는 `diceRoll`값 만큼 앞으로 이동합니다. 그리고 프로그램은 이동한 칸에 뱀이나 사다리가 있는지 확인합니다. 그런 다음 루프는 끝나고, 코드 실행은 `while` 조건부로 이동하여, 게임이 지속될지 여부를 판단합니다.


> NOTE
위 예제에서 `break`문 안에 `gameLoop`라는 구문 이름표를 쓰지 않으면, `while`문이 아니라 `switch`문에서만 빠져나오게 됩니다. `gameLoop`라는 이름표를 사용하였기 때문에 어느 흐름제어문(control statement)가 종료되어야 하는지 명확해 집니다.

>
또한 엄밀히 말하면, 루프의 다음번 이터레이션으로 넘어가기 위해서 `continue gameLoop`를 호출할 때에, 반드시 `gameLoop`를 써주어야 하는 것은 아닙니다. 게임 내에서 루프는 하나 밖에 없기 때문에, `continue`를 썼을 때 어느 루프의 다음 이터레이션으로 넘어갈지에 대해 애매모호함이 발생하지 않습니다. 그렇더라도, 이 때 `gameLoop` 이름표를 사용해서 나쁠 것은 없습니다. 오히려 이렇게 써주면, `break`문에서 이름표를 사용한 것과 일관성을 유지하는 효과가 있으며, 코드에서 게임의 규칙(game’s logic)을 읽어내고 이해하는데에 도움을 줍니다.

images/computedproperties_2x
images/staticpropertiesvumeter_2x