HTTP Method 는 요청( Request ) 시에 어떠한 수행이 필요한지 Request에 담아 보낼 수 있는 집합을 말합니다.

 

Method 에는 

HEAD, GET, POST, PUT, DELETE, PATCH, CONNECT, TRACE, OPTIONS 가 있습니다.

 

HEAD

동작자체는 GET과 같아 보이지만 Response 로 헤더만을 보내줍니다.

HEAD로는 Resource를 받지 않더라도 StatusCode 를 통해 데이터의 유무를 확인 할 수 있고

헤더로 Resource가 변경되었는지 알 수 있습니다.

HTTP/1.1 의 규약을 준수하려면 HEAD Method가 필수로 구현되어야합니다.

 

GET

서버에서 후처리가 필요하지않고 단순하게 Resource 만을 요청할때 사용됩니다.

GET으로 요청할때는 URL 뒤에 파라미터를 QueryString으로 작성하여 String의 형태로 전달해야합니다.

ex) http://1.1.1.1:80/getData?id=xxxx&pw=xxxx

QueryString으로 보내는 만큼 URL에 정보가 노출되므로 

보안의 위험이 상대적으로 큽니다.

 

POST

서버에서 DB에 대한 후처리(새로운 데이터 저장)이 필요하거나 정보를 재가공해 Response 해주는 경우에 사용됩니다.

GET에서는 QueryString으로 보내던 파라미터를 POST 에서는 BODY에 담아서 보냅니다.

그러므로 GET보다는 상대적으로 좀 더 안전합니다.

보낼 데이터의 용량도 URL뒤에 String방식으로 보내는 GET은 길이제한이있어 많은 양의 데이터를 보내기 힘들고

POST는 GET보다는 많은 양의 데이터를 보낼 수 있습니다( 물론 POST에도 용량의 제한은 있습니다. )

POST는 SQL Query에서 INSERT와 대응되는 메소드입니다.

 

PUT

전송구조는 POST와 유사하고 서버에서 DB에 들어있는 정보를 수정하기 위해 사용합니다.

DELETE와는 반대되는 메소드 입니다.

SQL Query 에서 UPDATE 와 대응되는 메소드입니다.

 

PATCH

PUT과 유사하게 UPDATE 와 대응되는 메소드이기도 하고

DB에 들어있는 정보를 수정하기 위해 사용하지만 PUT과는 의미를 다르게 사용합니다.

PUT은 정보의 전체를 갱신 및 저장하는 의미로 쓰이지만

PATCH는 해당 정보의 일부를 교체하는 의미로 사용합니다.

 

DELETE

전송구조는 POST와 유사하고 서버에서 DB에 있는 정보를 삭제하기 위해 사용합니다.

안전성의 문제가 있을 수 있으므로 클라이언트에서 보내는 DELETE 메소드는 서버에서 거부 할 수 있습니다.

PUT과는 반대되는 메소드 입니다.

 

CONNECT

요청한 URL에 대해 양방향 연결을 시작하는 메소드입니다.

클라이언트가 프록시를 통해 서버와 SSL 통신을 하고자 할 때 사용됩니다.

 

TRACE

클라이언트와 서버간의 통신관리 및 디버깅의 목적으로 만들어진 메소드입니다.

TRACE 를 지원하는 서버가 Request를 받게 되면 서버는 Request받은 메시지 전체를

Response Body에 담아 클라이언트에게 Response 를 보내줍니다.

TRACE Method는 Request를 브라우저에 표시하는 것이 가능하다는 특징이 있는데

그 특징을 이용하여 TRACE를 이용한 크로스 도메인 공격을 할 수 있습니다.

이러한 공격을 크로스 사이트 트레이싱( Cross-Site Tracing )이나 XST라고 부릅니다.

 

OPTIONS

클라이언트에서 서버로 통신을 위해 접근하고자 하는 URL에 대해

