-
[LokiJS] 나의 삽질 후기programing/Language 2020. 5. 21. 23:06
안녕하세요, Einere입니다.
(광고 차단 기능을 꺼주시면 감사하겠습니다.)
LokiJS
개인 토이 프로젝트를 진행하다가 데이터를 저장해야 해야 할 필요가 생겼습니다. 그런데 저는 따로 서버를 구현하고 싶지 않았습니다. (AWS 프리티어도 만료되었슴..) 그래서 client-side in-memory DB를 라이브러리를 찾다가, LokiJS라는 라이브러리를 찾게 되었습니다.
LokiJS is a document oriented database written in javascript, published under MIT License. Its purpose is to store javascript objects as documents in a nosql fashion and retrieve them with a similar mechanism. Runs in node (including cordova/phonegap and node-webkit), nativescript and the browser.
뭐 대충 보자면 mongo DB와 비슷하게, 도큐먼트 기반 DB라고 합니다. 여러가지 잡다한 기능이 있지만, 사실 그렇게 큰 기능을 바라지는 않았습니다. 할 일 정보만 잘 저장하고 불러오면 충분했기 때문이죠.
왜 안돼지..??
프로젝트에 LokiJS를 설치하고 할 일에 대한 CRUD기능을 구현하면서 DB를 이용하는 코드도 작성했습니다.
const updateTodoItem = useCallback((newTodoItem: Todo.TodoInfoTypeForUpdate) => { const copiedTodoInfos = deepCopy<Todo.TodoInfoType[]>(todoInfos); const indexForUpdate = copiedTodoInfos.findIndex((todoInfo) => todoInfo.id === newTodoItem.id); const todoItemForUpdate = makeTodoInfo(newTodoItem); copiedTodoInfos[indexForUpdate] = todoItemForUpdate; setTodoInfos(copiedTodoInfos); todoDB.findAndUpdate({ 'id': { '$eq': newTodoItem.id } }, (data) => { return { ...data, ...todoItemForUpdate }; }); db.saveDatabase(); }, [todoInfos, db, todoDB]);
코드 윗 부분은 리액트 컴포넌트의 상태를 갱신하는 코드이며, 아래 부분이 LokiJS를 이용해서 특정 도큐먼트를 갱신하는 코드입니다.
이후, 로컬에서 테스트를 해보니 도큐먼트가 전혀 갱신되지 않았습니다. 😳
공식 문서를 찾아보자
혹시나 싶어 공식 문서를 찾아봤습니다.
음.. 첫번째 인자는 object맞고, 두번째 인자도 function으로 맞는데.. 뭐가 잘못된거지?
수 많은 삽질
혹시라도
find()
가 제대로 작동하지 않는가 싶어,console.log()
를 이용해서 찍어 봤습니다.음.. 제대로 잘 찾는 것 같습니다. 그런데 왜 DB 갱신이 안되는지 아직도 이해를 하지 못했습니다.
공식 문서를 더 봐도 딱히 도움이 되는 게 없어서 코드를 직접 보기로 했습니다.
우선 현재
filterObject
는 함수가 아니라 객체이므로, else문이 실행되겠군요.다시 한번
find()
가 잘 작동하는지 체크해봅니다.로그가 좀 길긴 하지만, 변경전의 데이터입니다.
그럼 이제
update()
가 잘 작동하는지 체크해봅니다.확인 결과, 하단의 console.log()가 있는 부분이 실행 흐름이었습니다.
한번 로그를 볼까요?
놀랍게도 완전하게 동일합니다.
title
을foo1
로, content를bar1
로 변경했지만 전혀 의도대로 동작하지 않습니다.그런데 불현듯 무언가가 제 머리를 스치는 느낌이 들었습니다.
다시 한번 코드를 자세히 보니..
Mutable!
updateFunction
의 반환값을 전혀 사용하지 않고 있으며,rcd[this.filteredrows[idx]]
를 그대로update()
의 인자로 넘겨주고 있습니다...😳리액트를 하느라 immutable에 익숙해진 저로써는 정말 경악을 금치 못할 코드입니다..
"에이 저게 뭐 그리 대수인가?" 싶을 수 있지만, 진짜 대수입니다.
todoDB.findAndUpdate({ 'id': { '$eq': newTodoItem.id } }, (data) => { data = { ...data, ...todoItemForUpdate }; });
updateFunction
의 매개변수인data
에 새로운 객체를 할당했습니다. 이 경우, 바깥의rcd[this.filteredrows[idx]]
는 전혀 영향을 받지 않습니다. 따라서data
에 새로운 값을 할당하지 않으면서 갱신해야 됩니다.todoDB.findAndUpdate({ 'id': { '$eq': newTodoItem.id } }, (data) => { data.title = todoItemForUpdate.title; data.content = todoItemForUpdate.content; data.dueTime = todoItemForUpdate.dueTime; });
제 경우는 단순히 속성 3개만 갱신하면 되지만, 만약 갱신이 필요한 속성이 수십, 수백개라면 어떨까요? 생각만 해도 끔찍합니다.. 😱
심지어 더 골때리는건, 비슷한 역할을 하는 다른 함수에는 정상적으로 반환값을 사용하고 있습니다... 😡
후기
당연하게 콜백 함수의 반환값을 사용하겠지..라는 안일한 생각때문에 꽤나 고생했습니다만, 그래도 라이브러리를 왜 이렇게 만들었는지 이해하기는 좀 어렵습니다. (심지어 일관성도 없음..)
적어도 공식 문서에 예시 코드라도 나와 있었다면 이렇게 헤메지는 않았을텐데 말이죠..
그래서 LokiJS 저장소에 이슈를 올렸습니다.
그런데 메인테인이 안된지 꽤 되어 보여서, 반응이 올지 안올지 모르겠네요.
'programing > Language' 카테고리의 다른 글
[JS] input 태그에 한글 입력 막기 (5) 2020.08.02 [ESLint, Airbnb] import/extensions 규칙 설정하기 (0) 2020.06.28 [React] 함수형 컴포넌트와 훅 (0) 2020.05.18 [React] 클래스형 컴포넌트의 생명주기 (0) 2020.05.18 [TS] d.ts 파일 작성시 이모저모 (0) 2020.05.17 댓글