Grand Central Dispatch란?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Grand Central Dispatch(GCD)

Grand Central Dispatch(GCD)는 멀티코어와 멀티 프로세싱 환경에서 최적화된 프로그래밍을 할 수 있도록 애플이 개발한 기술이다다. 기본적으로 스레드 풀의 관리를 프로그래머가 아닌 운영체제에서 관리하기 때문에 프로그래머가 태스크(작업)을 비동기적으로 쉽게 사용할 수 있다. 프로그래머가 실행할 태스크(작업)을 생성하고 Dispatch Queue 에 추가하면 GCD는 태스크(작업)에 맞는 스레드를 자동으로 생성해서 실행하고 작업이 종료되면 해당 스레드를 제거한다.

디스패치 대기열(Dispatch Queue)

디스패치 대기열(Dispatch Queue)은 작업을 연속적 혹은 동시에 진행하기는 하지만, 언제나 먼저 들어오면 먼저 나가는 순서 로 실행된다. Serial Dispatch Queue는 한 번에 하나의 작업만을 실행하며, 해당 작업이 대기열에서 제외되고 새로운 작업이 시작되기 전까지 기다린다. 이와는 반대로 Concurrent Dispatch Queue는 이미 시작된 작업이 완료될 때까지 기다리지 않고 가능한 많은 작업을 진행한다. 디스패치 대기열(Dispatch Queue)은 GCD 기술 일부다.

Dispatch Queue의 종류

디스패치 소스 (Dispatch Source)

디스패치 소스(Dispatch Source)는 특정 유형의 시스템 이벤트를 비동기적으로 처리하기 위한 C 기반 메커니즘이다. 특정 유형의 시스템 이벤트에 대해 정보를 캡슐화하고, 해당 이벤트가 발생할 때마다 특정 클로저(블록) 객체 혹은 기능을 디스패치 대기열(Dispatch Queue)에 전달합니다. 디스패치 소스(Dispatch Source)는 GCD 기술 일부이다.

연산 대기열 (Operation Queue)

연산 대기열(Operation Queue)은 Concurrent Dispatch Queue와 동일하게 동작하며, Operation Queue 클래스에 의해 구현된다. 디스패치 대기열은 항상 먼저 들어오면 먼저 나가는 순서(FIFO - First in First out)로 작업을 실행하지만, 연산 대기열(Operation Queue)은 작업의 실행 순서를 결정할 때에 다른 요인들을 고려한다. 연산 대기열(Operation Queue)은 디스패치 대기열(Dispatch Queue)과 매우 유사한 클래스이다.

GCD와 연산 대기열 (Operation Queue)

차이점

  • Operation Queue에서는 동시에 실행할 수 있는 연산(Operation)의 최대 수를 지정할 수 있다.
  • Operation Queue에서는 KVO(Key Value Observing)을 사용할 수 있는 많은 프로퍼티들이 있다.
  • Operation Queue에서는 연산(Operation)을 일시 중지, 다시 시작 및 취소를 할 수 있다.

언제 사용해야 할까?

  • Operation Queue: 비동기적으로 실행되어야 하는 작업을 객체 지향적인 방법으로 사용하는 데 적합!
    • KVO(key Value Observing)를 사용해 작업 진행 상황을 감시하는 방법이 필요할 때도 적합하다
    • 앱 내에서 많은 동작을 지원할때는 이용하는게 더 편리함
  • GCD: 작업이 복잡하지 않고 간단하게 처리하거나 특정 유형의 시스템 이벤트를 비동기적으로 처리할 때 적합
    • 타이머, 프로세스 등의 관련 이벤트…
    • 얘를 많이 사용하는게 가장 일반적..

ATS(App Transport Security)란?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


ATS(App Transport Security)

ATS는 애플리케이션과 웹 서비스 사이에 통신 시 보안 향상을 위한 기능으로 iOS 9.0, macOS 10.11부터 적용 가능하다. 모든 인터넷 통신 시 안전한 프로토콜을 사용하도록 보장하는 것으로 사용자의 민감한 정보가 유출되는 것을 방지한다.

