iOS실무 9주차 Restful

2025. 5. 2. 21:53iOS앱개발

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "isVerified": true,
  "roles": ["user", "admin"],
  "address": {
    "city": "Seoul",
    "zip": "12345"
  }
}

다음부터는 open API를 활용한 실습을 진행하기때문에 영진위 api key 발급받기!

 

JSON형식으로 반횐되는것을 볼 수 있다.

{
  "boxOfficeResult": {
    "boxofficeType": "일별 박스오피스",
    "showRange": "20250501~20250501",
    "dailyBoxOfficeList": [
      {
        "rnum": "1",
        "rank": "1",
        "rankInten": "2",
        "rankOldAndNew": "OLD",
        "movieCd": "20232394",
        "movieNm": "야당",
        "openDt": "2025-04-16",
        "salesAmt": "1329431600",
        "salesShare": "25.2",
        "salesInten": "691659920",
        "salesChange": "108.4",
        "salesAcc": "18667746190",
        "audiCnt": "146883",
        "audiInten": "65952",
        "audiChange": "81.5",
        "audiAcc": "1988683",
        "scrnCnt": "1152",
        "showCnt": "3442"
      },
      {
        "rnum": "2",
        "rank": "2",
        "rankInten": "-1",
        "rankOldAndNew": "OLD",
        "movieCd": "20218800",
        "movieNm": "거룩한 밤: 데몬 헌터스",
        "openDt": "2025-04-30",
        "salesAmt": "1144166180",
        "salesShare": "21.7",
        "salesInten": "211519880",
        "salesChange": "22.7",
        "salesAcc": "2116850480",
        "audiCnt": "127361",
        "audiInten": "10330",
        "audiChange": "8.8",
        "audiAcc": "248671",
        "scrnCnt": "921",
        "showCnt": "3404"
      },

네이버의 통계를 확인해보면 영진위 api를 사용해 JSON데이터를 파싱하여 영화 순위를 보여주는 것을 알 수 있다.


https://codebeautify.org/jsonviewer

 

Best JSON Viewer and JSON Beautifier Online

Online JSON Viewer, JSON Beautifier and Formatter to beautify and tree view of JSON data - It works as JSON Pretty Print to pretty print JSON data.

codebeautify.org

JSON데이터를 예쁘게(보기쉽게) 볼 수 있는 사이트

 

 

Instantly parse JSON in any language | quicktype

 

app.quicktype.io

https://app.quicktype.io/

 

Instantly parse JSON in any language | quicktype

 

app.quicktype.io

위 사이트를 사용하면 JSON타입을 스위프트의 구조체, 클래스등으로 쉽게 만들 수 있다.

1. REST란?

REST(Representational State Transfer)는 웹의 아키텍처 스타일 중 하나로, 2000년대 초반에 로이 필딩(Roy Fielding)의 박사 논문에서 처음 제안되었습니다.

📌 REST의 핵심 개념

  • 자원(Resource): URI로 표현됨. 예: /users/1, /posts
  • 행위(Verb): HTTP 메서드로 표현. 예: GET, POST, PUT, DELETE
  • 표현(Representation): JSON, XML 등으로 데이터 전송



RESTful  API란 REST의 원리를 따르는 API를 의미합니다.

✅ RESTful API 설계의 6가지 핵심 원칙

1. 자원의 URI는 명사로 표현한다

  • URI는 **데이터(자원)**를 식별하며, 행위는 HTTP 메서드로 표현한다.
  • ❌ /getUser, /createPost → 비 RESTful
  • ✅ /users, /posts/1 → RESTful
http
복사편집
GET /users → 사용자 목록 조회 POST /users → 사용자 생성 GET /users/1 → ID=1인 사용자 조회 PUT /users/1 → ID=1인 사용자 전체 수정 DELETE /users/1 → ID=1인 사용자 삭제

2. HTTP 메서드의 의미에 맞게 사용한다

메서드의미
GET 자원 조회 (Read)
POST 자원 생성 (Create)
PUT 자원 전체 수정 (Update)
PATCH 자원 일부 수정 (Partial Update)
DELETE 자원 삭제 (Delete)
 

3. 계층적 URI 구조를 따른다

  • 자원 간 관계는 계층 구조로 표현한다.
http
복사편집
GET /users/1/posts → ID=1 사용자에 속한 게시글 목록 GET /users/1/posts/2 → ID=1 사용자의 게시글 중 ID=2

4. 무상태성 (Stateless)

  • 서버는 요청 간 클라이언트 상태를 저장하지 않는다.
  • 모든 요청은 자체적으로 완결적이어야 한다. 즉, 요청에 필요한 모든 정보(인증, 위치 등)를 포함해야 함.

5. 일관된 응답 구조와 상태 코드 사용

  • 응답은 일반적으로 JSON 포맷을 사용하고, HTTP 상태 코드도 적절히 설정해야 한다.
코드의미사용 예시
200 OK 정상 처리됨
201 Created 자원 생성됨 (POST 요청 후)
204 No Content 삭제 또는 응답 없음
400 Bad Request 요청 오류
401 Unauthorized 인증 실패
404 Not Found 자원 없음
500 Internal Server Error 서버 에러
 

6. HATEOAS (Hypermedia as the Engine of Application State) — 선택 사항

  • 클라이언트가 서버의 응답에 포함된 링크 정보를 따라 추가 행동을 할 수 있게 하는 REST 원칙
  • 실제 실무에서는 잘 사용되지 않거나 단순화된 형태로만 적용
json
복사편집
{ "userId": 1, "name": "John", "links": [ { "rel": "self", "href": "/users/1" }, { "rel": "posts", "href": "/users/1/posts" } ] }

✅ RESTful하지 않은 API 예시

GET /createUser?id=1 // 명사 대신 동사 사용 GET /users/create // GET 요청에 리소스 생성 행위

→ 이런 API는 RESTful하지 않으며, 클라이언트-서버 간 역할 분리 및 확장성에 문제가 생길 수 있음

 

JSON이란?

JSON (JavaScript Object Notation)은 데이터를 구조화하여 저장하거나 네트워크를 통해 전송할 때 사용하는 텍스트 기반의 데이터 형식입니다.

  • 가볍고, 사람이 읽기 쉬우며, 기계가 파싱하기 쉬움
  • 대부분의 언어에서 쉽게 생성, 파싱, 변환 가능
  • 특히 웹 API (특히 RESTful API)에서 표준 응답 형식으로 사용됨

JSON vs JavaScript 객체 리터럴

항목JSONJavaScript 객체
문자열 따옴표 항상 더블 쿼트 " " 싱글 '도 허용
key 따옴표 항상 필요 생략 가능
주석 ❌ 허용되지 않음 ✅ 허용됨 (//, /* */)
{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "isVerified": true,
  "roles": ["user", "admin"],
  "address": {
    "city": "Seoul",
    "zip": "12345"
  }
}

JSON 예시


APIApplication Programming Interface의 줄임말로 서로 다른 프로그램이나 컴포넌트 간에 기능이나 데이터를 주고받을 수 있도록 만든 명세 또는 규칙이다.

restful api
ex) GET /users/1 유저 1번 정보 요청 => 유저 1번 정보 name, age 등 응답 

이를 공개적으로 누구나 접근할 수 있게 제공해주는것을 Open API라고 한다.

https://api.visitkorea.or.kr/#/

 

TourAPI4.0

누구나 쉽게 접근하고 활용 할 수 있는 다국어 관광정보 고객 맞춤형 데이터

api.visitkorea.or.kr

 

누구나 사용 가능한 관광 데이터 

카카오와 같은 대기업에서 아래와 같이 오픈 API를 제공해주는 경우도 있다.

https://www.data.go.kr/data/15135102/openapi.do

한국관광공사의 반려동물 동반여부 api입니다.


반려 동물 동반여행지의 주변 좌표를 기반으로 관광정보 목록을 조회하는 기능입니다.
파라미터에 따라 제목순, 수정일순(최신순), 등록일순, 거리순 정렬검색을 제공합니다.
struct Items: Codable {
    let item: [Item]
}

struct Item: Codable {
    let cpyrhtDivCd: String
    let contentid: String
    let contenttypeid: String
    let title: String
    let createdtime: String
    let modifiedtime: String
    let tel: String
    let cat1: String
    let cat2: String
    let cat3: String
    let addr1: String
    let addr2: String
    let areacode: String
    let sigungucode: String
    let mapx: String
    let mapy: String
    let mlevel: String
    let dist: String
    let firstimage: String
    let firstimage2: String
}

다음과같이 1000m이내 반려동물 동반 관광지가 Json형태로 반환 => swift 구조체로 파싱하여 사용할 수 있다.

함수

함수를 잘 사용하기 위해서는 함수의 내부 매개변수와 외부 매개변수의 차이점 
그리고 스위프트의 함수는 1급 객체이기 때문에 인자로 함수를 전달, 리턴받을 수 있다는 점 등을 잘 알아두어야 한다.

 

func add(x: Int, y: Int) -> Int {
return(x+y)
}
add(x:10, y:20) // 30
print(type(of:add)) // (Int, Int) -> Int


함수의 타입은 인자의 타입, 리턴형으로 자료형이 생성된다.
func add(first x: Int, second y: Int)
함수에서의 first를 argument label, x 를 parameter name이라고 한다.

func add(_ x: Int, with y: Int) -> Int {
    print(#function) // add(_:with:)
    return(x+y)
}

 

함수의 이름은 위와같이 나오는것을 알 수 있다.

스위프트의 함수는 다음 3가지를 만족하기 때문에 1급 객체(1급 시민) 이다
1) 변수에 저장할 수 있다.

2) 매개변수로 전달할 수 있다.

3) 리턴값으로 사용할 수 있다.

func up(num: Int) -> Int {
    return num + 1
}
func down(num: Int) -> Int {
    return num - 1
}
let toUp = up
print(up(num:10))

1) 변수에 저장할 수 있다.

