Skip to content

Module‐Bible README.md

YangSeungHyun edited this page Apr 18, 2025 · 1 revision

디비 동시성 문제

https://dev-with-precious-dreams.tistory.com/300

  • 위 문제를 겪었음. 그래서 DAO에서 rootQueue를 통해서 sync하게 처리하려구함.

  • Sqlite3 오픈 소스인 GRDB같은 경우엔 내부적으로 synchronization처리를해서 동시 접근해도 내부적으로 serial 처리함.

  • 난 그냥 Sqlite3이니까.. 직접 해주어야 함.

  • 이 마저도 어차피 DAO를 서로다른 Repository에서 객체로 만들어서 사용하면 동시성 문제가 생기니까 Swinject 등록할 때 inObjectScope(.container) registration factory에 이거 추가했음. 앞으로 추후 디비 개발할 때도 이거 참고바람.

    [BibleAssembly 말이야!]

  • BibleSearch같이 여러 곳이 아닌 독립적으로 사용될 DAO는 task synchronization 처리 안함

검색 기능

  1. 약어 + chapter:verse or 약어 + chapter verse
  • 약어로 등록된 단어들은 전부 약어와 chapter, verse를 검색하여 특정한 verse를 바로 찾을 수 있는 기능 | e.g. 창세기 1장 1절 or 창 1:1 or 창세기 1:1
  1. query + *와일드카드로 일반적으로 사용자가 검색하는 단어들의 조사를 포함해서 폭 넓게 verse를 찾을 수 있도록 함
  • qeury보단 신뢰성을? 높이고자 좀 더 정확한 정보를 찾을 수 있게 조사까지 포함하도록 함
  1. 페이징 기능
  • 페이지가 더 이상 없을때는 0 or pageSize보다 낮은 verse를 반환함

주의할 점

1.

sqlite 디비에서 꺼내오는 bible은 BibleCode임 ( 문자열 ) 그래서 꼭! BibleBook(code:) 이거로 초기화 해야함. 사용하려면

2. 문자를 바인드할 때 아래와 같이

  let bookCString = (book as NSString).utf8String
  sqlite3_bind_text(statement, 1, bookCString, -1, nil)
  
  이렇게 cstring으로 변환해야함 안그러면 
  
  ? 위치에 '내용' 이 형식이 안될 수 있음

MccCheyne Reading Plan

맥체인 성경 읽기는 매일 4개 파트를 읽어야 한다. 즉 4개 챌린지라고 할 것이다. 하루에 도전해야할 챌린지는 4개! 내부적으로 저장할 때 day, book, chapter 를 primary key로 지정했다.

데이터를 day별로 받아올 때 무조건 해야할 것은 book column을 기준으로(Set -> Key로 만들던가) 딕셔너리로 만들어서 group 지어야 한다. 그 이유는 다음과 같다.

챌린지를 표시하기 위해 생각해야 할 경우는 다음과 같다.

Case 1 [ 편안하게 일반적인 경우 ]

Specific chapter를 4장 읽는 경우 ( 파트 4개 - 각각 1개의 chapter )

Case 2 [ 한 챌린지에서 두 장 이상을 읽어야 할 경우 ]

( day, book, chapter, verseStartNumber, verseEndNumber , alreadyRead) (9, '01', 9, NULL, NULL, 0) (9, '01', 10, NULL, NULL, 0)
(9, '40', 9, NULL, NULL, 0) (9, '15', 9, NULL, NULL, 0)
(9, '44', 9, NULL, NULL, 0)

이때 보면 창세기는 두 개 저장되어 있다. 특정 day를 전부 fetch 할 때 일단은 book을 set으로 해서, key로 group 지어야한다. 파트별로 읽어야할 chapter가 1장 이상일 수 있기 때문이다.

이 경우에는 "(Biblebook(code: "01").name)" + 9 ~ 10" 이렇게 하자. 만약 day별로 group지었을 때 3장 이상이면 first, last chapter로 표기하도록 하자.

Case 3 [ 한 챌린지에서 특정 구간의 verse를 읽어야 할 경우 ]

( day, book, chapter, verseStartNumber, verseEndNumber , alreadyRead) (45, '01', 47, NULL, NULL, 0)
(45, '42', 1, 1, 38, 0) (45, '18', 13, NULL, NULL, 0)
(45, '46', 1, NULL, NULL, 0)

이때는 읽어야 할 파트별로 각각 1 chapter만 읽으면 되는데, 여기서 verseStartNum, endNum 이렇게 지정된 경우가 있다.

이때 챌린지 표시는 book name chapter: startNumber: endNumber

Case 4 [ 한 챌린지에서 2장 이상의 chapter를 읽어야 하고 verseStart, End 가 정해져 있는 경우]

(59, '02', 11, 1, 12, 0)
(59, '02', 12, 1, 28, 0)
(59, '42', 14, NULL, NULL, 0)
(59, '18', 29, NULL, NULL, 0)
(59, '46', 15, NULL, NULL, 0)

이 경우다. 이때는 딕셔너리에서 배열로 그룹짓구,, 딕셔너리 특정 book key 에 대한 배열이 2개 이상이라면 그 시작, 끝을 찾아서,

book name + firstElement.chapter: firstElement.verseStartNumber ~ lastElement.chapter: lastElement.verseEndNumber

이렇게 챌린지 네임을 표기하면 된다.

  • 그니까.. 일단 그룹지어야하구, 그렇게 그룹 지어서 4개 group으로 만들어야만 이제 챌린지 indexPath 로 재사용 큐에서 서 데이터 주입할 때 이렇게 위에 처럼 단일화? 직렬화? 한줄로된 scope를 넘기면 된다.
  • 이제 상세 바이블 컨텐츠 화면으로 넘어가야 할때는 마찬가지로 indexPath.item을 받게되면, 그 item에 대응되는 book key를 찾고, book key를 소유한 배열이 여러개라면 그 중 가장 낮은 chapter, 마지막 chapter들 두 개만 데이터를 얻어두면 된다.

DailyReadingBiblePlan

  • 삭제 대신 alreadyRead = false, date = nil로 하자.
  • 사용자가 한번 읽었다 취소했다는 것은 언젠가 읽을 가능성 있다는 것으로,,(삭제보단 toggle)
  • 어차피 checked chapters fetch 할 때 내부적으로 where문 거침.

DB 모델링 -> 디비는 됨

이제 유저디폴츠에서 간단하게, bibleBook 별로 몇장 읽었는지 저장 ㄱㄱ 그리고 전체 읽은 개수 가져오기는 이제 book 이거 key로해서 value들 전부 더하면됨 : )

alreadyRead = true를 db에 insert할 때마다 유저디폴츠에 관련된거 값도 1 씩 업데이트 하자 !!


추후에 거의 모든 Date를 디비에 저장할 땐 yy-mm-dd hh-mm-ss 말고

  • 1970 년 sec로 변환하자.

Bible Reading Garden Log and hitmap

  • hitmap은 Core에 있음.
  • log은 여기에,,