ATS 등장 배경

다양한 종류의 애플리케이션이 개인의 여러 가지 정보(연락처, 사진, 건강정보, 메시지, 메일 등)를 다루게 되면서 사용자 정보보호에 대한 중요성이 한층 부각되었다. 그런데 기존의 보안/암호 기술은 오래되어 공격에 취약해졌지만, 컴퓨터 성능은 점점 발전하면서 새롭게 등장하는 네트워크 공격이 강력해지자 이에 대응하기 위해 2015년 ATS를 도입하게 되었다.

2016년부터 새롭게 만들어지는 애플리케이션은 반드시 ATS를 사용해야 하며, 기존에 개발된 애플리케이션은 ATS를 사용할 수 있도록 네트워크 보안을 강화해야 한다고 한다.

ATS 동작

URLSession, CFURL 그리고 NSURLConnection API를 이용해 데이터를 주고받을 때 ATS 기능을 기본적으로 사용하게 된다. ATS가 활성화되어있을 때는 HTTP 통신을 할 수 없으며 애플에서 권장하는 아래 요구 사항을 충족하지 않은 네트워크는 연결에 실패할 수 있다.

서버는 TLS(Transport Layer Security) 프로토콜 버전 1.2 이상을 지원해야 한다. 적어도 2048비트 이상의 RSA 키 또는 256비트 이상의 ECC(Elliptic-Curve) 키가 있는 SHA256을 인증서에 사용해야 한다. 암호 연결은 아래 허용된 암호 목록으로 제한한다.

  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

용어 정리

  • 전송 계층 보안 (Transport Layer Security - TLS)
    • 암호 프로토콜로 서버와 클라이언트 애플리케이션이 네트워크로 통신하는 과정에서 도청, 간섭, 위조를 방지하기 위해서 설계되었음
  • HTTPS (Hypertext Transfer Protocol Secure)
    • TLS를 사용해 암호화된 연결을 하는 HTTP(Hypertext Transfer Protocol)를 HTTPS라고한다

한 번 더 생각해보기

TLS는 다양한 종류의 보안 통신을 하려는 프로토콜이고, HTTPS는 TLS 위에 HTTP 프로토콜을 얹어 보안된 HTTP 통신을 하는 프토로콜을 의미한다.

예외 사항

애플리케이션이 ATS가 요구하는 사항을 충족하기 힘든 경우, ATS 기능을 비활성화할 수 있다. 아래는 ATS 기능을 사용하지 않을 수 있는 예외사항이다.

  • AVFoundation 프레임워크를 통한 스트리밍 서비스
  • WebKit을 통한 콘텐츠 요청
  • 로컬 네트워크 연결
  • 그 외에는 서버가 최신 TLS 버전으로 업그레이드할 때까지 애플리케이션의 유지 보수를 위해 일시적으로 ATS 기능을 사용하지 않는 것이 가능하며, App Store 심사 시 정당한 이유를 설명하는 문서가 필요할 수도 있다.

ATS 기능 비활성화 방법: 해당 프로젝트의 info.plist 파일에서 설정

모든 HTTP 통신 허용: 암호화 하지 않은 통신이므로 불가피한 때 외에는 사용하지 않는 것이 좋다.

<key> NSAppTransportSecurity </key>
<dict>
 	<key> NSAllowsArbitraryLoads </key>
 	<true/>
</dict>

ATS에서 제외할 특정 도메인 지정

<key>NSAppTransportSecurity</key>
<dict>
   <key>NSExceptionDomains</key>
   <dict>
       <key>www.abc.com</key>
       <dict>
           <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
           <true/>
       </dict>
   </dict>
</dict>

탭바(tap bar)란 무엇인가?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


탭바란?

사용자가 탭바의 항목(Item)을 선택하면 해당 항목에 연결된 뷰 컨트롤러의 콘텐츠가 화면에 보이게된다. 주로 여러 메뉴를 구성할 때 많이 사용하며 카테고리 사이의 전환을 위해 사용하거나 다양한 관점으로 같은 정보를 제공하는 데 사용한다.

