일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- AWS
- 게임
- typeORM
- nestjs
- jest
- Nest.js
- MongoDB
- MySQL
- GIT
- Bull
- Sequelize
- Python
- TypeScript
- OCR
- game
- Express
- 공룡게임
- 자료구조
- 정렬
- Dinosaur
- react
- flask
- Queue
- dfs
- cookie
- mongoose
- JavaScript
- nodejs
- class
- Today
- Total
포시코딩
3월 4주차 - 스파르타 내일배움캠프 19주차 본문
이번 주 알게 된 점
TypeORM
softDelete 데이터 가져오기
softDelete 후 deletedAt 날짜가 추가된 데이터를 제외할 생각만 해봤지
가져올 생각과 상황은 한 적이 없는데
이번에 모임 -> 채팅 기능을 구현하며
새롭게 chat 관련 table을 운용하기 보단 softDelete를 통해
meetup의 데이터를 그대로 쓰면서 chat이라고 지칭하는 아주 깜찍한 아이디어를 채용했다.
그 과정에서 softDelete 된 데이터를 가져오는데에 고생을 좀 했는데
결론만 말하자면
createQueryBuilder()를 사용할 때 아래의 키워드를 사용하면 된다.
.withDeleted()
.where('deletedAt IS NOT NULL')
withDeleted()만 쓸 경우 softDelete된 값과 안 된 값 모두를 가져오며
where('deletedAt IS NOT NULL')만 쓸 경우
TypeORM에서 deletedAt이 not null 인 값을 자동으로 제외하고 있기 때문에
찾지 못해 빈 배열만 반환하게 된다.
때문에 둘 다 같이 써야 원하는 softDelete 된 값을 가져올 수 있다.
whereInIds
TypeORM으로 sub query를 사용할 일이 없다가 이제서야 생겼는데
막상 쓰려고 하니 어떻게 구현해야 될지 감이 안잡혔다.
그냥 raw query를 쓰는 것도 같이 받아야 하는 join된 데이터를 array 형태로 가져와야 해서
그것도 피해야 되는 상황이었다.
아무리 검색해도 안나와서 ChatGPT의 도움을 받아 해결할 수 있었다.
그냥 단순하게 물어본게 아니고
내가 직접 sub query로 사용될 두 쿼리문을 DBeaver에서 테스트해보고
결과를 받는 상황에서
TypeORM을 어떻게 사용하면 좋을지 물어보니 금방 답을 알려주었다.
async getMeetupsWithJoined(userId: number, page: number, keyword: string): Promise<Meetup[]> {
const meetupIds = await this.joinRepository.createQueryBuilder('j')
.select('j.meetupId', 'meetupId')
.innerJoin('j.meetup', 'm')
.where('m.deletedAt IS NULL')
.andWhere('j.userId = :userId', { userId })
.andWhere('m.userId != :userId', { userId })
.getRawMany();
const tempQuery = this.createQueryBuilder('m')
.select([
'm.id',
'm.userId',
'u.email',
'u.username',
'm.title',
'm.content',
'm.place',
'm.schedule',
'm.headcount',
'm.createdAt',
'j',
])
.leftJoin('m.joins', 'j')
.leftJoin('m.user', 'u')
.whereInIds(meetupIds.map((id) => id.meetupId));
if (keyword !== '') {
tempQuery.andWhere('(m.title LIKE :keyword OR m.content LIKE :keyword)', {
keyword: `%${keyword}%`,
})
}
const meetups = await tempQuery
.orderBy('m.id', 'DESC')
.take(this.pageLimit)
.skip((page - 1) * this.pageLimit)
.getMany();
return meetups;
}
결과적으로 사용된 코드는 위와 같다.
해당 과정에서 키워드가 전달될 경우 결과값이 이상한 상황이 있었는데
tempQuery.andWhere('m.title LIKE :keyword OR m.content LIKE :keyword', {
괄호 () 없이 OR을 써서 앞에서 걸러낸 whereInIds가 무색하게 m.content LIKE 만 적용되는 문제였다.
원인을 찾기가 빡셌지 찾고나니 그냥 괄호 씌워주니까 바로 해결된 문제라 허무하긴 했다.
where 안에서 and, or을 쓸 땐 괄호()를 꼭 습관화 하자.
아무튼 whereInIds를 통해 sub query처럼 TypeORM을 다룰 수 있었고
여러번의 DB 요청 없이 단 한 번으로 원하는 데이터를 받아낼 수 있었다.
채팅 기능을 구현하면서 내가 참여중인 채팅에 대해 검색할 때
sub query를 사용하지 못해 멤버 목록을 다 못 불러오는 문제가 있어
멤버 목록을 구현하지 못했었는데
이번에 배운걸 사용한다면 멤버 목록도 채팅방 목록을 가져올 때 포함시킬 수 있을 것으로 보인다.
다음주에 시간날 때 구현해봐야겠다.
Front-End
e.target, e.currentTarget
e.target을 쓸 때
엘리먼트 안에 포함된 쪼그만 엘리먼트를 클릭하면
나는 감싸고 있는 엘리먼트에 대해 클릭한건데
마우스가 클릭한 그 쪼그만 엘리먼트에 대해 이벤트가 발생해버리는 문제가 있었다.
어이없게도 e.target 대신 e.currentTarget을 사용함으로써 금방 해결할 수 있었다.
e.target은 말 그대로 클릭한 그 것 그대로고
e.currentTarget은 이벤트가 바인딩 된 엘리먼트를 나타내기 때문에
부모 엘리먼트를 나타낸다고 한다. 때문에 e.currentTarget을 통해 해결할 수 있었던 것
onKeyUp, onKeyDown
채팅을 쓰면서 엔터를 통해 채팅을 보내는 상황이었는데
이상하게 onKeyUp 함수가 두 번 발동해서
채팅을 보내고 난 다음 채팅창에 썼던 채팅을 지웠는데
input에 텍스트를 써야 채팅을 보낼 수 있다는 alert가 실행되는 상황이 있었다.
구글링 하다가 Vue를 쓰는 한국 유저에게서 힌트를 얻을 수 있었는데
맥(!)에서 한글(!)을 쓰는 상황에서 onKeyUp, onKeyDown(!)을 쓸 때 발생하는 버그라고 한다.
React 뿐만 아니라 JavaScript에 옛날부터 존재하는 버그로
한글을 뭔가로 변환하는 과정에서 composing? 상태가 발생하고
229 에러코드가 계속 발생하여 정상적인 함수 작동이 안된다는 것으로 파악했다.
말로만 봐선 그래서 함수 두 번 실행되는 거랑 무슨 상관? 싶겠지만
나와있는 해결 방법을 통해 시도해보니 내 두 번 실행 버그도 해결되었다..
방법은 다음과 같다.
function pressEnterHandler(e) {
if (e.isComposing || e.keyCode === 229) return; // 해결 코드
if (e.key === "Enter") {
console.log('pressEnterHandler 실행');
test();
}
}
두 번째 줄의 코드를 포함시켜 놓으면 그 밑에 작성된 코드가 정상적으로 동작하게 된다.
react 쪽에서 windows 쓰는 다른 팀원이 만든 기능이 제대로 동작 안하는 경우가 가끔 있었는데
다 위의 원인이 문제가 아니었을까 싶다.
(다른 안됐던 상황은 onChange로 작성된 input text의 state 값을 엔터로 배열 state에 저장하는데
'하나' (엔터), '둘' (엔터) 로 저장하면 ['나나', '나'] 이런식으로 저장되는 문제였음)
꽤 오래전 문제였는데도 아직도 안고쳐지고 있고
레거시 되는 기능들은 많은 프론트엔드 쪽 개발자들도 참 고생이겠구나 를 느꼈던 해결과정이었다.
이벤트 버블링
오랜만에 만난 이벤트 버블링 문제.
항상 까먹어서 검색 후 해결하는 문제였는데
이번에도 똑같이 검색 후 e.preventDefault()를 적용하려다가
ChatGPT를 통해
이벤트 버블링을 해결하는 방법에 더 적합한건
e.stopPropagation();
stopPropagation 이라는 것을 알게 되었다.
말 그대로 전파를 멈추는 함수인데 사용했을 때 마찬가지로 이벤트 버블링을 막을 수 있었고
함수의 목적성도 맞는게 딱 이 상황을 위해 만들어진게 아닐까 싶은 함수를 새로 배울 수 있었다.
얼마나 자주 쓸진 모르겠지만
앞으론 기억해놨다 이벤트 버블링 문제가 발생할 때 써야겠다. stopPropagation()!
이번 주 목표 달성
socket.io를 통한 실시간 소통 기능 구현
드디어 벼르고 벼렸던 소켓 통신 기능을 내 손으로 구현할 수 있었다.
처음에 소켓을 통해 채팅 기능을 배우며 따라만 써봤지
직접 기능을 구현할 일이 없어 언제 해보지.. 싶었는데
딱 적용하기 좋은 상황이 생겨 바로 내가 담당하겠다 해서 구현하게 되었다.
nest.js에서 socket.io를 사용하는 방법이 gateway를 통해서라 낯설어 블로그 포스팅의 도움을 많이 받긴 했지만
실제 코딩 시간 약 30시간 정도만에 거의 카톡과 유사한 채팅 기능을 만들어 낼 수 있었다.
채팅 기록이 DB에 저장되어 나갔다 들어와도 유지되고 남이 쓴 것도 보이는..!!
이렇게 이번 프로젝트에 동시성 문제와 더불어 어필할 수 있는 기능이 하나 더 생겨
뿌듯 + 든든함을 동시에 느낄 수 있던 주간이 아니었나 싶다.
구현하면서 어려웠던 점은 딱히 없고
설계 단계에서 생각을 굉장히 많이 해야 됐었는데
어떤 상황에 어디서 어디로 어떤 데이터가 전달되어야 하고
데이터가 최신화 될 때 전달되야 하는 방향이나 데이터의 종류 등을 고려해야 되는 부분들이 있어
구현할 때 머리가 잘 돌아가는 상황에서만 집중해서 했던 것 같다.
소켓 통신이 이루어질 때 마다 디비에 기록을 저장하고 있는데
사용자가 많아지면 괜찮을지도 걱정이고
채팅 하나하나가 RDS에 저장되고 있는데 비용면에서도 과금이 심하지 않을까 걱정되는게 있다.
그래도 처음 구현 치곤 만족스러운 결과물이 나와
앞으로도 더 어려운 소켓 기능을 구현할 일이 생기면 도전해보고 싶은 마음이 생겼다.
확 게임 회사 가버려?
수집한 피드백에 대한 수정 적용
내가 맡은 모임쪽 피드백을 확인했을 때
내가 참여중인 모임을 파악하고 싶다는 의견이 90%는 됐던 것 같다.
모임에 참여중인 멤버 목록에 대한 얘기가 주를 이룰줄 알았는데 의외였고
왜 생각하지 못했지 라는 생각이 들었다. 역시 피드백은 받아봐야 해..
일단 리액트상에서 조건문을 통해
내가 주최, 참여중, 참여불가(다참)에 따른 디자인 구분을 해주었다.
css가 구리긴한데 어쩔 수 없다..
그냥 부트스트랩 기능을 사용했음
그래도 그 전보단 나아진 느낌
매일 WIL 작성
..은 실패..
프로젝트 기간이라 어떤 기능을 구현하게 되면 새롭게 배우더라도 작성하기가 쉽지 않다..
그리고 해당 기능을 구현하는데에 2~3일씩 걸리다 보니 작성하더라도 2~3일 치의 공부량을
하루치로 다 쓰게되니 그만큼 또 쓸 분량이 없어지는 상황
뭐 이래저래 다 핑계고
아마 다음주는 문서 정리 기간이라 더 힘들지 않을까 싶은데
알고리즘 공부라도 해서 TIL 작성거리를 늘려봐야 겠다.
다음 주 목표
- 프로젝트 문서 작업 및 마무리
- 팀원 백업
- 하루 최소 한 문제라도 알고리즘 문제 풀기
- 운동.. 다시 하는거 진지하게 생각해보기
- 집에서 공부 안되면 카페 가서라도 하자
'WIL' 카테고리의 다른 글
3월 3주차 - 스파르타 내일배움캠프 18주차 (0) | 2023.03.20 |
---|---|
3월 2주차 - 스파르타 내일배움캠프 17주차 (0) | 2023.03.13 |
3월 1주차 - 스파르타 내일배움캠프 16주차 (0) | 2023.03.06 |
2월 3주차 - 스파르타 내일배움캠프 14주차 (0) | 2023.02.20 |
2월 2주차 - 스파르타 내일배움캠프 13주차 (0) | 2023.02.12 |