물론 회사다닐 때는 있어야하긴 하는데..... 뭐 재밌으면 괜찮을 것 같다.
주말에도 작업을 계속 해야할만큼 분량이 많아서 적을 수 밖에 없다.
현재 우리 게시판의 DB 구조는 이렇게 되어있다.
한개의 게시글에는 다양한 종류의 태그를 가지고 있고 그것을 바탕으로 검색을 하려는 목적으로 설계를 해놓았는데
이게 크게 발목을 잡게 되었다.
그것은 바로 비동기의 문제였다(....)
심지어 아직도 해결 안되고 1단계정도만 해결이 된 상태이다.
현재 진행중인 게시글의 등록 로직은 아래와 같다.
이러한 과정을 사용해서 태그에 대한 정보 또한 되돌려주는 구조로 구현을 해놓은 상태이다.
문득 생각해보면 차라리 NoSQL로 했으면 조금 더 좋지 않았을까 라는 생각도 든다. 뭐 아무튼
어떤 문제점이 존재하냐면, 2번에서 새로운 정보를 저장하고 그 정보를 3번에서 긁어와야하는데
비동기의 구조가 조금 문제가 있어서 정보를 저장하기 전에 가져오는 불상사가 생기고 말았다.
이것을 어떻게 해결을 해야할까 고민을 하다가 일단 TypeORM의 save() 기능은 바로 버렸다.
왜냐하면 TypeORM save()는 실제로 확인을 해보면 두번의 쿼리가 발생한다는 것을 볼 수 있는데
다른 말로 하면 상대적으로 느리다는 말이라서 속도를 최대한 빠르게 하기 위해서는 안된다고 생각하여
바로 CreateQueryBuilder로 넘어가게 되었다.
얘는 rawQuery라서 1번으로 작업이 가능해서 일단 변경을 했는데
그래도 안됐다. 겁내 빨라서
별 짓을 다 해보았다. 왜냐하면 이유는 분명하게 조회를 0.2초라도 느리게 하면 해결이 될 것이라고 판단이 되었기에
setTimeOut()까지 넣어보고 별 짓을 다해봤는데 되질 않았다.
그렇다고 반복문을 돌리기엔 자존심이 허락하질 않았다(....) 굳이? 배운게 있는데 느린 길을 가는건 조금..
원래 구조는 Promise.all + map의 구조를 가지고 있었는데
Promise.all은 돌아가고 있는 것 자체의 종료 시점을 빠르게 해준다는 것은 있지만
속에서 작동하는 것들을 보장해주지 않기 때문에 문제가 발생하고 있던 것이였다.
게다가 map은 병렬처리와도 비슷해서 지멋대로 시작하다보니 정말로 너무 빠르게 실행이 되서
문제가 발생했다.
그래서 뭐를 해볼까 하다가 map과 비슷한 역할(따지면 아니긴한데)을 하는 reduce로 코드를 돌려봤는데...
해결됐다.
도무지 이해가 되지 않아 형한테 한번 물어봤더니
map은 지멋대로 돌아가지만
reduce는 결국 순서가 존재하기 때문에 map에 비해서는 코드가 늦게 종료된다. 라는 대답을 듣게 되었다.
아무튼 생성에 대한 문제는 해결이 되었고
이제는 검색에 대한 문제를 해결하면 게시판에 관련된 것들은 모두...모두 작업이 끝나게 된다...^^....
관계라는 것이 너무 재밌고 코드 짜는 것도 즐겁긴 한데 참....
await Promise.all([ boardTagMenu.map(async (el: string) => { const data: Promise<object> = new Promise(async (resolve, reject) => { const menu = el.substring(1); const menuData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagMenu: menu }) .getOne(); if (menuData) { console.log(menuData); resolve(menuData); } else { const data = await getConnection() .createQueryBuilder() .insert() .into(BoardTag) .values({ boardTagMenu: menu }) .execute(); const identifiers = data.identifiers[0].boardTagId; const menuData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagId: identifiers }) .getOne(); board_Tags.push(menuData); resolve(menuData); } board_Tags.push(data); return data; }); }), boardTagRegion.map(async (el: string) => { const data: Promise<object> = new Promise(async (resolve, reject) => { const region = el.substring(1); const regionData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagRegion: region }) .getOne(); if (regionData) { console.log('난 바보다'); resolve(regionData); } else { const data = await getConnection() .createQueryBuilder() .insert() .into(BoardTag) .values({ boardTagRegion: region }) .execute(); const identifiers = data.identifiers[0].boardTagId; const regionData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagId: identifiers }) .getOne(); console.log('난 천재다'); board_Tags.push(regionData); resolve(regionData); } board_Tags.push(await data); return data; }); }), boardTagTogether.map(async (el: string) => { const data: Promise<object> = new Promise(async (resolve, reject) => { const together = el.substring(1); const togetherData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagTogether: together }) .getOne(); if (togetherData) { console.log(togetherData); resolve(togetherData); } else { const data = await getConnection() .createQueryBuilder() .insert() .into(BoardTag) .values({ boardTagTogether: together }) .execute(); const identifiers = data.identifiers[0].boardTagId; const togetherData = await getConnection() .createQueryBuilder() .select('boardTag') .from(BoardTag, 'boardTag') .where({ boardTagId: identifiers }) .getOne(); board_Tags.push(togetherData); resolve(togetherData); } board_Tags.push(await data); return data; }); }), ]);