안드로이드 데이터베이스(DB) 프로그래밍 1. [관계형 데이터베이스] (Android Database 1) [Relational Database]
1. 데이터베이스 (Database, DB)
안드로이드 앱에서 사용자 데이터를 저장하고 로드하는 경우는 매우 흔한 일입니다. 앱 실행 중 메모리에 저장된 데이터는 앱의 실행이 종료되면 모두 사라지기 때문에, 앱의 실행 여부와 관계없이 유지되어야 하는 데이터는, 영구적 보관이 가능한 저장소에 저장을 해두어야 데이터가 삭제되는 것을 방지할 수 있죠.
이를 위한 방법은 여러 가지가 있습니다. SharedPreferences를 사용하여 앱의 설정 정보와 같은 간단한 데이터를 보관하는 방법, 파일 입출력 API를 통해 기기의 저장소(storage)에 데이터를 직접 읽고 쓰는 방법, SQL을 사용하여 로컬 데이터베이스에 데이터를 관리하는 방법, 인터넷을 통해 연결된 서버와 데이터를 주고받는 방법 등, 다양한 방법으로 데이터를 저장하고 저장된 데이터를 읽어올 수 있습니다.
위에서 나열한 방법 중 어떤 것을 사용할 것인지는, 앱에서 관리할 데이터의 크기와 형식, 범위, 그리고 각 방법의 장단점을 고려하여 결정할 수 있습니다. 하지만 그 중 가장 범용적이고, 보편적인 방법을 사용해야 한다면, 데이터베이스를 사용하여 데이터를 관리하는 방법을 선택할 수 있습니다.
데이터베이스를 사용하면, SharedPreferences의 키-값(key-value) 저장 형식의 한계점 극복, 파일 입출력 방법의 저장 형식 설계에 따른 복잡성 해소, 서버 통신 방법에서 요구되는 서버 구축 비용 절감 등의 장점을 획득할 수 있죠.
물론, 데이터베이스의 동작을 이해하기 위한 개념 학습, 데이터베이스에 저장될 데이터를 위한 스키마 구조 설계에 대한 고민, 데이터베이스에서 값들을 읽고 쓰기 위해 사용되는 SQL에 대한 사용법 숙지 등, 다른 방법들에 비해 비교적 선행적으로 준비해야 할 내용들이 많기는 합니다. 그러나 한번 익혀두면 큰 변화없이 지속적으로 활용할 수 있는 내용들이므로, 데이터베이스를 접하는 초반의 생소함만 극복하면, 프로그램 개발에 쉽게 적용할 수 있습니다.
1.1 데이터베이스 관리 시스템(Database Management System, DBMS)
데이터베이스를 만들고, 데이터를 저장하거나 관리할 수 있도록 만들어주는 소프트웨어를 데이터베이스 관리 시스템(DBMS)이라고 하는데, 현재 제품으로 출시된 데이터베이스 관리 시스템(DBMS, Database Management System)은 그 종류가 매우 다양합니다. Oracle, Mysql, MS-SQL, SQLite 등 개발자라면 누구나 한번 쯤은 이름을 들어본 적 있을 유명한 데이터베이스 시스템이 출시, 판매되고 있죠.
어떤 데이터베이스 관리 시스템(DBMS)을 사용할 것인지는 데이터베이스 관리 시스템에서 제공되는 기능과 데이터 처리 용량, 사용 편의성, 기능 확장성, 시스템 복잡성, 소요 비용 등의 여러 요소를 고려하여 선택할 수 있는데, 다른 프레임워크에 비해 성능과 용량 측면에서 제약이 존재하는 안드로이드에서는 기본적으로 SQLite를 사용합니다.
2. SQLite. (www.sqlite.org)
SQLite(www.sqlite.org)는 서버 단위에서 대용량 데이터를 처리하기 위한 용도보다는, 단일 응용 프로그램에서 비교적 적은 용량의 데이터를 처리하는데 적합한 데이터베이스 관리 시스템(DBMS)입니다. 즉, 안드로이드 앱과 같은 소규모의 프로그램에서 데이터베이스 관리가 필요한 경우 사용하기 적합한 데이터베이스 관리 시스템이죠.
SQLite를 사용하기 위해서 별도의 복잡한 시스템, 서비스, 프로그램이 요구되지 않습니다. 단지 SQLite를 위한 API 함수를 호출하는 것만으로 데이터베이스를 위한 기능을 사용할 수 있으며, 데이터베이스 API를 통해 관리되는 모든 데이터는 하나의 파일에 저장됩니다. (그래서 SQLite의 데이터베이스를 백업하는 작업은 하나의 데이터베이스 저장 파일을 복사하는 것으로 끝납니다.)
3. 안드로이드에서 SQLite를 사용하기 전 준비 사항.
안드로이드에서 SQLite를 사용하기 위해 기본적으로 알아야 할 내용은 당연히 SQLite를 다루는 클래스에 대한 구조와 API 함수들의 사용법입니다. 하지만 그 전에, 데이터베이스에 대한 기본 개념과 구성 요소 그리고 데이터베이스의 데이터를 관리하는데 사용되는 SQL(Structured Query Language) 등을 알아둘 필요가 있습니다.
물론, 데이터베이스에 대한 개념과 이론을 설명한 문서에는 매우 방대한 내용이 포함되어 있습니다. 모든 내용을 제대로 이해하고 습득하려면, 몇 일이 걸릴지, 몇 달이 걸릴지 알 수 없을만큼 많은 내용을 포함하고 있죠. 그리고 만약 여기서 그 모든 내용을 설명하려면, 공간도 한참 부족할 뿐더러, 원래 설명하려고 했던 안드로이드에서 데이터베이스를 다루는 내용 따위는 안드로메다로 날아가 버릴 수도 있습니다.
그래서 여기서는 아주 조금, 데이터베이스에 대한 개념을 맛 볼 수 있는 정도만 설명하겠습니다. 조금 더 깊고 상세한 내용들은 데이터베이스와 관련된 전문 서적이나, 앞으로 보여드릴 여러 예제들을 통해 습득하시길 바랍니다.
4. 관계형 데이터베이스(Relational Database)
안드로이드에서 기본적으로 제공하는 SQLite는 관계형 데이터베이스 관리 시스템(Relatinoal Database Management System, RDBMS)의 한 종류입니다.
4.1 관계형 데이터베이스에서 데이터 구조화하기.
관계형(Relational) 데이터베이스에서는 데이터베이스 내에 데이터를 저장할 때, 데이터들이 공통적으로 포함하는(그리고 논리적 구분이 가능한) 속성들을 식별한 다음, 각 데이터를 앞서 식별된 속성에 해당하는 값들로 나열하여 저장합니다. 음, 설명이 좀 어렵죠? 이해를 돕기 위해 한 가지 예를 들어보겠습니다.
과일을 판매하는 과일 가게를 떠올려보죠. 과일 가게에는 아래 그림과 같이, 종류가 다른 과일들이 각각의 바구니에 담겨져 있습니다.
고객의 요구사항은, "가게에 남아 있는 과일의 종류가 어떤 것인지, 종류 별로 몇 개가 남아 있는지를 관리하는 것"입니다. 이 정보를 저장할 때 관계형 데이터베이스를 사용한다면, 데이터베이스에 데이터가 구조화되는 과정은 아래와 같습니다.
4.1.1. 저장하고자 하는 데이터가 공통적으로 가지는 속성 식별하기.
먼저, 데이터가 가지는 공통 속성을 식별해야 합니다. 앞서 한 문장으로 기술된 요구사항에 적혀 있듯이 "1.과일의 종류"와 "2.남은 갯수"를 데이터가 가진 공통적인 속성이 될 수 있죠. 그리고 속성을 식별하고 나면, 속성들을 가로로 나열합니다.
4.1.2 데이터들을 속성에 해당하는 값들로 나열하기.
속성이 식별되고나면, 다음 단계는 각 데이터를 속성에 해당하는 값들로 나열하는 것입니다. 이 때 데이터는 세로 방향으로 나열합니다.
속성의 식별과 속성에 따른 데이터 나열이 완료되면 아래 그림과 같이 테이블 형태의 구조가 완성됩니다.
4.1.3 속성 식별 과정에서의 주의사항.
속성의 식별은 데이터베이스의 데이터 구조화 과정에 있어 가장 중요한, 그리고 데이터베이스 전체 용량을 결정하는 가장 중요한 요소입니다. 그래서 속성을 식별하는 과정에는 몇 가지 주의가 필요합니다.
먼저, 속성은 그 값의 크기와 관계없이 데이터들에 공통적으로 포함되는 것이어야 합니다. 만약 위의 과일 가게 관리 예제에서 "다리 갯수"라는 속성을 식별했다고 가정해보죠. 모든 과일은 다리를 가지고 있지 않으므로 "다리 갯수"라는 속성은 전혀 의미가 없는 속성입니다.
다음, 속성의 값들은 논리적 구분이 가능해야 합니다. 만약 위의 예제에서, "식물", "동물" 등으로 구분되는 "생물 분류"를 공통 속성으로 식별했다고 가정해보죠. 분명 데이터가 가지는 공통 속성임에는 분명하지만, 모든 데이터가 "식물" 값을 가지게 되어 논리적 구분이 불가능하죠. 즉, 모든 데이터가 같은 값을 가지므로 의미없는 속성이 되는 것입니다.
또 한가지, 속성은 데이터베이스를 사용하는 곳에서 기능적으로 유의미해야 합니다. 예제에서, 추가적으로 과일의 "색상" 속성을 추가해보죠. "색상" 속성은 모든 과일이 공통적으로 포함하고 있고, 각 과일은 저마다의 색을 가지고 있기 때문에, 논리적 구분도 가능합니다. 그런데 새롭게 구분된 "색상"은 요구사항에 적용되지 않는 속성입니다. 즉, 속성을 식별하고 값을 채운다고 해도 전혀 사용되지 않습니다. 과일 종류 별 남은 갯수를 관리하는 게 유일한 목적이기 때문에, "색상"은 무의미한 속성이 되는 것입니다.
4.2 관계형 데이터베이스 용어
앞선 단계에서, 관계형 데이터베이스에서 데이터를 속성과 데이터 값으로 구조화하면 2차원 표 형태의 구조가 만들어지는 것을 확인하였습니다. 속성은 가로 방향으로, 데이터 값은 세로 방향으로 나열되었죠. 이렇게 데이터들을 속성에 따라 값으로 나열한 2차원 표 형태를, 관계형 데이터베이스에서는 "관계(Relation)"라고 부릅니다. 즉, 관계형 테이터베이스에서 데이터를 구조화한다는 것은, 속성과 그 데이터 값들의 "관계(Relation)"를 찾아내고 그것을 표 모양의 구조로 도식화하는 것이라고 볼 수 있는 것입니다.
하지만 "관계(Relation)"라는 용어는, 설명을 아무리 쉽게 해도 그 의미가 쉽게 전달되지 않습니다. 데이터베이스와 관련하여 범용적으로 사용되지 않은 용어라서 더욱 그럴텐데요. 그래서 일반적으로 "관계(Relation)" 대신 2차원 표 모양에 기인한 "테이블(Table)" 이라는 용어가 더 익숙하게 사용됩니다.
그리고 관계형 데이터베이스의 "속성(Attribute)" 또한, (행/열에서 '열'을 의미하는) "컬럼(Column)" 또는 "필드(Field)"라는 용어로 더 자주 사용됩니다. 세로로 나열되는 데이터의 값은 관계형 데이터베이스 이론에서는 "튜플(Tuple)"이라는 용어로 불리지만, 이 역시, 일반적인 경우에 (행/열에서 '행'을 의미하는) "로우(Row)" 또는 "레코드(Record)"라는 용어로 더 많이 사용됩니다.
여러 용어들이 혼재되어 좀 헷갈릴수도 있습니다. 하지만 관계형 데이터베이스 이론에서 정의하는 용어인 "속성(Attribute)", "튜플(Tuple)" 등은 일반적인 상황에서는 잘 사용되지 않으므로 개념적으로만 알아두시고, "컬럼(Column)" 또는 "필드(Field)", "로우(Row)" 또는 "레코드(Record)" 등의 용어가 더 범용적으로 사용된다는 것을 기억해두시기 바랍니다.
4.3 데이터베이스 스키마(Schema)
앞서 설명한 범용 용어를 사용하여 데이터베이스 구조화를 정리하면, 관계형 데이터베이스에 데이터를 저장하기 위한 가장 기본이 되는 단위는 테이블(Table)이며, 테이블(Table)은 컬럼(Column)과 로우(Row)로 구성되어있습니다.
그래서 개발자가 데이터베이스를 사용하여 데이터를 저장할 때 첫 번째로 해야 할 일은, 관리하고자 하는 데이터의 공통 속성을 식별하여 컬럼(Column)으로 정의하고 테이블(Table)을 만드는 것입니다. 일단, 테이블이 만들어지면 새로운 데이터를 추가할 수 있고, 추가된 하나의 데이터는 하나의 로우(Row)로 삽입됩니다.
그런데 데이터베이스 내에 하나의 테이블만 만들어 사용하는 경우는 거의 없습니다. 물론 요구사항이 매우 단순한 경우라면 테이블 하나에 관리하고자 하는 모든 정보를 저장할 수 있겠지만, 대부분의 경우 하나의 테이블만으로는 고객의 요구사항을 만족시키기 힘들죠. 때론 구조의 복잡도에 따라 수십 개 또는 수백 개의 테이블이 만들어지기도 합니다.
자, 여기서 한 가지 궁금한 점이 생기는데요, 데이터 저장의 가장 기본 단위인 테이블과 (여기서 설명하지 않지만) 인덱스, 뷰, 권한 등과 같은 데이터베이스 요소들은 데이터베이스 내부에서 어떻게 만들어지고 관리되는 것일까요? 음, 구체적인 구현 방법은 정확히 알 수 없지만, 데이터베이스 내부에서 관리되는 요소들은 개념적으로 스키마(Schema)라는 것으로 관리됩니다.
스키마(Schema)라는 단어가 꽤 낯설긴 하지만, 그 의미를 정의해보자면, "데이터베이스의 테이블 구조 및 형식, 관계 등의 정보를 형식 언어(formal language)로 기술한 것"을 의미합니다. 즉, 스키마는 데이터베이스의 설계도 역할을 수행하며, 테이블, 인덱스, 뷰 등의 구조에 대한 모든 정보를 가진 것을 말하죠.
스키마(Schema)가 데이터베이스의 설계도와 같은 역할을 수행하고, 형식 언어(formal language)로 기술된다는 것은 데이터베이스 관리에 있어서 상당한 이점을 제공해줍니다. 하나의 데이터베이스 스키마(Schema)를 가지면, 다른 시스템에 똑같은 데이터베이스를 만들 수 있다는 것이니까요. 하지만 이를 데이터베이스 백업과 혼동해서는 안되고, 단지 동일한 구조의 데이터베이스를 새로 생성할 수 있다는 의미입니다.
음, 스키마(Schema)에 대해 설명하지 못한 내용이 훨씬 더 많지만, 이것 또한 여기서 다룰 내용은 아닌 듯 하네요. 좀 더 자세한 내용은 관계형 데이터베이스 관련 전문 서적을 참고하시기 바랍니다.
4.4 SQL(Structured Query Language)
SQL(Structured Query Language)은 관계형 데이터베이스 관리 시스템에서 데이터를 관리하기 위해 사용되는 표준 프로그래밍 언어(Language)입니다. 데이터베이스 스키마 생성 및 수정, 테이블 관리, 데이터 추가, 수정, 삭제, 조회 등, 데이터베이스와 관련된 거의 모든 작업을 위해 사용되는 언어이므로, 관계형 데이터베이스를 다루기 위해서는 필수적으로 알아야 할 언어입니다.
SQL이 프로그래밍 언어이긴 하지만 Java 또는 C 언어처럼 프로그램을 개발하기 위한 목적이 아닌, 데이터베이스를 관리하기 위해 사용되는 특수 목적 언어입니다.
SQL은 대화식으로 동작합니다. 즉, 하나의 기능을 수행하면 실행 결과를 확인한 다음 다른 기능을 실행하는 형태로 동작하는 것입니다. 예를 들어 테이블에 데이터를 추가하고 조회하는 경우, INSERT 명령으로 시작되는 SQL 문장을 실행하고 그 결과가 리턴되면, 그 다음 데이터 조회를 위한 SELECT 명령을 실행할 수 있습니다.
SQL에 정의된 명령어의 종류는 크게 세 가지로 나뉩니다. 이는 명령어가 사용되는 목적 및 대상에 따라 분류되며, 데이터 정의 언어(DDL, Data Definition Language), 데이터 처리 언어(DML, Data Manipulation Language), 데이터 제어 언어(DCL, Data Control Language)가 바로 명령어의 세 가지 종류입니다.
데이터 정의 언어(DDL, Data Definition Language)는 말 그대로 데이터의 구조를 정의하는 것을 말합니다. 테이블(TABLE), 인덱스(INDEX), 트리거(TRIGGER) 등의 개체를 만들고 관리하는데 사용되는 명령들이 데이터 정의 언어에 속하며, CREATE, ALTER, DROP 등이 있습니다.
DML 명령 | 설명 |
---|---|
CREATE | 테이블(TABLE), 인덱스(INDEX) 등의 데이터베이스 개체 생성. |
ALTER | CREATE로 생성된 테이블, 인덱스 등의 데이터베이스 개체 수정. |
DROP | CREATE 명령으로 생성된 데이터베이스 개체 삭제. |
[SQL-예제] 데이터 정의 언어(DDL) 사용 예.
/* CREATE 명령으로 FRUITSHOP_T 테이블 생성. */
CREATE TABLE FRUITSHOP_T (NAME TEXT NOT NULL, COUNT INTEGER) ;
/* ALTER 명령으로 FRUITSHOP_T 테이블에 새로운 컬럼(COLUMN) 추가. */
ALTER TABLE FRUITSHOP_T ADD SIZE INTEGER ;
/* DROP 명령으로 FRUITSHOP_T 테이블 삭제. */
DROP TABLE FRUITSHOP_T ;
데이터 조작 언어(DML, Data Manipulation Language)는 데이터 정의 언어로 생성된 개체(테이블 등)에 데이터를 추가하거나, 수정, 삭제, 조회 등의 기능을 수행할 때 사용합니다. 주로 사용되는 명령에는 INSERT, UPDATE, DELETE, SELECT 등이 있습니다.
DML 명령 | 설명 |
---|---|
INSERT | 테이블(Table)에 하나 이상의 데이터 추가. |
UPDATE | 테이블(Table)에 저장된 하나 이상의 데이터 수정. |
DELETE | 테이블(Table)의 데이터 삭제. |
SELECT | 테이블(Table)에 저장된 데이터 조회. |
[SQL-예제] 데이터 조작 언어(DML) 사용 예.
/* INSERT 문을 사용하여 FRUITSHOP_T 테이블에 데이터 추가. */
INSERT INTO FRUITSHOP_T (NAME, COUNT) VALUES ('apple', 2) ;
/* UPDATE 문으로 FRUITSHOP_T 테이블 데이터 수정. */
UPDATE FRUITSHOP_T SET COUNT=3 WHERE NAME='apple' ;
/* DELETE 명령으로 FRUITSHOP_T 테이블의 데이터 삭제. */
DELETE FROM FRUITSHOP_T WHERE NAME='apple' ;
/* SELECT 명령으로 FRUITSHOP_T 테이블의 데이터 조회 */
SELECT * FROM FRUITSHOP_T ;
데이터 제어 언어(DCL, Data Control Language)는 데이터를 다루는데 있어 권한을 설정하거나, 데이터의 무결성 처리 등을 수행하는데 사용되는 언어입니다. GRANT, BEGIN, COMMIT, ROLLBACK 등이 이에 속합니다.
DCL 명령 | 설명 |
---|---|
GRANT | 데이터베이스 개체(테이블, 인덱스 등)에 대한 사용 권한 설정. |
BEGIN | 트랜잭션(Transaction) 시작. |
COMMIT | 트랜잭션(Transaction) 내의 실행 결과 적용. |
ROLLBACK | 트랜잭션(Transaction)의 실행 취소. |
[SQL-예제] 데이터 제어 언어(DML) 사용 예.
/* GRANT 명령을 사용하여 FRUITSHOP_T 테이블 권한 설정. */
GRANT ALL ON FRUITSHOP_T TO PUBLIC ;
/* COMMIT 멸영으로 트랜잭션 실행 결과 적용. */
BEGIN TRANSACTION ;
INSERT INTO FRUITSHOP_T (NAME, COUNT) VALUES ('banana', 3) ;
INSERT INTO FRUITSHOP_T (NAME, COUNT) VALUES ('orange', 5) ;
COMMIT TRANSACTION ;
/* ROLLBACK 명령으로 트랜잭션 취소. */
BEGIN TRANSACTION ;
DELETE FROM FRUITSHOP_T ;
ROLLBACK TRANSACTION ;
5. 참고.
- 안드로이드 개발 Training - SQL 데이터베이스에 데이터 저장
- [SQL 데이터베이스에 데이터 저장]을 참고하세요.
- SQLite - SQL Syntax
- [SQLite - SQL Syntax]을 참고하세요.
.END.