BOID

[iOS] sqlite3 간단 구현해서 뽀시기~! - HoonIOS 본문

IOS 시작기

[iOS] sqlite3 간단 구현해서 뽀시기~! - HoonIOS

HoonIOS 2021. 6. 4. 11:31

안녕하세요, HoonIOS입니다.

저번에는 sqlite3에 대해 간단하게 설명하고 어떻게 흐름을 진행해야 하는지 포스팅을 했었습니다.

<DBMS에서 SQLite3란?>

 

이번에는 간단한 테이블을 만드는 방법으로 한번 구현을 해보겠습니다.

 

 sqlite3 구현하기

 

1. 제일 먼저 프로젝트 정보에서 Build Phases -> Link Binary With Libraries에서 libsqlite3을 추가해주겠습니다.

 

2. 이제 위에서 +버튼을 눌러주고 sqlite를 검색해서 추가해줍니다.

 

 

3. sqlite 라이브러리는 C형태로 되어 있으므로 브릿지 헤더 파일을 만들어 이 프로젝트와 라이브러리를 연결해줘야 합니다.

 

 

4. 브릿지 파일의 이름을 정해주겠습니다.

 

 

- 브릿지 파일의 이름을 정할 때 웬만해서는 프로젝트명-SQLite3-Bridging-Header.h로 정해주는 게 좋습니다.

다르게 적어도 되는데 이렇게 적는게 추후 유지 보수하기가 편하다고 합니다. ( 꼼꼼한 재은 씨 책에서 참고했습니다. )

 

5. Build Settings의 All의 Combined에서 Objective-C Bidging Header로 가서 경로를 설정해 줘야 합니다.

* 설명

  • 프로젝트 안에 파일이 있으므로 프로젝트 이름 / 헤더파일 이름 => 이런 식으로 설정을 해주면 됩니다.

6. 브릿지 파일에 가서 sqlite3 라이브러리를 import 시켜주겠습니다.

 

 

7. VC파일에 가서 sqlite3의 역할을 하는 db_sqlite3( OpaquePoiner)와 sqlite3_stmt( OpaquePointer ) 역할을 하는 변수를 지정해 주겠습니다.

 

 

8. FileManager() 객체를 생성하겠습니다.

 

※ FileManager() 객체란?

- 애플 공식 문서에서는 파일 시스템의 콘텐츠를 편하게 상호작용하기 위한 수단이라고 나와 있습니다.

- 파일을 찾거나 삭제 복사를 할 때 유용하게 사용하는 객체입니다.

* 설명

  • DOC_path변수를 보면 파일 매니저의 urls함수는 url을 가져오는 것으로 앱 내의 디렉터리에서 딕셔너리 경로를 찾는 함수입니다.
    첫 번째 매개변수는 무엇을 찾을지, 두 번째 매개변수는 찾는 범위가 해당합니다.

9. 위의 경로에서 해당하는 데이터베이스 경로를 만들어주겠습니다.

 

* 설명

  • . appendingPathComponent("파일")을 통해서 url로 얻어진 경로에서 파일에 해당하는 경로를 추가해 ~~~/db_practice라는  데이터베이스 경로를 만들어 주었습니다.
  • 이렇게 return 한 값을 URL객체 타입이므로 문자열 타입으로 변환을 해야 하는데 이때 path를 통해 문자열 타입으로 반환이 되게 하는 것입니다.

10. sql문을 작성해주겠습니다.

* 설명

  • 테이블을 생성할 것이므로 create를 사용해줬습니다.
  • HoonIOS테이블을 생성해 줄 것인데 테이블이 존재하지 않을 때만 생성을 하고 이미 존재했을 때는 create를 하지 않게 해 주기 위해 if not EXISTS라는 조건을 넣어줬습니다.
    (매번 테이블이 생기면 한 디비에 데이터가 겹치는 일이 생겨 원래 있던 데이터가 날아갈 위험이 있습니다.)
  • num, age의 integer칼럼병을 만들어주고 둘 다 int타입으로 지정을 해주었습니다.

11. 이제 DB에 연결해서 이 SQL문까지 반영을 하는 과정을 구현해주겠습니다.

* 설명

  • 앞 포스팅에서 나열을 했던 과정이지만 다시 한번 살펴보겠습니다.
  • sqlite3_open() 메서드를 호출해 DB_path에 있는 DB에 연결을 해줍니다. 이때 db연결 정보가 담긴 db_sqlite3 객체가 생성됩니다.
  • sqlite3_prepare()메서드를 통해 전달할 SQL 구문 객체를 컴파일을해 생성해 줍니다.
  • sqlite3_step() 앞에서 만든 컴파일된 SQL구문 객체를 DB에 적용을 합니다.
    이 과정을 통해서 SQL구문 객체를 생성해 DB에 적용을 하므로 테이블이 생성되는 부분입니다.
  • sqlite3_finalize() 컴파일된 SQL 구문을 삭제하고 db_sqlite_stmt를 메모리에서 해제합니다.
  • sqlite3_close() 메서드를 통해서 DB 연결을 해제해줍니다.

