본문 바로가기
IOS

swift를 공부하기 전에(2)

by 나이아카 2022. 1. 19.

 이전 글에서는 왜 스위프트를 공부해야 하는지에 대한 푸념글(?)이 었다면, 이번에는 아직 스위프트를 배우지 않은 제가 봤을 때 코틀린과 비슷한 점과 달라보이는 점들을 먼저 학습하고 들어가겠습니다.


정적 타입 검사

 스위프트는 코틀린과 동일하게 언어에서 사용되는 변수들의 타입이 올바른지 런타임 이전에 검사하는 정적 타입 언어입니다. 프로그래밍에서 타입이란 int, string, double과 같은 자료형을 의미하는데 이러한 정적 타입 검사 프로그래밍 언어는 컴파일 시에 각 변수의 타입이 고정되는 것을 의미합니다.

var a : Int = 3
a = "5" //type mismatching

 위 코드와 같이 이미 Int형으로 타입이 고정된 a라는 변수는 더 이상 Int 이외의 값을 저장하지 못하게 됩니다. 이러한 방식을 사용하는 것을 정적 타입이라고 합니다.

 

null == nil

 스위프트에도 코틀린에서 사용하는 null과 같은 마법의 변수가 존재합니다. 변수에 아무것도 존재하지 않는 경우를 nil로 표현할 수 있습니다. 왜 다른 언어와 같이 null로 표현하지 않고 nil로 표현하는지에 대해서 찾아봤는데, objective-C에서는 null은 포인터가 존재하지 않는 경우, nil은 객체가 존재하지 않는 경우로 각각 따로 사용하는데, 이러한 문법이 스위프트로 옮겨 오면서 포인터라는 개념을 숨겨버렸기 때문에 null이라는 것을 사용할 필요가 없어졌고, 기존의 nil의 개념을 그대로 사용하는 nil만 남게 된 것입니다.

 

Int?, nullable한 변수

코틀린에서는 null 값을 사용할 수 있는 타입의 경우 특정 타입(Int, String 등)의 뒤에 ?를 붙여 nullable함을 알려줍니다.

var data : String? = null //만약 data의 타입이 :String이라면 이 부분은 오류
data = "one"

 위와 같이 ?를 붙여주는 것으로 nullable을 알려줄 수 있는데, 이는 스위프트 역시 마찬가지로 ?를 붙여줌으로서 nil의 값이 이 변수에 참조될 수 있다는 것을 알려줍니다. 하지만, 상세하게 들어가면 스위프트의 경우에는 옵셔널이라는 타입으로 치환되기 때문에 코틀린과는 같은 문법으로 사용되지만 다른 결과가 발생하는 것을 알 수 있습니다.

 

불변(let, val) and 가변(var)

 코틀린과 스위프트 모두 변경할 수 없는 객체와 변경가능한 객체가 존재합니다. 먼저 코틀린에서 val로 표현되는 (자바 코드로 치환했을 때 final이 되는 상수를 의미합니다.) 값들은 스위프트에서 let으로 표현할 수 있습니다. let과 val은 한 번 값이 할당된 이후에는 다시 변경할 수 없지만, 값을 할당하기 전까지는 아래 코드와 같이 할당되지 않은 상태로 유지하는 것이 가능합니다.(물론 이러한 경우에 이 값을 참조하려는 순간 에러가 납니다.)

val data: String
data = "data"

//swift
let data : String
data = "data"

 또한 변수는 더욱 반갑습니다. 코틀린에서 변경 가능한 값을 저장하는 변수의 경우 var로 표현했는데, 스위프트 역시 코틀린과 동일하게 var로 표현하는 것을 알 수 있습니다.

 

Int, String, Double, Float, Character, String, Bool(Boolean)

 스위프트의 기본 타입들은 Bool 타입만 제외하고는 전부 코틀린과 동일하게 사용할 수 있습니다. 또한 타입을 명시해주는 것도 코틀린과 동일하게 변수 이름 뒤에 ':'를 통해 작성해주면 됩니다.

 