탭바는 화면에 보여지기 위한 뷰 요소이므로 제어를 하기 위해서는 컨트롤러가 필요하다. 프로그래머가 직접 탭바를 제어할 컨트롤러 클래스를 작성하여 사용할 수도 있지만, 대부분의 경우 프레임워크에서 제공하는 탭바 컨트롤러(UITabBarController)를 사용하여 제어한다. 이렇게 탭바와 탭바 컨트롤러를 사용하여 인터페이스를 구성한 것을 탭바 인터페이스라고 부른다.

탭바의 구조

탭바 인터페이스는 탭바 컨트롤러가 생성한 탭바 뷰(View)와 탭바 컨트롤러가 관리하는 콘텐츠 뷰 컨트롤러로 구성되어 있다. 탭바 컨트롤러는 연결된 콘텐츠 뷰 컨트롤러의 컨테이너 뷰 컨트롤러이다. 각 콘텐츠 뷰 컨트롤러는 탭바에서 하나의 탭에 해당하며, 사용자가 탭바에서 탭을 선택할 때, 탭바 컨트롤러 객체가 해당 콘텐츠 뷰 컨트롤러의 뷰를 화면에 보여준다.

탭바 인터페이스 생성하기

객체라이브러리 사용 방법

1. 탭바 컨트롤러를 객체 라이브러리로부터 드래그한다

2. 생성된 탭바 컨트롤러를 선택한 후 속성 인스펙터 탭에서 Is Initial View Controller 옵션을 선택

Is Initial View Controller 옵션은 스토리보드의 컨트롤러 중에 하나만 설정할 수 있으며, 해당 스토리보드의 맨 처음 진입화면이 된다.

이미 존재하는 뷰 컨트롤러를 탭바 컨트롤러에 연결하기

1. 기존에 있는 뷰 컨트롤러(들)를 선택하고 Editor -> Embed in -> Tab bar controller를 선택하여 뷰 컨트롤러를 탭바 컨트롤러에 포함

탭바 컨트롤러에 뷰 컨트롤러 추가하기

1. 탭바 컨트롤러에 새롭게 추가할 뷰 컨트롤러를 생성

2. 탭바 컨트롤러에서부터 키보드의 ‘control’키를 누른 상태로 드래그하여 추가할 뷰 컨트롤러에 드롭하여 세그(Segue)창이 나타나면 Relation Segue의 view controllers를 선택

3. 탭바 컨트롤러에 뷰 컨트롤러가 새롭게 추가된 것을 확인할 수 있다.

탭바 아이템이란?

탭바 뷰에서 각 탭은 이름과 이미지를 표시할 수 있고 뷰 컨트롤러는 이러한 용도로 tabBar프로퍼티를 관리한다. 탭바 컨트롤러가 콘텐츠 뷰 컨트롤러를 포함하면 해당 뷰 컨트롤러의 탭바 아이템이 탭바 컨트롤러의 탭바에 추가된다. 탭바 컨트롤러의 탭바 아이템이 6개 이상인 경우, 5번째 탭에 ‘More’이라는 아이템이 표시되고 사용자가 More 버튼을 누르면 나머지 탭 항목을 선택할 수 있는 인터페이스가 표시된다.

탭바 델리게이트

사용자가 탭바 인터페이스와 상호작용할 때, 탭바 컨트롤러 객체는 이 상호작용에 관한 알림(notification)을 델리게이트 인스턴스로 보낸다. 사용자가 탭을 선택하지 못하게 하거나, 탭을 선택한 후 추가 작업을 수행하거나, 탭 관련 사항을 모니터링하고 사용자화 하기 위해서 델리게이트를 활용한다.

UITabBarController 클래스

UITabBarController 클래스에는 탭바를 구성하고 각 탭에 해당하는 뷰 컨트롤러들을 관리하기 위한 메서드와 프로퍼티가 정의되어 있다.