서버에서 지원하고 있는 메소드의 종류를 확인 할때 사용합니다.

 

 

'Http' 카테고리의 다른 글

What is HTTP  (0) 2019.04.05

HTTP( Hyper Text Transfer Protocol )

서버가 HTML로 된 문서를 유저에게 보여주기 위함을 목적으로 한 프로토콜.

일반적인 인터넷 통신에 사용되는 프로토콜입니다.

HTML을 보여주기 위함이지만 HTML뿐만 아니라 각종 이미지, 비디오, 데이터 등의 전송도 가능합니다.

동작은 간단하게 접근하려는 URL로 요청(Request)를 보내고 응답(Response)를 받는 형태입니다.

 

큰 범위의 특징으로 HTTP는 Connectionless 하고 Stateless 합니다.

Connectionless 는 웹(클라이언트)와 서버가 연결 되면 요청(Request)를 하고 응답(Response)를 보낸 뒤엔 접속을 해제합니다.

간단하게 클라이언트와 서버가 항상 연결이 되어 있지는 않다는 뜻입니다. 

위와 같은 이유로 상대와 연결이 끊기고 새롭게 연결되는 과정을 반복하기때문에

클라이언트와 서버는 연결에 대한 정보를 따로 저장할 쿠키나 세션같은 방법이 필요합니다.

 

Stateless는 통신이 끝나고 연결이 해제될때 당시에 상태가 저장이 되지않으므로 Stateless하다고 합니다.

간단하게 어떠한 페이지에 로그인할때 세션이나 쿠키에 따로 저장해두지 않으면 로그인을 했던 정보가 바로 사라지게 됩니다.

 

이러한 특징으로 인해 실시간 데이터 변경 및 갱신의 상황에서는 단점으로 작용합니다.

실시간으로 통신하여 데이터를 갱신해야하는 게임이나, 주식 등의 데이터를 표현하기 위해서

일반적으로 Socket이라는 인터페이스를 사용하게 됩니다.

'Http' 카테고리의 다른 글

What is HTTP Method  (0) 2019.04.05

옵셔널 (Optional)


옵셔널 (Optional) 은 랩핑이 되어있는 값과 존재하지 않는 값인 nil 중 하나를 나타내는 형태입니다.

간단하게 설명하면 이 변수에는 값이 있을수도 있고, 없을수도 있다는 표현입니다.

옵셔널 (Optional) 은 변수에 들어있는 값을 안전하게 꺼내 사용 할 수 있어 런타임 에러 (Runtime Error) 에 매우 안전한 방법입니다.


옵셔널 (Optional) 은 "?" 라는 특수문자로 표현합니다, 이 표현은 뒤에 설명될 옵셔널 체이닝 (Optional Chaining) 에도 사용됩니다.


기본적으로 표현하는 형태는 다음과 같습니다.


var optionalIntValue: Int?                 // Shorthand Form
var optionalIntValue: Optional<Int>        // Longhand Form



 위 코드와 같이 Shorthand Form 과 Longhand Form 이 있는데

글자수는 작지만 의미가 똑같이 축약되어있는 Shorthand Form 을 많이 사용합니다.






옵셔널 바인딩 (Optional Binding)


위에서 설명했듯이, 옵셔널 (Optional) 은 변수에 들어있는 값을 안전하게 꺼내 사용 할 수 있는 방법입니다.

그럼 이 옵셔널 변수를 어떻게 사용해야 안전하게 사용하는 것 일까요?


옵셔널 바인딩은 옵셔널 제어 구조 (Optional Control Structures) 를 사용하여 옵셔널 변수값을 꺼내 사용하는 형태를 말합니다.

옵셔널 제어 구조를 사용한 옵셔널 바인딩의 사용방법은 다음과 같습니다.


// if let
if let intValue = optionalIntValue {
    print(intValue)
}
 
// guard let
guard let intValue = optionalIntValue else {
    return
}
 
print(intValue)
 