여기서 sqlite3_open의 &는 참조값을 가져오는 것으로 해당 변수의 주소 값을 가져오는 거라고 생각을 하시면 됩니다.

 

sqlite3_finalize, sqlite3_close의 순서를 헷갈리시면 안 됩니다. 즉 안에 있는 거부터 메모리를 해제하고 밖에 있는 것을 메모리 해제해야 됩니다. 순서가 바뀌면 오류가 발생을......ㅠㅠ

viewDIdLoad에서 해주는 것이 싫다면 init()을 통해 연결을 해주고 deinit()으로 디비 연결을 해제하는 방식으로 해줘도 됩니다.

 

 

이렇게 디비 연결을 하고 SQL컴파일하고 해제하는 과정까지 다 했지만 사실 이 방법은 틀렸습니다. 왜냐하면 디비 연결을 실패했는데 sqlite3_prepare() 구문이 실행이 되면 안 되기 때문이죠

 

12. 따라서 각 조건마다 성공을 했을 때 구현을 할 수 있도록 작성을 해야 됩니다.

* 설명

  • sqlite3_open 하고 sqlite3_prepare메서드를 성공하면은 SQLITE_OK라는 값을 반환합니다. 따라서 이에 맞게 조건을 걸어줘야 되지만 slqite3_close() 위치를 보면 sqlite3_open이 이미 성공을 해 연결이 되어 있으면 sqlite3_prepare메서드가 성공을 하든 말든 이미 연결이 되어 있으므로 연결 해제를 해야 합니다. 따라서 sqlite_prepare조건절 안에 넣지 말고 아예 밖에서 구현을 해줬습니다.
  • 비록 여기서는 if로 구현을 해줬지만 guard구현을 해주셔도 상관없습니다. 가독성은 guard가 더 좋기 때문에 guard 하시는 게 좋습니다.
  • 만약 연결을 실패했을 때 SQLITE_ERROR, SQLITE_INTERNAL, SQLITE_PERM 등등 다양한 에러코드가 발생을 합니다.

    더 다양한 에러코드와 발생 이유를 알고 싶다면 https://runebook.dev/ko/docs/sqlite/rescode 에서 확인을 해보시면 좋을 것 같습니다.

13. 객체를 다 DB에 연결을 하고 SQL객체도 생성을 하였으니 적용을 해야 합니다.

 

* 설명

  • sqlite3_step을 통해 커밋한 sql을 디비에 적용을 해야 합니다.
  • 여기서 또 주의를 하려 할 부분이 SQL객체를 해제하는 것이 중요합니다. 왜냐하면 SQL객체는 디비에 적용하는 것을 성공을 했든 실패를 했든 이미 SQL객체가 생성이 되어 있기 때문입니다. 이 객체의 메모리를 해제를 해야 디비 연결을 해제하기 때문이죠

    따라서 if 조건절 안에 넣는 것이 아니라 밖에다가 무엇을 하든 코드를 타게 구현을 해주시면 됩니다.

14. 이제 실행결과를 살펴보기 전에 경로를 저장해 줄 DB경로를 설정해줬는데 이 경로는 임의의 설정으로 되어 있기 때문에 어디에 설정되었는지 몰라 print를 찍어줘야 합니다.

 

 

15. 콘솔 창에 결과를 보겠습니다.

 

* 설명

  • 경로가 나온 것을 확인할 수 있습니다.
  • DB Succeess로 로그도 찍히는 걸 보아 잘 생성이 되어 ㅆ네요

16. 해당 경로로 가서 확인해보겠습니다, 터미널로 들어간다음 cd ~ 경로를 통해 들어가 open. 을 실행을 하면 현재 위치에 있는 파일을 finder에서 열게 됩니다.

 

17.  잘 나와있네요 

 

 

18. 이제 DB툴로 안에 있는 데이터가 맞게 들어갔는지 확인해보겠습니다.

* 설명

  • 테이블 이름 HoonIOS로 num, age의 칼럼 값이 integer로 들어가는 것을 확인할 수 있습니다.

 

이렇게 sqlite3로 디비를 만들어 봤습니다.

혹시 select를 사용해 조회를 하실 거면 sqlite3을 쓰는거보다 이 sqlite3를 기반으로 만든 FMDB가 있으니 그것을 사용하는 것을 추천드립니다.

 

sqlite로 구현하기가 많이 힘들다고 하네요!

반응형
Comments