오늘의 주제

Objective-C의 상수와 스위프트의 상수


안녕하세요 야곰입니다.

Objective-C를 쓰다가 스위프트로 넘어왔을 때 고민되었던 부분 중의 하나인 스위프트의 상수에 관해 이야기해 보려 합니다.


혼자 프로젝트를 진행하다 보면 상수의 필요성을 많이 느낄 수 없을지 모르지만, 누군가 협업을 하게 된다면, 혹은 미래 또는 과거의 나와 협업(?)을 하게 된다면 상수의 필요성을 많이 느끼게 됩니다. 바꾸면 안 되는 데이터를 실수로 바꿔서 난감했던 경험이 없나요? 혹시 그런 적이 있다면 상수의 필요성에 대해서는 많이 공감하실 것으로 생각됩니다.


* 오해가 생길 소지의 표현들이 있어서 처음 발행 이후 조금 수정하였습니다. 좋은 의견 주신 과니님 고맙습니다 :)


사라진 const


사실 저는 Objective-C에서 특별한 경우가 아니면 const를 많이 사용하지 않았습니다(반성).


그런데 스위프트에서는 전역이든 지역이든 데이터를 저장할 공간(변수 또는 상수)에는 var 또는 let을 사용하여 변수인지 상수인지 명확히 명시해 주어야 하므로 상수에 대한 고민을 많이 하게 되었습니다.


사실 지역상수가 필요한 경우에 const 키워드를 쓰는 귀찮음 때문에 상수를 많이 사용하지 않았는데 스위프트에서는 var 또는 let을 선택해야 하는 시간이 조금 걸렸지만, 지금은 큰 시간 들일 필요 없이 자연스럽게 상수를 많이 사용하고 있습니다. 또, 혹시라도 상수로 사용해야 하는 경우임에도 변수로 선언하고 사용한다면 Xcode에서 변수 대신 상수를 사용하는 게 어떻냐는 경고를 보여줍니다. 




[Xcode의 경고]


지역상수


지역상수를 사용하는 경우에는 사실 Objective-C와 크게 다를 바 없이 사용할 수 있습니다. 상수의 이름을 지어주는 명명법도 크게 다를 바 없습니다. 

상수로 사용할 변수 앞에 const를 붙여 쓴 것처럼 let을 사용하여 상수를 선언하여 사용하면 됩니다.



// Objective-C
const NSInteger someConstant = 100;


// Swift
let someConstant: Int = 100



전역상수


전역상수를 사용할 때 조금 더 생각해보아야 할 것들이 있습니다. 저는 처음 스위프트를 사용할 때 별생각 없이 Objective-C에서 사용하던 것과 같은 명명법으로 전역상수를 사용했습니다.


// Objective-C NSInteger const  YGSomeGlobalConstant = 100;


// Swift
let YGSomeGlobalConstant: Int = 100


그런데 Objective-C에서 'YG'와 같이 접두어(prefix)를 붙이는 것은 Objective-C에는 네임스페이스(name space)가 없기 때문인데, 스위프트에는 이 단점을 극복했다는 것에 대한 생각이 문득 스쳤습니다.


Objective-C에는 네임스페이스가 없어서 전역변수를 선언하고 사용할 때 꽤 골치가 아팠습니다. 귀찮기도 아주 귀찮았죠. 이름도 매우 길어지기만 했습니다. 열거형(enum)은 정수밖에 지원하지 않기 때문에 다른 타입의 값들은 관련된 상수끼리 묶어 쓰기도 어렵기도 했지요.


