본문 바로가기
iOS

iOS 실무 9주차

by asd135 2025. 5. 5.
728x90

응답 예시

http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?
key=82ca741a2844c5c180a208137bb92bd7&
targetDt=20120101

키는 발급 받은 자신의 키를 사용해야함

 

 

{
  "boxOfficeResult": {
    "boxofficeType": "일별 박스오피스",
    "showRange": "20250504~20250504",
    "dailyBoxOfficeList": [
      {
        "rnum": "1",
        "rank": "1",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20232394",
        "movieNm": "야당",
        "openDt": "2025-04-16",
        "salesAmt": "1449279360",
        "salesShare": "28.9",
        "salesInten": "-12642880",
        "salesChange": "-0.9",
        "salesAcc": "22422374350",
        "audiCnt": "150345",
        "audiInten": "-1609",
        "audiChange": "-1.1",
        "audiAcc": "2379864",
        "scrnCnt": "1421",
        "showCnt": "4376"
      },
      {
        "rnum": "2",
        "rank": "2",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20253280",
        "movieNm": "A MINECRAFT MOVIE 마인크래프트 무비",
        "openDt": "2025-04-26",
        "salesAmt": "986682760",
        "salesShare": "19.7",
        "salesInten": "-133922790",
        "salesChange": "-12",
        "salesAcc": "7543522440",
        "audiCnt": "102981",
        "audiInten": "-15209",
        "audiChange": "-12.9",
        "audiAcc": "800795",
        "scrnCnt": "1269",
        "showCnt": "3735"
      },
      {
        "rnum": "3",
        "rank": "3",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20244883",
        "movieNm": "썬더볼츠*",
        "openDt": "2025-04-30",
        "salesAmt": "979371450",
        "salesShare": "19.6",
        "salesInten": "-120093930",
        "salesChange": "-10.9",
        "salesAcc": "4789521800",
        "audiCnt": "93375",
        "audiInten": "-11343",
        "audiChange": "-10.8",
        "audiAcc": "477913",
        "scrnCnt": "1160",
        "showCnt": "4024"
      },
      {
        "rnum": "4",
        "rank": "4",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20218800",
        "movieNm": "거룩한 밤: 데몬 헌터스",
        "openDt": "2025-04-30",
        "salesAmt": "858146540",
        "salesShare": "17.1",
        "salesInten": "-45822740",
        "salesChange": "-5.1",
        "salesAcc": "4538586600",
        "audiCnt": "87251",
        "audiInten": "-6078",
        "audiChange": "-6.5",
        "audiAcc": "499344",
        "scrnCnt": "1097",
        "showCnt": "3110"
      },
      {
        "rnum": "5",
        "rank": "5",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20240398",
        "movieNm": "파과",
        "openDt": "2025-04-30",
        "salesAmt": "365865200",
        "salesShare": "7.3",
        "salesInten": "11261900",
        "salesChange": "3.2",
        "salesAcc": "1701051020",
        "audiCnt": "37271",
        "audiInten": "877",
        "audiChange": "2.4",
        "audiAcc": "184070",
        "scrnCnt": "724",
        "showCnt": "1396"
      },
      {
        "rnum": "6",
        "rank": "6",
        "rankInten": "1",
        "rankOldAndNew": "OLD",
        "movieCd": "20253101",
        "movieNm": "극장판 진격의 거인 완결편 더 라스트 어택",
        "openDt": "2025-03-13",
        "salesAmt": "69873700",
        "salesShare": "1.4",
        "salesInten": "4800300",
        "salesChange": "7.4",
        "salesAcc": "8334615370",
        "audiCnt": "6390",
        "audiInten": "439",
        "audiChange": "7.4",
        "audiAcc": "823784",
        "scrnCnt": "116",
        "showCnt": "176"
      },
      {
        "rnum": "7",
        "rank": "7",
        "rankInten": "-1",
        "rankOldAndNew": "OLD",
        "movieCd": "20253530",
        "movieNm": "시크릿쥬쥬 마법의 하모니",
        "openDt": "2025-05-01",
        "salesAmt": "56316800",
        "salesShare": "1.1",
        "salesInten": "-18867440",
        "salesChange": "-25.1",
        "salesAcc": "286022620",
        "audiCnt": "6141",
        "audiInten": "-2107",
        "audiChange": "-25.5",
        "audiAcc": "31755",
        "scrnCnt": "526",
        "showCnt": "761"
      },
      {
        "rnum": "8",
        "rank": "8",
        "rankInten": "1",
        "rankOldAndNew": "OLD",
        "movieCd": "20246318",
        "movieNm": "해피엔드",
        "openDt": "2025-04-30",
        "salesAmt": "40966800",
        "salesShare": "0.8",
        "salesInten": "-552360",
        "salesChange": "-1.3",
        "salesAcc": "259767160",
        "audiCnt": "4103",
        "audiInten": "-79",
        "audiChange": "-1.9",
        "audiAcc": "26952",
        "scrnCnt": "102",
        "showCnt": "152"
      },
      {
        "rnum": "9",
        "rank": "9",
        "rankInten": "-1",
        "rankOldAndNew": "OLD",
        "movieCd": "20253924",
        "movieNm": "쫑알쫑알 똘똘이: 이상한 마을 대모험",
        "openDt": "2025-04-30",
        "salesAmt": "35250300",
        "salesShare": "0.7",
        "salesInten": "-9782700",
        "salesChange": "-21.7",
        "salesAcc": "164753000",
        "audiCnt": "3852",
        "audiInten": "-1013",
        "audiChange": "-20.8",
        "audiAcc": "18350",
        "scrnCnt": "187",
        "showCnt": "299"
      },
      {
        "rnum": "10",
        "rank": "10",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20249251",
        "movieNm": "콘클라베",
        "openDt": "2025-03-05",
        "salesAmt": "32851000",
        "salesShare": "0.7",
        "salesInten": "-2019300",
        "salesChange": "-5.8",
        "salesAcc": "2992140420",
        "audiCnt": "3238",
        "audiInten": "-60",
        "audiChange": "-1.8",
        "audiAcc": "314143",
        "scrnCnt": "76",
        "showCnt": "96"
      }
    ]
  }
}

