http & URLSession

Bright Hyeon·2022년 4월 19일
0

iOS

목록 보기
9/9
post-thumbnail
post-custom-banner

HTTP란?

  • Hyper Text Transfer Protocol : 하이퍼텍스트를 전송하기 위한 프로토콜(규약)

  • 인터넷 상에서 정보를 주고받기위한 프로토콜(양식과 규칙의 체계) - 많은 정보들을 주고받기에 인터넷에는 엄격한 규약이 존재.

  • 암호화되지않은 방법으로 데이터를 전송한다. (악의적인 감청, 데이터 변조의 가능성)

  • http 통신: 요구하는 정보를 주고나면 연결이 종료됨. 그때그때 처리함.

  • http 통신을 통해 주로 html파일을 주고받는다. html은 Hyper Text Markup Language의 약자.

http의 특징

  1. Stateless 프로토콜
  • 클라이언트의 상태 정보를 가지지 않는 서버 처리 방식이다.
  • 클라이언트와 첫번째 통신에서 데이터를 주고받았다해도, 두번째 통신에서 이전 데이터를 유지하지 않는다.
  1. Connectionless 프로토콜
  • 클라이언트가 서버에 요청(Request)했을 때, 그 요청에 맞는 응답(Response)을 보낸 후 연결을 끊는 처리방식이다.

하지만, 실제로는 데이터 유지가 필요한 경우가 많다.
정보가 유지되지 않으면, 매번 페이지를 이동할 때마다 로그인을 다시 하거나, 상품을 선택했는데 구매 페이지에서 선택한 상품의 정보가 없거나 하는 등의 일이 발생할 수 있다.

따라서, Stateful 경우를 대처하기 위해서 쿠키와 세션을 사용한다.
쿠키와 세션의 차이점은 크게 상태 정보의 저장 위치이다.
쿠키는 '클라이언트(= 로컬 = 사용자브라우저)'에 저장하고, 세션은 '서버' 에 저장한다.

출처: https://ryusae.tistory.com/7 [초보자 전용 마을]

http 패킷

  • 헤더와 바디로 구성됨.
  • 헤더는 보내는 사람의 주소, 받는 사람의 주소, 패킷의 생명시간(값 만료기간?) 등으로 구성된다.
  • 바디는 전하고자하는 실제 내용이 담긴다.

http 메서드

  • Client가 서버에 http 요청을 하려면 url주소와 http 메서드를 정해줘야 한다.
  • 서버에서는 메서드에 따라 어떤 요청인지 파악을 할 수 있다.
  • GET: 클라이언트가 서버에 리소스를 요청할 때 사용.
  • POST: 클라이언트가 서버의 리소스를 새로 만들 때 사용. ex) 로그인, 회원가입, 게시글 업로드 등
  • PUT: 클라이언트가 서버의 리소스를 전체 수정할 때 사용. ex) 회원정보 전체수정 등
  • PATCH: 클라이언트가 서버의 리소스를 일부 수정할 때 사용. ex) 회원정보 일부 수정 등
  • DELETE: 클라이언트가 서버의 리소스를 삭제 할 때 사용.
  • HEAD: 클라이언트가 서버의 정상작동여부를 확인할때 사용.
  • OPTIONS: 클라이언트가 서버에서 해당 URL 이 어떤 메소드를 지원하는지 확인 할 때 사용.
  • CONNECT: 클라이언트가 프록시를 통하여 서버와 SSL 통신을 하고자 할 때 사용.
  • TRACE: 클라이언트와 서버간 통신 관리 및 디버깅을 할 때 사용.

SSL (보안계층)

  • SSL 디지털 인증서: 클라이언트와 서버 간의 통신을 공인된 제3자(CA)업체가 보증해주는 전자화된 문서

  • 장점 및 역할: 통신 내용이 노출, 변경되는 것을 방지 / 클라이언트가 접속하려는 서버가 신뢰할 수 있는 서버인지 확인가능 / SSL 통신에 사용할 공개키를 클라이언트에게 제공한다.

