티스토리 뷰

Frontend/iOS

Core Data와 Database의 차이점

데니 Denny 2020. 2. 18. 09:41
반응형
SMALL

Apple 공식 문서에 따르면 Core Data는 Database가 아니라고 명시되어 있습니다.

Core Data와 Database 모두 영속적인 저장소를 제공하는 방법이므로 구체적으로 어떤 차이점을 갖고 있는지는 명확하지 않습니다.

이번 포스트에서는 Core Data가 동작하는 방식을 살펴보면서 어떻게 Database와 다른지 살펴보도록 하겠습니다.

 

 

데이터베이스(DB)의 주된 기능

데이터베이스(DB)는 영속적이고 검색 가능한 테이블 형태의 구조로써 Column과 Row로 구성된 데이터 저장소라고 할 수 있을 것입니다.

이 저장소의 주된 목적은 Disk에 항상 최신의 데이터를 저장하는 것이며, 데이터를 불러오고 업데이트를 하는 것이 그 다음으로 중요한 목적일 것입니다. 이러한 주된 기능들을 훨씬 넘어서는 고급 데이터베이스들이 많이 존재하고 있지만, 대부분의 개발자들이 사용해보고 익숙한 SQLite Style의 데이터베이스(DB)가 가지는 핵심 기능들을 살펴보도록 하겠습니다.

 

비록 많은 데이터베이스들이 관계형(RDB)이라고 불리지만, SQLite와 많은 다른 관계형 데이터베이스들은 실제로 객체들의 직접적 연결을 다루지는 않습니다. 테이블간의 Column / Row 에 관한 관계를 유지하는 것은 데이터베이스를 사용하는 사용자가 해야합니다. 이러한 관점에서 데이터베이스는 “멍청한(dumb)” 저장소라고 할 수 있습니다. 테이블의 열(rows)을 다룰 경우 읽기/쓰기 이상의 동작이 거의 전부이고 이를 확장하거나 커스터마이징하기 위해서는 결국 데이터베이스 시스템 자체를 확장하게 될 수밖에 없습니다. 트리거(trigger)기능이 지원되더라도 프로그램 가능한 범위는 제한될 수 밖에 없습니다.

Core Data의 주된 기능

Core Data의 주는 Object Graph Manager라고 할 수 있습니다. 이는 Life Cycle, 영속성, Search기능을 가지고 있습니다.

- Core Data는 서로 다른 객체들과 연결할 수 있습니다.

즉, 객체 A를 객체 B와 연결할 수 있으며, 해당 연결은 영속적으로 동기화가 됩니다. 객체 A에서 내용을 변경하는 등의 연결을 변경하게 되면, 객체 B가 업데이트 되면서 그에 따른 알림(notification)을 발생시키게 됩니다.

- 한 쪽에서 객체를 삭제할 경우 연결을 타고 cascade 삭제가 일어나도록 할 수도 있고, nullify 시켜서 해당 객체만 삭제할 수도 있습니다.

- 연결된 객체가 로딩되는 순간에 바로 연결에 접근한 것이 아니라면, 연결의 반대편에 있는 객체가 out of memory (faulted) 상황에 빠져있을 수도 있습니다.

 

보통의 데이터베이스들과는 다르게 코어데이터는 완전한 인메모리(in-memory) 형태로 사용이 가능합니다. 일반적으로 사용자들이 영속성 특성을 대부분 사용하기 때문에 코어데이터가 “객체 영속성(object persistence)” 프레임워크라고 불리지만, 실제로는 어떠한 형태의 영속성도 지니지 않은 in-memory형태로 사용하는 것이 가능한 것입니다.

(코어데이터는 명시적으로 저장 명령(save)을 내릴때까지 디스크에 저장하지 않습니다.)


즉, 코어데이터를 사용할때 “영속성”이 의무적인 기능이 아니라는 것을 알아두는 것이 중요합니다.

또한 코어데이터를 어떠한 형태의 검색기능 없이도 사용이 가능합니다. 우선 객체들이 할당되고 연결되었을 경우, 한 객체에만 접근이 가능하다면, 추가적인 Fetch 작업 없이 해당 객체로부터 나머지 연결된 객체들을 타고 넘어가면서 접근이 가능합니다. 일단 데이터들이 메모리에 로딩되면, 연결고리를 따라 이동하는 것은 검색 없이도 가능하기 때문에 코어데이터가 이러한 비검색(seachless) 특성을 갖게되는 것입니다.

 

