본문 바로가기

개발/App Developer

2010.08.11 - coredata 이해

코어 데이터는 객체를 관리하는 것이다.

 

* 기능

- 사용자 정의 객체를 읽고 저장할 수 있는 기능

  코어 데이터는 엔티티 기술문 (Entity description)에 기술된 사용자 객체를 읽고 저장할 수 있습니다.

  또한 객체간의 관계, 다른 버전의 데이터로 이전, 필수 및 선택 필드, 그리고 필드값 검증(filed validation)도 처리할 수 있습니다.

 

- 데이터를 다양한 방법으로 저장 가능

  코어 데이터는 데이터가 실제로 어떻게 저장되는 지 신경 쓰지 않도록 해줍니다.

  코어 데이터에 어떻게 저장하는지만 지정하면, 앱에서는 SQLite 데이터베이스에 저장하는지

  임의의 이진 파일에 저장하는지 신경쓰지 않아도 됩니다.

 

- 메모리 관리 및 실행취소(undo)와 실행복귀(redo) 지원

  코어 데이터는 메모리 상의 객체를 관리하는 데 매우 효율적입니다.

  그리고 객체에 대한 변경도 추적하고 있습니다. 그래서 실행취소(undo)와 실행복귀(redo)를

  사용할 수 도 있고, 커다란 데이터 베이스를 필요한 만큼의 페이지 단위로 읽을 수도 있습니다.

 

// 코어 데이터를 사용하기 전에 코어데이터에게 객체에 대해서 설명해 주어야 한다.

 

코어 데이터는 Objecive-C 클래스와 객체를 사용하고, 필드의 프로퍼티를 선언하고, 데이터 형을 바로 사용할 수 있다.

하지만 코어 데이터는 처음에는 특정한 데이터 형만 지원한다. 그래서 제공되는 형을 이용하여 엔티티를 정의해야 한다.

 

코어 데이터 형

Int32         32비트 정수형    - NSNumber로 표현

String       NSString과 거의 같은 형

Boolean   불형 (Yes or No)

Decimal    고정 소수점 10진수   - NSDecimalNumber 로 표현

Date         날짜및 시간 정보     - NSDate 로 표현

 

* Managed Object

- 코어 데이터에 의해서 제어되는 엔티티

 

* Managed Object Model

- 코어 데이터에서 엔티티를 설명하는 (프로퍼티, 관계, 형 정보 등) 방법

 

// 코어 데이터는 매니지드 오브젝트 모델을 참조하여 실행 시에 데이터 베이스 등의 저장소에서 데이터를 로드하고 저장하는 방법을 알아낸다.

- Xcode의 템플릿은 비어있는 매니지드 오브젝트 모델을 제공하며, 템플릿은 시작 할 때 코어 데이터가 모든 매니지드 오브젝트 모델을 읽어오도록 설정되어 있다. (Resourced폴더에 파일명.xcdatamodel 형태로 모델파일 제공)

 

* 주의점

- 코어 데이터 형은 Objective-C 클래스와 정확히 대응되지는 않는다.

 

* 파일명.xcdatamodel 파일로 Xcode에서 프로퍼티를 생성할때 옵션으로 나오는 3가지

- Optional : 선택적 속성 (필수 사항이 아님)

- Transient (임시) :

  코어 데이터가 해당 프로퍼티를 읽어 들이거나 저장할 필요가 없다는 것을 나타냄.

  임시 프로퍼티를 사용하면, 보통 코어 데이터가 엔티티를 로드하고 나서 호출하는 awakeFromFetch : 메소드를 구현하게 된다.

  이 메소드에서 임시 속성을 가진 프로퍼티를 계산하고 초기화 한다.

- Indexed (색인) :

  코어 데이터로 하여금 해당 프로퍼티에 대해서 색인을 만들도록 함. - 엔티티 검색을 빠르게 수행

  그러나 색인은 별도의 저장 공간을 필요로 하고 또한 데이터를 추가하는 것을 느리게 만들 수 있음.

  (검색 성능 향상을 위해 꼭 필요한 경우에만 사용 권장 그 외에 비추)

 

* 코어 데이터가 지원하지 않는 형을 사용하는 방법

