티스토리 뷰

Swift/Swift

Swift Alamofire 시작하기

ylog 2022. 3. 10. 15:24

Alamofire란?

iOS 앱을 개발하다보면 네트워크를 이용하여 데이터에 접근해야 하는 경우가 생긴다. 물론 기본적으로 Foundation의 URLSession을 이용할 수도 있지만, 다소 번거로운 경우가 생기기도 한다. (이 경우는 따로 정리해보겠습니다.) 이로 인해 Alamofire를 많이 사용한다.

Alamofire는 swift를 기반으로 한 HTTP 네트워킹 라이브러리이다. 이는 공통적인 네트워크 작업을 함에 있어 매우 우아한 인터페이스를 제공한다. 기능으로는

  • chainable request/response methods
  • JSON, Codable decoding
  • authentication

등으로 다양하다.

여기에선,

  • third-party RESTful API로부터 데이터를 요청
  • request parameter 전송
  • 응답을 JSON으로 변환
  • 응답을 Codable 프로토콜을 통해 스위프트 데이터 모델로 변환

하는 작업을 해보겠다.

기본적으로 소스코드는 링크에서 받으실 수 있다.

여기에선 SW API(스타워즈 API)를 사용한다. https://swapi.dev

HTTP, REST, 그리고 JSON에 대한 이해

위를 간략히 설명하고 넘어가겠다.
HTTP는 서버에서 클라이언트로 데이터를 전송할때 사용되는 Application Protocol 입니다. HTTP는 아래와 같이 다양한 request method들을 정의하여 바람직한 동작들을 가리킬 수 있게끔 한다.

  • GET : 데이터를 받는다. 하지만 서버의 어떤 데이터도 변경할 수 없다.
  • HEAD : GET과 비슷하지만, 진짜 데이터가 아닌 header만 전달한다.
  • POST : 데이터를 서버에 전송한다. 가령 form을 채우거나 submit 버튼을 누를 때 사용한다.
  • PUT : 데이터를 특정한 장소에 전송한다. 가령 유저 프로필을 업데이트할 때 사용한다.
  • DELETE : 특정한 장소의 데이터를 삭제한다.

JSON은 JavaScript Object Notation의 약자로, 시스템 간 데이터 전달에 있어 직관적이고 사람이 읽을 수 있는 메커니즘을 제공한다. JSON은 string, boolean, array, object/dictionary, number, null 과 같이 한정된 수의 데이터 타입만 가질 수 있다.
Swift 4 전에는 JSON에서 data object로, 또 그 반대로 변환하려면 JSONSerialization 클래스를 사용해야 했는데, 요즘은 Codable이 대세이다. Codable은 JSON와 data model 사이에 자동화된 변환을 해준다.

REST는 REpresentational State Transfer의 약자로, 지속적인 웹 API를 만들기 위한 규칙의 집합이다. REST는 request 사이에 상태를 지속하지 않거나, cacheable request를 만들고, 동일한 인터페이스를 제공한다. 이를 통해 request간 데이터의 상태를 추적하지 않고도 API를 우리가 만든 앱에 통합하는 것을 쉽게 만들어준다.

근데 왜 Alamofire인가.

이미 애플이 제공하는 URLSession이 있음에도 왜 사용할까? Alamofire는 URLSession을 기반으로 하지만, 네트워크 요청하는 과정 속에서 생기는 어려움들을 우리 눈에 보이지 않게 처리하여 우리 본연 작업에만 집중할 수 있게 도와준다.

Alamofire에는 아래와 같은 대표적 기능이 있다.

  • AF.upload : 파일을 업로드한다.
  • AF.download : 파일을 다운르도하거나 이미 진행중인 다운로드를 재개한다.
  • AF.request : 파일 전송과 무관한 다른 HTTP 요청

데이터 요청하기

강의 자료는 여기에서 다운받는다.

MainTableViewController.swift 에

import Alamofire

를 작성한다.

강의자료에는 Alamofire가 설치되어 있어 import만 하면 되지만, 쌩 프로젝트에서 alamofire를 import하기 위해선 해당 프로젝트 폴더에서 터미널을 연 후,

  1. pod init
  2. Podfile에 pod 'Alamofire', '~> 5.4' 작성
  3. pod install을 하시면 됩니다.

파일 맨 밑에 아래를 작성한다.

extension MainTableViewController {
  func fetchFilms() {
    // 1
    let request = AF.request("https://swapi.dev/api/films")
    // 2
    request.responseJSON { (data) in
      print(data)
    }
  }
}
  1. Alamofire는 namespacing을 사용하기 때문에, 우리가 사용할 호출 앞에는 AF를 붙입니다.
    request(_:method:parameters:encoding:headers:interceptor:)는 data의 endpoint를 파라미터로 입력받고, 우리는 URL만 보내고 나머지는 default 값으로 사용하겠다.
  2. 요청으로부터의 응답을 JSON으로 받겠다. JSON 데이터를 한번 출력도 해본다.

viewDidLoad()에 아래를 추가한다.

fetchFilms()

실행하면 이를 통해 Alamofire 요청을 실행할 것이다.

실행하면 아래와 같이 출력된다.

success({
  count = 7;
  next = "<null>";
  previous = "<null>";
  results =  ({...})
})

이를 통해 우리는 JSON data를 서버로부터 fetch하는 것을 마쳤다.

Codable 데이터 모델 사용하기

