목록일지 (40)
가수면
초기 상태값을 설정하는 과정에서 'next referenceerror: localstorage is not defined'와 같은 오류가 발생하는 경우가 있다. 단순 해결 방법이야 간단하다.상태값의 업데이트를 useEffect 안에서 수행하거나, typeof window === 'undefined'와 같은 타입 가드를 사용하면 오류를 해결할 수 있다. 그러나 만약 '로그인 한 상태에서 새로고침 시 로딩이나 로그인 버튼 노출 없이 바로 닉네임이 노출되도록 하는 기능'을 구현한다고 한다면, 위 방법으로는 해결할 수 없다. 내가 바로 이 경우였는데, 오류 해결 이후 원하는 기능을 구현하기 위해 나는 '왜 이런 오류가 발생한 것일까?', '구조적으로 이게 진짜 한계인 건가?'라는 의문을 품게 되었다..
스프링 부트를 이용해 서버를 실행했을 때 Web server failed to start. Port 8080 was already in use.라는 오류가 발생하며 서버가 실행되지 않는 문제가 발생했다. 별도로 실행시킨 것이 없는데 이랬던 경우 재부팅해서 몇 번 해결한 경험이 있었기에 재부팅을 해봤지만 이번에는 해결되지 않았다. 포트를 바꿔 실행하면 되겠지만, 언제까지고 그렇게 작업을 해갈 수는 없는 노릇이다. 오류를 해결하기 위해 검색을 통해 몇 가지 방법을 시도해봤다. 이 글을 통해 일반적인 해결 방법과 내가 해결한 방법을 정리한다. 'Web server failed to start. Port 8080 was already in use.'가 뜨는 경우 일반적인 해결 방법. 1. 실행 포트 변경 app..
MySQL Shell을 사용해봤는데 직관적이지 않은 것 같아 Workbench를 사용해보려 설치하다가 두 가지 오류를 겪었다. 1. 버전 호환 문제 workbench를 설치하면서 server를 설치하고 mysql로 연결하는 과정에서 아래 오류가 발생했다. Connection warning (local instance mysql) incompatible/nonstandard server version or connection protocol detected (8.2.0) connection to this database can be established but some Mysql workbench features may not work properly since the database is not full..
의문의 발단은 스터디 톡방에 올라온 코드로부터 시작되었다. 아래는 화면이 md사이즈일 때 요소들이 보이고 안 보이는 것을 조절한 반응형 레이아웃 코드다. 코드와 함께 올라온 주제는 메인 페이지에서 저 무거운 컴포넌트를 전부 불러오고 있는데 좋은 방법이 없느냐. 나는 아래 display: none요소들을 컴포넌트로 묶어 react lazy를 사용할 것을 권했다. 레이지 로딩을 쓰면 저런 식으로 구성해도 모바일 뷰가 되기 이전에 안 불러오는 것이 맞는지 걱정된다는 말이 돌아왔다. 나는 2가지 이유를 들어 안 불러와질 것이라 답변했다. 1. '반환된 구성 요소를 처음 렌더링하려고 시도할 때까지 호출하지 않습니다.' (리액트 공식 문서에 나와있는 lazy의 설명) 2. display: none이 적용된 요소는 ..
들어가기 전 필요한 기본 지식 strokeDasharray - 점선의 길이와 간격 (길이와 간격을 각각 전체 선 길이로 설정할 경우 선이 감춰진다.) strokeDashoffset - 선이 시작되는 위치 (선의 전체 길이 = 선의 시작점, 0 = 끝점 ) 원리는 다음과 같다. 1. svg를 숨김 2. svg가 보여지는 순간을 0, svg가 완전히 다 지나면 1이 되는 비율값을 구한다. 3. strokeDashoffset에 비율값을 적용해 스크롤을 내릴 때마다 마치 선이 그려지는 듯한 효과를 낸다. 구현 과정 1. ref 설정 svg가 그려지는 구역의 ref와 svg 길이의 ref를 저장한다. interface Props { containerRef: MutableRefObject; } const Curve..
일반적인 페이지네이션 혹은 슬라이드를 구현한다고 한다면 다음과 같은 준비물이 필요할 것이다. 1. 한 번에 몇 개의 요소를 렌더링 시킬 건지 렌더링시킬 요소 개수 2. 전체 배열을 1번으로 나눈 페이지 수 3. slice 자, 그렇다면 길이가 제각각인 현재 나의 키워드의 개수가 영역을 넘어가면 어떻게 처리할 것인가..! 기능 구현에 있어 가장 큰 문제는 한 페이지에 몇 개가 렌더링되는지가 키워드 길이에 따라서 랜덤하게 결정된다는 것이었다. 레퍼런스를 어느 곳에서도 찾을 수 없었기에 나는 차근차근 접근해보았다. 로직 구상 먼저 구현에 있어 가장 중요한 것은 영역 안에 몇 개가 렌더링되는지 카운팅하는 것이다. 현재 로직은 flex-wrap과 overflow hidden 속성을 이용해 레이아웃을 구현한 상태다..
넥스트에서 Link태그나 useRouter를 이용해 경로 이동하는 테스트를 시도하면 "Not implemented: navigation" 같은 오류가 발생한다. await userEvent.click(screen.getByText("Tech")); expect(window.location.pathname).toEqual("/tech"); 이것은 React Testing Library환경에서 Next를 사용하는 데 오는 문제다. 기본적으로 RTL와 Jest는 리액트 환경에 초점이 맞춰져있으며, Next에서 제공하는 useRouter와 Link태그는 Next 자체에서 제공하는 유틸리티다. 즉, RTL에 없는 기능을 사용하려니 문제가 발생하는 것이다. 리액트에서처럼 react-router-dom에서 제공하는 ..
카카오 로그인의 테스트 코드를 작성하던 중 테스트 코드 상의 경로가 제대로 이동되지 않는 문제가 발생했다. 하나씩 클리어해 간 과정과 잊어버리지 않도록 주의해야 할 점들을 기록한다. 1. axios 오류 평범하게 msw를 설치해 axios를 사용할 경우 모듈 외부에서 import 문을 사용할 수 없다며 axios import하는 부분에 오류가 발생하게 된다. Jest는 Node.js 환경에서 사용되는 테스트 프레임워크다. 그러나 애플리케이션이 웹 클라이언트용으로 빌드되고, axios가 버전업이 되면서 CommonJS 대신 ES 모듈로 빌드되도록 변경되었기 때문에 CommonJS 형식으로 작성된 Node.js에서 실행되지 않는 문제가 발생한 것이다. 여러 해결 방법이 있었는데, 나는 axios를 CJS 모..
서비스를 여기 저기 돌아다니며 인터렉션 테스트를 하다가 스크롤을 내리지도 않았는데 내가 보지도 않을 모든 슬라이드들이 렌더링 되는 것이 너무 비효율적이라는 생각이 들었다. 이에 렌더링을 최적화 하려다가 아예 프로젝트 최적화 작업을 지금 시점에서 대대적으로 하기에 이르렀다. 그렇게 준비한 최적화의 진행 순서는 코드 정리 리팩토링 -> 메모이제이션 -> 코드 스플리팅 -> 레이지 로딩 먼저, 최적화가 잘 이루어졌는지 측정할 항목들은 다음과 같다. 측정 항목: 'App', 'Home', 'Slide' 컴포넌트 a. 'Home' 페이지에서 새로고침을 했을 때 측정 항목의 렌더링 시간을 측정한다. b. 다른 페이지로 왔다 갔다 하다가 'Home' 페이지로 다시 돌아왔을 때 측정 항목의 렌더링 시간을 측정한다. c..
Wrapper에 임시로 200vh를 주고 작업하던 것을 삭제하니 스크롤이 두 개 생기는 문제가 발생했다. 스크롤 없애는 거야 overflow 속성을 사용하면 된다지만, 어떤 놈이 스크롤을 발생시키고 있는지 감이 잡히질 않았다. 세로 영역을 지정해준 것은 Wrapper가 유일했었기 때문이다. 그렇게 한참을 찾아 헤매다가 나는 슬라이드가 한 개일 경우 스크롤이 정상적으로 한 개가 표시되지만, 두 개일 때부터 스크롤이 추가 생성되는 것에 주목했다. 이 얘기는 곧 SlideBox와 SlideItemRowBox는 용의선상에서 제외라는 소리였다. 이것들이 문제였으면 슬라이드가 한 개만 있을 때도 스크롤이 두 개여야 했으니까. 그래서 SlideContainer의 css 속성을 들여다보다가 그간 몰랐던 것에 대해 알게..
넷플릭스 클론코딩 도중 슬라이드를 똑같이 구현하는데 생각보다 많은 시간을 보내고 있다. 잦은 코드 변경이 있었는데, 그 과정에서 꽤 유익한 공부를 하게 되어 간만의 일지를 적는다. 문제 발생 opacity 조작과 관련해 슬라이드의 여러 기능이 얽혀 어려움을 겪고 있는데, 구현하려는 주요 기능은 다음과 같다. A = '슬라이드 이동 화살표' B = '슬라이드 페이지네이션 인디케이터' 1. 초기엔 A와 B가 보이지 말아야 한다. 2. 슬라이드에 마우스가 호버되면 A와 B가 나타나야 한다. 3. 슬라이드 아이템에 호버하고 0.5초 뒤 scale이 커지면 A와 B가 다시 사라져야 한다. 4. scale이 커지기 전까진 슬라이드 내에서 마우스를 움직여도 A와 B가 사라져선 안 된다. 5. 슬라이드 '이동 버튼'에..
이전 글에서 이어짐 https://jhchoi1182.tistory.com/141 클라이언트 전역 상태 관리 Redux Vs React Query 코드 리팩토링 도중 전역 상태 관리는 리액트 쿼리로도 가능한데(데이터를 저장하고 뽑아쓰면 리렌더링까지 일어나는 것을 확인) 그럼 리덕스는 안 써도 되는 것 아닐까 하는 생각에서 실험 시 jhchoi1182.tistory.com 지금은 공부를 하며 보는 눈이 트여(?) 위 글의 결론을 수정한 상태지만, 당시만 해도 나는 '리액트 쿼리의 캐싱된 데이터는 state가 아니라 data였다.'라는 생각을 하지 못하고 'setQueryData를 하는 곳에서는 리렌더링이 이루어지는데, 뽑아서 쓰기만 하는 컴포넌트에서는 리렌더링이 일어나지 않는다'라고 생각했었다. 컴포넌트 ..
우여곡절 끝에 실전 프로젝트가 끝났다. 일단 너무 아쉽다. 지금 다시 하면 이렇게 했을 텐데, 이렇겐 안 했을 텐데 등등... 뭐, 하지만 그건 반대로 생각해 봤을 때 그만큼 내가 성장했다는 긍정의 의미일지도 모르겠다. 만족스러운 부분을 한번 찾아볼까. 그동안 프로젝트들을 스프린트로 꽤 거쳐왔는데 처음 코딩을 시작했을 때의 나와 비교해본다면, 확실히 장족의 발전이 있었다. 후회없는 시간을 보낸 보상은 꽤나 달콤했다. 계속 추가되는 요구 사항을 전부 구현해낸 과정을 통해 이젠 어떤 기획이 주어져도 할 수 있겠다는 자신감이 생겼고, CRUD 중점적으로 기본을 다지고 싶다는 초기의 내 바람은 공교롭게도 세 프로젝트 연속으로 메인 CRUD를 맡게 되면서 얼결에 이루어져 버렸다. 일단 지금 준비해야 할 것은 면접..
1. 최적화에 대한 필요성 인지 몇 주전 유저 테스트 중에 글 목록 조회하는 부분에서 로딩이 조금 느린 것 같다는 피드백이 있었다. 계속 추가되는 달력 기능으로 인해 달력 로직이 상당히 무거워졌었고, 달력은 글 목록 조회하는 부분에 있었기 때문에 당시엔 나의 달력으로 인한 문제인 줄 알았다. 그리고 피드백이 있고 몇 주가 지나 드디어 여유가 조금 생긴 나는 다른 팀원들을 기다리며 내가 맡은 파트들을 먼저 조금씩 리팩토링해보기로 했다. 그렇게 라이트하우스를 돌려본 결과, 점수는 처참했다. 사용하지 않는 자바스크립트가 너무 많다며 bundle.js의 용량도 비대했다. 달력도 달력이지만 레이아웃 등 하나의 컴포넌트로 묶어서 사용할 수 있는 것을 팀원들 각자 만들어 무분별하게 중복 사용하고 있다는 것도 개선해야..
원래 진작에 리팩토링이 다 끝났어야 했을 터다. 팀원들을 기다리는 사이 내 파트에 대한 리팩토링은 1차적으로 이미 끝낸 상태지만, 프로젝트 전체 컴포넌트에 대한 리팩토링은 아직 이루어지지 않은 상태. 이젠 기한이 진짜 얼마 남지 않아 내일부터는 어쩔 수 없이 혼자서라도 컴포넌트 다 쪼개는 작업을 들어가야 한다. 이번 주 한 작업 달력 로직 메모라이징 작업 및 렌더링 최적화 자주 쓰이는 함수에 대한 리팩토링 input 컴포넌트화 프로젝트 오류 수정 유저 테스트 피드백 반영 트러블 슈팅 - useMemo, useCallback, React.memo - 최적화를 위해 공부하는 과정에서 위의 훅들을 너무 무분별하게 쓰고 있었다는 것을 깨닫고 공부하기 시작함. 어떨 때 사용해야하고 어떻게 써야 적절하게 사용하는 ..
코드 리팩토링 도중 전역 상태 관리는 리액트 쿼리로도 가능한데(당시 푸터에서 데이터를 저장하고 뽑아쓰면 리렌더링이 일어나는 것을 확인해서 착각함) 그럼 리덕스는 안 써도 되는 것 아닐까 하는 생각에서 실험 시작. 왼쪽처럼 dispatch를 사용하여 전역으로 관리하던 값을 쿼리로 교체해보았다. 그러나 예상과 달리 쿼리에 저장된 값은 바뀌고 있는데 콘솔이 찍히질 않는다. 이 말은 곧 렌더링이 일어나지 않는다는 소리. 값이 바뀌었으니 화면이 바뀌어야 하는데 역시나 화면이 바뀌질 않았다. 여기서 의문. 푸터에 박혀있는 아이콘은 클릭 시 변경되는 값에 따라 초록색으로 잘 바뀌고 있는데, 대체 왜 같은 onClick함수에 담겨 있는 diaryViewState를 사용하는 다이어리는 바뀐 값에 따라 렌더링이 일어나고 ..
최적화와 컴포넌트를 쪼개는 것에 대한 고민은 기획 단계에서부터 했었던 고민들이다. 그러나 기능부터, 기능부터라며 차일피일 미뤄왔던 것들... 이젠 그 작업이 코앞으로 다가온 것이다! light house 점수가 낮게 나와 걱정이 크지만...리팩토링 하다보면 나아지겠지...? 이번 주 한 작업 컴파운드 패턴의 모달 만들기 수정 되거나 추가 된 디자인 반영 일기 설정 페이지 기능 구현 프로젝트에 PWA 적용 추가된 달력 기능 작업 중 트러블 슈팅 - 지난 주 모달이 자꾸 닫히던 오류 원인 해결 - 지난주 어디를 눌러도 모달이 꺼지던 문제가 발생했었는데, 모달을 새로 만들어 해결은 했었지만 끝내 찾지 못했었던 원인을 찾음. 부모 컴포넌트로부터 전파된 이벤트가 적용되던 것이었음. - 도움을 받은 블로그 - ht..
Compound 합성. 하나의 컴포넌트를 잘게 쪼개 레고 블럭처럼 조립해 쓴다니, 이 얼마나 리액트 컨셉에 잘 맞아떨어지는 패턴이란 말인가 내가 컴파운드 패턴을 공부하기 시작한 데에는 몇 가지 이유가 있었다. 첫째, 중복된 코드들로 인해 난잡해진 팀 프로젝트의 코드 수를 대폭 줄일 필요가 있었으며, 둘째, 중구난방으로 쓰이고 있는 모달들을 통합할 필요가 있었고, 셋째, 팀원들의 부탁도 있었던 데다가, 넷째, 현업에서 많이 쓰이는 패턴이라는 소리를 어디선가 들은 것에 더해, 다섯째, 클린해보였다...! 컴파운드 컴포넌트 이렇게 쓰는 거 맞음? 나는 바로 코딩에 들어갔다. 뚝딱! 아주 기본적인 컴파운트 패턴의 모달 컴포넌트가 완성되었다.(거의 이틀이 걸렸다.) notClose를 주냐 안 주냐에 따라 배경을 ..
코딩만하느라 바빴던 주차였다. 생각보다 오류들도 많이 있었고... 그것들을 해결하느라 mvp로 잡았던 기능들도 미처 다 못했고... 개인적으로는 만족스럽지 못한 결과물이었기에 더욱 아쉬움이 남은 중간 발표였던 것 같다. 이번 주의 작업 회원가입 페이지 뷰 작업 메인 페이지 CRUD 기능 구현 다이어리 북마크 기능 구현 설정 페이지들 뷰 작업 트러블 슈팅 - 모달이 다이어리 하나일 땐 되고 두 개 이상 땐 안 됨 - 다이어리 전체 조회에서 다이어리의 수정/삭제를 위한 모달을 열면 버튼의 클릭이 다이어리가 하나일 땐 되지만, 두 개 이상이면 버튼 클릭 시 기능이 작동되지 않는 버그 발생 해결 과정 및 해결 (1) 다이어리의 수정/삭제를 위해 props로 넘어오는 다이어리 id를 콘솔로 찍어보면 같은 id가 ..
난 이번 주 뭘했던 걸까 고민만 한가득하다가 뭘했는지도 모르겠는 채 보낸 한 주였다. 프로젝트의 기술 스택이 여러번 번복되면서 결국 리액트 쿼리를 쓰기로 결정했다. 코드 컨벤션을 정했지만 각자의 코딩 스타일이 다르거나 지켜지지 않아 코드가 난잡해졌고, 초반부터 리팩토링을 염두에 두고 틀을 정해서 잡아놓고 가자와 하드코딩하더라도 일단 다 쓰고 가자가 중간에 여러번 바뀌며 코드의 일관성도 없어졌다. 그러다 보니 프로젝트의 스타일드 컴포넌트의 이름들이나 컴포넌트 나누는 작업 마저도 이도저도 아닌 게 되어버렸다. 어떻게 했어야 더 좋은 방법이었을까. 이런 고민들이 팀원들 모두 처음이다보니 알 도리가 없다. 어찌됐든 이번 주 발표 전에 리팩토링을 적어도 한번은 해야만 하게 된 바쁜 일정이기에 마음을 다 잡아야 한..