Struct vs data class

 컴퓨터 공학과에 입학해서 언어를 배우던 초기에 배웠던 조금 신기하지만 되게 쓸모 있을거라 생각했던 그러한 친구가 있는데요. 자바와 코틀린을 거치게 되면서 잘 보기 어려웠던 이름인 struct를 스위프트에서 다시 보게되었습니다. 이 친구의 역할은 데이터를 저장하는 것입니다. 그것과 유사한 기능을 하는 친구가 코틀린에도 존재합니다. data class 라는 친구인데, 이는 기존 자바에서 데이터를 저장하기 위한 목적으로 만들어내는 클래스들을 아예 문법화시켜 사용할 수 있도록 처리해준 코드인데요.

 코틀린의 데이터클래스처럼 struct를 사용할 때 명심해야 할 점이 하나 있었습니다. 바로 struct는 데이터를 이용할 때 callByReperence 방식이 아닌 callByValue 방식이라는 것입니다. 코틀린의 data class는 이름부터 어찌됐든 클래스의 형태를 유지하고 있습니다. 그리고 코틀린의 클래스는 callByReperence 방식을 이용하고 있습니다. 이는 파라미터로 넘겨받은 클래스 내부의 데이터를 다른 메소드에서 수정했을 때 리턴 없이 값을 변경할 수 있음을 의미하는데요. struct는 이와 다르게 값을 복사해서 넘겨주기 때문에 파라미터로 주고 받는 데이터가 어디선가 꼬일 염려를 줄일 수 있습니다.

 물론 그렇다고 Swift에 class가 없는 것은 아니니, 효율적인 참조 방식에 따라 사용할 수 있을 것 같습니다.

 

고차함수

 고차함수는 "다른 함수를 전달인자로 받거나 함수 실행의 결과를 함수로 반환하는 함수 를 뜻한다." 라고 합니다. 똑똑하신 분들은 이 글만 읽고도 고차함수가 무엇인지 이해하셨을 지 모르지만 저는 그런 사람이 아니기 때문에 고차함수에 대한 키워드를 찾아보았습니다.

 먼저 스위프트의 고차함수에는 map, filter, reduce 등이 존재합니다. 이러한 키워드를 가지고 보니, 제가 코틀린이나 자바에서 사용하던 것들과 유사한 것이라는 것을 알 수 있었습니다. 

func solution(_ absolutes:[Int], _ signs:[Bool]) -> Int {
    return (0..<absolutes.count).map{signs[$0] ? absolutes[$0] : -absolutes[$0]}.reduce(0, +)
}

 프로그래머스에서 이러한 고차함수를 이용하여 푼 간단한 문제 하나를 가지고 왔습니다. 위의 문제는 음양더하기라는 문제로, signs의 값이 true or false에 따라 absolutes 배열에 들어있는 값을 더하거나 빼게끔 하는 코드입니다.

 고차함수의 키워드인 map을 잘 보면 {}로 묶여있는 것을 알 수 있습니다. 이는 map이라는 함수가 파라미터로 함수를 가져오고 있다는 것을 확인할 수 있습니다. 또한 이러한 고차함수는 반환값이 존재함을 알 수 있죠.

 자바로 문제를 풀다보면 저런 형식의 코딩 방법을 자주 볼 수 있습니다. 바로 자바의 스트림인데요. 이름이나 내부 동작이 다름은 분명하지만, 자바에서 스트림을 사용한 적이 있다면 스위프트의 고차함수를 이해하는 것은 모르겠지만 사용법에 대한 숙련도는 확실히 빨리 늘 것 같습니다.

 

Dictionary

 또한 스위프트에서 딕셔너리라는 객체를 발견했습니다. 이는 키 값과 밸류 값으로 이루어진 자료구조로 비정렬 특징을 가지고 있습니다. 아래와 같은 방식으로 생성할 수 있습니다.(자세한 사용 방법은 추후에 따로 글을 작성하게 된다면 그때 작성하겠습니다. 이 글의 주제는 어쨌든 스위프트를 배우기 전에 미리 알아두면 좋은 것들을 다루는 것이기에...)

var dic: [String: Int] = ["data1": 165, "data2" : 100]

// 3. 생성자로 생성하기
var dict = Dictionary<String, Int>()
var dicti = [String: Int]()