// switch
switch optionalIntValue {
    case 1:
        print(optionalIntValue)
    default:
        print("default")
}



1. if let 

옵셔널 값인 optionalIntValue 의 값을 nil 체크 후에 nil 이 아닌 값이 있다면 intValue 변수에 값을 전달하고

그 안에서 intValue 변수를 컨트롤합니다.


2. guard let

옵셔널 값인 optionalIntValue 의 값을 nil 체크 후에 nil 이 아닌 값이 있다면

intValue 변수에 값을 전달하고 해당 코드를 통과하여 다음코드가 실행됩니다.

값이 nil 이라면 해당코드를 통과하지못하고 else 로 진입 후에 코드를 실행하고 return 에 의해 다음 코드와 상관없이 함수가 종료됩니다.


3. switch

옵셔널 값인 optionalIntValue 값을 미리 정해 놓은 값으로 필터링 할때 사용됩니다.

기본적으로 case 를 사용하여 원하는 값을 정해주고 일치할때 각각 실행될 코드를 구현합니다.

미리 정해놓지 않은 값이 나왔을땐 default 로 진입하여 코드를 실행합니다.


추가적으로 switch로 구분할 property가 enum 과 같이 명확하게 갯수가 정해져있다면

 default를 따로 정하지않고 enum에서 정해놓은 case 만 구현해도 에러가 나지 않습니다.






옵셔널 강제 언래핑 (Optional Forced Unwrapping)


옵셔널 값을 안전하게 사용하게 위해서는 위에 설명한 옵셔널 바인딩을 사용해야 합니다.

그 외에 확실하게 값이 있다는 가정하에 사용하는 옵셔널 강제 언래핑이 있습니다.


옵셔널 강제 언래핑은 "!" 라는 특수문자를 사용합니다.


기본적으로 표현하는 형태는 다음과 같습니다.


var optionalIntValue: Int!
 
optionalIntValue = 0
 
print(optionalIntValue)    // print 0



위 코드와 같이 "!" 를 사용하여 선언하고 print 로 출력하는건 중간에 0이라는 값을 optionalIntValue 에 넣어뒀기때문에 에러없이 동작합니다.

이렇게 있을수도 있고 없을수도 있는 애매한 옵셔널 값을 명확하게 드러내지만

옵셔널 바인딩 없이 강제로 언래핑하여 사용한다면 말 그대로 강제로 벗겨내기때문에

값이 nil 일 경우 런타임 에러가 발생하게 됩니다.


var optionalIntValue: Int!    // nil
 
print(optionalIntValue)        // Runtime Error
 
 
var optionalIntValue: Int?    // nil
 
print(optionalIntValue!)    // Runtime Error



위 코드와 같이 선언할때 강제 언래핑을 사용했거나 옵셔널 변수를 강제 언래핑 할경우에 런타임 에러가 생기는 경우가 굉장히 많으므로

옵셔널 바인딩을 사용해 값을 확인하고 언래핑하여 사용하는 방법이 제일 안전한 방법이라고 생각합니다.





nil 과 합쳐진 연산자 (Nil-Coalescing Operator)


옵셔널 값을 언래핑하여 사용할때 옵셔널 바인딩 (Optional Binding) 을 사용하기도하지만

nil 과 합쳐진 연산자 (Nil-Coalescing Operator) 를 사용하여 좀더 간단하게 사용하기도합니다.


nil 과 합쳐진 연산자는 "??" 라는 특수문자를 사용합니다.


var optionalIntValue: Int?    
let nonOptionalIntValue: Int = 0
 
print(optionalIntValue ?? nonOptionalIntValue)        



위 코드는 기본적으로 optionalIntValue 를 print 하지만 optionalIntValue 의 값이

nil 일경우 nonOptionalIntValue 의 값을 print 하는 방법입니다.

nil 과 합쳐진 연산자를 사용할땐 전자는 항상 옵셔널 타입 (Optional Type) 이어야 하고 후자는 전자와 타입 (Type) 이 같은 값이 있어야 합니다.