네이버 영화순위는 영진위에서 제공하는 데이터를 사용함

 

REST란?

-웹에서 정보를 주고받는 방법(아키텍처 스타일)

 

REST의 특징

리소스(resource)

-인터넷에 존재하는 모든 정보 

-예시: /user/10(10번 회원), /posts(계시글 전체)

 

주소(URI, URL)

-리소스마다 주소가 있음

-예시: https://site.com/users/10

 

행동(HTTP 메서드)

-어떤 행동을 할지 정하는 방법

-GET(가져오기), POST(생성), PUT(수정), DELETE(삭제)

-1번 유저 정보 가져오기(GET/users/1)

RESTful 정의

-로이 필딩(Roy FieIding)이 2000년에 UC 어바인에서 "Architectural Styles
nd the Design of Network—based S0ftware Architectures" 라는 박사 학위
논문에 REST를 정의

-REST 설계 지침을 따르는 웹 서비스를 RESTful이라 함

 

RESTful

 

-REST의 규칙을 최대한 잘 지켜서 만든 서비스

-REST의 원칙대로 주소와 동작을 깔끔하게 잘 설계한 API는 "RESTful"하다고 함

-RESTful한 API 예시

GET /users 회원목록 보기

POST /users 회원 추가

-RESTful하지 않은 예

-주소에 동작이 섞여 있음

-POST /users/getUser 회원 정보 보기

-GET /users/deleteUser 회원 삭제

 

JSON(JavaScript Object Notation)

-기존 XML의 단점을 극복하기 위해 만들어진 경량의 데이터 교환 방식

-프로그래밍 언어로부터 독립적이기 때문에 데이터 교환에 많이 사용

-JSON에 사용되는 데이터 구조 두가지

-집합구조: 여러가지 속성을 다양하게 정의할 수 있는 집합구조 {}

-리스트구조: 비슷한 상황이 반복되는 리스트 구조 []

 

JSON 데이터를 프로그래밍 언어로 구현할 때는 순서대로 타고 들어가는 식으로 구현 함

 

API(Application Programming Interface)