// Objective-C의 상수들... // 네임스페이스가 없기 때문에 // 연관된 상수들을 접두어를 사용하여 표현합니다 // 요일 상수들 NSString *const YGWeekMonday = @"MON"; NSString *const YGWeekTuesday = @"TUE"; NSString *const YGWeekWednesday = @"WED"; NSString *const YGWeekThursday = @"THU"; NSString *const YGWeekFriday = @"FRI"; NSString *const YGWeekSaturday = @"SAT"; NSString *const YGWeekSunday = @"SUN"; // 네트워킹 관련 상수들 NSTimeInterval const YGNetworkingTimeoutInterval = 10.0f; NSUInteger const YGNetworkingMaxRetryCount = 3; NSString *const YGNetworkingBaseURLString = @"https://abc.com";


정말 보기만 해도 정신이 없습니다. 또, 실수로 복사 붙여넣기를 하다가 중복된 값을 넣었다면 컴파일 오류가 발생하지 않기 때문에 실수를 찾아내기도 매우 어려워집니다.


스위프트에서는 이런 전역 상수들을 조금 더 멋진 방법으로 표현해 볼 수 있습니다. 타입 내부에 다른 타입을 정의하는 방법으로 네임스페이스를 사용할 수 있습니다. 더군다나 네임스페이스 덕분에 접두어는 더 이상 스위프트에서 사용하지 않습니다.


// Week라는 구조체 타입 내부에
// 여러 타입 상수를 선언
struct Week {
    static let mon: String = "MON"
    static let tue: String = "TUE"
    static let wed: String = "WED"
    static let thu: String = "THU"
    static let fri: String = "FRI"
    static let sat: String = "SAT"
    static let sun: String = "SUN"
}

// 실제 사용시 Week.mon // "MON" Week.sat // "SAT"


처음에 이렇게 선언해 보았습니다. 그런데 만약 복사 붙여넣기를 하다가 실수로 중복된 값을 넣는다면...? 가령 "SUN"을 넣어야 하는데 "SAT"를 넣어버렸다면? 이때는 중복 값이 들어있는지 확인할 수 없습니다. 물론 의도적으로 다른 이름의 상수에 같은 값을 넣을 수도 있지만 그렇지 않은 경우에는 낭패입니다.


그래서 이렇게 개선해 봅니다.


// 열거형의 연관 값(associated value)을 사용하여
// 상수처럼 사용
enum Week: String {
    case mon = "MON"
    case tue = "TUE"
    case wed = "WED"
    case thu = "THU"
    case fri = "FRI"
    case sat = "SAT"
    case sun = "SUN"
}

// 실제 사용시 Week.mon.rawValue // "MON" Week.sat.rawValue // "SAT"



이렇게 사용하면 열거형 내부의 연관 값이 중복되는 경우에 컴파일오류가 발생하게 됩니다. 그래서 미리 실수를 발견하기도 좋습니다.


또, 위의 Objective-C로 선언했던 네트워킹 관련 상수를 스위프트에서 선언한다면 이렇게 바꿔볼 수 있을 것 같습니다.


// Objective-C NSTimeInterval const YGNetworkingTimeoutInterval = 10.0f; NSUInteger const YGNetworkingMaxRetryCount = 3; NSString *const YGNetworkingBaseURLString = @"https://abc.com";
// 사용 YGNetworkingTimeoutInterval // 10.0


// Swift
struct Networking {
    static let timeoutInterval: TimeInterval = 10.0
    static let maxRetryCount: Int = 3
    static let baseURL: URL? = URL(string: "https://abc.com")
}

// 사용

Networking.timeoutInterval // 10.0


이처럼 꼭 열거형의 연관 값을 사용하지 않고 용도에 맞게 구조체의 타입 상수(static let)로 사용해도 좋습니다. 


상수뿐만 아니라 전역변수, 전역함수(메서드) 등에도 충분히 응용할 수 있습니다.


또한 구조체 내부에 다른 타입(구조체, 클래스, 열거형) 등등 몇 단계를 걸쳐 내부 타입을 정의할 수 있기 때문 연관된 값을 타입의 타입의 타입까지 여러 번에 걸쳐 정의도 가능합니다.



struct CalendarItem {
    typealias Year = Int
    typealias Day = Int
    
