[TIL / 25.04.17] URLSession으로.. 네트워크 통신을 어떻게 하는지.. 보여줄래요

2025. 4. 17. 23:19·iOS/Swift

URLSession

An object that coordinates a group of related, network data transfer tasks.

네트워크 데이터 전송 작업과 관련된 그룹을 조정하는 객체. 라고 공식문서에 나와있듯이 이제 API를 통해 데이터를 주고 받으려면 서버와 통신할 수 있어야 합니다. 이를 가능토록 하는 게 URLSession이라고 할 수 있습니다 !

 

이 URLSession을 통해서 어떻게 앱과 데이터를 주고받는지에 대한 방식은 일단 두가지. 비교적 전에 쓰던 Completion Handler 패턴, 그리고 이보다 최근에 나온 Swift Concurrency를 이용한 방식이 있는데... 일단 이것들을 다루기 전에 이 안에선 어떻게 해야 URLSession을 가지고 데이터들을 불러올 수 있을지에 대해 알아보도록 하겠읍니다.

 


 

일단 URLSession에서 큰 개념 두가지! URLSessionConfiguration과 URLSessionTask.

 

URLSessionConfiguration

세션의 동작 방식을 구성하는 설정 객체

  • default: 기본 구성, 디스크 캐싱 지원
  • ephemeral: 캐시, 쿠키 등을 저장하지 않는 임시 세션 (애플 개인정보 보호 모드같은..!)
  • background: 앱이 백그라운드에 있을 때도 네트워크 작업을 계속할 수 있음

URLSessionTask

실제 네트워크 작업을 수행하는 태스크 객체

  • URLSessionDataTask: 데이터를 메모리에 받는 일반적인 HTTP 요청
  • URLSessionDownloadTask: 파일 다운로드를 위한 태스크
  • URLSessionUploadTask: 파일 업로드를 위한 태스크
  • URLSessionWebSocketTask: WebSocket 통신을 위한 태스크(iOS 13+)

뭐 그밖에도 일단 알아야 될 부분들을 말하자면 

 

URL 객체, URLRequest 객체 !!

결국 우린 허공에 대고 데이터 보내주세요~하고 네트워킹하는게 아니기 때문에 데이터를 보내달라고 할 곳이 필요합니도

이를 우린 해당 자원이 있는 주소인 url을 가지고 swift 프레임워크 안에 있는 URL 객체로 넣어서 만들고 이를 가지고 URLRequest라는 객체를 만들 것입니다 ~

 

 

자 일단 !! 제일 기초적인 get 요청부터 어떻게 할지 알아보도록 해요 (get은 해당 url에 대고 서버한테 나 이 데이터 좀 보내주셈!!하는거라고 이해하면 됩니다, 모르면 RESTFUL API 한번 슥 훑어보고 오십쇼)

 

일단 하면서 만들어야하는 준비물을 대충 말해보자면, 

  • URL - 어느 주소에 있는 자원에 접근할 수 있게 이를 swift에서 쓰려면 객체로 만들어야됨 !!
  • URLSession - 요 부분은 따로 configuration을 입혀줘도 되고 자체 제공되는 URLSession.shared로 접근해도 됨!! 이거 많이 쓰임
  • URLConfiguration - URLSession에다가 네트워크 작업할때 세션이 어떻게 동작할지에 대한 방식을 여기서 넣어준다고 했죠?
  • URLRequest - 저희가 실제로 이 세션이 작업을 할 수 있게 명령해줄 때 필요한 요구사항임. 요 request에 위에서 말한 URL 객체를 넣고 .. get말고도 다른 작업을 할거면 지정해줄 수 있고 다양한 설정들을 해줄 수 있음. 요청 보낼때 이거 참고해주세요 !! 하는 Header라는 것도 넘겨줄 수 있고, 이 Request도 정말 많이 씁니다.
  • URLSessionTask - 앞서 관련된 요구사항들을 미리 설정해두고 이를 가지고 이제 요청을 해야 되잖아요? 앞에서 정의해둔 요구사항 가지고 실제 작업을 하도록 하는게 이 URLSessionTask. 데이터를 받아올 수도 있고 뭐 다운로드 등등 다양한 작업이 있읍니다..^^*

 

그래서 이 준비물을 어떤식으로 꺼내 쓰냐!?