SSL에서 사용하는 암호화의 종류

  • 암호: 텍스트를 아무나 읽지 못하도록 인코딩하는 알고리즘
  • 키: 암호의 동작을 변경하는 매개변수, 키에 따라서 암호화 결과가 달라지기 때문에 키를 모르면 복호화가 불가능.
  1. 대칭키 암호화 방식

    인코딩과 디코딩에 같은 키를 사용하는 알고리즘
    단점 : 단점은 발송자와 수신자가 서로 대화하려면 둘 다 공유키를 가져야 한다는 것이다.
    대칭키를 전달하는 과정에서 키가 유출이 되면 암호의 내용을 복호화할 수 있기 때문에 위험하다
    이를 보완하기 위해서 나온 방법이 공개키 암호화 방식이다.

  1. 공개키 암호화 방식

    인코딩과 디코딩에 다른 키를 사용하는 알고리즘
    A키로 암호화를 하면 B키로 복호화를 할 수 있고, B키로 암호화 하면 A키로 복호화 할 수 있는 방식
    인코딩 키 (public key)는 공개되어 있으며 (그래서 공개키 암호방식이라는 이름이 붙었다.) 보통 디지털 인증서안에 포함되어 있다.
    디코딩 키는 (secret key)는 호스트만이 개인 디코딩 키를 알고있다.
    공개키와 비공개키의 분리는 메시지의 인코딩은 누구나 할 수 있도록 해주는 동시에, 메시지의 디코딩은 비밀키 소유자에게만 부여한다.
    이는 클라이언트가 서버로 안전하게 메시지를 발송하는 것을 쉽게 해준다.
    단점 : 공개키 암호화 방식의 알고리즘은 계산이 느린 경향이 있다.

HTTPS

  • HTTP + SSL = HTTPS
  • (HyperText Transfer Protocol) + (Secure Socket Layer) = (HyperText Transfer Protocol Secure)
  • 보안이 강화된 HTTP
  • 모든 HTTP 요청과 응답데이터는 네트워크로 보내지기 전에 암호화된다.
  • HTTPS는 HTTP의 하부에 SSL과 같은 보안계층을 제공함으로써 동작한다.

http Status

  • 서버는 클라이언트의 요청에 응답하면서 요청이 성공적으로 완료됐는지 알려주는 상태코드를 함께 보냄.
  • 이 코드는 100번대~500번대로 이뤄져있음.
  • 100번대는 요새 잘 사용하지 않음.
  • 대부분의 에러는 500번대 에러임.

URLSession

  • 특정한 url을 이용하여 데이터를 다운로드하고 업로드하기 위한 API
  • 한 마디로, 앱에서 서버와 통신하기 위해 제공하는 API
  • 앱은 하나 이상의 URLSession 인스턴스를 생성하며, 각 인스턴스는 관련 데이터전송작업그룹을 조정함.
  • 예를 들어 웹브라우저를 만드는 경우, 앱은 탭 또는 창 당 하나의 세션을 만들 수 있다.
  • 각 세션 내에서 앱은 특정 url에 대한 요청을 나타내는 일련의 작업을 추가함.
  • URLSession은 reguest와 response를 기본구조로 가지고 있는데, request는 서버로 요청을 보낼 때 어떤 http메서드를 사용할 것인지 캐싱정책을 어떻게 할 것인지 등의 설정을 할 수 있고, response는 url요청의 응답을 나타내는 객체이다.

애플 문서 오버뷰

URLSession 클래스와 관련 클래스는 URL로 표시된 엔드포인트에서 데이터를 다운로드하고 업로드하기 위한 API를 제공합니다. 앱이 실행되지 않거나 iOS에서 앱이 일시 중지되는 동안 이 API를 사용하여 백그라운드 다운로드를 수행할 수도 있습니다. 관련 URLSessionDelegate 및 URLSessionTaskDelegate를 사용하여 인증을 지원하고 리디렉션 및 작업 완료와 같은 이벤트를 받을 수 있습니다.

URLSessionConfiguration, URLSessionTask

  • URLSession은 URLSessionConfiguration을 통해 생성할 수 있다.

  • 이렇게 생성된 URLSession을 통해 한 개 이상의 URLSessionTask를 생성할 수 있으며, 이 URLSessionTask를 통해 실제 서버와 통신할 수 있다.

  • URLSession API는 여러가지 유형의 세션을 제공한다. 이 타입은 URLSession객체가 소유한 Configuration프로퍼티 객체에 의해 결정되는데, URLSessionConfiguration을 사용하면 ...와 같은 세션 프로퍼티를 구성할 수 있습니다.

URLSession의 종류

  1. 공유 세션 (Shared Session) - URLSession.shared()
  • 싱글톤으로 사용할 수 있고, 기본요청을 하기위한 Session이다.
  • 직접만든 세션만큼 맞춤설정을 할 수는 없지만 쉽게 만들어 사용할 수 있다.
  1. 기본 세션 (Default Session) - URLSession(configuration: .default)
  • 공유 세션과 유사하게 작동하지만 직접 원하는 설정을 할 수 있고, 캐시와 쿠키 인증 등을 디스크에 저장함.
  • 또 순차적으로 데이터를 처리하기위해 delegate를 지정할 수 있음.
  1. 임시 세션(Ephemeral Session) - URLSession(configuration: .ephemeral)
  • 공유 세션과 비슷하지만 캐쉬, 쿠키, 사용자 인증 정보를 디스크게 저장하지 않음.
  • 메모리에 올려서 세션을 연결하고, 세션 만료 시 데이터가 사라짐.
  1. 백그라운드 세션(Background Session) - URLSession(configuration: .background)
  • 앱이 실행되지않는동안 백그라운드에서 컨텐츠 업로드 및 다운로드를 수행할 수 있음.

