대메뉴 바로가기 본문 바로가기

데이터 기술 자료

데이터 기술 자료 상세보기
제목 스위프트 파헤치기 : 스위프트 고급 문법(클래스와 구조체)
등록일 조회수 5161
첨부파일  

스위프트 파헤치기

스위프트 고급 문법(클래스와 구조체)



애플의 개발자 컨퍼런스(WWDC15)가 6월 8일부터 5일간 샌프란시스코에서 열렸다. 첫날 키노트 발표에서 스위프트(Swift) 프로그램 언어에 대해서 의미 있는 언급이 있었다. 스위프트 프로그램 언어의 버전이 ‘스위프트 2’로 변경됐다(이전까지 버전은 1.2). Xcode 7과 조합해 사용할 수 있다. 문법적으로 크게 달라진 점은 없지만, 애플에서는 스위프트 2 프로그램 언어부터 오픈 소스로 배포한다는 정책을 발표했다. 이것은 약간 제한적이었던 스위프트 개발환경(OS X와 Xcode 사용)을 다른 플랫폼을 사용하는 개발자도 쉽게 이용할 수 있도록 공개했다는 점에서 의미가 있다고 하겠다.



스위프트의 클래스와 구조체 사용 방법에 대해서 알아보겠다.



클래스와 구조체의 비교

일반적으로 프로그램 언어에서 클래스와 구조체는 코드를 블록화 하거나 재사용 가능하도록 할 때 사용하게 된다. 클래스와 구조체 함수를 구성하는 방식은 기존의 상수, 변수, 함수를 구현하는 방식과 유사하다. 오브젝티브-C등의 언어에서는 클래스를 구성할 때 정의하는 interface 부분과 실제로 그것을 구현하는 Implementation을 나누어서 작성하는 방식을 사용한다. 스위프트에서는 다른 프로그램 언어와 달리 클래스와 구조체를 구성하는 것을 하나의 파일에서 처리한다.

다음의 예는 오브젝티브-C언어의 헤더 파일과 소스 파일 에서 ‘_0100819_playmp3AppDelegate’라는 클래스를 선언한 예다. @interface 부분에서 클래스를 정의했고 @implementation에서 실제 구현부에 해당되는 내용을 작성하게 된다.





스위프트에서는 이러한 코드를 하나로 정의해 표현할 수 있다. 이번에는 클래스와 구조체의 공통점과 차이점에 대해서 확인해 보겠다. 기본적으로 스위프트에서 클래스와 구조체에서 사용되는 프로퍼티, 메소드, Subscripts, 초기화, 확장, 프로토콜등에 대해서 는 사용방법이 유사하다.



클래스와 구조체의 공통점

스위프트의 클래스와 구조체는 아래와 같은 공통점을 가지고 있다.

- 값을 저장하기 위해서 프로퍼티를 정의할 수 있다.
- 함수를 제공하기 위해서 메소드를 정의할 수 있다.
- 서브스크립트(subscript) 문법을 제공해서 해당값에 접근하는 것을 가능하도록 정의할 수 있다.
- 초기 상태를 지정하기 위해서 초기화 연산자를 정의할 수 있다.
- 기본적인 구현을 확장하기 위한 확장 방식을 제공한다.특정 형태의 표준 함수를 제공하기 위해서 프로토콜을 지원한다.



클래스만의 부가기능

스위프트에서 구조체는 가지고 있지 않은 클래스만의 부가적인 내용은 다음과 같은 것들이 있다.

- 상속을 제공해 다른 클래스의 속성등을 가져와서 적용할 수 있다.
- 런타임에 클래스 인스턴스의 타입을 해석해서 타입캐스팅이 가능하다.
- 할당된 어떠한 리소스들에 대해서도 메모리에서 해제가 가능하다.
- 하나 이상의 클래스 인스턴스에 대해서 레퍼런스 카운팅이 가능하도록 한다.

이제부터는 스위프트에서 사용되는 클래스와 구조체의 문법에 대해서 코드를 통해서 자세히 알아보자.



클래스와 구조체의 정의

클래스와 구조체는 동일한 형태의 구조를 가지고 있다. 각각 정의할 때 사용하는 키워드가 다르다. 클래스는 ‘class’라는 키워드를 사용하고, 구조체는 ‘struct’로 표현된다. 두 가지 모두 중괄호 기호 ‘{ }’를 사용해서 표현한다. 다음의 예는 클래스와 구조체를 표현한 코드다.

