[iOS] RESTful API 완벽 이해하기

2024. 7. 22. 08:00·Apple/iOS
728x90
반응형

안녕하세요! 피피아노입니다 🎵

 

이번 포스팅에서는 실무에서 많이 쓰이는 기술인 RESTful API에 대해서 한번 공부해보려고 합니다. 

 

그럼 바로 시작하겠습니다!

 

RESTful API란 무엇인가?

RESTful API는 Representational State Transfer (REST) 원칙에 따라 설계된 API를 의미합니다. REST는 웹 서비스 설계 아키텍처로, 클라이언트와 서버 간의 상호 작용을 단순화하고 표준화하는 데 중점을 둡니다. RESTful API는 HTTP를 사용하여 리소스(데이터)를 생성, 읽기, 업데이트 및 삭제(CRUD) 작업을 수행합니다.

 

RESTful API의 특징

  • 무상태성(stateless): 각 요청은 클라이언트의 상태를 서버에 저장하지 않고 독립적으로 처리됩니다. 이는 서버 확장성을 높이고 클라이언트와 서버 간의 의존성을 줄입니다.
  • 클라이언트-서버 구조: 클라이언트와 서버는 독립적으로 개발될 수 있으며, 클라이언트는 서버가 제공하는 API를 호출하여 필요한 데이터를 얻습니다.
  • 캐시 가능성: RESTful 응답은 HTTP 캐시 메커니즘을 사용할 수 있어 성능을 향상시킵니다.
  • 계층 구조: 클라이언트와 서버 사이에 미들웨어(예: 로드 밸런서, 프록시)가 있을 수 있으며, 이는 시스템의 확장성과 보안성을 높입니다.
  • 통일된 인터페이스: 일관된 URI, HTTP 메서드, 상태 코드, 헤더 등을 사용하여 클라이언트가 서버와 상호작용할 수 있습니다.

 

왜 RESTful API를 사용하는가?

  • 단순성과 명확성: REST는 HTTP 프로토콜을 기반으로 하여 잘 알려진 표준을 따릅니다. 이는 학습 곡선을 낮추고 이해하기 쉽게 만듭니다.
  • 유연성: 다양한 클라이언트(웹, 모바일 앱 등)가 동일한 API를 사용할 수 있어 코드 재사용성을 높입니다.
  • 확장성: 무상태성 덕분에 서버를 쉽게 확장할 수 있습니다.
  • 성능: 캐시를 사용함으로써 네트워크 성능을 최적화할 수 있습니다.

 

REST와 SOAP 비교

 

SOAP(Simple Object Access Protocol)은 REST와 다른 웹 서비스 프로토콜입니다. SOAP는 XML 메시지를 사용하고 복잡한 보안 및 거래 메커니즘을 포함하고 있지만, REST는 더 가볍고 HTTP 표준을 따릅니다. REST는 단순함과 확장성 때문에 더 널리 사용됩니다.

 

RESTful API 사용 방법

기본적인 HTTP 메서드

  • GET: 서버로부터 리소스를 조회
  • POST: 서버에 새로운 리소스를 생성
  • PUT: 서버의 리소스를 업데이트
  • DELETE: 서버의 리소스를 삭제
  • PATCH: 서버의 리소스를 부분적으로 변경할 때 사용

 

iOS에서 RESTful API 사용하기

1. URLSession을 이용한 RESTful API 호출

iOS에서 RESTful API를 호출하는 가장 일반적인 방법은 URLSession을 사용하는 것입니다.

import Foundation

struct Post: Codable {
    let id: Int
    let title: String
    let body: String
}

class APIClient {
    let baseURL = URL(string: "https://jsonplaceholder.typicode.com")!
    
    func fetchPosts(completion: @escaping ([Post]?) -> Void) {
        // 요청할 URL 설정
        let url = baseURL.appendingPathComponent("posts")
        
        // URLSession 데이터 태스크 생성
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            // 에러 처리
            guard let data = data, error == nil else {
                print("Error fetching data: \(String(describing: error))")
                completion(nil)
                return
            }
            
            // JSON 디코딩
            do {
                let posts = try JSONDecoder().decode([Post].self, from: data)
                completion(posts)
            } catch {
                print("Error decoding JSON: \(error)")
                completion(nil)
            }
        }
        // 태스크 시작
        task.resume()
    }
}

let apiClient = APIClient()
apiClient.fetchPosts { posts in
    if let posts = posts {
        for post in posts {
            print("Post \(post.id): \(post.title)")
        }
    }
}

 

  • URLSession.shared.dataTask: URLSession의 공유 인스턴스를 사용하여 데이터 태스크를 생성합니다. 여기서 with 파라미터로 URL을 전달하여 서버에 요청을 보냅니다.
  • data, response, error: 클로저에서 요청의 결과로 반환되는 데이터, 응답, 오류를 처리합니다.
  • JSONDecoder: 응답 데이터를 [Post] 타입으로 디코딩합니다. Post는 Codable 프로토콜을 준수해야 합니다.

2. Alamofire를 이용한 RESTful API 호출

Alamofire는 Swift 기반의 HTTP 네트워킹 라이브러리로, URLSession보다 간단하게 네트워크 요청을 처리할 수 있습니다.

import Alamofire

struct Post: Codable {
    let id: Int
    let title: String
    let body: String
}

class APIClient {
    let baseURL = "https://jsonplaceholder.typicode.com"
    