nil 과 합쳐진 연산자는 조건의 검사와 언래핑을 좀더 간결하고 읽기 쉽게 만들어 줍니다.


또한 ?? 연산자는 여러개를 이어서 사용할 수 있습니다.


var optionalIntValue: Int?
var optionalIntValueSecond: Int?
let nonOptionalIntValue: Int = 0
 
print(optionalIntValue ?? optionalIntValueSecond ?? nonOptionalIntValue)        




옵셔널 체이닝 (Optional Chaining)


옵셔널체이닝(Optional Chaining)은 값이 있을지도 모르는 Property, Method, Subscript를 쿼리를 통해 호출하는 Process입니다.

Optional 요소에 값이 들어있다면 PropertyMethodSubscript의 호출에 성공합니다.

Optional 요소에 값이 nil 이라면 PropertyMethodSubscript의 호출에 nil 이 반환됩니다.

여러개의 쿼리(Multiple query)를 함께 연결 할 수 있고, 여러개의 쿼리가 연결되있을때 한곳이라도 반환이 nil 일 경우 전체가 nil 로 반환됩니다.



Swift 에서의 옵셔널 체이닝(Optional Chaining) 은 Objective-C 의 메시징(Messaging) 과 비슷 하지만 

모든 유형에서 작동하고, 성공 과 실패 여부를 확인하는 방식으로 되어있습니다.






강제 언래핑을 대체한 옵셔널 체이닝 (Optional Chaining as an Alertnative to Forced Unwrapping)


Optional 요소의 값이 nil 이 아닐경우 호출하길 원하는 PropertyMethodSubscript 값 뒤에 ? (물음표, Optional Chaining) 를 붙여서

Optional Chaining을 지정합니다.

이와같은 형식은 Optional 요소의 값을 강제로 해제하기 위한 ! (느낌표, Forced Unwrapping) 과 비슷합니다.


? (물음표, Optional Chaining) 와 ! (느낌표, Forced Unwrapping) 의 가장 큰 차이점은


Optional Chaining을 사용하여 Unwrapping시에 Optional 값이 nil 이라면 에러가 아닌 정상적으로 nil 값을 반환합니다.

즉 항상 Optional에 대한 값이 있습니다

Forced Unwrapping을 사용하여 Unwrapping시에 Optional 값이 nil 이라면 정상적인 nil 반환이 아닌 런타임 에러를 반환하며 앱이 죽습니다. 


추가적으로 Optional Chaining을 사용하여 값을 호출했을때 결과값은 생각하고있는 타입과 같지만 Optional로 wrapping되어있습니다.

예를들어 Optional Chaining을 사용하여 접근했을때 일반적으로 생각하는 Int 타입이 아닌 Int? 타입을 반환합니다.


class Person {
    var residence: Residence?
}
 
class Residence {
    var numberOfRooms = 1
}


2개의 클래스를 정의한 예를들어 설명하자면 


Residence 인스턴스는 numberOfRooms 라는 Int Property를 가지고 있습니다.

Person 인스턴스는 Residence? 타입의 residence Property를 가지고 있습니다.


Person 인스턴스를 새로 생성했을때 residence Property는 Optional로 선언되어있으므로 기본적으로 nil 로 초기화됩니다.


let john = Person()



따라서 이 코드에서 선언된 john 안에 residence 프로퍼티는 nil 값을 가지게 됩니다.

이제 john.residence 에 대한 Optional 값을 추출해봅니다.


let roomCount = john.residence!.numberOfRooms


코드를 보면 john.residence 가 Optional이 아닌 값이었다면 이상없이 값이 반환되어 roomCount 변수에 저장됩니다.

하지만 john.residence 가 Optional 타입으로 선언되어있기때문에 이 코드는 런타임 에러가 발생합니다.


Optional Chaining은 이런 상황에서 값에 접근할 수 있게 합니다.

