관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 8. 네트워크 통신 (RESTFUL API, JSON, SOAP, XML) 본문

iOS 기본 (swift)

[iOS - swift] 8. 네트워크 통신 (RESTFUL API, JSON, SOAP, XML)

jake-kim 2020. 4. 3. 23:25

1. 네트워크에 대한 기본 지식

 1) 통신을 위한 프로그래밍 방향

 - 소켓 방법 : 명시적으로 끊을 떄까지 지속해서 연결을 유지하는 방법 (TCP, UDP를 통한 화상통화, RPG 게임)

 - 비연결성 방법 : HTTP/HTTPS

 

* 앞으로 비연결성 방법에 관한 내용만 진행

 

2) 웹 서비스의 종류 (웹 서비스 : 웹 페이지 같은 것이 아닌 데이터만을 주고받을 수 있도록 설계된 모듈)

 - SOAP(Simple Object Access Protocol) : HTTP, HTTPS, SMTP등의 프로토콜들을 통해 XML(eXtensibal Markup Language)형태의 메시지 주고 받는 것

 

 - RESTful (Representational State Transfer) : HTTP프로토콜을 통해 조금더 쉬운 형식으로 데이터 주고받음 (SOAP는 header, body와 같은 복잡한 것을 실어서 보내야함, 또한 데이터 사이즈 커짐)

RESTful에서는 GET형식과 POST방식 뿐만이 아닌, PUT(갱신), DELETE(삭제)방식을 이용

CRUD각각 POST, GET, PUT, DELETE이며, GET은 parameter(URL의 쿼리스트링에 실어서 전송)에 데이터를 넘기므로, GET에서의 보안상 우려되는 것은 가급적이면 POST(body에 데이터 실어서 전송)를 사용

 

 REST방법으로 구현한 시스템을 RESTful이라 함

 

* 앞으로 RESTful에 관한 내용만 진행

 

2. RESTful을 구현하기에 앞서

1) CRUD 구현 방식

 - URI(Uniform Resource Identifier)를 따라서 URL에 그대로 정보를 집어넣는것은 안좋음

  "http://127.0.0.1/sns/article/update" // update요청

 

 - URI에 CRUD동작을 포함하는 대신, URI 헤더에 HTTP메소드를 사용하여 구현

 - 요청시 GET, 데이터 전송시 POST사용 (GET을 데이터 전송시 1024바이트 이하 정보만 가능)

 

2) JSON(JavaScript Object Notation)

 - JSON객체 : { 키 : 값, 키 : 값 } 

    문자열, 정수, 실수, 논리형 사용가능

    "outer": {

         "title" : "다크나이트",

         "rating" : 8.95

     }

 

 - JSON배열 : [ 객체1, 객체2, 객체3 ]

    "outer":[

         { "title" : "다크나이트", "rating" : 8.95},

         {"title" : "시크릿", "rating":9.9}

   ]

 

3. REST API를 이용한 데이터 획득

 1) GET방식으로 REST API를 호출하여 데이터 획득

 - Data(contentsOf: URL타입의 객체) 사용 (REST API를 호출하여 데이터 요청)

1
2
3
4
5
      // viewDidLoad안에 작성
        
        let apiURI: URL! = URL(string: url)
        
        let apiData = try! Data(contentsOf: apiURI) // Data와 URL타입 객체 모두 Foundation프레임 워크에서 제공하는 클래스
 

※ 잘못된 URL이거나 서버에 문제가 있는 경우 nil값을 반환하므로 Data(contentsOf:)에 생성되는 인스턴스는 옵셔널타입

* URL주소에 https가 아닌 http라면 info.plist에 ATS보안 설정을 해줘야 함

이 부분을 추가
 
1
2
3
4
5
<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
 
 
 
2) REST API를 이용하여 얻어온 apidata(JSON형태로 왔다고 가정)를 파싱하여 데이터 획득
 
REST API로 얻어온 apidata

