관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 10. FMDB 데이터베이스 (기본) 본문

iOS 실전 (swift)/데이터베이스

[iOS - swift] 10. FMDB 데이터베이스 (기본)

jake-kim 2020. 5. 9. 22:15

* libsqlite3는 swift 아키텍쳐 전용의 데이터 타입을 지원하지 않음

  대신에 objectibe-c로 sqlite3를 재구성한 FMDB사용하는 것이 유리

 

1. FMDB란?

 macOS/iOS용으로 개발된 오프소스 SQLite3라이브러리

 

가장 중요한 메인 클래스 세 가지

 - FMDatabase : 하나의 SQLite 데이터베이스를 나타내는 객체 (SQL문 실행할 때 사용)

 - FMResultSet : FMDatabase 인스턴스를 통해 수행된 SQL의 처리 결과를 담는 객체

 - FMDatabaseQueue : FMDatabase의 한 종류로 SQL구문의 멀티 스레드 실행을 지원 (SQL구문을 동시에 여러 개 실행하고 싶을 때

                                     FMDatabase대신 사용)

 

2. FMDB 세팅

1) libsqlite3.tbd를 프로젝트에 추가

2) xcode에서 git hub주소를 이용해서 FMDB라이브러리 파일 다운

 Source Control -> Clone...

FMDB 주소 입력

http://github.com/ccgus/fmdb 

clone버튼 

 

3) fmdb파일만 이용하려는 프로젝트 파일에 드래그앤 드롭

4) fmdb는 오브젝트-c로 작성되어 있으므로 브리지 헤더 추가, 임포트

#import "FMDB.h"

 

-> 브리지 헤더 파일 경로를 target, "swift compiler - General"에서 설정

 

* 브리지 헤더에 추가하는 방법

 

5) fmdb파일에서의 info.plist파일 제거

(기존 파일의 info.plist와 이름이 중복 되므로 파일 제거)

2. DBMS에 전송된 SQL구문의 처리 과정

1) 구문분석(Parsing) : SQL구문의 문법과 의미가 정확한지 검사하는 단계

 - 이상이 없다면 내부캐시 검사 -> 발견시 바로 실행(excute), 최적화와 컴파일 과정 건너 뜀

 

2) 최적화(optimizing) : DB에 내장된 Optimizer가 테이블 구조, 데이터 크기, 저장 공간, 리소스 등을 고려하여 최적화

 

3) 컴파일(compliation) : 테이블 액세스 방법, 정렬, 필터 등을 위한 실행 계획이 "Tree"구조로 생성 후 "cache"에 저장(재사용을 위함)

  (바이너리 코드이므로 .exe, .dll등의 파일이 아니기 때문에 메모리에 빠르게 올라감)

 

4) SQL 실행(Execute)

 

* prepared statement(선처리 상태)의 장점 : 미리 SQL템플릿을 1)~3)단계까지 수행 후 이 정보를 cache에 저장 -> "?"자리에 값만 들어가므로 저장된 이 값을 재사용 가능 (hash탐색)

 

※ Prepared Statement보다 Statement방식이 빠른 경우

- 최적화 단계(2)번에서 실제 데이터 분포에 대한 히스토그램 데이터를 활용할 수 없다는 점

- 단발성 쿼리의 경우 DBMS에 대한 추가 왕복 작업으로 인해 불필요한 리소스가 소비될 수 있는 점

   (Stetement방식은 SQL문을 DBMS에 전송하여 한번에 실행하지만, Prepared Statement는 SQL문을 전송한 다음 인자값을 추가로 DBMS에 다시 전송)

 

3. 프로그래밍

1) DB connection & open

        // viewDidLoad()
        /// DB 접근
        let db = FMDatabase(path: <#T##String?#>)
                
        /// DB open
        guard db.open() else {return}

 

2) SQL execution

 - SQL은 두 가지(갱신하는 문과 select문)

 (갱신하는 로직은 Bool형을 리턴, select문은 FMResultSet을 리턴)

        /// 1) update (INSERT INTO), 핵심은 true or false리턴
        do {
            let sql = "INSERT INTO department (depart_title, depart_addr) VALUES(?, ?)"
            try db.executeUpdate(sql, values: ["인사팀", "301호"])
            return true
        } catch let error as NSError {
            print("Insert Error : \(error.localizedDescription)")
            return false
        }
        /// 2) SELECT
        /// SELECT SQL -> executeQuery() -> 성공시 FMResultSet자료형 반환
        do {
            let sql = "SELECT depart_id, depart_title FROM department WHERE depart_id > ?"
            let rs = try db.executeQuery(sql, values: [2]) /// prepared statement 방ㅂ(sql문에 '?'로 선처리된 구문 사용)
            
            where rs.next() {
                let depart_id = rs.int(forColumn: "depart_id")
                let depart_title = rs.string(forColumn: "depart_title")
                
                /// 칼럼 이름을 모를 땐, 칼럼 인덱스로 접근
                // let depart_id = rs.int(forColumnIndex:)
                // let depaprt_title = rs.string(forColumnIndex:)
                
            }
        } catch let error as NSError {
            print("failed: \(error.localizedDescription)")
        }

 

* 실제로 위 코드를 사용하여 실습해보는 것은 아래 링크 참고

www.ios-development.tistory.com/88

 

Comments