목록전체 글 (66)
개발여행
setInterval 함수를 사용해 카운트다운 타이머를 구현한 내 웹앱을 모바일에서 실행했을 때 치명적인 오류를 발견했다. 타이머를 실행한 상태에서 모바일 기기의 화면을 끄면, 화면이 꺼진 상태로 있는 동안에는 setInterval 함수도 멈춰버리는 것이다. 당연히 화면이 꺼진 상태에서도 setInterval 함수로 인해 카운트다운이 계속 진행되고 있을 거라고 생각했는데, 실제로는 타이머의 시간이 흐르지 않고 멈춘 상태였다가 모바일 기기의 화면이 다시 켜지면 그때 이어서 동작하도록 돼있었다. 찾아보니 모바일 기기에서는 배터리 수명 보존과 퍼포먼스 향상을 위해 setInterval, setTimeout과 같은 시간과 관련된 함수들을 스로틀링한다고 한다. 화면이 꺼져있는 동안에는 동작을 일시정지 시켰다가, ..
Firebase에 앱을 호스팅한다면 원치 않는 외부인으로부터 내 앱의 데이터를 보호할 수 있도록 보안규칙을 작성하게 된다. Firebase에서는 Firestore와 Firebase Storage 각각의 서비스마다 별도로 보안규칙이 필요하다. 초창기에는 Firebase Storage 보안규칙에서 Firestore에 저장된 데이터를 알 방법이 없어서, Firestore 데이터베이스의 데이터를 Storage가 참조할 수 있도록 각종 방법으로 복잡한 함수들을 구현해야 했다고 한다. 하지만 2022년 업데이트 후로는 Storage에서도 Firestore 데이터베이스의 데이터를 활용해 규칙을 작성할 수 있도록 Firestore를 간편하게 참조하는 함수를 사용할 수 있게 됐다. firestore.get 함수로 특정 ..
Next.js 프로젝트에서는 다양한 방법으로 페이지의 route path와 쿼리 파라미터를 읽을 수 있는데, 그중 Pages Router에서 useRouter 훅 외적으로 쓸 수 있는 방법을 정리해봤다. useParams 훅으로 dynamic route값 읽기내 페이지가 dynamic route를 쓴다면 useParams() 훅으로 바로 그 값에 접근할 수 있다. useRouter() 훅의 라우터 객체를 통하지 않고 순수하게 query 객체만 읽을 수 있는 전용 훅이다.// src/pages/[hello]/index.tsximport { useParams } from "next/navigation";export default function Page() { const params = useParams(..
Next.js 13 이상부터 App Router를 사용하면서 내비게이션 동작 방식이 변경됐다. 이전 버전의 pages 디렉토리를 사용하던 Pages Router에서 app 디렉토리를 사용하는 App Router로 전환하려면 라우터 관련 코드를 수정해줘야 한다. useRouter 훅 사용App Router에서도 클라이언트 컴포넌트에 한해 useRouter 훅으로 router를 생성해 router.push() 메소드를 사용할 수 있다. 다만 기존 Pages Router의 "next/router"에서 import하던 라우터를 App Router에서 그대로 사용하게 되면 "NextRouter was not mounted." 오류가 발생한다. App Router 디렉토리에 생성된 컴포넌트의 경우 useRouter..
Next.js를 배우고 여러 자료를 읽으면서 종종 SSR이나 RSC 등의 단어를 접했었는데, 좀처럼 이해되지 않아서 개념을 정리해보기로 했다. Server-side rendering(SSR)서버사이드에서의 서버는 클라이언트 코드가 호스팅되는 서버를 말한다. 깃헙 pages에 내 웹앱을 호스팅한다면 깃헙이 서버인 것이고, Vercel 같은 서비스에 호스팅하면 Vercel의 서버를 쓰는 것이다. 서버사이드 렌더링은 클라이언트 코드가 호스팅된 서버에서 내 컴포넌트를 렌더링한다는 뜻이다. 지금까지는 React 컴포넌트를 생성할 때 컨텐츠가 없는 빈 HTML 문서를 먼저 다운로드 받고, HTML 문서 안에 있는 태그를 읽어 필요한 자바스크립트 파일을 추가로 다운로드해서 DOM 요소들을 자바스크립트를 통해 주입하..
Material UI(MUI)는 구글의 디자인 프레임워크(Material Design)를 기준으로 하는 리액트 전용 UI 라이브러리다. 디자인 프레임워크는 간단히 말해서 하나의 표준으로 삼는 UI 스타일이라고 보면 된다.MUI는 Material Design을 따라 input, button, select처럼 웹에 흔히 쓰이는 구성 요소들을 컴포넌트화했기 때문에, 커스터마이징에만 익숙해지면 빠르고 간편하게 어디에서나 통용되는 UI 컴포넌트를 활용할 수 있다. MUI 컴포넌트를 내 사이트에 맞게 커스터마이징하는 방법은 다양한데, 그 중 커스텀 스타일을 개별적으로 적용하는 방법과 일괄로 적용하는 방법이 가장 보편적인 것으로 보인다. sx prop 사용 (개별 적용)각 MUI 컴포넌트에는 리액트 컴포넌트의 sty..
리액트 앱에서 setInterval처럼 자동으로 반복 실행되는 함수를 사용할 땐 리렌더링으로 인한 사이드이펙트를 걱정할 수밖에 없다. 내 앱은 1초마다 시간을 세는 타이머 앱인데, 부모 컴포넌트의 상태가 변하면 부모 컴포넌트는 물론 자식 컴포넌트까지 리렌더링되는 리액트의 특성 때문에 타이머와 상관없는 상태 값을 바꿔도 타이머가 리셋되는 현상이 있었다.// 부모 컴포넌트 - TimerContainerconst TimerContainer = () => { const [isRunning, setIsRunning] = useState(false); // 부모 컴포넌트의 상태 const intervalId = useRef(null); const startTimer = () => { setIsRunnin..
참여하고 있는 팀 프로젝트에서 계획에는 없었던 실시간 채팅 기능을 만들기로 결정됐다. 노마드코더에서 Socket.IO로 Zoom 클론코딩을 해봤던 경험이 있어서 자신있게 프론트에서는 내가 웹소켓을 맡겠다고 했으나... 서버쪽 구현을 맡은 멤버가 처음 들어보는 STOMP로 웹소켓을 구현했다고 해서, 같은 웹소켓이지만 완전 새로운 공부를 하게 됐다. STOMP란?STOMP는 Simple(또는 Streaming) Text Oriented Messaging Protocol의 약자로, 웹소켓(WebSocket) 환경에서 돌아가는 HTTP 서브프로토콜이다. 메세지 기반 전송에 특화되어 있어서 실시간 채팅 서비스 등을 구현할 때 사용하기 좋다고 한다. STOMP의 구독—발행 구조가 이해하기 쉬워서 다행히 사용법을 빨..