func upDown(Fun: (Int) -> Int, value:Int) {
    let result = Fun(value)
    print(result)
}

func up (value: Int) -> Int {
    return value + 10
}

upDown(Fun: up, value: 20)

2) 매개변수로 전달할 수 있다.

func createUp () -> (Int) -> Int {
    func inner(value: Int) -> Int {
        return value + 10
    }
    return inner
}

let up = createUp()
print(up(10))

3) 리턴값으로 사용할 수 있다.

 

클로저

클로저: 특정 작업(함수)과 그 작업이 일어난 곳(환경 또는 상태)을 모두 기억하고 있는 도구

let add1 = { (x: Int, y: Int) -> Int in
    return(x+y)
}

print(add1(1,2))
print(type(of: add1)) // (Int, Int) -> Int

이를 클로저 표현식이라 하며,
익명함수에서는 아규먼트 레이블을 사용할 수 없다.

후행 클로저

func someFun(cl: () -> Void) {
    cl()
}
// trailing closure를 사용 안하면
someFun(cl: {
 print("후행 클로저 미사용")
})
// trailing closure 사용
someFun() { //"cl:"을 생략하고 함수 소괄호 다음에 클로저 작성
 print("후행 클로저 사용 ")
}

 

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
    return cal(x, y)
}

result = math(x: 1, y: 2, cal: {(a: Int, b: Int) -> Int in
    return a + b
}) //클로저 소스를 매개변수에 직접 작성하면 코드가 더러워지며 가독성이 저하됨