모든 코어데이터 객체들은 완전히 인스턴스화된(fully instantiated) Objective-C 객체이며 속성값과, 관계, 라이프사이클을 관리하는 것이 가능합니다. 이것은 또한 객체들의 속성들(property)과 동작들이 메서드(method)에 의해 구현될 수 있음을 의미하며, 이러한 메서드들은 서브클래싱을 통해 옵저브와 오버라이드가 가능하다(observable & overridable).

 

Core Data Stack

데이터베이스(DB) vs. 객체 그래프 관리 (Object Graph Manager)

데이터베이스와 코어데이터의 객체 그래프 관리자 기능은 완전히 배타적인 관계는 아닙니다. SQLite에서는 기본적으로 외래키(foreign key)가 지원되지 않지만, MySQL 등의 다른 데이터베이스 들은 여러 테이블들에 대해 identifier들을 관리하여 관계가 설정된 레코드들간의 싱크를 맞출 수 있으며 심지어 cascade 삭제 또한 가능합니다. 즉 오버라이드 가능한 객체들을 이용하여 코드를 작성하는 커스터마이제이션은 불가능하지만 기본적인 수준의 관계 관리는 가능하다는 의미로 볼 수 있습니다.

 

코어데이터의 모델과 비슷한 다른 객체 관계 프레임워크들이 존재하긴 하지만 대부분 원자성(atmomicity)을 보장하며, 트랜잭션(transaction)기반의 데이터베이스들입니다.

이런 프레임워크들이 객체 그래프를 업데이트 하기 위해서는 다음과 같은 절차를 따릅니다.

 

데이터베이스로부터 적절한 레코드 행(row)을 불러온다.
이러한 레코드들로부터 객체 인스턴스를 생성한다.
인스턴스화되어 메모리상에 존재하는 그래프 객체들을 수정한다.
수정된 내용들을 다시 데이터베이스에 반영(commit) 한다.

원자성을 보장하기 위해서는 위의 4가지 절차가 하나의 트랜잭션으로 수행되어야 합니다. (즉, 트랜잭션이 진행중일때는 다른 읽기/쓰기 작업이 레코드에 영향을 주면 안된다는 의미입니다.) 이러한 원자성 보장이 요구되는 시스템들도 있긴하지만, 이 방법은 일반적인 객체 그래프 시스템에 대해 적용할 경우 성능이 저하될 수 밖에 없습니다.

따라서 더 일반적인 객체 관리 시스템을 위해 설계된 코어데이터는 더 나은 성능과 유연성을 위해 이 모델을 따르지 않습니다.

인메모리(In-Memory) DB vs. 디스크(On-Disk) DB

실제 코어데이터의 소스코드에 접근할 권한이 없기 때문에 완벽하게 내부적인 동작을 알 수 없지만, NSManagedObjectContext가 힙(heap)에 존재하는 객체 인스턴스들 혹은 나중에 다시 접근 가능한 형태의 구조화된 컨테이너(structured container)들을 트래킹(tracking)하고 있을거라 추측할 수 있습니다.

 

이러한 코어데이터의 트래킹 구조는 인메모리(in-memory) 데이터베이스와 비슷하게 동작하지만 인스턴스화된 객체들을 트래킹하는 특징을 가집니다. 또 한 가지 주목할 점은 중앙집중적인 NSManagedObjectContext NSManagedObject인스턴스들을 다루기 위해서 NSManagedObject 포인터에게 메시지를 보내는 방식을 사용한다는 점입니다.

 

코어데이터는 처리속도를 위해 이러한 인메모리(In-Memory) 방식에 초점을 맞추고 있습니다. 객체 그래프의 변화로인해 연결된 여러 객체들이 수정될 필요가 있을 때, 모든 객체들이 메모리에 이미 올라와있으면 훨씬 빠르게 작업이 가능하다 (데이터베이스에서 해당 내용을 Retrieve 하는 것은 속도가 느릴 수 밖에 없죠.).

 

Disk에 영속적으로 저장될 필요 없이 임시 내용을 담는 객체가 필요한 경우, 데이터베이스에 비해 코어데이터가 훨씬 빠른 속도로 객체를 생성 / 수정 / 변경이 가능합니다. SQlite의 경우 관련 인덱스와 B-tree의 노드를 업데이트해야 하기때문에 속도가 더 느리게 됩니다. 코어데이터가 수 초동안 수백만 개의 객체들을 생성 가능한데 반해, SQLite가 수백만 개의 객체 생성을 하려면 분 단위의 시간이 걸립니다.

 