-컴퓨터와 사람을 연결하는 UI와 달리 API는 컴퓨터나 소프트웨어를 서로 연결

 

 

오픈 API

https://www.data.go.kr/index.do

https://data.seoul.go.kr/

 

오픈 API를 활용하여 앱을 만드는데 유용하게 사용할 수 있음

 

네이버에서 제공하는 API

 

Open API를 이용하는 앱 개발 단계

1. 원하는 정보를 제공하는 웹 서비스와 사용할 Open API 선정

2. Open API 사용을 위한 신청과 인증키 발급

3. 네트워크를 통해 데이터 요청

4. 받은 데이터를 파싱하여 앱에서 사용

 

 

관광 데이터를 제공하는 API

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

호출방법

 

요청

 

응답

 

 

응답 예제

 

 

{
  "response": {
    "header": {
      "resultCode": "0000",
      "resultMsg": "OK"
    },
    "body": {
      "items": {
        "item": [
          {
            "contentid": "2491622",
            "contenttypeid": "32",
            "title": "힐리언스 선마을",
            "createdtime": "20170502195646",
            "modifiedtime": "20250116173519",
            "tel": "010-4148-8713 / 02-1588-9983",
            "telname": "이지현",
            "homepage": "\u003Ca href=\"https://www.healience.co.kr/\" target=\"_blank\" title=\"새창 : 힐리언스 선마을 홈페이지로 이동\"\u003Ehttps://www.healience.co.kr/\u003C/a\u003E",
            "addr1": "강원특별자치도 홍천군 종자산길 122",
            "addr2": "",
            "zipcode": "25104",
            "overview": "강원도 홍천군에 위치한 힐리언스 선마을은 웰에이징 힐링리조트로, 정신과 의사이자 뇌과학자인 이시형 박사가 함께 만든 곳이다. 종자산 중턱에 있어 온전한 자연 속에서 쉼을 경험할 수 있다. 객실은 숲속동, 정원동, 황토방, 그리고 건강한 자연의 기운을 담은 바람의 집과 흙의 집 등 등 총 92개가 있고, 반려견 동반이 가능한 객실도 있다. 또한 식당과 카페, 와인바 등의 식음시설과 스파, 찜질방, 테라피센터, 황톳길 등의 힐링공간, 갤러리, 공방, 세미나실 등의 문화공간, 웰니스공간, 힐리펫공간, 키즈공간, 편의공간 등 다양한 시설이 있어 다채로운 힐링을 경험할 수 있다."
          }
        ]
      },
      "numOfRows": 1,
      "pageNo": 1,
      "totalCount": 1
    }
  }
}

 

스위프트 구조체형식으로 변경

import Foundation

struct ApiResponse: Codable {
    let response: Response
}

struct Response: Codable {
    let header: Header
    let body: Body
}

struct Header: Codable {
    let resultCode: String
    let resultMsg: String
}

struct Body: Codable {
    let items: Items
    let numOfRows: Int
    let pageNo: Int
    let totalCount: Int
}

struct Items: Codable {
    let item: [TourItem]
}

struct TourItem: Codable {
    let contentid: String
    let contenttypeid: String
    let title: String
    let createdtime: String
    let modifiedtime: String
    let tel: String
    let telname: String
    let homepage: String
    let addr1: String
    let addr2: String
    let zipcode: String
    let overview: String
}

 


Swift 방식 함수

func add(x: Int, y: Int) -> Int {
	return(x+y)
}
add(x:10, y:20)

 

함수의 타입: (자료형, 자료형,...) -> 리턴형

위 함수의 자료형은 (Int, Int) -> Int

 

리턴형이 Void형이면 () or Void

Swift에서 빈튜플()은 Void와 같은 역할을 함

 

 

함수명(외부매개변수명: 외부매개변수명:)

add(x:y:)

 

1급 객체 기준

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

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

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

 

Swift의 함수는 1급 객체이다.

 

일급 객체 실습

func up(num: Int) -> Int {
    return num + 1
}

func down(num: Int) -> Int {
    return num - 1
}

let toUp = up
print(up(num: 10))
print(toUp(10))

let toDown = down

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