보통 크게 봤을 때 URL 만들어주고 이거가지고 URLRequest를 만들어줍니다. 요구사항 만들어주고, 이걸 가지고 써야하니깐 가장 큰 개념인 Session을 만들어줘요(필요하다면 configuration에 추가 설정 넣고!). 그 담에 이 요구사항과 세션을 가지고 실제 작업을 한다!

 

사실 순서는 앞쪽은 크게 상관없음. request보다 세션을 먼저 만들어줘도 쨋든 둘다 쓸거니깐 문제 없게 알아서 만들면 되고..

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData()
    }
    
    // 서버 데이터를 불러오는 메서드 선언
    private func fetchData() {
        guard let url = URL(string: "https://reqres.in/api/users/1") else {
            print("URL이 올바르지 않습니다")
            return
        }
        
        // URLRequest 설정
        var request = URLRequest(url: url)
        
        // GET 메소드 사용
        request.httpMethod = "GET"
        
        // URLSession 생성 (공유 세션 사용)
        let session = URLSession.shared
        
        // dataTask
        session.dataTask(with: request) { (data, response, error) in
            // 에러 체크
            if let error = error {
                print("네트워크 오류: \(error.localizedDescription)")
                return
            }
            
            // HTTP 응답 체크
            guard let httpResponse = response as? HTTPURLResponse else {
                print("HTTP 응답이 아닙니다")
                return
            }
            
            let successRange = 200..<300
            
            // 상태 코드 체크
            print("상태 코드: \(httpResponse.statusCode)")
            
            if !successRange.contains(httpResponse.statusCode) {
                print("요청 실패: 상태 코드 \(httpResponse.statusCode)")
                return
            }
            
            // 데이터 체크
            guard let data = data else {
                print("데이터가 없습니다")
                return
            }
            
            // 디코딩
            do {
                let userInfo = try JSONDecoder().decode(ResponseData.self, from: data)
                print(userInfo)
                
                // UI 업데이트는 메인 스레드에서 수행
                DispatchQueue.main.async {
                    // UI 업데이트 코드
                }
            } catch {
                print("JSON 디코딩 오류: \(error.localizedDescription)")
            }
        }.resume()
    }
}

 

 

이게 뭐지....하고 바로 눈 돌렸던 URLSession 첨볼때의 제 자신..

일단 다 한번에 집어넣으려하면 배탈나니깐 실제 URLSession 관련 작업들을 수행하는 fetchData() 메서드를 뜯어봅시다 ~!

 

아까 말했듯 URL을 만든다고 했어요

guard let url: URL = URL(string: "https://reqres.in/api/users/1") else {
            print("URL is not correct")
            return
        }

 

우린 보통 주소를 가져다가 쓰겠죠? 뭐 users/뒤에 있는 1같은경우 메서드 파라미터로 받아와서 2나 3같은 다른 값을 넣어줄수도 있는거고 쨋든, 이 주소가지고 URL을 생성해줍니다. 근데 이 URL을 단순히 만들게 되면 

옵셔널로 줘요. 이를 언래핑 해줘야하니 guard let을 쓰면서 URL 객체를 넣어주는 것 !

근데 이 변환 과정에서 언래핑이 안되면 URL 객체를 생성하는 과정에서 문제가 있다는거겠죠? 그럼 else 타고 들어가서 return으로 그 흐름을 끊습니다.

 

쨋든 URL을 만들었으니 URLRequest를 이거가지고 만들면 됩니다.

 

// URLRequest 설정
var request: URLRequest = URLRequest(url: url)

// GET 메소드 사용
request.httpMethod = "GET"

 

일단 기본적으로 URLRequest 생성시엔 url을 받게 되어있는데 위에서 만들었던 url 객체를 넣어주면 됩니다. 

그리고 아까 말했듯 다양한 설정을 해줄 수 있는데 여기선 이 네트워킹 메서드로 get을 쓴다고 말해주는 것!

 

// URLSession 생성 (공유 세션 사용)
let session = URLSession.shared

 

그 담엔 아까 말했던 것 처럼 URLSession을 만들어주는데, 이미 shared라는 걸 쓸 수 있으니 가져다 씁니다.

 