URLSessionTask

  • URLSession이 구성되었으면, URLSessionTask를 이용해서 각 세션 내의 작업을 추가할 수 있음.
  1. URLSessionDataTask
  • 데이터 객체를 사용하여 데이터를 요청하고 응답받음.
  • 주로 짧고 빈번하게 요청하는 경우 사용.
  1. URLSessionUploadTask
  • 데이터 객체 또는 파일 형태의 데이터를 업로드하는 작업을 수행함.
  • 앱이 실행되지않았을 때 백그라운드 업로드를 지원함.
  1. URLSessionDownloadTask
  • 데이터를 다운로드받아서 파일의 형태로 저장하는 작업을 수행함.
  • 앱이 실행중이지않을 때는 백그라운드 다운로드를 지원함.
  1. URLSessionStreamTask
  • TCP/IP 연결을 생성할 때 사용됨.
  1. URLSessionWebSocketTask
  • 웹소켓 프로토콜 표준을 통해 통신하는 Task.

URLSession Life Cycle

  1. Session Configuration 을 결정하고, Session 을 생성
  2. 통신할 URL과 Request 객체를 설정
  3. 사용할 Task 를 결정하고 그에 맞는 Completion Handler 나 Delegate 메소드들을 작성
  4. 해당 Task를 실행
  5. Task 완료 후 Completion Handler 클로저가 호출이 됨
  • 클로저 안에서 작업에 대한 결과값을 받아볼 수 있음.

예시 코드


import SwiftUI

class ModelData: ObservableObject {
    
    @Published var posts: [PostModel] = []
    
    init() { //초기화코드. ModelData()가 호출되는 시점에 실행됨.
        getPosts()
    }
    
    func getPosts() {
        
        //url을 만들때는 옵셔널이기 때문에 guard let을 사용. String타입 -> URL타입
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1") else { return }
        
        //URLSession(configuration: .default) // - 기본 세션
        //URLSession(configuration: .ephemeral) // - 임시 세션
        //URLSession(configuration: .background(withIdentifier: "")) // - 백그라운드 세션
        
        //URLSession.shared.dataTask(with: URLRequest, completionHandler: (Data?, URLResponse?, Error?) -> Void) // - URLRequest
        URLSession.shared.dataTask(with: url) { data, response, error in // - URL
            
            //1. 데이터 확인
            guard let data = data else {
                print("데이터가 존재하지 않습니다.")
                return
            }
            
            //2. 오류 확인
            guard error == nil else {
                print("Error: \(String(describing: error))")
                return
            }
            
            //3. http 응답을 받음.
            //URLResponse? -> HTTPURLResponse // - URLResponse는 statusCode프로퍼티 없음.
            guard let response = response as? HTTPURLResponse else {
                print("잘못된 응답입니다.")
                return
            }
            
            //4. 응답 상태 확인.
            guard response.statusCode >= 200 && response.statusCode < 300 else {
                print("Status code는 2xx이 되야 합니다. 현재 Status Code는 \(response.statusCode)입니다.")
                return
            }
            print(response.statusCode)
            print("데이터를 성공적으로 다운로드 했습니다!")
            //print(data) // - 292bytes라고만 출력됨. 이를 문자열로 반환해야함.
            
            //5. data를 문자열로 반환해주어야 함. (Json -> JsonString)
            let jsonString = String(data: data, encoding: .utf8)
            print(jsonString ?? "")
            
            //6. 옵셔널 해제하며 JsonDecoding.
            guard let newPost = try? JSONDecoder().decode(PostModel.self, from: data) else { return }
            
            //7. UI를 업데이트하는 부분은 DispatchQueue를 통해 Main Thread로 이동시키기. 안해주면 보라돌이나타남.
            DispatchQueue.main.async { [weak self] in //TODO: 강한참조 -> [weak self] -> 약한참조.
                self?.posts.append(newPost)
            }
        }
        .resume() //Essential. 실제로 호출될 때까지 시작되지 않도록 설정하는 것.
    }
}
profile
i'm Obsessed with Swift. iOS
post-custom-banner

0개의 댓글