탭바 컨트롤러의 탭을 구성하기 위해서는 뷰 컨트롤러를 탭바 컨트롤러의 viewControllers 프로퍼티에 할당한다. 탭바 아이템은 해당 탭에 연결된 뷰 컨트롤러를 통해 구성되며 UITabBarItem 클래스의 인스턴스를 뷰 컨트롤러의 tabBarItem 프로퍼티에 할당한다. 만약에 UITabBarItem 클래스의 인스턴스를 뷰 컨트롤러에 따로 할당하지 않을 경우, 탭바에는 이미지 없이 뷰 컨트롤러의 title 프로퍼티에 해당하는 텍스트로만 탭바의 항목으로 표시한다.

탭바 컨트롤러의 뷰

UITabBarController 클래스는 UIViewController 클래스를 상속받기 때문에 탭바컨트롤러는 view프로퍼티를 통해 접근할 수 있는 자신만의 자체 뷰(view)를 가지고 있다. 이 뷰는 탭바와 선택된 뷰 컨트롤러의 콘텐츠를 나타내는 뷰로 구성되어 있다.

  • UITabBarControler 클래스의 주요 프로퍼티 및 메서드
  • var tabBar: UITabBar: 탭바 컨트롤러와 연결된 탭바 뷰
  • var viewControllers: [UIViewController]?: 탭바 컨트롤러가 관리하는 뷰 컨트롤러의 배열! 즉, 각각의 탭바 항목에 해당하는 뷰 컨트롤러의 목록
  • func setViewControllers([UIViewController]?, animated: Bool): 탭바 컨트롤러가 관리할 뷰 컨트롤러들을 설정
  • var selectedViewController: UIViewController?: 현재 선택된 탭 항목과 연결된 뷰 컨트롤러
  • var selectedIndex: Int: 현재 선택된 탭 항목의 인덱스(index)

실습

여러개의 vc를 잡고 embed in > tabbar interface 지정해준다.

탭바 인터페이스 안에서 네비게이션 인터페이스는 가능하지만 그 반대는 안된다. 즉, 네비게이션 인터페이스 안에서 갑자기 어느 한 뷰에서 탭바를 가지고 갈 수는 없다는 것!

얼럿(alert)과 액션시트(action sheet)란 무엇인가?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


얼럿과 액션시트

UIAlertController 클래스

UIAlertController 클래스는 사용자에게 표시할 얼럿 또는 액션시트의 구성에 관한 메서드와 프로퍼티를 포함하고 있다. UIAlertController 클래스를 통해 얼럿 또는 액션시트를 구성한 후 UIViewController의 present(_:animated:completion:) 메서드를 사용하여 사용자에게 얼럿 또는 액션시트를 모달로 보여준다.

UIAlertController의 주요 메서드

  • init(title:message:preferredStyle:) > 얼럿 뷰 컨트롤러의 객체를 초기화
  • func addAction(UIAlertAction) > 얼럿이나 액션시트에 액션을 추가
  • func addTextField(configurationHandler: ((UITextField) -> Void)? = nil) > 얼럿을 통해 텍스트를 입력받고자 하는 경우 텍스트 필드를 추가

UIAlertController의 주요 프로퍼티

  • var title: String? > 얼럿의 제목
  • var message: String? > 얼럿에 대해 좀 더 자세히 설명하는 텍스트
  • var actions: [UIAlertAction] > 사용자가 얼럿 또는 액션시트에 응답하여 실행할 수 있는 액션
  • var preferredStyle: UIAlertController.Style > 얼럿 컨트롤러의 스타일로 얼럿(alert)과 액션시트(actionSheet)가 있다.

UIAlertAction 클래스

사용자가 얼럿 또는 액션시트에서 사용할 버튼과 버튼을 탭 했을 때 수행할 액션(작업)을 구성할 수 있다. UIAlertAction 클래스를 사용하여 버튼을 구성한 후 UIAlertController 객체에 추가하여 사용한다.

UIAlertAction의 주요 프로퍼티

  • var title: String? > 액션 버튼의 타이틀
  • var isEnabled: Bool > 액션이 현재 사용 가능한지를 나타냄
  • var style: UIAlertAction.Style > 액션 버튼의 적용될 스타일