    enum Week: String {
        case mon = "MON", tue = "TUE" //...
    }
    
    enum Month: Int {
        case jan = 1, feb, mar //...
    }
    
    static let startYear: Int = 1970
    static let startMonth: CalendarItem.Month = .jan
    
    struct Date {
        var day: Day = 1
        var weekDay: CalendarItem.Week = .mon
        var month: CalendarItem.Month = .jan
        var year: Year = CalendarItem.startYear
    }
}

var userBirthday: CalendarItem.Date userBirthday = CalendarItem.Date.init(day: 10, weekDay: .tue, month: .mar, year: 2017)



마치며


같은 Cocoa 플랫폼 위에서 코드를 작성하는데도 불구하고 역시나 언어의 특성을 살려 새로이 구조를 설계하기는 쉽지 않습니다 하핳


무언가 두서없이 써내려간 느낌입니다만, 잘 이해가 가지 않거나 궁금한 점이 있다면 댓글 남겨주세요 :D





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


저작자 표시 비영리 변경 금지
신고
Posted by yagom


Ubuntu에 Swift 설치하기

1. 우분투 서버에 스위프트(Swift) 언어 라이브러리 설치

2. 간단한 스위프트 프로그램 작성/실행


안녕하세요 야곰입니다.


애플의 새로운 언어 스위프트는 맥 운영체제 외에도 리눅스(우분투)에서 사용할 수 있습니다.

우분투에서 스위프트를 사용하기 위해 설치하고, 스위프트 프로그램을 간단히 작성해봅니다.


# 사전 준비지식


본 포스팅을 함께 해보기 위해 필요한 기초 사전지식입니다.

  • vi 사용법
  • 기초 리눅스 명령어(옵션)
  • ssh 사용법(옵션)


# 사전 준비


우분투(Ubuntu Server 16.04.2 LTS 64bit) 에 스위프트를 설치해 보겠습니다.


우분투 설치방법은 아래글을 참고하세요.


또, 미래에 이 글을 보고계실 여러분께서 현재 스위프트가 어떤 리눅스 버전에서 지원하는지, 스위프트 최신 버전이 몇인지 먼저 체크하시기 바랍니다.


[여기서 체크]



2017년 3월 현재 

  • 지원 리눅스 버전 : Ubuntu 16.04, Ubuntu 14.04 [64bit]
  • 최신 스위프트 버전 : 3.0.2


만약 가상머신을 사용하여 설치한 분께서는 혹시모를 꼬임에 대비하여 작업시작 전 스냅샷을 남겨두시길 권합니다


저는 mac 터미널에서 우분투 서버로 ssh 접속을 하여 작업을 진행하였습니다.



# 스위프트 설치


필요 패키지 설치

의존성 관리도구를 통해 필요한 패키지(clang, libicu-dev)를 먼저 설치합니다.

아래 명령어를 통해 설치할 수 있습니다.


sudo apt-get install clang libicu-dev


암호를 입력하면 패키지가 설치가 됩니다. 설치 확인 물음에서 Y를 입력해주면 됩니다.




다음으로 스위프트 소스를 다운로드 받습니다.


이건 옵션사항인데, 저는 리눅스에서 바로 스위프트 패키지를 다운로드 받고 싶어서 wget을 사용합니다.

혹시 wget이 설치되어 있지 않을 수 있으니 설치해봅니다.


sudo apt-get install wget



저는 이미 최신버전이 설치되어있다고 나오네요~


스위프트 패키지 설치

먼저 스위프트 패키지를 다운로드 할 경로로 이동합니다. (현재 폴더에서 다운로드 받으려면 이동하지 않아도 됩니다)


mkdir ~/swift_package
cd ~/swift_package