upDown(Fun: toUp, value: 10)    // toUp(10)
upDown(Fun: toDown, value: 10)  // toDown(10)

func decideFun(x: Bool) -> (Int) -> Int {
    // 매개변수형 리턴형이 함수형
    if x {
        return toUp
    } else {
        return toDown
    }
}

let r = decideFun(x: true)  // let r = toUp
print(type(of: r))          // (Int) -> Int
print(r(10))                // toUp(10)

 

클로저

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

add함수를 클로저 표현식으로 변경

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

print(add1(x:10, y:20)) //주의 error: extraneous(관련 없는) argument labels 'x:y:' in call
print(add1(10, 20)) //OK
print(type(of:add1)) //(Int, Int) -> Int

 

후행 클로저

- 클로저가 함수의 마지막 argument라면 마지막 매개변수명(cl)을 생략한 후 함수 소괄호 외부에 클로저를 작성

func someFun(cl: () -> Void) {
}

매개변수도 없고 리턴값이 없는 함수가 인자로 들어올 수 있다는 의미

 

후행클로저 미사용

someFun(cl: {
//closure’s body
})

 

후행클로저 사용

someFun() { //"cl:"을 생략하고 함수 소괄호 다음에 클로저 작성
//trailing closure's body goes here
}

 

func mul(a: Int, b: Int) -> Int {
    return a * b
}

let multiply = { (a: Int, b: Int) -> Int in
    return a * b
}

print(mul(a: 10, b: 20)) // 200
print(multiply(10, 20)) // 200

let add = { (a: Int, b: Int) -> Int in
    return a + b
}

print(add(10, 20)) // 30

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

var result = math(x: 10, y: 20, cal: add)             // return add(10, 20)
print(result) // 30

result = math(x: 10, y: 20, cal: multiply)            // return multiply(10, 20)
print(result) // 200


// 마지막 argument가 함수이면 클로저 사용 가능
result = math(x: 10, y: 20, cal: { (a: Int, b: Int) -> Int in
    return a + b
})                                                    // 클로저를 직접 매개변수로 작성
print(result) // 30

result = math(x: 10, y: 20) { (a: Int, b: Int) -> Int in
    return a + b
}                                                     // trailing closure
print(result) // 30

 

클로저의 축약 표현들

result = math(x: 10, y: 20, cal: {(val1: Int, val2: Int) -> Int in
return val1 + val2
}) //클로저 소스를 매개변수에 직접 작성
print(result) // 30

후행클로저 사용

result = math(x: 10, y: 20) {(val1: Int, val2: Int) -> Int in
return val1 + val2
}//trailing closure
print(result) // 30

리턴형 생략

result = math(x: 10, y: 20) {(val1: Int, val2: Int) in
return val1 + val2
} //trailing closure, 리턴형 생략
print(result)

단축인자 사용( $0 = x, $1 = y )

result = math(x: 10, y: 20) {
return $0 + $1
} //trailing closure, 매개변수 생략하고 단축인자사용
print(result) // 30

리턴 생략

result = math(x: 10, y: 20) { $0 + $1 } //return 생략
print(result) // 30

 

디폴트 매개변수(아규먼트) 정의하기

func sayHello(count: Int, name: String = "길동") -> String {
return ("\(name) 번호는 \(count)")
}
var message = sayHello(count:10, name: "철수")
print(message) //철수 번호는 10
message = sayHello(count:100) //name에 값을 전달하지 않음
print(message) //길동 번호는 100

함수를 호출할 때 name 매개변수에 인자를 전달하지 않을 경우 디폴트로 할당된 "길동"을 사용 

 

iOS에서 제공하는 디폴트 메서드

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

 

present(alert, animated: true, completion: nil) // 화면을 띄운 후에 하고 싶은 작업이 없는 경우
present(alert, animated: true) // 위 소스에서 디폴트 매개변수를 생략한 소스(같은 소스임)

 

'iOS' 카테고리의 다른 글

iOS 실무11주  (0) 2025.05.14
iOS 실무10주차  (0) 2025.05.07
iOS 실무 7주차  (0) 2025.04.16
iOS 실무 6주차  (0) 2025.04.09
iOS 실무 5주차  (0) 2025.04.02