라벨이 React인 게시물 표시

Next.js Turbopack dev에서 렌더링이 두 번씩 될 때

Next.js Turbopack dev에서 렌더링이 두 번씩 될 때 dev 실행 시 렌더링/이펙트가 두 번 실행된다? React Strict Mode 리액트의 StrictMode 는 디버그를 위한 몇 가지 기능을 제공해 준다. 그 중에는 이펙트나 렌더링 단계의 버그를 잡기 위해 실행되는 다음과 같은 기능이 이런 문제를 만든다. 렌더링 단계에서 발생하는 문제를 찾기 위해 컴포넌트가 한 번 더 렌더링 된다. 이펙트 정리 누락으로 발생하는 문제를 찾기 위해 이펙트가 재실행 된다. Deprecated된 API 사용을 탐지한다. 이 중 1번과 2번 때문에 이펙트/렌더링이 두 번씩 실행되는 문제가 발생하게 된다. 발생할 수 있는 문제? StrictMode는 디버그 단계에서 매우 유용하지만, 간단한 예시로 다음과 같은 코드에서 문제가 발생할 수 있다. "use client" import { ReactNode , useEffect , useState } from "react" ; export default function ClientComp ( { children } : { children : ReactNode } ) { const [ count , setCount ] = useState ( 0 ) ; useEffect ( ( ) => { setInterval ( ( ) => { setCount ( count => count + 1 ) ; } , 1000 ) ; } , [ ] ) ; return < div > < h1 > Hello , Next . js ! ! ! { count } < / h1 > { children } < / div ...

브라우저에서 사용할 간단한 로거 만들기

이미지
브라우저에서 사용할 간단한 로거 만들기 로깅 개발 단계에서든 프로덕션 단계에서든 로깅은 필수다. 각 단계마다 로그에 포함되는 정보의 차이는 있을지라도 로깅 기능이 없는 프로그램은 개인적으로 제대로 된 프로그램이 아니라고 생각한다. 디스코드의 로그 개발 단계에서는 더 상세한 로그를 작성하게 하여 번거롭게 브레이크포인트를 걸지 않고서 간단한 로직들이 제대로 돌아가는 중인지 확인할 수 있고, 프로덕션 단계에서는 문제가 발생할 경우 개발자가 사용자의 로그를 보고 어떤 문제가 어떻게 발생한 것인지 분석하는 데 사용할 수 있다. 로깅 라이브러리 이러한 로깅의 중요성 덕분에 언어를 막론하고 다양한 로깅 라이브러리가 꾸준히 업데이트되고 있다. C#에서는 NLog를, Java에서는 log4j를 사용했었는데, 이제는 NodeJS용 라이브러리를 찾아야만 했다. 검색하니 나오는 것들이 몇 개 있었는데, 그 중 Winston 라이브러리가 좋아 보여서 사용하려 했다. 그러나 실행해보니 process is undefined 관련 예외를 쓰로우하면서 정상적으로 작동하지 않았다. 설마 하는 마음에 이슈를 뒤져보니 윈스턴은 공식적으로 브라우저 로깅을 지원하지 않는다고 한다. 굳이 라이브러리를 써야 하나? 그러던 중 문득 의문이 들었다. 어차피 지금 하려는 작업은 로그를 DB에 전송하는 등의 복잡한 단계가 필요 없는 작업이다. 그냥 브라우저 콘솔에 디스코드마냥 로그를 출력해주면 되는 일이다. 단, 확장 프로그램에서 사용하는 로깅이기 때문에 콘텐츠 스크립트에서 로그를 작성할 경우 사이트 자체의 로그와 겹치지 않게 적절한 레이블을 출력해주면 된다. 이런 간단한 로거를 사용하자고 라이브러리를 추가해 사용하는 것은 낭비라는 생각이 뒤늦게 들었다. 직접 구현 그리고 나서 생각해 보니 구현에 시간이 그렇게 많이 들 것 같지 않았다. 예전이었다면 패키지를 찾기 전에 구현할 생각부터 했을 텐데 시간에 쫓기다 보니 패키지를 먼...

react-toastify 사용 시 토스트가 끝날 때에 맞춰 코드를 실행하는 방법

이미지
react-toastify 사용 시 토스트가 끝날 때에 맞춰 코드를 실행하는 방법 토스트 알림 웹 페이지에서 전통적인 메세지 표시 방법은 역시 alert , confirm , prompt 이다. 2000년대 초반, 중반, 심지어 2010년대에 들어서도 가끔씩 prompt 를 사용해 입력 값을 받아오는 사이트를 볼 수 있었다. 1 허나 alert , confirm 은 2000년대 말 들어서 서서히 사라지다가, 어느 순간 메이저 사이트는 물론 어지간한 일반 사이트들에서도 사라졌다. 물론 아직도 일부 사이트, 특히 보안 프로그램을 가장한 스파이웨어를 심어대는 국내 사이트들에서는 보이기도 하지만 아무튼 예전에 비해서는 압도적으로 많이 사라진 상태이다. 토스트? 처음 이 용어를 들었을 때 떠오른 것은 당연하게도 음식 토스트였다. 토스터기를 아주 어렸을 때 빼고는 사용한 적이 없던 나는 곧바로 용어의 어원을 유추하기가 힘들었다. 위 문단에서 알 수 있듯, 토스트 메세지의 토스트는 말 그대로 토스트를 의미한다. 정확히는 토스터기에서 튀어 올라오는 토스트 이다. 나는 이런 형식의 알림을 웹이 아닌 안드로이드 스마트폰에서 처음 접했다. 화면 아래에서 페이드 인/슬라이드 되며 튀어올라오는 메세지. 이게 바로 토스트 메세지였던 것이다. 물론 꼭 아래에서 튀어올라오라는 법은 없다. 지금 와서는 스크린 가장자리 또는 외부에서 나타나는 알림 메세지를 전부 토스트 메세지라고 퉁치는 것 같다. react-toastify 이러한 토스트 메세지를 리액트에서 손쉽게 구현할 수 있도록 해주는 라이브러리가 바로 react-toastify 이다. <ToastContainer {...} /> 를 토스트를 출력해야 하는 컴포넌트 2 에 선언하고 원할 때마다 toast(), toast.info(), toast.promise, toast.error, ... 메서드를 호출하여 컨테이너의 설정에 따라 토스트 메세지를 화면에 출력할 수 있다. ...

MUI와 Tailwind CSS를 같이 사용할 때 TextField의 아웃라인 문제

MUI와 Tailwind CSS를 같이 사용할 때 TextField의 아웃라인 문제 MUI, Tailwind CSS MUI 도 Tailwind CSS 도 UI 스타일을 간편하게 작성할 수 있도록 도와주는 좋은 라이브러리들이다. MUI는 구글의 Material Design 을 리액트 기반 프론트엔드에서 손쉽게 적용할 수 있도록 도와주고, Tailwind CSS는 flex , p-auto 등 미리 정의된 1 클래스들을 가지고 순식간에 여러 컴포넌트들을 유연하게 작성할 수 있게 도와준다. 하나씩 쓰면 문제가 없는데 각각 모두 굉장히 유용한 라이브러리이다. 쓰는 것과 쓰지 않는 것의 개발 속도 차이가 어마어마하게 날 정도로 말이다. 문제는, 이것도 유용하고 저것도 유용해서 둘 다 한번에 쓰려고 할 때 생겼다. MUI의 TextField 컴포넌트 우선 말하자면, 방금 전까지 이게 두 라이브러리를 동시에 사용해서 생긴 문제라는 사실 자체를 인지하지 못했다. 그 문제는 다음과 같다. 일단, 어느 순간부터 MUI의 TextField 컴포넌트의 outlined variant가 :focus 되었을 때 크롬의 기본 유저 에이전트 스타일인 파란색 아웃라인이 보이기 시작했다. 처음 이 증상이 생겼을 때는 UI가 문제가 아니라 일단 전체적인 로직 흐름이 더 중요해서 무시했는데 이제는 앱의 윤곽이 잡혀과는 단계라 눈에 밟히게 되었다. 다행히도, 지금까지 이것 저것 리액트 기반 라이브러리들을 사용해오면서 스치듯 지나친 여러 문서들 중에 MUI와 Tailwind CSS를 동시에 쓰면 문제가 생긴다 는 글을 본 기억이 얼핏 나게 되었다. 해당 글 들 은 한국 문서였고, 어떤 사람은 MUI를 프로젝트에서 빼서 해결했다 하고, 어떤 사람은 Tailwind CSS를 프로젝트에서 빼서 해결했다고 했다. 하지만 난 도대체가 이해가 안 됐다. 두 라이브러리는 이미 유명해질대로 유명해진 라이브러리들이고, 나온지도 오래 되었는데 절대로 호환성이 없...

개발 단계에서 리액트 컴포넌트가 두 번 렌더링 되는 이유

개발 단계에서 리액트 컴포넌트가 두 번 렌더링 되는 이유 분명 empty array([])를 전달했는데 왜 두 번 렌더링되나 리액트를 처음 접했을 땐 클래스형 컴포넌트를 작성해서 사용했었으나, 함수형 컴포넌트의 엄청난 편리함을 알아차린 뒤로는 쭉 함수형 컴포넌트를 사용해오고 있다. 클래스형 컴포넌트에서 componentDidMount 에 해당하는 역할을 하는 함수형 컴포넌트의 훅은 useEffect 의 두 번째 인자에 [] 를 넘겨주면 된다. useEffect ( ( ) => { // do something... console . log ( "Hello, world!" ) ; } , [ ] ) ; 문제는, Hello, world! 가 두 번 출력된다는 것이었다. React.StrictMode 컴포넌트 결론부터 말하면, 원인은 React.StrictMode 컴포넌트였다. 공식 문서 를 보면, 적용된 컴포넌트가 남는 시간에 재 렌더링 된다는 내용이 있다. 뿐만 아니라, 각종 이펙트 역시 다시 호출된다고 한다. 해당 컴포넌트의 조상 중 React.StrictMode 가 적용된 부분을 제거하니 정상적으로 Hello, world! 가 한 번만 출력되는 것을 확인할 수 있었다. 공식 문서는 항상 꼼꼼히 챙겨보자 난 시간이 촉박한 경우가 아니라면 코드를 완전히 똑같이 베끼게 되더라도 복사/붙여넣기 하지 않고 손으로 베껴 쓰는 편이다. 이번 경우도 마찬가지로, StrictMode 가 적용된 컴포넌트를 구현할 때 참조한 소스 코드를 베끼는 과정에서 도대체 이 StrictMode 가 뭘까? 하며 공식 문서를 본 기억이 있다. 언제나 하는 실수를 또 반복했던 나. 또 한 번 제대로 읽지 않아서 일을 두 번 하게 되었다. 심지어 저 공식 문서 링크의 내용이 아직도 기억에 남아있다. 다만, 제대로 읽지 않았기에 구글링해서 스택오버플로우의 답변을 볼 때까지 생각이 나지 않았을 뿐...