현재 Swift 3.0.2 버전의 소스는 [https://swift.org/builds/swift-3.0.2-release/ubuntu1604/swift-3.0.2-RELEASE/swift-3.0.2-RELEASE-ubuntu16.04.tar.gz] 주소로 배포되어 있는데, 버전에 따라 주소가 달라질 수 있습니다. 애플의 릴리즈 링크를 참고하세요.


아래 명령어를 통해 다운로드 받습니다. (만약 wget을 설치하지 않았다면 다른 방법을 통해 리눅스로 파일을 전달하면 됩니다)


wget https://swift.org/builds/swift-3.0.2-release/ubuntu1604/swift-3.0.2-RELEASE/swift-3.0.2-RELEASE-ubuntu16.04.tar.gz





처음으로 Swift를 설치한다면 다운로드 후에 GPG 키를 추가해주어야 합니다. 이미 다운로드 받고 Swift를 사용한 적이 있다면 다음 단계로 넘어가도 됩니다.


wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -





아까 다운로드한 스위프트 패키지의 압축을 풀어줍니다. 다운로드한 버전에 따라 파일명은 다를 수 있습니다. 자신이 다운로드한 파일을 확인하고 압축을 해제해주세요.


tar xzf swift-3.0.2-RELEASE-ubuntu16.04.tar.gz





압축을 해제하면 폴더가 생성되는데 이 폴더를 /opt 폴더로 이동시킬거예요. 이동시키면서 폴더명도 조금 간단하게 swift-3.0.2로 바꿔줍니다.


sudo mv swift-3.0.2-RELEASE-ubuntu16.04 /opt/swift-3.0.2


/opt 폴더로 이동하여 제대로 이동이 되었는지 확인합니다.


cd /opt
ls




이제 swift 명령어를 사용하기 위해 환경변수에 추가합니다.


export PATH=/opt/swift-3.0.2/usr/bin:"${PATH}"


swift 명령어를 설치된 스위프트 버전을 확인해봅니다.


swift --version




그런데 서버를 재시작 하고나면 swift 명령어를 사용할 수 없습니다. export 환경변수를 다시 등록해줘야 하기 때문인데요, 매우 귀찮으므로 재시작 되어도 문제없도록 환경변수를 등록해둡니다.


sudo vi /etc/profile




맨 아랫줄에 


export PATH=/opt/swift-3.0.2/usr/bin:"${PATH}"
를 추가해줍니다.



이제 서버를 재시작해도 문제없이 swift 명령어를 사용할 수 있습니다.



# 스위프트 작성/실행


이제 스위프트 REPL을 사용하기 위해 swift 명령어를 입력해 봅니다.




앗차 그런데 이게 무슨일입니까? 실행이 되질 않아요!! 파이썬이 없다네요... 망할... 설치해주어야죠?


sudo apt-get install libpython-dev





설치가 끝나고 다시 swift 명령어를 입력하면 REPL이 실행됩니다.

간단히 코드를 입력하여 동작하는지도 확인해봅니다.




간단한 스위프트 파일을 생성하여 실행도 해봅니다.


vi test.swift


swift test.swift





이렇게 우분투에 스위프트를 설치하고 간단한 프로그램도 작성해 보았습니다.


이제 스위프트를 설치해 봤으니, 스위프트를 가지고 서버를 만들어 볼까요?

후헿


기대됩니다~ 곧 스위프트로 API 서버를 만들어 봅시다요!


by yagom

facebook : https://facebook.com/yagomsoft

facebook group : https://www.facebook.com/groups/yagom/

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   



저작자 표시 비영리 변경 금지
신고

'Swift > Perfect' 카테고리의 다른 글

사진 게시판 API 만들기 [3]  (0) 2017.08.09
사진 게시판 API 만들기 [2]  (0) 2017.07.11
사진 게시판 API 만들기 [1]  (6) 2017.06.27
Perfect 라우팅  (0) 2017.05.24
Perfect 시작하기  (0) 2017.05.17
우분투(Ubuntu)에 스위프트 설치하기  (0) 2017.04.03
Posted by yagom


티스토리 툴바