인메모리 방식의 코어데이터를 사용하더라도 실제로 데이터의 영속성을 위해 저장소(backing store)로 SQLite를 많이 사용하게 됩니다. (실제로 코어 데이터 파일도 sqlite로 끝나는 파일이죠.)

 

이 경우 Disk에서 읽기/쓰기를 할때의 SQLite의 기본적인 오버헤드에 코어데이터와 SQLite 간의 컨버전을 위한 오버헤드가 추가되서 느려지는 단점이 존재합니다.

Core Data 실제 파일과 인 메모리 작업 과정

데이터베이스(DB)에서는 할 수 있지만 Core Data가 하지못하는 작업

Core Data가 데이터베이스(DB)에 비해 좋은 점들도 있지만, 반대로 부족한 점들도 존재합니다.

Core Data는 데이터를 메모리에 로딩하는 과정 없이는 작업이 불가능하다.

SQL Statement에서 DROP TABLE을 하거나 레코드를 업데이트하기 위해서 “DROP person” 이나 “UPDATE person SET age = 26 WHERE name = 'hong'” 명령이 이용됩니다. 명령 처리를 위해서 각 레코드에 해당하는 작은 크기의 데이터만 메모리에 로드를 하면 되기때문에, 데이터의 양이 많더라도 효율적으로 업데이트가 가능합니다.


하지만 Core Data는 메모리상의 객체를 수정하는 것 만 가능하기 때문에 이러한 온디스크(on-disk) 방식의 사용이 불가능합니다. 심지어 Core Data는 객체를 삭제 할 때도, 일단 인스턴스화 한 다음 메모리에 로드를 먼저 해야 삭제가 가능합니다. 객체에 추가적으로 오버라이드된 동작들이 로드되고 실행되기 위해서, 그리고 다른 객체와의 연결정보를 최신으로 유지하기 위해서는 사전의 메모리 로딩 작업이 필수가 될 것입니다. 따라서 Core Data에서 많은 객체를 수정할 경우 다음과 같은 방법들을 사용하여 Memory Footprint를 최소로 유지할 필요가 있습니다.

refreshObject:mergeChanges:메서드를 이용하여 주기적으로 변하지 않은 객체들을 해제
NSFetchRequest사용시 setIncludesPropertyValues:NO 설정을 이용하여 객체의 전체데이터를 불러오는 것을 피하기
전체 컨텍스트를 저장한 후, 로드되어 있던 모든 객체들을 릴리즈

코어데이터는 데이터 로직을 다루지는 않는다.

SQL에 존재하는 저장되는 데이터를 제약할 수 있는 “unique” key 같은 기능이 Core Data에는 포함되지 않습니다.

Core Data로부터 생성된 모델 클래스를 상속받아서 사용할경우, Core Data의 attribute에대해 getter/setter를 오버라이드 할 수 있다보니 Core Data 입장에서는 이것이 unique key 인지 아닌지 알 수가 없습니다. 결국 이러한 제약조건(Constraint)들이 Core Data에서 제어가능한 도메인 밖에 있다보니 모델에 적용하려면 직접 비지니스 로직상에서 따로 구현해야 합니다.

( Data Fetch 과정에서 이미 존재하는 데이터인지 Iteration을 통해 알아보는 방법 등)

멀티스레드(Multi-threaded), 멀티유저(multi-user) 시나리오

Core Data는 Multi Threading을 지원하지 않습니다. SQLite 또한 Single Threading만 지원하지만, 다른 데이터베이스들은 Multi Threading, Multi User를 지원합니다.


일반적으로 Thread를 위한 락(lock) 기법(ex. Semaphore, Mutex 등)을 사용 하지 않을 경우 프레임워크는 훨씬 빠르고 심플하게 구현될 수 있으며 Single User 환경(PC / iPhone 등)에서 발생할 수 있는 일반적인 시나리오들을 충분히 실현 가능하기 때문에 Core Data는 Multi Threading을 제공하지 않습니다. 하지만 여전히 특수한 경우에는 Multi Thread를 이용하여 데이터를 읽어올 필요가 있습니다.

 

NSManagedObject NSManagedObjectContext의 경우는 Single Thread에서만 접근이 가능해야 하므로, 만약 다른스레드가 같은 데이터에 대해 접근해야 한다면 기존 스레드에서 데이터를 저장 한 후, 다른 스레드에서 새로운 NSManagedObjectContext를 이용하여 데이터를 읽어들여야 한다.

 

이번 포스트에서는 Core Data와 데이터베이스의 차이에 대해 정리해보았습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
LIST
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
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 26 27 28
글 보관함