    func fetchPosts(completion: @escaping ([Post]?) -> Void) {
        // Alamofire를 사용하여 요청
        AF.request("\(baseURL)/posts").responseData { response in
            switch response.result {
            case .success(let data):
                // JSON 디코딩
                do {
                    let posts = try JSONDecoder().decode([Post].self, from: data)
                    completion(posts)
                } catch {
                    print("Error decoding JSON: \(error)")
                    completion(nil)
                }
            case .failure(let error):
                // 에러 처리
                print("Error fetching data: \(error)")
                completion(nil)
            }
        }
    }
}

let apiClient = APIClient()
apiClient.fetchPosts { posts in
    if let posts = posts {
        for post in posts {
            print("Post \(post.id): \(post.title)")
        }
    }
}

 

  • AF.request: Alamofire의 기본 요청 메서드로, URL 문자열을 전달하여 요청을 만듭니다.
  • responseData: 응답 데이터를 Data 타입으로 처리합니다.
  • response.result: 결과를 성공과 실패로 나누어 처리합니다.
  • success(let data): 요청이 성공하면 데이터를 JSON으로 디코딩합니다.
  • failure(let error): 요청이 실패하면 오류를 처리합니다.

3. Combine을 이용한 RESTful API 호출

Combine 프레임워크를 사용하여 비동기 네트워크 요청을 더욱 선언적으로 처리할 수 있습니다.

import Combine
import Foundation

struct Post: Codable {
    let id: Int
    let title: String
    let body: String
}

class APIClient {
    let baseURL = URL(string: "https://jsonplaceholder.typicode.com")!
    var cancellables = Set<AnyCancellable>()
    
    func fetchPosts() -> AnyPublisher<[Post], Error> {
        // URL 설정
        let url = baseURL.appendingPathComponent("posts")
        
        // Combine을 사용하여 네트워크 요청
        return URLSession.shared.dataTaskPublisher(for: url)
            .map { $0.data } // 응답 데이터 추출
            .decode(type: [Post].self, decoder: JSONDecoder()) // JSON 디코딩
            .eraseToAnyPublisher() // 타입 변환
    }
}

let apiClient = APIClient()
apiClient.fetchPosts()
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("Finished")
        case .failure(let error):
            print("Error: \(error)")
        }
    }, receiveValue: { posts in
        for post in posts {
            print("Post \(post.id): \(post.title)")
        }
    })
    .store(in: &apiClient.cancellables)

 

  • URLSession.shared.dataTaskPublisher: URLSession의 데이터를 Combine 퍼블리셔로 처리합니다.
  • map { $0.data }: 응답 데이터만 추출합니다.
  • decode(type:decoder:): JSON 데이터를 [Post] 타입으로 디코딩합니다.
  • eraseToAnyPublisher: 퍼블리셔의 타입을 AnyPublisher로 변환하여 반환합니다.
  • sink(receiveCompletion:receiveValue:): 퍼블리셔에서 데이터를 구독하고 처리합니다.
  • store(in:): 구독을 취소할 수 있도록 cancellables에 저장합니다.

 

오늘은 여기까지 :)


 

감사합니다.

 

잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!

궁금하신 부분은 댓글로 질문 부탁드립니다!

728x90
반응형

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

[iOS] CocoaPods 알아보기  (7) 2024.08.13
[iOS] Live Activity 알아보기  (0) 2024.08.09
[iOS] Core Data는 뭘까?  (0) 2024.05.24
[iOS] Open API 연결하는 방법  (0) 2024.05.19
[iOS] 화면 전환 방식 (Present, NavigationController + Source, NavigationController + Segue)  (2) 2024.03.24
'Apple/iOS' 카테고리의 다른 글
  • [iOS] CocoaPods 알아보기
  • [iOS] Live Activity 알아보기
  • [iOS] Core Data는 뭘까?
  • [iOS] Open API 연결하는 방법
P_Piano
P_Piano
Apple 생태계 개발자가 되기 위한 학습과 경험의 기록
    반응형
    250x250
  • P_Piano
    피피아노의 개발 일지
    P_Piano
  • 전체
    오늘
    어제
    • 분류 전체보기 (200) N
      • Apple (118) N
        • iOS (22) N
        • visionOS (4)
        • Swift (64)
        • UIKit (2)
        • SwiftUI (20)
        • RxSwift (2)
        • Xcode (4)
      • C언어 (5)
      • C++ (8)
      • Dart (1)
      • Python (3)
      • JavaScript (17)
      • Git (1)
      • CS (39)
        • 디자인 패턴 (6)
        • 네트워크 (20)
        • 운영체제 (8)
        • Database (5)
        • 자료구조 (0)
      • IT 지식 (2)
      • IT 뉴스 (4)
      • 출처 표기 (1)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    클래스
    변수
    combine
    코딩테스트
    비동기
    티스토리챌린지
    연산자
    운영체제
    배열
    네트워크
    Initializers
    오블완
    Optional
    프로세스
    제어문
    Vision Pro
    프로퍼티 래퍼
    Xcode
    스위프트
    자바스크립트
    UIKit
    swiftUI
    SWIFT
    이니셜라이저
    ios
    옵셔널
    디자인패턴
    메서드
    함수
    visionOS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
P_Piano
[iOS] RESTful API 완벽 이해하기
상단으로

티스토리툴바