본문 바로가기
YAGOM CAREER STARTER

[TIL] 20221221: Naming, Optional, Split, Components

by Rhode 2022. 12. 21.

본문은 야곰 아카데미 커리어 스타터 캠프를 통해 학습한 내용을 회고한 글입니다.

 


 

네이밍 Naming

Avoid abbreviations: 축약어를 피하라!

Abbreviations, especially non-standard ones, are effectively terms-of-art, because understanding depends on correctly translating them into their non-abbreviated forms.
축약어, 특히 비표준 약어는, 사실상 terms-of-art(상황이나 분야에 따라 달리 이해될 수 있는 특정한 말)이다. 왜냐하면 축약어가 아닌 형태로 정확하게 번역하는 것에 따라 이해가 달려있기 때문이다.)
func CreateRandomNums() -> [Int] {
	...
 }

위와 같은 상황에서 CreateRandomNums라고 함수명을 짓기 보다는, CreateRandomNumbers라고 함수명을 짓는게 낫다. 조금 더 길어져도 의미가 명확한게 좋기 때문이다. 나는 이 함수명을 이해했을지라도, 협업하는 상대는 그렇지 못했을 수도 있다. 그러므로 축약어를 사용하지 말고 명확하게 네이밍을 하자!

옵셔널 Optional

func countBallAndStrike(comparing randomNumbers: [Int]) -> [String: Int] {
    var result = [String: Int]()
    result["strike"] = 0
    result["ball"] = 0

    for i in 0...2 {
        if computerRandomNumbers[i] == randomNumbers[i] {
            result["strike"]? += 1
        } else if randomNumbers.contains(computerRandomNumbers[i]) {
            result["ball"]? += 1
        }
    }

    return result
}

위의 코드에서 의문이 들었다. result["strike"]에 접근하기 위해서 물음표(?)를 사용하는 것이 맞는 것일까? 이에 대해 공부를 하게 되었다.

딕셔너리의 반환값은 옵셔널

딕셔너리에서 키값(key)을 통해 value를 꺼내오면 그 반환값은 기본적으로 옵셔널(Optional)이 된다. '특정 키값에 해당하는 value가 확실히 존재하는데 왜 옵셔널이지?'라고 생각했다. 그런데, 컴파일러는 그것을 알지 못한다고 한다. 그래서 nil의 등장에 대비하여 기본적으로 모든 value에 옵셔널을 씌운다고 한다. 즉, 딕셔너리에 존재하지 않는 키값이 입력되면 nil이 반환 될 수 있기 때문이다.

var items = [1: "하네스", 2: "패딩", 3: "리드줄", 4: ""]

items[1] // Optional("하네스")
items[4] // Optional("")

item[0] // nil: 만약 딕셔너리에 존재하지 않는 키값이 입력되면, nil이 반환된다.

그렇기 때문에, result["strike"]는 Optional(변수)이다. 그러면, Optional(1)에 물음표(?)를 붙이는 것은 무슨 의미를 가질까? 이것은 옵셔널을 추출하는 방법을 공부해보면 알 수 있다.

옵셔널 추출

옵셔널 추출은 크게 네 가지가 있다고 볼 수 있다. 강제 추출, 옵셔널 바인딩, 암시적 추출 옵셔널, 옵셔널 체이닝.

강제 추출

강제 추출은 옵셔널을 추출하는 가장 간단한 방법이다. 옵셔널의 뒤에 물음표(?)를 붙여주면 된다. 이 때, 옵셔널 안의 값이 nil이라면 런타임 오류가 생긴다.

var 변수이름: String = 옵셔널인변수나상수!

 

옵셔널 바인딩

if문이나 guard문 등과 결합해 사용할 수 있는 방법이다. 다음과 같은 형태로 쓴다.

if let 상수이름 = 옵셔널 {
	실행할 구문 
}

guard let 상수이름 = 옵셔널 else {
	실행할 구문
}

if문과 guard문은 다음과 같은 차이를 가진다.

  • if문과 달리 guard문은 항상 else문이 뒤따라온다.
  • if문은 값이 true라면(nil이 아니라면) 블록 내부의 코드가 실행되는 반면, guard문은 값이 false라면(nil이라면) 블록 내부의 코드가 실행된다.
  • if문에서 바인딩 된 상수는 그 블록 안에서만 사용 가능하지만, guard문으로 바인딩을 한다면 함수내부의 지역상수처럼 사용이 가능하다.
  • guard문을 사용하면 예외사항만을 처리할 때 용이하므로 코드가 더 간결해지고 읽기 좋아진다.
  • guard문은 return, break, continue, throw 등의 명령어들을 필수로 가진다.
  • guard문은 함수나 메서드, 반복문 등 특정 블록 내부에 위치해야한다.

 

암시적 추출 옵셔널

옵셔널의 타입 뒤에 느낌표(!)를 붙여 반환해준다. 강제 추출이 옵셔널 값을 사용할 때마다 추출해준다면, 암시적 추출 옵셔널은 그냥 옵셔널이 아닌 것처럼 상수나 변수를 사용할 수 있는 것이다. 즉, 옵셔널에 접근할 때마다 옵셔널 값을 풀 필요가 없다. 강제 추출과 마찬가지로 옵셔널 안의 값이 nil이면, 런타임 오류가 생긴다.

var 변수이름: String! = "rhode"

 

옵셔널 체이닝

옵셔널 체이닝은 옵셔널 뒤에 물음표(?)를 붙여서 접근할 수 있다. 이 때, 옵셔널에 값이 존재한다면 값을 반환하고 그렇지 않다면(nil이라면) nil을 반환한다. 어떤 값을 반환하기 위해 사용한다기보다는 옵셔널인 값들을 바인딩을 사용하지 않으면서 로직을 수행하기 위해 사용한다.

다시 질문으로 돌아가보자.
result["strike"]에 접근하기 위해서 물음표(?)를 사용하는 것이 맞는 것일까? result["strike"]는 Optional(변수)라고 했다. 여기에 물음표(?)를 붙이는 것은 무슨 의미인가? 바로 옵셔널 체이닝을 사용한 것이다! 옵셔널 바인딩을 사용하지 않으면서 로직을 수행하기 위해 물음표(?)를 붙여준 것이라고 볼 수 있다.

var result = ["strike": 0, "ball":0]

result["strike"]? += 1  //1
result["hello"]? += 1  //실행되지 않음(nil)

 

Split과 Components

split을 사용하였는데, substring이라는 놈이 튀어나왔다!! 그래서 components로 바꿔 사용하게 되었다.

Split

func split(
    separator: Self.Element,
    maxSplits: Int = Int.max,
    omittingEmptySubsequences: Bool = true
) -> [Self.SubSequence]

components

func components(separatedBy separator: String) -> [String]

이렇다고 한다.
오늘의 공부 끝!