result = math(x: 10, y: 20) {(a: Int, b: Int) -> Int in
    return a + b
}//trailing closure를 더 많이 사용함

클로저 축약 표현

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
    return cal(x, y)
}

//1. 리턴형 생략 (자동 타입 추론)
let result = math(x: 10, y: 20) {(a: Int, b: Int) in
    return a + b
}

//2. 매개변수를 생략하고 단축인자 사용
let result2 = math(x: 10, y: 20) {
    return $0 * $1
}

//클로저는 마지막줄을 리턴하므로 return 생략 
let result3 = math(x: 20, y: 10) { $0 / $1 }

print(result)
print(result2)
print(result3)

 

디폴트 아규먼트

func sayHello(count: Int, name: String = "길동")  {
    print("\(name) 번호는 \(count)")
}

sayHello(count: 1, name:"하이") // 하이 번호는 1
sayHello(count: 2) // 길동 번호는 2

함수에 값이 들어오지 않았을때 기본으로 사용할 값을 지정 가능하다.

 

func present(
    _ viewControllerToPresent: UIViewController,
    animated flag: Bool,
    completion: (() -> Void)? = nil
)

클로저와 디폴트 매개변수 활용 예시

completion 매개변수는 클로저를 사용하여 새로운 뷰 컨트롤러가 표시된 후의 동작을 정의할 수 있습니다. 이 매개변수는 디폴트 값으로 nil이 설정되어 있어, 필요하지 않을 경우 생략이 가능합니다.

예시 1: 기본 사용

present(alert, animated: true)
completion을 생략하여, 새로운 뷰 컨트롤러를 애니메이션과 함께 표시합니다.

예시 2: 클로저를 사용한 추가 동작 정의

present(alert, animated: true) { print("Alert가 화면에 표시되었습니다.") }

새로운 뷰 컨트롤러가 표시된 후, 콘솔에 메시지를 출력합니다.

'iOS앱개발' 카테고리의 다른 글

iOS 실무 11주차  (0) 2025.05.15
iOS실무 10주차  (0) 2025.05.08
iOS 실무 7주차 enum struct 구조체와 클래스  (0) 2025.04.17
iOS실무 6주차  (0) 2025.04.10
iOS실무 5주차- 맛집 앱 개발(1) Table View  (0) 2025.04.03