UIAlertAction.Style

  • default: 액션 버튼의 기본 스타일
  • cancel: 액션 작업을 취소하거나 상태 유지를 위해 변경사항이 없을 경우 적용하는 스타일
  • destructive: 취하게 될 액션이 데이터를 변경되거나 삭제하여 돌이킬 수 없는 상황이 될 수 있음을 나타낼 때 사용하는 스타일

얼럿과 액션시트는 언제 사용할까?

얼럿

  • 중요한 액션을 하기 전 경고가 필요한 경우
  • 액션을 취소할 기회를 제공해야 하는 경우
  • 사용자의 작업을 한 번 더 확인하거나 삭제 등의 작업을 수행하거나 문제 사항을 알릴 때
  • 결정이 필요한 중요 정보를 표시할 경우

액션시트

  • 사용자가 고를 수 있는 액션 목록이 여러 개일 경우
  • 새 작업 창을 열거나, 종료 여부 확인 시
  • 사용자의 결정을 되돌리거나 그 동작이 중요하지 않을 경우

실습

import UIKit

class ViewController: UIViewController {

    @IBAction func touchUpShowAlertBtn(_ sender: UIButton) {
        // 해당 버튼을 누르면 showAlertController를 실행하게 되고
        // 스타일을 alert 스타일로 해달라고 지정
        self.showAlertController(style: UIAlertController.Style.alert)
    }

    @IBAction func touchUpShowActionSheetBtn(_ sender: UIButton) {
        self.showAlertController(style: UIAlertController.Style.actionSheet)
    }

    func showAlertController(style: UIAlertController.Style) {
        let alertController: UIAlertController
        alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: style)

        let okAction: UIAlertAction
        // handler는 alert action이 선택됐을때, OK버튼이 실행된다면
        // 실행될 코드 블럭을 의미한다
        okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: { (action: UIAlertAction) in print("OK pressed")
        })

        let cancelAction: UIAlertAction
        // nil은 사용자가 누르면 아무 액션없이 alert이 dismiss된다
        cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil)

        // action을 추가해줘야 실행된다.
        // 액션 순서에 상관없이 어떻게 넣어주더라도 위치는 UIAlertController가 알아서 지정해준다
        alertController.addAction(okAction)
        alertController.addAction(cancelAction)

        // 모달로 올려줌! completion은 모달이 올라오는 애니메이션이 끝나고 직후에 호출될 블럭
        self.present(alertController, animated: true, completion: { print("Alert controller shown") })
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

위 코드는 문제없이 진행될 것이고 이제 아래 코드를 더 추가해보자

let handler: (UIAlertAction) -> Void
        // handler라는 상수를 따로 빼놓음으로써 handler가 해야할 일을 지정해줌
        // 반복적으로 사용되는 작업은 이같이 사용하는 게 좋다
        // 어떤 응답에 대한 처리인지 써놔주었기 때문에 더 편리!
        handler = { (action: UIAlertAction) in print("action pressed \(action.title ?? "")")}

        let someAction: UIAlertAction
        someAction = UIAlertAction(title: "Some", style: UIAlertAction.Style.destructive, handler: handler)

        let anotherAction: UIAlertAction
        anotherAction = UIAlertAction(title: "Another", style: UIAlertAction.Style.cancel, handler: handler)

        alertController.addAction(someAction)
        alertController.addAction(anotherAction)

아래와 같은 에러가 뜰 것이다.

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’

해당 에러는 다음과 같다. 현재 위 코드에서 액션 스타일 cancel을 두번 사용하고 있는데, 다른 스타일은 상관없지만 cancel은 하나의 액션만 스타일을 사용할 수 있다. 따라서 cancel 스타일은 하나만 남겨놓고 another action의 스타일을 default로 바꾸어주고 해보자!

let anotherAction: UIAlertAction
        anotherAction = UIAlertAction(title: "Another", style: UIAlertAction.Style.default, handler: handler)