- 제공되는 형에 맞추는 것이 제일 쉽다. 하지만 그러지 못할 경우,

  커스터마이즈된 형을 생성하고, 코어 데이터가 이 데이터를 읽고 쓰는 것을 도와줄 메소드를 구현해야 한다.

  최후의 방법으로는 데이터를 이진 형태 (이진 데이터 또는 BLOB, Binary Large OBject)로 저장하고, 실행 시에

  사용하는 형태로 저장(Encode) 및 읽는(Decode) 코드를 작성하는 방법도 있다.

 

* 코어 데이터 지원 저장소 형태

- 코어 데이터는 아이폰에서 세 가지 형태(이진파일, SQLite 데이터 베이스, In-Memory) 의 저장소를 지원한다.

  그 중 SQLite 데이터베이스가 가장 유용하며, 기본으로 제공된다.

  이진파일은 원자성(모든 것이 한꺼번에 저장되거나, 아니면 아무것도 저장되지 않음)을 제공한다.

  그러나 원자성을 제공하기에 파일 내용이 조금만 변경되어도 파일 전체를 저장해야 한다. - 아이폰에서 많이 사용되지 않는다.

  인-메모리 저장소는 실제로 디스크에 저장하지 않는다 .

  그러나 검색, 정렬, 실행취소 및 실행복귀 등 코어 데이터가 제공하는 기능을 메모리상에서 구현한다.

 

* 코어 데이터 스택구조

- Managed Object Context (매니지드 오브젝트 컨텍스트)

  이 클래스가 앱에서 메모리에 있는 모든 엔티티(매니지드 오브젝트)를 관리한다.

  코어 데이터가 객체를 통해서 데이터를 읽어올 때, 매니지드 오브젝트 컨텍스트에게 요청한다.

 

- Persistent Store Coordinator (영구 저장소 코디네이터)

  Persistent Object Store(영구 객체 저장소) 관리한다. 저장소가 데이터를 실제로 읽고 쓰는 방법을 알고 있다.

  메모리에 데이터가 있지 않다면, 영구 저장소 코디네이터를 통해 찾아서 읽어 들인다.

 

- Persistent Object Store (영구 객체 저장소)

  코어데이터가 지원하는 영구 저장소 형태별로 별도의 영구 객체 저장소가 존재한다. (SQLite 데이터베이스와 같은)

 

정리

 

- 코어 데이터는 영속성을 제공하는 프레임워크로써 읽기, 저장, 버전화, 실행취소, 실행 복귀를 제공한다.

 

- 코어 데이터는 SQLite 데이터 베이스, 이진파일, 또는 임시적인 메모리(In-Memory)를 사용할 수 잇다.

 

- Managed Object Model은 코어 데이터를 사용해 작업할 때 필요한 엔티티를 정의한다.

 

- Managed Object Context 가 데이터를 사용하는 관문이다. 이것은 모든 Managed Object 를 관리하고 있다.

 

- 코어 데이터 클래스 스택 중에서 영속성 객체 저장소(Persistent Object Sotre)가 실제 데이터를 읽고 저장하는 일을 담당한다.

rorcp

 

* NSManagedObject

- 코어데이터 프레임워크.

- 프로퍼티를 메모리에 저장하는 책임을 지고 있다.

- 필요할 경우 이 프로퍼티 메소드를 오버라이드 할 수 있지만, 대부분의 경우 원하는 작업을 수행할 수 있다.

- 프로퍼티 또한 구현해 준다.

   @dynamic 명령어로 선언되어 프로퍼티에 대한 메모리 부분을 처리하고 있으므로, 게터와 세터 메소드들도 구현해 준다.

   //@dynamic : 컴파일러에게 프로퍼티에 대한 게터 및 세터 메소드에 대해서 걱정하지 말라고 알려줌

- 장점

  1. NSMAnagedObject 는 프로퍼티가 변하는 때를 알 수 있으므로, 새로운 데이터를 검증하고, 변경되었을 때

     다른 클래스에게 알려줄 수도 있다.

  2. NSManagedObject 는 프로퍼티 정보를 가져와야 할 때를 누군가 요청할 때까지 최대한 늦출 수 있다.

     - 다른 객체가 요청해야 실제로 읽어온다.

  3. NSManagedObject 가 프로퍼티의 변화를 알고 있으므로, 실행취소 및 실행복귀를 지원할 수 있다.

  4. 이 모든 것이 코딩 한 줄 없이 제공된다.

 

