🤠 그룹활동
web21조의 활동
이번 주차의 그룹에서는 저번 그룹 활동과 똑같은 프로그램으로 팀빌딩을 시작했다. 그룹원 들이 다들 잘 하시는 분들 이었고, 다양한 고민거리들을 함께 나누면서 개발에 대해 더 알아갈 수 있었던 것 같다. 우석 님이 특히 너무 웃겼고, 다른 분들도 웃음이 많으셔서 일주일 동안 즐거운 시간을 보냈다.
💳 멤버십 일상
시작부터 불길한 기운??
이번 주차는 개천절과 함께 여유롭게 시작되었다!! 주말 없이 일하다가 저번 주말에 좀 놀았더니 계속 놀고 싶다. 놀고 오면 충전이 될 줄 알았는데, 오히려 집중력이 흐트러진 느낌이랄까. 결국 이번 주말도 똑같이 놀자판 엔딩
평일을 최대한 불 태웠다. 구현과 학습, 코드 리뷰, 그룹 활동 신경쓸 게 너무 많았다. 나만 힘든 줄 알았는데 다른 분들도 똑같았나 보다. 웹풀스택 팀의 전체적인 PR의 양이 많이 줄어들었다. 이번 미션 때 내가 잘한 유일한 것이 있다면 00시에 맞춰 PR 보내는 것을 놓치지 않았다는 점이다. 하지만 빈깡통일 때도.. 결과적으로 기대했던 것만큼 학습과 미션을 많이 수행하지는 못했던 것 같다.
10/3(월) - 전초전
OAuth와 JWT, 그리고 쿠키 삽질을 한 끝에!! 기능을 완성했다!! typeorm은 나를 화나게 만든다... 그냥 SQL 쿼리문 쓰는 게 훨씬 쉬운 거 같은데 착각 탓인가..?
리뷰어 님의 피드백대로 전역 상태 관리가 useState에 굉장히 의존적이었기 때문에 useReducer 형태로 개선해보려 하고 있다. 그런데 useReducer로 삽질을 몇 시간째 하고 있는 건지 모르겠다. 뭘해도 빨간 줄이 사라지질 않는다. 이놈의 typescript... 아예 처음 해보는 거라 맨땅에 헤딩하는 식으로 해결하고 있는데 너무 스트레스 받는다... 시간 여유만 있었다면 타입스크립트만 1~2일 정도 공부하고 싶다.....
결국 any를 사용해서 빨간 줄을 없앴다. 나중에 리뷰어님한테 여쭤봐야할 것 같다. 그런데??? dispatch가 2번씩 실행된다?? 카운터가 하나씩만 올라가는 게 맞는데 2씩 올라간다. 이벤트를 확인해보니 1번씩만 실행된다.. 왜일까..?
10/4(화) - P3 Day6
위 문제를 그룹 활동 때 공유했었다. <React.StrictMode> 로 감싸면 App이 2번씩 실행되기 대문에 reducer도 2번씩 실행됐던 거 였다. 이상하다.. 분명히 이벤트는 1번만 실행됐는데..?? 캠퍼 분들 덕분에 끙끙 앓던 몇 가지 문제들도 함께 고민하고 해결할 수 있어서 좋았다.
10/5(수) - P3 Day7
week4 그룹원 분들과 했던 JWT에 대한 토론이 아직까지도 이어지고 있다. refresh 토큰을 DB에 저장해야할까? 하지 말아야할까? 수빈 님이 리뷰어 님한테 여쭤봤는데 그 답변은 아래와 같다. refresh 토큰을 저장해 검사하는 것이 좋겠다는 생각을 가지고 계셨다.
토큰 관리에 대해서는 실무에서도 항상 논쟁?이 되는 부분입니다. 저는 개인적으로 github OAuth로 구현하였다면 그만큼 로그인을 심플하게 가져가는 의도이기 때문에 굳이 DB에 저장하지 않아도 된다고 생각합니다. 그러나 로그인 및 회원가입을 직접 구현한 서비스라면 refresh 토큰도 DB에 저장하여 관리하는 것이 좋을 것 같습니다. 실무에서는 토큰 관리에 있어 정책들이 존재합니다. accessToken과 refreshToken의 유효기간 및 인증 방법 등 이를 직접 컨트롤하기에는 아무래도 서버에서 저장 및 검사하는 것이 좋지 않을까요?
refresh를 저장해야한다는 승민 님의 의견을 갈무리해 리뷰어 님께 여쭤봤는데 슬랙 DM과 깃허브 PR을 통해 여러 생각들을 전해주셨다. 대충 정리한 내용은 아래 참고 바람! JWT와 보안, 그리고 세션까지 그동안 개발 공부를 하면서 한 문제에 대해 이렇게까지 고민하고 탐구한 적이 있나 싶을 정도로 완전히 JWT에 사로잡혀 있다.
JWT 관리는 정답이 없는 문제라... 제 생각과 다른 분들 생각이 충분히 다를 수 있다고 생각해요. 단순히 제 생각만 말씀드리면, 저는 유저를 식별하는 데 충분하면서도 보안에 '심각한' 문제가 없는 한, 굳이 DB나 캐시에 저장하진 않을 겁니다. 다만 서비스 성격을 봐야 할 거 같아요.
최소한의 보안이란 개념은 정말, 너무 애매한 표현인 거 같아요. 은행에서는 3분 이상 반응이 없으면 자동으로 로그인이 해제되고, 둘 이상의 클라이언트가 로그인하지 못하게 합니다. 우리 서비스에서는 얼마나 체크해야 할까요?
토큰이 있다면 믿어도 될까요? 토큰에 들어있는 userId가 지금 시점에서는 ban 당했거나 삭제된 유저거나 권한이 강등당했거나, 그 외 이유로 사용 불가능해지진 않았을까요?
그래서 사실 질문해주신 부분은 기술적인 문제라기보다, 토큰과 세션은 얼마나 분산됐는가, 중앙화됐는가의, 철학 문제인 거 같아요. 말이 좀 횡설수설한데 사실 보안만 따지면 세션이 무조건 나을 거 같긴 해요
10/6(목) - P3 Day8
뭔가 많이 한 거 같은데, 막상 작업물은 많이 없다. 오전에는 그룹 활동, 리뷰 요청 및 마스터 클래스, 그리고 리뷰어님 특강까지 듣고 나니 하루가 그냥 지나가 버렸다. 집중력이 떨어진 것도 한 몫 했다. 관심사가 많아서 집중이 분산된 느낌이다. 이것도 해야 하고, 저것도 해야 하고 신경써야할 일들이 너무 많다.
마스터 클래스를 들었다. 황준일 마스터님은 JWT를 이용할 때 refresh 토큰을 redis에 저장하는 걸 선호한다고 하셨다. 사람들마다 생각이 다 달라서 혼란스럽다.
10/7(금) - P3 Day9
열심히 해야한다는 생각을 내려놓으니깐 오히려 더 잘 되는 느낌? 뭔가 해야된다는 부담감이 나를 짓누르고 있었던 것 같다. 여유가 없으니 시야가 좁아지고, 코드가 점점 산으로 갔던 것 같다.
오늘은 여유를 가지고 그룹원들과 코드 리뷰를 하는 것으로 일정을 시작했다. 모임을 2시간 10분 정도 진행했던 것 같다. 우리 그룹원들 너무 재밌어.... ㅎㅎㅎ 점심을 간단히 먹고 리뷰어 님들의 리뷰를 정독하고 답을 남겼다. 모르는 게 한 바가지다.. 오늘만큼은 학습 위주로 하루가 흘러갔다. 몰랐던 부분들을 보충하고 이해하는 시간을 가졌다.
3일 동안 휴일
주말에는 명일이와 수빈 님과 인천에서 만나 모각코도 했고 맛있는 것도 먹었다. 또 쉬면서 체력을 충전하는 시간을 가졌다. 자도자도 졸리다
10/11(화) - P3 Day10
12시에 PR하고 개인 일정은 끝이 났다. 피어세션과 마스터 클래스를 차례로 진행되었다. 마지막에 취업에 관련된 이야기가 많이 나왔다. 이력서를 어떻게 써야 되는지부터 코딩테스트가 왜 있는 건지, 면접을 진행할 때는 어떤 부분들을 고려하는지 등에 대한 얘기를 해주셨다.
마스터 님이 추천해주신 블로그글: 인프런 심야 FE 네트워킹 후기
🍻 피어세션
벌써 프로젝트3이 끝났어..?
피어세션을 들어가기 전부터 이번에는 뭘 해야할까 고민했고, 미션 프로젝트를 진행하면서 많이 사용하는 모듈이나 기능을 직접 만들어보는 것이 좋을 것 같다고 생각했다. fetch로 axios만들기 , http모듈로 express만들기 를 제안했고, 해당 내용을 주제로 팀을 나눠 학습 및 구현한 후, 공유하는 시간을 가졌다. 우리 팀은 http 모듈로 express만들기를 진행했다. 시간이 많이 부족했지만, 내부 원리에 대해 자세히 고민해보고 직접 구현해보는 시간을 가질 수 있어 좋았다.
특히 http.createServer() 를 할 때 반환되는 Server 객체의 on 메소드 에서 콜백 인자로 던져주는 Response와 express의 Response가 약간 달랐는데 이 부분이 약간 어려웠다. 시간이 얼마 남지 않았을 때 우석 님이 아이디어를 내셨고, 그 방식대로 구현할 결과 express 흉내를 약간은 낼 수 있었다.
이번 주에도 피어세션을 함께한 다른 조원 분들과 사진도 같이 찍고, 팀회고도 같이 진행했다. 사진을 찍을 때 기종 님이 거꾸로 매달려 계셨는데 웃겨 죽는 줄 알았다.. 줌의 특수 분장과 환장의 콜라보
✍리뷰활동
기대되는 리뷰 활동!!
인상적인 리뷰 내용
단순히 changePath를 위한 이벤트를 만들었는데, 이를 컴포넌트화하면 어떨까요? <Link href="/place"></Link> 로 만들어서 처리하고 안에서 <a> 엘리먼트를 출력하는것이죠.
(내가 너무 이벤트 관점으로 생각했던 것 같다. 굳이 필요없는 이벤트를 만들고 있었다.)
리액트는 자동으로 이벤트 위임을 해주기 때문에 각각의 p에다가 onClick={handleMenu} 를 해줘도 크게 문제 없습니다.
(리액트에 자동 이벤트 위임이 기능이 있다니??!리액트 너는 없는 게 뭐니..)
div만을 가리키고 싶다면 event.currentTarget 으로 가져올 수 있습니다. 이벤트를 부여한 개체를 선택합니다.
되도록 렌더링에 영향을 가는 값이 아니면 useState로 관리하지 않길 바랍니다. 예를 들어 입력할때마다 에러 메세지를 바꾸거나 밸리데이션을 한다면 state로 관리해야하지만, 그게 아닌 submit을 할때만 값을 사용하는거면 ref로도 충분히 같은 기능을 할 수 있어요.
리뷰어님 typeorm 특강
10/6 목요일 오후 9시 30분부터 TypeORM과 nestjs 백엔드에 대한 특강을 해주셨다. 2시간 가량 진행되었다. 열정이 엄청나시다!! 강의 내용은 대충 아래와 같다.
TypeORM에서의 Entity
- @Column 데코레이터 사용법
- Entity의 Relation 설정 => @OneToMany와 @ManyToOne, 그리고 @JoinColumn의 사용
- ManyToMany는 어떻게 설정해야할까?? @ManyToMany 데코레이터를 통해서 다대다 관계를 만들 수 있다. 중간테이블을 따로 Entity를 만들지 않고 자동으로 생성할 수 있는 것이다. 해당 내용을 더 찾아보니 실무에서는 중간테이블에 다른 정보들이 추가될 수 있기 때문에 따로 Entity를 만드는 것을 추천하고 있었다!!
쿼리빌더 vs 레포지토리 패턴
- 자유도가 높은 쿼리빌더
- 쿼리 빌더는 변수로 선언해놓고, 필요에 따라 뒤에 코드를 추가해 사용할 수도 있다. 쿼리를 안 날릴 수도 있다.
- 반면, 편리한 레포지토리 패턴!
- 레포지토리 패턴은 간단하게 쿼리문을 날릴 수 있지만, 층이 깊어질 수 있다는 단점이 있다.
몽키패치??
런타임에 코드의 동작을 동적으로 업데이트하는 데 사용되는 기술
1대 N 문제? N+1 문제??
연관 관계에서 발생하는 이슈로 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오게 된다.
스프레드 연산자와 비트 연산자를 통해 if문 대체하기??
this.repository.find({
where: {
id: 1,
...(search && { title: search }), // 만약 search가 참이라면 title을 search의 내용으로 바꾸기
}
})
Left Join과 Inner Join
자세한 내용은 아래 코드 내용 참고(outer join으로 inner join을 수행할 수도 있다.)
🍶스몰토크
한~~잔~~해~~
금요일에 오후 9시에 9명의 캠퍼가 모여 행사가 진행되었다. 1시간 30분 정도 얘기를 나눴다. 생각보다 주제가 무거워서 저번처럼 웃고 떠들기 보다는 다들 생각에 잠겨있었다.
- 단일 책임의 원칙이 지켜지지 않는 객체를 어떻게 관리하는가? => 객체를 나눈다. 못본 척 한다....
- 근데 사실 단일 책임의 원칙이 지켜지는지 여부도 판단하기가 힘들다.
- 사람을 바꾼다..??? 어려운 일이다. 나말고 바꿀 수 있는 게 없다...
- 다른 사람이 바뀔 거라고 생각하는 것 자체가 기대다.
- 기대가 많으면 좌절감도 크다. 받아들이는 게 중요한 것 같다.
- 왜 변해야 할까?? 조금 더 완벽해 지기 위해서?? 점진적으로 발전해나가기 위해서??
- 우리들은 오늘보다 내일 더 나은 사람이 되고 싶어한다. 성장