본문 바로가기
WWDC

WWDC 20 - Core Data: Sundries and maxims

by vapor3965 2021. 7. 3.

목차

     

     


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

     

     

    https://developer.apple.com/wwdc20/10017

     

    Core Data: Sundries and maxims - WWDC20 - Videos - Apple Developer

    Core Data is the central way to durably and persistently store information from your app — and we're going to show you how to refine that...

    developer.apple.com

     


    요약

    • 가능하면 batch operations들을이용하고, 
      • 대신 notificaion은발생하지않는다.  
    • fetch request 들은 최대한 필요한정보들로만 간추리고,
      • fetch batch size
      • 필요한 attribute만 명시 
    • 변화를 확인하기위해 모두 가져오지말고, notification을 이용하라! 
      • objectID관련한 notification 생겼다.

     

     

     

     

     


     

     

     

    우선 지진앱을 소개하겠다.

    UI를 위한 View Context와,

    US Geological Survey ( USGS) 로부터 데이터를 받아오는 bcakground context가있다.

    local container와, USGS는 JSON으로 데이터를 준다. 

     

    USGS의 JSON파일은 JSON parser에게 전달하고, 

    JSON Parser는 background context에게 전달하고,

    background context는 Container에게 전달한다.

    그리고 ViewContext는 변화들을 merge하여 UI업데이트한다.

     

    그리고 background context에서 Container로 가는 활동이 굉장히많다. 

     

    그러므로, 이런곳에서 batch operation이 빛을발한다!

     

     

    insert, update, delete를 굉장히 쉽게해주고, 

    굉장히 싸다.

    save notification을 발생하지않는데, 그이유는 저장하지않기때문이다. 

    변화에대해 어떠한 콜백도없다.

    • 하지만 이는 persistent history에 의해 할수있다. 

     

     

    Persistent history 

    • batch operation들이 capture되어지고, notification을 받을수있다. 
    • 콜백들은 persistent history를 parsing하여 달성할수있따? 

     

     

    우선 앱은 데이터를 persistent store에 로드해야한다.

    그때, BatchInsertRequest를 이용하자.  수많은 데이터를 쉽게 로드해준다. 

    또한 우리는 batch insert request의 기능을 확장시켰다.

    기존에는 dictionary의 배열을통해서 batch insert가 가능하다. 

     

    이제는 클로저를통해서 dictionary 또는 manged object로 전달할수있게 만들었다.

    • 이방법은 메모리사용을 굉장히줄여준다?

     

     

    이전에는 batch operation을 사용하지않고 아래와같이 구현했었다. 

     

     

     

    batchInsert를 적용하면? 

    우선 딕셔너리배열을 만들어주고, 

    이를통해 BatchInsertRequest로 만든다.

    그다음에? 그냥 execute하면됌!!

     

    클로저가있는 구문으로 활용하면 다음과같이 작성할수있다. 

    클로저는true일때까지 계속호출된다. 

     

     

    자 그럼, 앞서 수행한 3가지의 성능을비교해보자 .

     

    각각 처음 높은부분들은 JOSN data때문이고

    context save한것은 수많은 트렌젝션과 변화에따른 notification등으로 시간이굉장히오래걸린다 ( 1분 ) 

    하지만, batch insert는 13sec밖에안걸리고, 메모리도적고!!

    batch insert with block ( 클로저 )는 더 메모리가적고 ! 11sec

     

     

     

     

     

     

     

    Quake 모델을 살펴보면, 인스펙터에서 Constraint - code 가 Unique Constraint으로 되어있다. ( code는 attirbute ) 

    이것이 의미하는것은 다른 quake들은 같은 code를 가질수없다는뜻이다. 

     

     

    예를들어, 지진데이터는 30일동안 발생한지진들을 가져오는데, 

    처음은 모두 insert되어야할것이다.

    만약 사용자가 리프레시하거나 다음에또받아와도 똑같은 데이터가많을것이다.

    이런경우에 같은데이터는 delete하고 insert하고싶진않을것이다.

    그대신 변화가있는경우에만 update하고싶을것이다.

    이를 SQL용어로 UPSERT라한다.

     

    batch insert Request에서도 UPSERT가가능한데, 

    가능하기위해서는 policy만 설정해주면된다.  - TrumpMergePolicy

     

     

     

     

    그리고 대량으로 업데이트를 쉽게하는 batch 도있다.

    BatchUpdateReuqest

    만약 지진이 2.5이상 발생한경우에 validated로 true하겠다고가정하면 다음과같이 작성할수있다. 

    정말 간결하고 !! 

     

     

    자그럼 마지막 batch delete를살펴보자

    손쉽게 대량의데이터를 delete시켜주고, relationship도 적용된다.

     

     

     

    30일이지난 지진데이터를 삭제한다고가정하자.

     

    우선 limit없이,

    clean-up task이므로, 비동기적으로 백그라운드우선순위로 실행했다. 

     

     

     

    만약 삭제해야할 데이터가엄청많다면요?!

    락도걸어야하고, 등등 시간이엄청ㅇ걸릴수있다.

     

    그러므로 Fetch limit를 설정하여 완화시킬수있다. 

     

     

     

     

     

     

    데이터를 가져오는작업에서 어떻게 성능을 향상시킬수있을까? 

     

    우선 managedObjectResultType이 가장쉬운방법이된다.

    이는 FetchResultsController를 이용할경우에 굉장히좋다.

    데이터가 업데이트되어도 fetchResultController가 반응하고 적용한다

     

     

     

    처음에 앱을켰을때는 아무것도안보이다가, 

    fetchreusltController를이용해서 데이터를가져온다. 

    보시다시피 보이는 지진데이터는 15개밖에없는데 우리는 훨씬많은 데이터를 fetch했다.

     

     

     

    그러므로 우리는 여기서 fetch batch size를 정함으로써 성능을 향상시킬수있다. 

     

     

     

    fetch batch size를 정하고안정하고 메모리사용의 차이가있다. 

     

     

     

     

    추가적으로 성능을 향상시킬수있는데, 

    가져오고자 하는 데이터들을 최대한 줄이는것이다. 

    • 가져오고자하는 attribute들만 명시하거나,
    • relationship도 정하거나...? 

     

     

    오직 보여지는 attribute들만 가져온다고하면 역시 메모리도줄어든다.

     

     

     

    다음으로 ObjectID를 살펴보자 

    데이터가많을수록 쓰레드에 전달하는것은 좋지못할것이다. 

    이때 ObjectID가 유용한데, 특정기준에만족하는 것을 찾고자할때, 이 간단한 ObjectID가 더나은 프로세싱을위해 다른쓰레드가 넘겨질수있따? 

     

    그리고 dictionary result은 굉장히 간단하고 가볍다.  ( read-only data ) 

    또한 복잡한데이터의 작업을할때 , 많은연산들을줄여줄수잇다. 

     

    place별로 평균 진도를 뽑고자할때 다음과같이 작성할수잇다. 

    그러면 아래와같은 dircionary타입으로 나타난다. 

     

     

     

    그다음으로는 countResultType가 있는데, 엄청간단하고, elegant하고 최적화디어있다.  

    무슨설명이 더필요하랴?! ( 그래도설명해주지 ㅠ ) 

     

     

     

     

     

    Core Data에는 변화가있을떄( 삭제, 추가 등등 ) notification이 발생한다. 

    그중에서 몇가지를 살펴볼건데,

     

    그중하나가 ObjectID notification이다. 

     

    objectID관련된걸 추가했고, 

     

    더쉽게 접근하기위한 key들도 추가했다.  물론 objectID관련된것도!

     

     

     

    ㄷ그리고 Remote Change notifications

     

     

     

     

     

    앱이 포그라운드가아닐때 이런저런 외부에의해 데이터변화가 발생할경우, 

    앱이 포그라운드일때 앱의변화를 가져오기위해서 모두 가져올수있지만, 이는 비싼작업이므로,

    remote change notification을 이용해서 손쉽게 변경내역들을 가져올수있다.

    오른쪽하단에 author, tId, proess 테이블이있는데, 이것보다 훨씬 더 많으 정보( 누가,무엇을,언제,어디서, 등 ) 들이 포함된 notifiation을 받을수있따. 

     

     

     

     

    persistent history에서 몇가지 팁을 보자면,

    위에서마찬가지로, 최대한 필요한내용들만 간추리도록하는것.

    특정날짜이후로 특정ID로 변화만 가져오도록한것.

     

     

     

     

    전체요약하면,

    가능하면 batch operations들을이용하고, 

    fetch request들은 최대한 필요한정보들로만 간추리고,

    변화를 확인하기위해 모두 가져오지말고, notification을 이용하라! 

     

     

     

     

     

    댓글