위에서 받은 JSON 데이터를 그대로 사용하긴 힘들 것이다. 그래서 데이터를 저장하기 위한 모델을 만들어보겠다.

프로젝트에서 Networking 폴더에 새로운 Film.swift 파일을 작성하겠다. 그리고 아래와 같이 입력한다.

struct Film: Decodable {
  let id: Int
  let title: String
  let openingCrawl: String
  let director: String
  let producer: String
  let releaseDate: String
  let starships: [String]

  enum CodingKeys: String, CodingKey {
    case id = "episode_id"
    case title
    case openingCrawl = "opening_crawl"
    case director
    case producer
    case releaseDate = "release_date"
    case starships
  }
}

JSON을 데이터모델로 변환하기 위해 Decodable을 struct가 Decodable를 채택한 것을 볼 수 있다.

enum CodingKeys를 통해 JSON으로부터 "episode_id"에 해당하는 정보가 들어온다면 이를 Film 구조체에선 id로 받아들이는 모습도 볼 수 있다.

우리 프로젝트는 디테일한 정보를 간단히 보여주기 위해 Displayble이라는 프로토콜을 정의하고 있다. Film.swift 밑에 아래 코드를 추가한다.

extension Film: Displayable {
  var titleLabelText: String {
    title
  }

  var subtitleLabelText: String {
    "Episode \(String(id))"
  }

  var item1: (label: String, value: String) {
    ("DIRECTOR", director)
  }

  var item2: (label: String, value: String) {
    ("PRODUCER", producer)
  }

  var item3: (label: String, value: String) {
    ("RELEASE DATE", releaseDate)
  }

  var listTitle: String {
    "STARSHIPS"
  }

  var listItems: [String] {
    starships
  }
}

이 extension은 뷰컨트롤러의 자세한 정보가 model의 film에 대한 올바른 label과 값을 가질 수 있도록 한다.

Networking 폴더에 Films.swift를 추가하고 아래를 작성한다.

struct Films: Decodable {
  let count: Int
  let all: [Film]

  enum CodingKeys: String, CodingKey {
    case count
    case all = "results"
  }
}

이 구조체는 films의 collection을 나타낸다. 앞 결과창에서 봤듯이 swapi.dev/api/films endpoint는 count, next, previous, results를 반환합니다. 하지만 우리는 count와 results만 필요하므로 이에 해당하는 변수만 적어준다.

coding keys를 통해 서버의 results라는 정보가 all로 변환된 것을 볼 수 있다.

또한, 데이터모델이 Decodable을 채택함으로써, Alamofire는 JSON 데이터를 우리가 작성한 데이터모델로 변환할 수 있게 된다.

MainTableViewController.swift의 fetchFilms()안의 내용을

request.responseJSON { (data) in
  print(data)
}

에서

request.responseDecodable(of: Films.self) { (response) in
  guard let films = response.value else { return }
  print(films.all[0].title)
}

로 교체한다.
이를 통해, response를 JSON이 아니라, 우리가 작성한 데이터 모델로 바꿀 수 있게 되었다. 실행해보면
A new Hope가 출력된다. 이는 첫번째 film의 title이다.

Method Chaining

Alamofire는 Method Chaining을 사용한다. 이는 한 메소드의 응답을 다른 메소드의 입력으로 연결하는 것이다. 이를 통해 코드도 컴팩트하고 보기 쉽게 작성할 수 있다.

fetchFilms()의 모든 코드를 아래로 교체한다.

AF.request("https://swapi.dev/api/films")
  .validate()
  .responseDecodable(of: Films.self) { (response) in
    guard let films = response.value else { return }
    print(films.all[0].title)
  }

이를 통해 endpoint를 request하고, 응답이 200~299 범위의 HTML status code를 반환하는 것을 보증함으로써 response를 validate하고, response를 우리가 작성한 데이터 모델로 decode했다.

테이블뷰 세팅

MainTableViewController의 맨 위에

var items: [Displayable] = []

를 작성한다. 우리는 정보의 배열을 저장하기 위해 이 property를 사용할 것이다.
fetchFilms()의

print(films.all[0].title)

self.items = films.all
self.tableView.reloadData()

로 교체한다. 이는 가져온 모든 films를 items에 할당하고, 테이블뷰를 reload한다.

테이블뷰에 내용을 보여주기 위해서 tableView(_:numberOfRowsInSection:) 의 return 값을

return items.count

로 교체하고,
tableView(_:cellForRowAt:)의 cell 선언 바로 밑에

let item = items[indexPath.row]
cell.textLabel?.text = item.titleLabelText
cell.detailTextLabel?.text = item.subtitleLabelText

를 작성한다.

이를 통해 Displayable를 통해 제공된 property들을 사용하여 cell을 film name과 episode ID로 채워넣었다.

실행해보자

Alamofire를 통해 손쉽게 데이터를 외부서버로부터 가져와 ViewController에 표시할 수 있었다.

Detail View Controller 설정을 비롯한 보다 자세한 내용은 https://www.raywenderlich.com/6587213-alamofire-5-tutorial-for-ios-getting-started#toc-anchor-009 에서 이어진다.

참고자료 및 원본 : https://www.raywenderlich.com/6587213-alamofire-5-tutorial-for-ios-getting-started#toc-anchor-009


작성 : 2021년 7월 14일 https://velog.io/@yoonjong/swift-Alamofire-시작하기-2

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함