본문 바로가기
WWDC

WWDC 19 - Advances in Networking, Part 1

by vapor3965 2021. 6. 24.

목차


    • 세션보면서 정리한 내용입니다. 해석이 잘못된 경우가 있을수있으니 발견하시면 댓글로 남겨주시면 감사하겠습니다🙏🏻

     

    https://developer.apple.com/videos/play/wwdc2019/712/

     

    Advances in Networking, Part 1 - WWDC 2019 - Videos - Apple Developer

    Keep up with new and evolving networking protocols and standards by leveraging the modern networking frameworks on all Apple platforms...

    developer.apple.com

     




    관련내용

    • Data mode,
    • Combine in URLSession,
    • WebSocket 배워보자

     

    요약

    • iOS 13 부터 Low Data Mode 라는 것으로, 사용자가 설정할수있는 기능이생겼다. 이를통해, 과도한 네트워크사용량은 에러가날수있으므로, 처리해야한다.
    • 👍URLSession을 위한 Combine, DataTaskPublisher 가 새로생겼다. 이를 통해 쉽게 중복코드를 제거할수있다!
    • iOS 13부터, WebSocket이 생겼으며, URLSession. webSoketTask 를 사용할수있따!
      • HTTP 통신에따른 오버헤드없이 통신할수있다!
    • 👍NWListener를 통해, 로컬네트워크내에서 서버로 동작할수있따 !
      • 덕분에 실제로 구현해보았다!
      • 덕분에, 봉주르의 힘을 알게됐다.

     


    애플에서 네트워킹통신방법으로는, URLSession과 Network.framework가있다.

     

    Low Data Mode


    iOS13의 새로운 특징이다.



    사용자에게 preference를 제공하는것으로, 네트워크에서 데이터를 사용할떄 최대한 careful되고싶다고, application, system에게 알려주는것이다.

     

    이를키게된다면, system policy에 변화가생기고, 어플리케이션이 Low Data mode를 채택하도록한다.

     

    system policy에는, Low Data Mode를 키는동안, background discretionary(자율방임) task를 미룰것이다.

    • 예를들어, 비행기에있을때, 이를켜서, 미루고, 호텔에들어가 와이파이연결되면 그때부터 resume하도록한다.

    또한, Background App Refresh는 disable되어진다.

     

     

     

    LowDataMode에서는 어떻게 애플리케이션에서 해야할지 알아보기전에,
    우선 네트워크데이터를 어떻게 이용하는지부터 봐야한다.

     

     

    적용방법

    • task를 discretionary( 뜻: 자유재량에의한 ) 로 마킹하면, system이 자유롭게 처리하도록한다.
    • low data mode를 킨다고해서 모든 네트워킹에대해 팝업을 뜨도록하지말아라, 그건 사용자경험에 해를끼치는거니까,

     

     

     

    URLSession, Network.framework에서 LowDataMode확인하는방법

    • constrained property가 켜지게된다.

    URLSessiono - allowasConstrained 는 defualt 로 true이다.

    • 즉, Low Data Mode 네트워크를 허용한다라는뜻
      또는 false로정할수있다.
    • 그러므로, 큰데이터를할경우에는 false로 두어라.

    URLSession request, URLSession configuration 둘다 적용할수있다.

     

     

    constrained이여서 네트워킹에실패할경우, 큰리소스일경우, 작은리소스를 fetch하도록하라. pre-fetch인경우에는 유저가 진짜로원할때까지 기다려라.

     

    Network.framework에서는 LowDataMode를막고싶다면, prohibitConstrainedPath를 true로설정해라.

     

    그리고 connection되어있는동안, constrained property가 바뀔가능성이높다. 이러한경우에 핸들링하라.

    또다른 옵션으로, Expensive 가있다.
    이번에 Network.framework에있던 allowsExpensiveNetworks프로퍼티를 URLSesison에 도입했다.
    이를 키게되면 셀룰러, 핫스팟에서 다운받도록한다?

    되도록이면 이를 켜두록하라? 셀룰러만할경ㅇ 나중에 셀룰러를 지원안할수도있으니..?

     

     

     


    👍Combine with URLSession

    • 입력할때마다 요청할수도있지만, 특정길이이상일때만 요청할수도있고,
    • 사용자가 멈췄을때 요청하도록할수있다 - 👍debounce !

    • 또한, 사용자가 입력하고 다시삭제하고,입력하고 삭제하고, 함으로써 결국에는 같은 내용을 반복해서요청하는경우도생길수있다. 이런경우에 👍removeDuplicated() 를 이용한다.
      • 이는 받은마지막 값을 기억하면서, 이값과 변화가있는경우에만 진해앟도록해주게한다.

     

     

    👍DataTaskPublisher

    • 성공할경우 data와 response를보내주고, 실패할경우 error를 보낸다.

     


    Demo

    LowDataMode를 적용했다.
    그래서, LowDatMod일때는 이미지를 검은색바탕으로받아오고
    그렇지않은경우에는 컬러풀로받아온다.


    우선, allowsConstraintNetwrok를 false로하여, 고퀄이미지를 받아오고,
    실패했는데, 그이유가 lowdataMode라면, lowImage로 받아오도록했다.
    둘다 resume()을해주어야한다.

     

    ❌여기서문제점은, 상태코드채크와 이미지변환이 중복되있다는 점과,
    가장문제는 받아온데이터를 cell을캡쳐하여 cell에 비동기적으로 부여한다는점이다
    UIKit은 cell은 재사용되어지기때문에, 스크롤을하게되면, cell에 버그가생긴다. 이전요청과다음요청이 둘다 반영되기때문이다.

     

     

     

    개선방법


    cell에서는 이미지를 받기때문에, subscriber를 등록할 좋은 장소다.
    그리고 prepareForReuse()에 subscriber를 cancel해준다.
    cacel은 그즉시 되어지기때문에 잘못된이미지를 받을수없게되낟.

    그리고, cellForRowAt에서, 마찬가지로, URLReqeust를 만들어내지만,
    Data Task를 만들지않고, Data Task Publisher를 만들어낸다.

    그리고, 👍tryCatch operator를 이용하여, 실패할경우, lowimage를받는 새로운 data task publisher를 생성한다.


    그리고, 👍tryMap 을 통하여, data,reponse중에서, response가 올바른경우에 이미지를 return하고, 그렇지않으면 error를 throw한다.
    이를통해, 중복되었던 상태코드체크, 이미지반환을 해결햇다!

    그리고, error에 대해서 placeHolder이미지로 바꿔주고,
    main queue에서 받도록 하고, 이미지를 부여해주었따!


    하지만 에러날경우 한번더 다시 하게할수는없을까?

     

    고것은 바로 👍retry( )

    • 에러가발생할경우, 다시 retry하도록해준다!
    • 하지만! 네트워킹은 expensive하므로, retry도 예외가아니다. ㅡ그러므로 가능하다면 피하도록하라.
    • 그리고 idempotent 인 request일때만 해라. ( 뭐 결제이런경우에는 하지말고 )

     

     

     

     

     



    👍WebSocket


    iOS 13 , macOS Catalina에 새로등장했다. ( 박수박수 )


    sing HTTP연결에서 bidirectional communication을 가능하게해준다.

    • 쳇, 멀티플레이어게임, 실시간앱등을 가능하게해준다.
      proxies, CDns, firewall 연결을가능하게해준다.
      이미잘알려진 HTTP 포트에서 동작이가능하고, 기존웹인프라와 잘 호환이된다.

    HTTP/1.1 Long-polling

    • 보내고, 서버가 데이터있을경우 body를담아보내고,
    • 다시 요청하고, 그런다.

    단점으로는

    • HTTPrequest, response둘다 오버헤드가 많다.
    • 롱폴링을 하기위해 서버에 복잡함이 있을수밖에없다.

     

     

    웹소켓은 이러한 단점을 어떻게 해결했을까?

     

    우선, 클라이언트는 웹소켓핸드쉐이킹의 첫번째로,
    서버에게 요청을 보낸다. 이 요청은 이연결을 웹소켓으로 업그레이드해달라는 지시가담겨있다.
    그러면 서버는 응답을 하는데, 101switching protocol로 응답한다.


    101switching protocol응답은 bidirecitonal stream을 갖게된것을 의미한다.


    그럼이제, 두 곳에서 자유롭게 메세지를 보낼수있게된다.
    HTTP 오버헤드없이 데이터를 보낼수있다.

     

    사용방법

     

    websocket의 핸드쉐키잉을 우리가 전혀 고려하지않아도된다.

     

    웹소켓의 핸드쉐키잉은 HTTP를 그대로이용한다. - URLSession configuration에 작성된것을 사용할것이다.
    또한, netowrk storage를 사용하여, 쿠키, 룩업을 ㅅ용하고, 어떠한 문제들에대해서 delegate에 전파해줄것이다.

     

    receive는 비동기적으로 발생한다.


    URLSession - WebSocket은 JavaScript API와 매우 closer하고, 이는 완전한 메세지와 콜백에 묶여있다?

     

    몇 개발자는 서버의지원 또는 부분메세지만 읽고싶어할수있다.
    그래서, 이를 Network.framework 에서 지원하돍 한다.

    • NWConnection , NWListener를 통해서.

    최소,최대바이트를 지정하여, 부분적메세지를 읽을수있다.

     

    만약 리스너만 만들고싶 다면, 리스너만만들면된다.


     

     

     

     


    서버에서변화가있을경우, 사용자가 리프레쉬하여 받아오는것도 뭐 썩 괜찮다.
    하지만, 사용자가 리프레쉬하지않고도 저절로 바뀌면얼마나좋을까?

     

     

    서버


    우선, 서버코드에서는,
    파라미터에 웹소켓옵션을 추가한다.

    • 이는 서버에게 웹소켓핸드쉐키잉을 어떻게할지 말한다.

    ( 서버는 listener가 되고, listener는 newConnectionHandler를 통해서, 새로운 연결자(클라이언트)가 있는 경우, 해당연결자와 start한다! )

     


    그다음변경할곳은, 가격이변할때 전송해주는것으로,
    모든연결된 클라이언트들에게 보내는 방식이다.
    아래는어떠한 메세지framing을 가지고있지않는다.

    그러므로, 웹소켓 message frame으로써 데이터를 보내도록한다.


    클라이언트

    • URLSession. websocketTask( ) 로 WebSocketTask를 만들어준다.
    • resume()을통하여 핸드쉐이킹을진행한다.

    readMessage()를구현하자

    • 성공할경우, UI업데이트를하고, 다시 readMessage()를 호출한다.

    웹소켓 bidirectional communication - HTTP오버헤드없이!

    추가적으로, 정보들을나타냈는데, RTT는 서버와클라이언트 사이의 pings , pongs을 계산한 round-trip time이다.

     

     

     

     

    요약하면
    서버는 웹소켓옵션으로 정한 NWListener를 사용했으며,
    클라이언트는 웹소켓으로 서ㅓㅂ와연결했으며,
    trasnport ( 전달 )은 웹소켓 메세지를 이용했다.
    그장점으로 HTTP 오버헤드가없게된다.

     

    웹소켓을 추가할수있는 가능한 API들.

     

    URLSessionWebSocketTask는
    URLSession에서 작동하며 그러므로
    automatic cookie, authentication support를 지원한다.
    또한 round-trip time과같은 정보제공해주는 convenientway를 지원한다.

     

    Network프레임워크에서는 complete and partial message를 지원해준다. 마찬가지로 쿠키와같은 커스텀헤더를 set할수있다.

     

     

     

     

    ( 여기까지가 40분 내용이구, 나머지 Mobility Improvements는 나중에 보겠습니다 ㅎㅎ.. ) 

    댓글