- JSON 객체로 변환 -> 파싱 -> VO객체에 저장 후 기록 list.append(VO)

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
        do{
            // JSON객체로 변환 : Foundation 프레임 워크에서 제공하는 JSONSerialization객체 이용
            // 단, apiData가 처음에 객체라서 NSDictionary로 다운 캐스팅 한 것이며, 배열이면 NSArray로 다운캐스팅 할 것
            let apiDictionary = try! JSONSerialization.jsonObject(with: apiData, options: []) as! NSDictionary
            
            // JSON파일 파싱 (다운 캐스팅에 유의할 것)
            let hoppin = apiDictionary["hoppin"as! NSDictionary
            let movies = hoppin["movies"as! NSDictionary
            let movie = movies["movie"as! NSArray
            
            // 얻어온 데이터들을 VO객체에 저장하며, list에 추가하는 작업
            for row in movie {
                // 다운 캐스팅 할 것
                let r = row as! NSDictionary
                
                let mvo = MovieVO()
                
                mvo.title = r["title"asString
                mvo.description = r["genreNames"asString
                mvo.thumbnail = r["thumbnailImage"asString
 
                
                self.list.append(mvo)
            }
            
        }
 
 
 
 
 

- Serialization(직렬화)란?
객체의 직렬화는 객체의 내용을 바이트 단위로 변환하여 파일 또는 네트워크를 통해서 스트림(송수신)이 가능하게 하는것을 의미

 

※ 이미지 삽입

 - 이미지를 삽입 할 때, UIImage(named:)가 아닌 UIImage(data: 이미지 url을 가진 Data객체)로 사용

 - 비동기 처리로 구현

1
2
3
4
5
6
7
8
// tableVeiw(_:cellForRowAt)
 
DispatchQueue.main.async {
    let row = self.list[indexPath.row]
    let url: URL! = URL(stirng: row.thumbnail!)
    let imageData = try! Data(contentsOf: url)
    cell.thumbnail.image = UIImage(data:imageData) // 클로저 특성상 외부에 있는 cell객체 참조 가능
}
 
 

 

※ "더보기"와 같은 버튼을 테이블 뷰 밑에 만들어서, 데이터를 더욱 요청하여 로드하는 방법

 - 전역변수에 page = 1 선언

 - 버튼을 눌릴때마다 url을가져와서 파싱까지 모든 작업 다시 시행, 단, url에 요청시 "page=\(page)"와 같이 작성 후, page +=1

 - self.tableView.reloadData()를 통해 데이터를 다시 읽어오도록 테이블 뷰를 갱신(tableView메소드가 다시 실행되는 것)

 

※ JSON데이터가 한글로 있는경우(EUC-KR형식인 경우)

 - URL객체까지 불러온 후 다음과 같이 NSString으로 인코딩해야함 : EUC-KR -> UTF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
do {
    // 16진수로 80000422는 EUC-KR을 의미함
    // urlObj는 URL객체임
    let stringdata = try NSString(contentsOf: urlObj!, encoding: 0x80_000_422)
    
    // UTF로 인코딩하여 Data객체로 변환
    let encdata = stringdata.data(using:String.Encoding.utf8.rawValue)
    
    do {
        let apiArray = try JSONSerialization.jsonObject(with: encdata!, options: []) as? NSArray
        for obj in apiArray! {
            self.list.append(obj as! NSDictionary)
        }
    } catch {}
    
    self.startPoint += sList
    
catch {}
 
 

 

결과)


 

* 내용 출처 : 꼼꼼한 재은씨의 스위프트 - 기본편

 

* 네트워크 통신에 많이 사용되는 프레임워크는, Alamofire : ios-development.tistory.com/63

 

[iOS - swift] 4. 서버 - Alamofire를 이용한 회원가입 요청, 응답

1. API문서 - rubypaper API사용 항목 내용 API 명 Join API 설명 사용자 정보를 입력받아 계정 생성 API 도메인 http://swiftapi.rubypaper.co.kr:2029/userAccount/join API 경로 userAccount/join 전송방식 POS..

ios-development.tistory.com

f

Comments