swift JSON & API 대해 공부해보자
JSON (JavaScript Object Notation) 은 데이터를 표현하는 형식 중 하나이다.
- 이름은 Arthur, 전화번호는 010-1111-2222 라는 전화번호 정보를 알고 있습니다. 이 정보를 다른 누군가에게 전달할 때 어떤 포맷으로 전달하는게 좋을까요?
- 그냥 쉽게 문자열로 “이름Arthur,전화번호010-1111-2222” 로 보낸다면..?
- 아니면.. “이름:Arthur,전화번호:010-1111-2222” 이렇게? 🤔
- 일반적으로 데이터를 표현하는 형식이 있다면, 그걸 따르는 게 좋을 것 같습니다.
- 이렇게 네트워크에서 데이터를 주고받으려면, 아무렇게나 주고 받는 것이 아니라 정해진 형식을 지켜서 데이터를 교환하는 것이 좋습니다.
- 이 중 서버와 클라이언트가 가장 많이 사용하는 데이터 형식이 JSON 형식입니다.
- JSON 은 key-value 형태를 가집니다.
제이슨은 서버와 통신하기 위한 룰이고 키와 밸류로 이루어져 있다고 보면 된다.
제이슨을 코드로 표현하면 아래와 같다.
[
{
"name": "Arthur",
"phoneNumber": "010-1111-2222"
},
{
"name": "Eve",
"phoneNumber": "010-3333-4444"
},
{
"name": "Abel",
"phoneNumber": "010-5555-6666"
}
]
- 이 JSON 데이터는 리스트[ ] 안에 3개의 전화번호부 데이터를 표현한다.
- JSON 은 특정한 프로그래밍 언어 안에 속하지 않으며, 대부분의 프로그래밍 언어에서는 JSON 포맷의 데이터를 다룰 수 있는 기능을 제공합니다. Swift 역시 마찬가지
즉 어디 언어에서도 존재한다고 보면 된다. 우리의 기반은 HTTP 기반이니깐 HTTP라는 바다 안에서 모여사는 작고 큰 동물들 정도라 보면 된다 우리는
그럼 바다를 갈려면 가는 경로를 알아야겠죠? 그 경로를 알려주는게 API 라고 생각하면 될 듯 합니다.
API (Application Programming Interface) 란?
- API 를 이해하기 위해서는 먼저 API 의 I(Interface) 가 뭔지 먼저 이해해야 합니다.
- 개발 용어에서 인터페이스(Interface)는 항상 창구를 의미합니다.
- 너는 나의 내부가 어떻게 생겨먹었는지는 정확히 알 필요가 없어. 그저 내가 뚫어준 창구를 통해 나와 소통하면 돼.
예를 들어, TV 를 컨트롤 하기 위한 리모콘을 생각해봅시다.
- 리모콘의 전원 버튼, 채널 버튼, 음량 버튼 은 TV 를 컨트롤 하기 위한 **창구 = API**입니다.
- 여러분들이 실제로 음량 버튼 내부 회로 및 하드웨어가 어떻게 동작하는지 알 필요가 있을까요?
- 그저 음량 버튼을 눌렀을 때 → TV 음량이 조절된다. 의 결과가 잘 도출되는지가 중요합니다.
- 음량 버튼을 눌렀다 = API 에게 내가 원하는 요청을 했다 = API Request
- 음량이 조절 되었다 = API 로 부터 요청의 결과를 받았다 = API Response
조금 더 실제 개발 상황을 예로 들어볼까요?
- 서버의 데이터베이스에 모든 유저의 정보를 담고 있습니다. 전화번호까지요.
- 클라이언트 (= iOS 네이티브 앱) 에서 “아담” 이라는 유저의 정보를 알고 싶습니다.
- 서버는 API 로 UserInfo 라는 API 를 뚫어 놓았고, 이 API 를 사용하면 유저의 정보를 알 수 있습니다. API 명세는 다음과 같습니다.
- API Request 는 이렇게 보내주세요.
{
name: "Arthur"
}
API Response 는 이렇게 보내주겠습니다.
{
"name": "Arthur",
"phoneNumber": "010-1111-2222",
"Mbti": "ENTJ"
}
- iOS 개발자인 여러분은 이제 이 API 명세를 보고, Request JSON 과 Response JSON 형식을 지켜서 서버와 소통하는 코드를 작성하면 됩니다.
- 서버가 이 데이터를 돌려주기 위해서 내부적으로 어떤 로직을 수행했고, 서버 데이터베이스 내부가 어떻게 생겨먹었고를 알 필요가 없습니다.
- 그저 서버가 뚫어놓은 API 라는 창구 를 통해서 서버와 소통을 하고, 원하는 결과를 얻으면 iOS 개발자의 책임은 끝입니다.
다시, 이번엔 레스토랑에 비유해보겠습니다.
- 클라이언트 앱 = 레스토랑의 손님
- API = 레스토랑의 메뉴판, 웨이터
- 서버 = 레스토랑의 요리사
- 손님이라는 클라이언트는 메뉴판, 웨이터 라는 창구를 통해서 요리사라는 서버의 음식을 받습니다.
- 손님이 메뉴판을 보고 웨이터를 부른다 → API 명세를 파악한다
- “봉골레 파스타 주세요” → API Request
- 요리사가 파스타를 손님에게 바친다 → API Response
마지막으로 API 가 뭔지 정리해보면,
- API 는 직역 그대로 Application Programming 에 필요한 Interface 입니다.
- 즉, 어떤 프로그램을 개발할 때 원하는 기능들을 제공해주는 창구, 설명서, 도구 입니다.
즉 우리가 바다로 갈 수 있는 네비게이션 역활이다. 하지만 왜 길을 이렇게 알려줬는데 우린 알 필요 없듯이
따라가기만 하면 된다 ~
자 그러면 바다를 가야하는데 길을 네비게이션한테 물어봤는데 답변이 영어로한다?? 잉 난 영어 모르는데
이렇게 되면 안되겠지요 ~ 그래서 동일안 언어로 변경 해줘야한다.
그 역활이 바로 인코딩과 디코딩이다.
Swift 의 인코딩과 디코딩
- 인코딩: 데이터를 특정 형식으로 변환하는 것.
- 디코딩: 인코딩 된 데이터를 다시 원본으로 변환하는 것.
- Swift 의 Codable 프로토콜을 채택한다는 것은 인코딩과 디코딩이 될 수 있음을 의미.
- Codable 안을 열어보면 Decodable & Encodable 로 구현되어있음.
- 서버와 통신하기 위해서, JSON 형식으로 인코딩을 많이 한다.
struct PhoneBook: Codable {
let name: String
let phoneNumber: String
}
Codable 을 채택함으로써 인코딩 디코딩이 가능한 객체가 됨.
JSON 형식의 데이터에서 Swift 로 데이터를 디코딩해서 추출하는 과정
import Foundation
struct PhoneBook: Codable {
let name: String
let phoneNumber: String
}
// string 으로 json 모양의 데이터를 생성.
let jsonString = """
[
{
"name": "Adam",
"phoneNumber": "010-1111-2222"
},
{
"name": "Eve",
"phoneNumber": "010-3333-4444"
},
{
"name": "Abel",
"phoneNumber": "010-5555-6666"
}
]
"""
// jsonString 으로 jsonData 를 생성.
let jsonData = jsonString.data(using: .utf8)!
// Swift 가 제공하는 JSON 디코더.
let jsonDecoder = JSONDecoder()
// JSON -> Codable 디코딩 진행.
do {
let phoneBooks = try jsonDecoder.decode([PhoneBook].self, from: jsonData)
for phoneBook in phoneBooks {
print("name: \(phoneBook.name), phoneNumber: \(phoneBook.phoneNumber)")
}
} catch {
print("JSON 디코딩 실패")
}
이런식으로 작성하게 되면 서버에 연결이 가능하다고 보면 된다~.
서버에 저장된 내용을 받아올수도 저장할수도 지울수도 업데이트도 다 가능하다고 생각하면 된다.
그럼 안뇽