class SomeClass { // 클래스의 내용은 이곳에 기술된다. } struct SomeStructure { // 구조체의 내용은 이곳에 기술된다. }



이제 구조체와 클래스의 사용예를 통해서 정의 방식을 알아보자. 다음의 코드는 구조체와 클래스의 전형적인 정의 방법이다. 구조체와 클래스의 이름을 각각 ‘Res’ ‘Vmode’라고 정의했다.

‘Res’ 구조체는 width와 height라는 이름의 프로퍼티 항목이 정의됐으며 초기화 될 때 값이 0으로 주어진다. ‘Vmode’ 클래스는 비디오 항목의 프로퍼티들로 구성하도록 작성했다. 이 클래스는 4개의 프로퍼티로 구성되며 각각의 항목은 의미있는 값들이 주어진다. resolution 변수는 ‘Res’ 구조체로부터 값들을 가져오도록 했으며, interlaced 변수와 같이 Boolean 타입을 가질 수도 있다. framerate라는 변수에는 실수형의 값을 넣을 수 있으며, name이라는 변수는 String 뒤에 ‘?’ 기호를 붙여서 Optional 타입의 값이 할당될 수 있다. 이것의 의미는 String 타입의 값을 가질 수도 있고, 가지지 않을 수도 있다(nil)는 뜻이다.



struct Res { var width = 0 var height = 0 } class Vmode{ var resolution = Res() var interlaced = false var frameRate = 0.0 var name: String? }



스위프트 언어에서의 카멜표기법 스위프트에서 클래스나 구조체의 이름을 정의할 때 일반적으로 표시하는카멜표기법(UpperCamelCase)에 따라서 표기해 주면 좋다. - 카멜표기법이란 낙타의 등이 위로나와있는 것처럼 상수, 변수, 함수나 클래스의 이름을 지을 때 명사에 해당되는 부분의 첫글자를 대문자로 하여 표기하는 방식이다. 일반적으로 아래의 예에서와 같이 시작과 단어의 중간을 표기하는 첫 글자는 대문자로표기된다. SomeClass SomeStructure 스위프트에서는 프로퍼티와 메소드를 표기할 때 아래와 같이 첫 번째 단어의 표기하고 연결되는 단어의 첫글자는 대문자로 표기하는 방식을 사용한다. lowerCamelCase frameRate incrementCount



클래스와 구조체의 인스턴스

클래스와 구조체를 직접 코드에서 사용하기 위해서는 인스턴스를 정의해서 그것을 사용하게 된다. 인스턴스는 클래스와 구조체 함수를 대표해서 사용할 수 있는 형태다. 클래스와 구조체는 매우 유사한 형태로 인스턴스를 정의할 수 있다. 다음의 코드를 살펴보자.

let someResolution = Res()
let someVideoMode = Vmode()

‘Res()’ 구조체와 ‘Vmode()’ 클래스의 인스턴스로 각각 some Resolution, someVideoMode 를 정의했다. 새로운 인스턴스가 생성될 때 값은 초기화 된다.



프로퍼티 접근

구조체와 클래스에서 정의된 프로퍼티의 값을 사용하고자 할 때 인스턴스 이름에 ‘.’를 붙여서 기술한다. 다음의 코드는 구조체와 클래스의 값을 “인값들은 0과 false로 기본값이 들어가 있어서 해당값을 출력해 주는 것을 볼 수 있다.



클래스의 프로퍼티는 구조체의 값을 가져와서 사용할 수도 있는데 다음과 같이 ‘클래스 인스턴스+구조체 속성값+클래스 속성값’ 형태로 표기할 수 있다.



구조체나 클래스의 프로퍼티 값을 변경하려면 다음과 같이 사용할 수 있다.
클래스인스턴스.프로퍼티.구조체프로퍼티 = 해당값
다음 코드는 가로해상도 값을 초기값에서 1920으로 변경한 예다.





구조체와 열거형(enumerations)의 사용

구조체와 열거형에서 사용되는 상수나 변수의 타입 값들은 함수에서 사용되는 시점에 결정된다. 이것을 밸류 타입(Value Type)이라고 한다. 사실 스위프트에서 사용되는 모든 기본적인 타입들-정수형, 실수형, 블리언, 배열, 문자열, 딕셔너리-은 구현될 때 밸류 타입으로 선언된다. 이것은 실제로 코드에서 사용될 때 복사(copied)된다고 말한다. 이렇게 복사되는 값들은 각각에 맞는 속성값을 가지고 있게 되며, 쓰이는 시점에 따라서 구조체와 열거형의 인스턴스로 생성된다. 이해를 위해서 화면의 해상도를 표시하는 상수와 변수를 정의한 아래의 코드를 살펴보자.

let hd = Res(width: 1920, height: 1080)
var cinema = hd

위의 예에서 상수 hd는 구조체 Res의 인스턴스가 초기화 되면서 width는 1920으로, height는 1080으로 결정된다. 이후에 변수 cinema를 선언했다. cinema는 상수 hd의 값을 복사해서 설정(sets)되고 그 값을 유지하게 된다. 왜냐하면 Res는 구조체이기 때문에 기존에 존재하는 인스턴스의 값은 그대로 가지고 있으려는 속성이 있기 때문이다. 이 상태에서 cinema 의 width 값을 다음과 같이2048로 변경해 보겠다.

cinema.width = 2048

이 경우 cinema의 width 값은 2048로 설정된다. 이것을 출력해보면 cinema.width 값이 2048인 것을 알 수 있다. 그렇다면 위의 예에서 변수 cinema를 선언할 때 상수 hd의 인스턴스를 복사(copied)해 생성한 것을 알고 있다. hd.width 값은 어떻게 돼 있는지 확인해 보면 처음 구조체를 정의할 때 선언한 1920인 것을 확인할 수 있다. 이것으로 알 수 있는 것은 상수 hd의 현재 값을 복사해 생성한 변수 cinema의 인스턴스는 독립적으로 값을 저장한다는 것을 알 수 있다.

다음과 같은 코드의 실행 결과로 확인 가능하다. 상수 hd. width는 cinema와는 독립적으로 상수값을 저장하고 있는 것을 볼 수 있다. 이와 같은 결과를 열거형(enumerations)에서도 동일하게 확인할 수 있다. 다음의 코드는 CompassPoint라는 열거형을 선언하고 네 방향을 가리키는 상수로 ‘동East, 서West, 남South, 북North’를 선언했다.



이후에 변수로 현재 방향을 나타내는 currentDirection을 ‘CompassPoint.서West’ 값을 갖도록 선언하고, 상수로는 이 값을 복사(Copied)한 rememberedDirection을 작성했다. 이후에 currentDirection 값을 ‘.동East’로 지정했다. 그 다음 rememberedDirection의 값이 최초 변수에서 선언한 ‘.서West’ 값을 그대로 가지는지 확인해 보았다. 그 결과 다음의 예제 코드에서와 같이 별도의 인스턴스로 동작해 값이 그대로인 것을 확인할 수 있었다.





클래스와 레퍼런스(Reference) 타입

이전에서 살펴본 것 처럼 구조체와 열거형은 상수나 변수에 값을 할당할 때 복사(copied)하는 방식을 사용했는데, 클래스는 동일한 인스턴스의 레퍼런스 타입으로 값이 할당된다. 값을 레퍼런스 타입으로 할당하는 예제를 살펴보자. 다음의 코드는 Vmode 클래스를 사용한 예제다. 클래스로 선언한 Vmode의 값들이 초기에 사용했던 값들에서 새로운 값들로 참조(Reference)되는 것을 확인할 수 있다. 아래 코드에서 각각 hd, true, 1080i, 30.0으로 값이 참조되는 것을 볼 수 있다.



이제 Ref 클래스의 속성값들이 참조형으로 사용되는지 확인하기 위해서 ‘frameRate’의 값을 다른 상수를 선언해서 변경한 후 그 값이 변하는지 알아보겠다. 다음의 코드는 Ref클래스의 인스턴스를 가지는 상수 otherRef를 선언하고 클래스 인스턴스의 framerate 값을 변경해 본 예다. 처음에 클래스에서 Ref는 상수로 정의됐다. 상수로 정의된 값은 변경이 어렵다는 것을 알고 있다. 하지만, otherRef라는 상수를 만들고 Ref 클래스의 값을 참조형으로 가지게 되면 다음 예제 코드에서 볼 수 있는 것처럼 값이 변경되는 것을 볼 수 있다(Ref.frameRate 값이 30.0 에서 25.0 으로 변경된 것을 확인할 수 있다).



이처럼 클래스의 인스턴스는 구조체와 열거형이 값을 그대로 복사(copied)해 사용하는 것과 다르게 참조형으로 사용하고 있다는 것을 알 수 있다.



마치며

스위프트에서 사용되는 클래스와 구조체의 특징과 사용법을 예제 코드를 통해서 확인해 보았다. 구조체는 속성값들을 그대로 복사(copied)해 사용하는 형식을 가지는 반면에 클래스는 인스턴스의 참조형으로 속성값들을 사용한다는 점이 다른 점이다. 구조체와 클래스 모두 코드를 블록화해 사용할 수 있다는 점에서 유용한 방식이라고 할 수 있겠다.



출처 : 마이크로소프트웨어 7월호

제공 : 데이터 전문가 지식포털 DBguide.net