완벽하게 진행될 것이다. 추가로,,

destructive 스타일이 쓰이는 떄는 삭제를 하거나 동작을 취했을때 혹은 되돌릴 수 없을때와 같이 주의해야하는 동작을 할때 사용하는 스타일이다.

그리고 우리가 보통 앱스토어에서 로그인을 해야할때와 얼럿과 함께 텍스트필드를 사용하는 경우가 있다.

이는 아래와 같이 작성하면 된다.

alertController.addTextField(configurationHandler: { (field: UITextField) in
            field.placeholder = "플레이스 홀더"
            field.textColor = UIColor.red
        })

그런데 이 텍스트필드는 액션시트에서는 사용이 안되나보다…!

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert’

무언가 조금 아쉽….!

여튼! 이렇게 하면 아래와 같은 얼럿을 볼 수 있게 된다.

기본연산자 정의(Basic Operators)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


파이썬으로 처음 개발 공부를 시작했던 나에게 초반 머리에 잘 들어오지 않던 연산자 개념이 있었다. 그것은 바로 범위연산자
어떤때에는 .. 어떤때에는 … 이게 무슨의미지 헀는데, 막상 찾아보니 별거아닌(?) 개념이어서 그냥 간단하게 정리해보겠습니다 :)

기본연산자

swift에서는 통상적으로 이용하는 +, -, /, % 등과 같은 산술연산자와 $$과 같은 논리연산자 뿐만 아니라 a..<b, a…b와 같이 값의 범위를 지정할 수 있는 범위연산자를 지원한다.

  • 단항 연산자: -a, !b, c!와 같이 하나의 대상 앞뒤에 바로 붙여 사용하는 연산자
  • 이항 연산자: 2 + 3과 같이 두 대상 사이에 위치하는 연산자
  • 삼항 연산자: a? b : c 형태로 swift에 삼항연산자는 이 연산자 단 하나만 존재

할당연산자(Assignment Operators)

할당 연산자는 값을 초기화시키거나 변경 > 상수, 변수 모두에 사용 가능하다.

let a = 10
var b = 5

b = a  // b의 값은 10

let (x, y) = (1, 2)  // 튜플을 이용해 한번에 할당 가능

사칙 연산자(Arithmetic Operators)

  • 더하기, 뺴기, 곱하기, 나누기 + 나머지
1 + 2  // 3
5 - 3  // 2
2 * 3  // 6
10.0 / 2.5  //4.0
9 * 4  // 1

비교 연산자(Comparison Operators)

  • 같다 (a == b)
  • 같지 않다 (a != b)
  • 크다 (a > b)
  • 작다 (a < b)
  • 크거나 같다 (a >= b)
  • 작거나 같다 (a <= b)

삼항 조건 연산자(Ternary Conditional Operator)

삼항 조건 연산자는 question ? answer1 : answer2의 구조를 갖는다. 그래서 question 조건이 참이면 answer1, 거짓인 경우 answer2가 실행된다.

if question {
  answer1
} else {
  answer2
}

Nil 병합 연산자(Nil-Coalescing Operator)

nil 병합 연산자는 a ?? b형태를 갖는 연산자다. 옵셔널 a를 벗겨서(unwrap) 만약 a가 nildlaus b를 반환한다.

a != nil ? a! : b

즉, 옵셔널 a가 nil이 아니면 a를 unwrap하고 nil이면 b를 반환한다는 의미!

범위 연산자(Range Operators)

  • 닫힌 범위 연산자: a..b 의 형태로 범위의 시작과 끝이 있는 연산자
  • 반 닫힌 범위 연산자: a..<b의 형태로 a부터 b보다 작을때까지의 범위를 갖는 연산자 » a부터 b-1까지의 값
  • 단방향 범위: [a..] 혹은 [..a]의 형태로 범위의 시작 혹은 끝만 지정해 사용하는 연산자

논리 연산자(Logical Operators)

  • 논리부정: NOT(!a)
  • 논리 곱: AND(a&&b)
  • 논리 합: OR(a||b)