* NSFetchRequest

- 객체의 조건과 결과로 나오는 객체를 어떻게 코어데이터가 정렬할 것인지를 설명한다. (검색할 조건 기술)

   Entity Info : 어떤 형의 데이터를 검색하려고 하는지, 매니지드 오브젝트 모델에 있는 엔티티 중에서 선택하여

                    NSFetchRequest에 알려줌.

   Predicate : 엔티티가 충족해야 하는 조건을 기술. 모든 객체를 찾으려고 하는 경우에는 비워둔다.

   Sort Descriptor : 검색된 결과를 코어데이터가 어떻게 정렬해서 보여줄 지 설명.

 

// 매니지드 오브젝트 컨텍스트에게 NSFetchRequest를 실행하도록 요청해야 한다.

    이렇게 하기 위해서는 매니지드 오브젝트 컨텍스트에 대한 참조를 할수 있어야 한다.

    템플릿은 앱 델리게이트 안에 이것을 참조할 수 있도록 준비해 두었다.

    아래 예문과 같은 방법으로 포인터를 얻어올 수 있다.

 

예문 )

 

iBountyHunterAppDelegate *appDelegate = (iBountyHunterAppdelegate*)[[UIApplication sharedApplication] delegate];

NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;

 

//UIApplication은 프로그램 내에서 단 한개의 인스턴스만이 존재하고, 이 인스턴스를 여러 부분에서 공유해서 사용하기 때문에

   'shared' 라는 접두사가 붙은 것이다.

    'sharedApplication' 이  하는 일은 UIApplication의 인스턴스를 반환하는 일이고,

    유일한 인스턴스에 대한 반환이기 때문에 프로그램 내에서 늘 동일한 인스턴스를 반환하게 된다.

   디자인 패턴에서는 이러한 설계 방법을 싱글톤 패턴(Singleton pattern)이라고 한다.

  

   * Singleton Pattern

     특정 클래스에 대해서 객체가 하나 뿐인 특별한 객체를 만들 수 있게 해주는 패턴이다.

     전역변수(프로그램 전반에 걸쳐 사용할 수 있는 변수)처럼 애플리케이션이 시작될 때 객체가

     생성되지 않고 필요할 때 객체를 생성할 수 있다.

   

    1. Singleton Pattern의 정의

        해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다.

    2. Singleton Pattern의 특징

        클래스에서 자신의 단 하나뿐인 인스턴스를 관리하도록 만들어야한다.

        인스턴스가 절대 둘 이상이 될 수 없도록 해준다. 객체 인스턴스가 여러개 생기면은 의도하지 않은 버그가 생긴다.

        public으로 지정된 생성자가 없고 private로 지정되어 있다.

        인스턴스가 필요하면 반드시 클래스 자신을 거쳐야 하며, 어디서든지 그 인스턴스에 접근할 수 있어야 한다.

        싱글턴 인스턴스를 요청할 때에는 getInstance라는 정적 메소드를 사용한다.

     3. Singleton Pattern의 다이어 그램

 

        4. Singleton Pattern의 구성

            ㄱ. uniqueInstance 클래스 변수에 싱글턴의 유일무이한 인스턴스가 저장된다.

            ㄴ. getInstance() 메소드는 정적 메소드, 즉 클래스 메소드이다. 언제 어디서든 이 메소드를 호출 할 수 있다.

                 전역변수에 접근하는 것만큼이나 쉬우면서도 게으른 인스턴스 생성을 활용할 수 있다.

            ㄷ. 일반적인 클래스를 만들 때와 마찬가지로 다양한 데이터와 메소드를 사용할 수 있다.

        5. Singleton Pattern과 동기화

            멀티 쓰레드 환경에서는 객체가 한개 이상 생성 될 수 있다. 멀티 쓰레드 환경에서 객체가 한개 이상 생성되는 것을

            방지하기 위해 동기화(Synchronized)를 사용한다. 하지만 동기화 방식을 사용하면 불필요한 오버헤드만 증가시킨다.

            멀티 쓰레드를 사용하는 애플리케이션에서는 속도와 자원 문제를 파악해보고 적절한 구현법을 사용해야 한다.

            인스턴스를 필요로 할 때 생성하지말고, 처음부터 만들어서 해결하는 방법도 있다.

   

  //전역변수와 지역변수

  전역변수 : 프로그램 전반에 걸쳐 사용 할 수 있는 변수

    - 함수 외부에서 선언되어 모든 함수에서 사용할 수 잇다.

    - 프로그램이 실행될 때 메모리가 할당되며 프로그램이 종료되어야 메모리에서 소멸된다. - 유통기한

    - 초기화 하지 않으면 0으로 자동 초기화 된다.

 

   지역변수 : 사용할 변수가 함수 내부에서 선언되어 일정 영역의 ( ) 안에서만 사용할 수 있는 변수

    - 함수나 일정영역 내에서 선언된다.

    - 함수가 종료되면 메모리에서 소멸된다. - 유통기한

    - 매개변수도지역변수에 포함된다.

    - 초기화 하지 않으면 쓰레기 값을 갖는다.

 

    * 전역변수와 같은 이름의 지역변수는 자신의 영역에서 전역변수보다 우선이다.

 