session.dataTask(with: request) { (data, response, error) in

 

그 다음 줄 보면 이제 task를 처리하도록 명령합니다. 근데 뒤에 있는 (data, response, error) in은 뭐냐면

 

completionHandler라는건데 해당 작업이 끝나면 저 자원들을 가지고 어느 작업을 수행하겠다! 정도로 이해하면 될 것 같아요

 

data은 Data?타입이고 서버로부터 받은 실제 데이터를 가지고 있고,

response는 URLResponse? 타입으로 보통 HTTP 프로토콜에 특화된 추가 정보를 포함하는 HTTPURLResponse라는 타입으로 캐스팅해서 씁니다. 이는 상태코드(statusCode)와 응답 헤더(Content-Type, Content-Length, Authorization 등)이 있어요.

Error는 말그대로 어떤 오류가 있는지 담겨있읍니다.

 

// 에러 체크
if let error = error {
    print("네트워크 오류: \(error.localizedDescription)")
    return
}

// HTTP 응답 체크
guard let httpResponse = response as? HTTPURLResponse else {
    print("HTTP 응답이 아닙니다")
    return
}

let successRange = 200..<300

// 상태 코드 체크
print("상태 코드: \(httpResponse.statusCode)")

if !successRange.contains(httpResponse.statusCode) {
    print("요청 실패: 상태 코드 \(httpResponse.statusCode)")
    return
}

// 데이터 체크
guard let data = data else {
    print("데이터가 없습니다")
    return
}

 

내부를 보면 error가 있는지 확인하고 없으면 response를 HTTPURLResponse로 타입 캐스팅하도록 합니다.

이 과정에서 실패한다하면 response가 HTTP 응답이 아니니 return되도록 하고.

이 과정도 통과를 한다면 보통 HTTP 성공 코드 범위인 200에서 299까지 현재 응답받은 statusCode가 있는지! 확인합니다.

즉 성공 여부를 보게 되는 과정이고, 이 과정도 통과했을 때 실제 데이터가 실려 왔는지 guard let data로 확인합니다.

(guard let data = data는 guard let data로 축약가능)

 

// 디코딩
do {
    let userInfo = try JSONDecoder().decode(ResponseData.self, from: data)
    print(userInfo)

    // UI 업데이트는 메인 스레드에서 수행
    DispatchQueue.main.async {
        // UI 업데이트 코드
    }
} catch {
    print("JSON 디코딩 오류: \(error.localizedDescription)")
}

 

이제 문제 없다는 걸 알았으니 기존에 만들어두었던 틀에다가 decode해줍니다. 데이터들을 맞춰 넣어서 쓸 수 있게 !!

 


 

일단 가볍게 get 요청을 할 수 있는 정도까지 알아보는걸로..!!

'iOS > Swift' 카테고리의 다른 글

[TIL / 25.05.08] RxSwift.. 처음 공부해볼게요 1  (0) 2025.05.08
[WIL / 25.05.06] 8~9주차 회고 및 To-do  (2) 2025.05.06
[TIL / 25.04.16] Lv3 서치바 관련 트러블슈팅 기록  (0) 2025.04.16
[TIL / 25.04.11] UICollectionView Compositional Layout 1  (0) 2025.04.11
[TIL / 25.03.31] 앨범에서 사진 고르고 잘라서 쓸 수 있도록! (feat. PHPickerViewController, TOCropViewController)  (1) 2025.03.31
'iOS/Swift' 카테고리의 다른 글
  • [TIL / 25.05.08] RxSwift.. 처음 공부해볼게요 1
  • [WIL / 25.05.06] 8~9주차 회고 및 To-do
  • [TIL / 25.04.16] Lv3 서치바 관련 트러블슈팅 기록
  • [TIL / 25.04.11] UICollectionView Compositional Layout 1
subkyu-ios
subkyu-ios
subkyu-ios 님의 블로그 입니다.
  • subkyu-ios
    subkyu-ios 님의 블로그
    subkyu-ios
  • 전체
    오늘
    어제
    • 분류 전체보기 (52) N
      • iOS (35)
        • Swift (35)
      • 내일배움캠프 (7)
      • Git, Github (3)
      • Algorithm (6)
      • 회고 (1) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    stackview
    알고리즘
    UIKit
    Swift
    RxSwift
    KPT
    의존성 주입
    프로그래머스
    algorithm
    본캠프
    트러블슈팅
    내일배움캠프
    Wil
    회고
    ios
    사전캠프
    TableView
    tabman
    github
    til
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
subkyu-ios
[TIL / 25.04.17] URLSession으로.. 네트워크 통신을 어떻게 하는지.. 보여줄래요
상단으로

티스토리툴바