Optional Chaining을 사용하기 위해 ! (느낌표, Forced Unwrapping) 위치에 ? (물음표, Optional Chaining) 를 사용해봅니다.


if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
else {
    print("Unable to retrieve the number of rooms.")
}



Swift 에서 residence Optional Property Chain은 residence 가 존재한다면 numberOfRooms 의 값을 가져오라는걸 뜻합니다.

numberOfRooms 값에 접근하는건 실패할수도 있기 때문에 Optional Chaining은 Int? 값을 반환합니다.

예제를보면 residence 가 nil 일때 Int? 는 nil 이 되어 numberOfRooms 값에 접근할수 없기 떄문에

else 구문으로 빠져서 Unable to retrieve the number of rooms. 라는 print를 출력할것입니다.

residence 가 nil 이 아니라면 numberOfRooms 로 접근하여 반환될 Int? 라는 정수를 Unwrapping 하기 위해

옵셔널바인딩(Optional Binding)을 사용하여 roomCount 변수에 Int 값을 반환합니다.


또 하나의 중요한점은 numberOfRooms 의 값은 Int 지만 

Optional Chaining을 통해서 numberOfRooms 의 값을 받아온다면Int가 아닌 Int? 값을 반환한다는 부분입니다.





그럼 20000








'Swift' 카테고리의 다른 글

[Swift] typealias  (0) 2018.05.28
[Swift] VLC ( View Life Cycle )  (0) 2017.11.09
[Swift] ALC ( App Life Cycle )  (0) 2017.11.08
[Swift] Thread  (0) 2017.11.07
[Swift] GCD (Grand Central Dispatch)  (1) 2017.11.07

typealias


기존에 선언되어있는 유형에 새로운 유형의 별칭을 사용함으로써

코드를 더 읽기 쉽도록, 이해하기 쉽도록 명확하게 만드는문법입니다.


Swift 에서는 typealias 를 대부분의 유형에 사용이 가능하고 크게 3가지 유형으로 나눠볼 수 있습니다.


1. 내장 유형 -> String, Int, Float 등..

2. 사용자 정의 유형 -> Class, Struct, Enum 등..

3. 복합 유형 -> Closure




1. 내장 유형에 대한 예시


1
typealias Name = String



간단한 예로 String 유형을 Name 이라는 별칭으로 사용한다 선언합니다.


1
let name: Name = "홍길동"



1
let name: String = "홍길동"



위에 선언한 Name 이라는 typealias 를 사용하는 예입니다.

바로 위 선언된 2개의 변수는 같은 String 타입이지만

특별한 분류가 필요하거나 구분지어 사용하고싶을때

typealias 를 사용하여 이 변수는 Name 이라는 유형의 String 이다. 라는 방식으로 사용할 수 있습니다.






2. 사용자 정의 유형에 대한 예시


자체적인 데이터 형식을 만들어야 할 경우가 있을때 Class를 사용하여 만들 수도 있습니다.

간단한 예로 학생들의 대한 데이터를 구현해봅니다.


1
2
3
Class Student {
 
}



학생에 대한 Class를 구현합니다.


1
typealias Students = [Student]



만들어 둔 Student Class를 typealias 를 통해 Students 라는 Student배열로 선언합니다. 


1
var students: Students = []



students 라는 변수를 Students 타입으로 초기화합니다.

이때 Students 라는 타입은 Array<Student>, [Student] 타입과 같은 타입이 됩니다.






3. 복합적인 유형에 대한 예시


Closure 를 입력 매개 변수로 사용하는 함수를 typealias 를 사용하여 깔끔하게 만들어볼 수 있습니다.