//Entity Info

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription

                                          entityForName:@"Fugitive" inManagedObjectContext:managedObjectContext];

//NSEntityDescription : 검색을 실행하는 테이블을 가르키는 SQL 스테이트문에서의 'FROM~' 부분에 해당

[request setEntity:entity]; //문자열로 엔티티를 지정한다. 여기서는 @"Fugitive"

 

//Sort Descriptor

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

//NSSortDescription : 'SELECT ~' 나 'order~' 에 해당. 검색 결과가 알파펫 순으로 정렬.

NSArray *sortDescroptors =[[NSArray alloc] initWithObjects:sortDescriptor, nil];

[request setSortDescriptors:sortDescriptors];

[sortDescriptors release];

[sortDescriptor release];

 

//매니지드 오브젝트 컨텍스트에게 NSFetchRequest 를 실행하라고 요청하는 것입니다.

   결과는 배열로 돌려달라고 요청할 것이며, mutableCopy 메소드로 객체를 복사하였으므로, 사용 후에는 릴리스 합니다.

NSError *error;

NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest : request error:&error] mutableCopy];

if (mutableFetchResults == nill){

    // Might want to do something more serious....

    NSLog(@"Can't load the Fugitive data!");

}

[mutableFetchResults release];

[request release];

 

 

위 예문은 구현파일(.m)의 viewWilAppear:메소드에 들어가는 것이 좋다.

검색 결과는 배열에 저장되어서 넘어오지만, 우리는 이 배열을 바로 릴리스 합니다.

뷰 컨트롤러가 이 배열을 리테인해서 유지해야 한다.

이 데이터를 실제로 보여주기 위해서는 배열에서 데이터를 가져오도록 cellForRowAtIndexPath 메소드를 구현해야 한다.

//TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testcell"];

  화면을 스크롤 할때 반드시 한쪽 방향으로 셀이 사라지게 된다. 그럼 그 셀을 다시 불러다 데이터만 바꿔 씌어져 보여준다.

  
      

 

 

 

 

 

 

-----------------------------------------------------------------

NSManagedObject : 생성된 프로퍼티에 대한 저장 및 메모리 관리를 수행 및 프로퍼티 구현

NSManagedObjectModel : 데이터베이스의 구조

NSManagedObjectContext : 데이터 베이스 파일내의 데이터 전체의 집합체

NSPersistentStoreCoordinator : 데이터 베이스 파일에의 입출력관계를 처리

NSFetchedResultsController : NSManagedObjectContext 로 부터 테이블 뷰에 데이터를 표시하기 좋게 데이터를 가공해 주는

                                          CoreData 형식의 데이터와 테이블 뷰와의 다리 역활을 해주는 것

 

- Fetch 란 SQL 스테이트 문을 실행을 의미

 

NSFetchRequest : SQL 스테이트문

NSEntityDescription : 검색을 실행하는 테이블을 가르키는 SQL 스테이트문에서의 'FROM~' 부분에 해당

NSSortDescription : 'SELECT ~' 나 'order~' 에 해당


'개발 > App Developer' 카테고리의 다른 글

디버깅과 코드 분석  (0) 2010.08.30
Xcod 4의 반가운 새로운 기능 두 가지  (0) 2010.08.30
기본적인 상호작용  (0) 2010.08.30
사용자 인터페이스  (0) 2010.08.30
자동회전과 자동크기 조절  (0) 2010.08.30