//value 값에 특정 타입이 아닌 여러 타입을 넣고 싶은 경우
var dictio: [String: Any] = ["string": "string data", "int": 100]
var diction: NSDictionary = ["string": "string data", "int": 1234]

 위와 같이 Any 타입을 사용하면 여러 타입을 한 번에 저장할 수 있으나 나중에 사용할 때 의외로 어지러워지기 때문에 개인적으로는 저렇게 사용하지 않을 것 같습니다. 여러 타입을 한 번에 저장하는 방식은 많으니까요. 하지만 사용헐 수 있는 자료구조는 많으면 많을 수록 좋은 것 같습니다.

 

Optional?

 마지막으로 볼 것은 옵셔널 타입입니다. Optional 타입은 위에서 잠깐 설명했던 특정 타입(String, Int 등)의 뒤에 ?가 붙은 친구들에게서 볼 수 있습니다. (물론 그 경우에만 사용되는 것은 아닙니다.)

 이미 코틀린에서 이 optional과 비슷한 유형의 타입이 사용되고 있기 때문에 다른 언어에서 비슷한 문법을 보았다면 이해 자체가 어려운 내용은 아닐 겁니다. 옵셔녈은 쉽게 말해서 특정 변수가 값이 존재할 수도 있고 존재하지 않을 수도 있다는 것을 의미하는데요.

 모든 변수에 기본적으로 값이 존재한다면 좋겠습니다만, 아쉽게도 제가 만든 변수가 nil 값을 가지고 있다가 추후에 데이터를 받을 수도 있고, 아니면 기존에 값이 존재했다가 저장하고 난 후, 폐기해야 하는 경우가 있을 수 있습니다. 이때는 아예 데이터를 사용하지 않으면 좋겠지만, 우리의 프로그램과 애플리케이션은 그렇게 친절하지 않죠.

 만약 당신이 특정 버튼을 이용해 데이터를 잠시 추가한 후, 서버로 전송해야 한다고 가정합시다. 물론 서버에 전송하기 전까지는 버튼을 계속해서 누를 수 있고, 누를때마다 값이 변합니다. 하지만 서버로 전송한 후에는 데이터를 다시 초기화해야 합니다. 이때 default 값을 설정해줄 수 있지만, 만약 데이터가 default로 정의할 수 없는 변수라면 nil과 같이 아예 없는 값으로 만들어주어야 할 것입니다. 이럴 때 우리는 optional 타입을 이용해서 값의 존재 유무를 따질 수 있게 됩니다.

 이 optional이 잘 이해되지 않을 수 있는데, 이는 스위프트의 변수가 기본적으로 nil 값을 허용하지 않는다는 것을 모르는 것에서부터 오는 문제일 것이라고 생각합니다. 하지만 스위프트에서 일반 변수는 무조건 값이 존재해야 하고, nil과 같은 존재하지 않는 값을 넣으려고 하면 syntax error를 일으킨다는 사실을 알고난 후, nil 값을 허용하는 optional 타입을 본다면 이해가 조금 더 쉬울지도 모르겠습니다.

 


 스위프트를 공부하기 전에 알아둬야 할 키워드는 좀 더 존재한다고 생각합니다. 하지만 이것보다 더 많은 키워드를 알고 난 후 스위프트를 들어가기에는 제 인내심이 너무 부족하기 때문에 여기까지 작성했습니다. 사실 위에서 작성한 키워드들은 간단하지만 이해를 위해 충분한 설명이 필요한 부분이 있는데, 이 글에서는 이러한 것들이 있고 그러한 것들을 추후에 제가 배울 것이라는 이정표 같은 것이기 때문에 따로 설명을 적어두지는 않았습니다.(그걸 적어둘 정도로 제가 스위프트를 공부하지 않았다는 게 가장 큰 문제구요.)

 추후에 제가 저 키워드들을 가지고 꼭 이 블로그에서 글을 작성할 수 있다면 좋겠습니다.

'IOS' 카테고리의 다른 글

Swift - ARC(Automatic Reference Counting)  (0) 2022.07.29
SwiftUI vs UIKit  (0) 2022.02.13
swift를 공부하기 전에(1)  (0) 2022.01.16

댓글