1
2
3
func test(completeHandler: (Void-> (Void) ) {
 
}



test 라는 함수에 completeHandler 라는 Closure 를 선언했을때


1
typealias voidHandler = (Void-> (Void)



voidHandler 라는 typealias를 선언한뒤에


1
2
3
func test(completeHandler: voidHandler) {
 
}



이런 방법으로 Closure를 typealias 를 사용하여 좀 더 깔끔하게 사용할 수 있습니다.





의식하고 신경써서 사용한다면 꽤나 간편하고 이해하기 쉽게 코딩이 가능할 것 같다고 생각합니다.


그럼 20000



'Swift' 카테고리의 다른 글

[Swift] 옵셔널 (Optional)  (7) 2018.06.01
[Swift] VLC ( View Life Cycle )  (0) 2017.11.09
[Swift] ALC ( App Life Cycle )  (0) 2017.11.08
[Swift] Thread  (0) 2017.11.07
[Swift] GCD (Grand Central Dispatch)  (1) 2017.11.07

VLC ( View Life Cycle )


앞서 포스팅했던 ALC 와 마찬가지로 사용자에게 직접적으로 보여지게 되는 뷰에도 생명주기가 있다.

싱글 뷰 로만 구현되어있는 앱은 없다고 보는게 맞을만큼 앱은 여러개의 뷰가 복합적으로 연결 및 표현되고 있다.

사용자에게 직접적으로 보여지게 되는 부분인만큼 ALC와 마찬가지로 생명주기는 꼭 이해가 필요한 부분이고 신경써서 구현해야하는 부분이다.



애플의 개발자가이드 에서는 크게 5부분으로 나눠 설명하고있다.




1. viewDidLoad()

뷰 컨트롤러 클래스가 만들어질때 실행된다.

뷰에 진입하면서 한번만 실행하기 때문에 보통 초기화 할때 사용한다.


2. viewWillAppear()

viewDidLoad() 가 호출된 후 뷰가 화면에 나타나기 직전에 실행된다.

viewDidLoad 와 달리 뷰가 화면에 나타나기 직전마다 실행되므로

앱에서 정보를 수정하는 작업이라던지 변경작업 후 다시 돌아오는 뷰에서 데이터를 갱신을 할때 사용하면 좋다.


3. viewDidAppear()

뷰가 화면에 나타난 직후에 실행된다.

viewWillAppear 와 마찬가지로 뷰가 나타난 직후마다 실행된다.

뷰의 변경이나 애니메이션표시를 할때 사용하면 좋다.


4. viewWillLayoutSubviews()

뷰의 bounds 가 변경되면 하위 뷰의 레이아웃이 변경되는 시점이 필요한데

그 작업이 진행되기 직전에 호출된다.


5. viewDidLayoutSubviews()

뷰의 하위뷰 레이아웃이 변경된 직후에 호출된다.


6. viewWillDisappear()

뷰가 화면에서 사라지기 직전에 실행된다.

뷰의 변경사항을 커밋하거나 상태 종료와 같은 정리 작업을 할때 사용하면 좋다.


7. viewDidDisappear()

뷰가 화면에서 사라진 직후에 실행된다.

최종적인 마무리작업을 할때 사용하면 좋다.


설명한 7가지의 함수중 상황에 따라 동작을 구현함으로써 사용자에게 보여주게될 화면을 부드럽고 깔끔하게 보여줄수 있다. 



'Swift' 카테고리의 다른 글

[Swift] 옵셔널 (Optional)  (7) 2018.06.01
[Swift] typealias  (0) 2018.05.28
[Swift] ALC ( App Life Cycle )  (0) 2017.11.08
[Swift] Thread  (0) 2017.11.07
[Swift] GCD (Grand Central Dispatch)  (1) 2017.11.07

ALC ( App Life Cycle )


앱 생명주기는 앱의 시작과 끝 사이에 실행되는 여러가지 상태를 정의한것이다.

다양한 앱의 상황에서 대응해야 하기 때문에 반드시 이해하고 넘어가야 될 부분이다.



앱의 상태 구분




1. Not Running    -> 실행 하고 있지 않은 상태

2. Inactive             -> 실행 중인 상태지만 이벤트가 없는 상태

3. Active                -> 실행 중이고 이벤트가 생긴상태 

4. Background    -> 백그라운드 상태에서 이벤트가 있는 상태

5. Suspended      -> 백그라운드 상태에서 이벤트가 없는 상태


2번과 3번을 묶어 보통 Foreground 라고 칭한다.



앱의 상태에 대응되는 함수


각 5가지의 상태는 

AppDelegate 에서 대응되는 함수가 정의되어 있어 상태에 따라 동작하는 코드를 작성하여 상태에 따른 동작을 수행할 수 있다.


func application (_: didFinishLaunchingWithOptions) {}

앱이 처음 시작될때 실행되는 함수


func applicationWillResignActive (_: application) {}

앱이 Active 상태에서 Inactive 상태로 진입 할때 실행되는 함수


func applicationDidEnterBackground (_: application) {}

앱이 Background 상태로 진입 할때 실행되는 함수


func applicationWillEnterForeground (_: application) {}

앱이 Background 상태에서 Foreground 상태로 진입 할때 실행되는 함수


func applicationDidBecomeActive (_: application) {}

앱이 Active 상태로 진입 할때 실행되는 함수


func applicationWillTerminate (_: application) {}

앱이 종료 될때 실행되는 함수


필수로 전부 구현해야되는 함수는 아니지만 상황에 따른 적절한 구현으로 깔끔하고 자연스러운 동작의 앱을 만들수 있다.

'Swift' 카테고리의 다른 글

[Swift] typealias  (0) 2018.05.28
[Swift] VLC ( View Life Cycle )  (0) 2017.11.09
[Swift] Thread  (0) 2017.11.07
[Swift] GCD (Grand Central Dispatch)  (1) 2017.11.07
[Swift] Email, Password Validation extension (이메일, 비밀번호 검증)  (0) 2017.05.25

스레드란 - 위키백과 참조


어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말한다.

일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있다.


스레드는 싱글스레드 와 멀티스레드 가 있고


보통 싱글스레드일때는 메인스레드만 있다고 생각하는게 좀더 이해하기 쉽지않을까싶다. 물론 정답은아님.

메인스레드 같은경우는 사용자와 상호작용을 하기 위한 UI를 책임지고있기에 아주 중요한 스레드이다.

그래서 오랜시간이 필요하거나 연산이 복잡한 작업을할때 메인스레드에서 작업하게되면

사용자 인터페이스와의 상호작용을 하는 스레드인만큼 사용자에게는 앱 자체가 느려보이고 좋아보이지않게되거나 작업이 꼬여 프로세스가 죽어버리게될 경우도있다.


그럴땐 멀티스레드를 활용하여 메인스레드가 아닌 별도의 스레드에서 작업을 처리하고 

결과물을 메인스레드를 통해 반영하는방법이 제일 좋은방법인것 같다.



GCD 란


Multicore Process 를 위한 Thread programming 의 방법이다.

기존의 스레드 관리는 직접 락을 걸고, 스레드풀을 관리하는 수고가 있었지만

GCD는 스레드를 OS 에서 관리하고 분배한다.


Dispatch Queue


Dispatch Queue는 작동방식이 Serial이든 Concurrent든 항상 FIFO ( First in First out ) 방식으로 동작한다.


Queue 의 동작방식


Serial Queue -> 동작이 순차적으로 FIFO 한다.

Concurrent Queue -> 동작이 동시적으로 GCD 에서 컨트롤하여 FIFO 한다.



Queue 의 종류


여러가지의 Queue 중에 대표적으로 main과 global 이있다.


DispatchQueue.main


시스템시작시 자동으로 생성하는 메인스레드 큐 이다.

기본적으로 Serial Queue 로 동작한다.

대표적인 예로 UI 변경작업은 메인큐에서 실행해야한다.


DispatchQueue.global


메인스레드 큐 와 반대되는 개념으로 백그라운드에서 동작하는 큐이다.

기본적으로 Concurrent Queue로 동작한다.

대표적인 예로 서버와의 통신작업같은경우 시간이 얼마나 걸릴지 모르고 작업량이 많기때문에 

백그라운드로 실행하여 후처리를 메인큐에서 하는경우가있다.

Qos 를 활용하여 우선순위를 설정해줄수있다


DispatchGroup


여러가지 작업을 동시에 실행할때 Group을 Concurrent queue 로 작업하여 결과물을 빠르게 얻는다

Group queue는 실행되는 작업이 다 완료되었을때 Notify 를 호출하여 끝났다는 신호를 준다


Qos (Quality of Service)


작업을 Multi-threading & Concurrent 하게 실행하고자 할때 Qos 를 정의한 Global queue 를 사용한다

userInteractive

중요도가 높고 즉각적인 반응이 요구되는 작업을 실행할때 사용하는 Qos

UI 업데이트같은 유저의 액션에 즉각적으로 반응해야하는 작업이 필요할때 사용

Global queue 지만 main-thread 에서 실행된다

userInitiated

userInteractive 에 비해 우선순위는 낮지만 async 하고 빠른결과값을 기대할때 사용

utility

시간이 상대적으로 오래걸리는 작업을 위해 사용

I/O, 통신 등의 작업에 주로 사용

background

유저가 인지하지도 못하는 백단에서 실행되는 작업

utility 에 비해 상대적으로 천천히 작업하는경우 사용



Sync, Async


Sync


큐에 등록한 스레드가 작업이 끝날때까지 대기하고 작업이 끝났다는 신호가 오면 다음 큐를 실행한다. ( 등록해놓은 큐를 순차적으로 실행한다 )


Async


큐에 등록한 스레드가 작업이 끝날때까지 대기하지않고 다음 큐를 병렬로 실행한다. ( 등록해놓은 큐를 동시적으로 실행한다 )


차이점은 작업이 완료될때까지 기다리느냐 아니냐의 차이이다.

Sync 같은 경우 사용법을 제대로 숙지하지않으면 스레드가 죽지않는 교착상태에 빠질 수가있어 되도록이면 Async를 사용하는게 좋다.


After


큐에 등록한 스레드에 시간차를 두어 실행 할 수 있게 한다.









로그인 기능을 구현할때 빠지지않는 이메일, 패스워드 정규식 검사를 extension 으로 구현했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension String {
    
    // 이메일 정규식
    func validateEmail() -> Bool {
        let emailRegEx = "^.+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2}[A-Za-z]*$"
        
        let predicate = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
        return predicate.evaluate(withself)
    }
    // 패스워드 
    func validatePassword() -> Bool {
        let passwordRegEx = "^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8}$"
        
        let predicate = NSPredicate(format:"SELF MATCHES %@", passwordRegEx)
        return predicate.evaluate(withself)
    }
}



기본적으로 이메일이나 패스워드는 String 문자열로 처리하기때문에 extension 은 String으로 구현했고

샘플로 구현되어있는 정규식패턴은 

이메일은 기본적으로 사용되는 @. 패턴으로 구현되어있고

패스워드는 최소8자이상, 대문자, 소문자, 숫자 조합인지 검증하게되어있습니다


더 많은 extension 들은 개인적으로 GitHub에 올려두고 업데이트 및 관리를 하고있습니다.

https://github.com/oper0960/ExtensionsForSwift



회원가입시 ID 나 Password 같이 공백이 들어가면 안되는 문자열에 공백을 삭제하여 처리할 수 있게 할 수 있습니다.


1
2
3
4
5
6
7
extension String {
    
    // 문자열 공백 삭제
    func stringTrim() -> String {
        return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
}



더 많은 extension 들은 개인적으로 GitHub에 올려두고 업데이트 및 관리를 하고있습니다.

https://github.com/oper0960/ExtensionsForSwift

+ Recent posts