favicon

Jayden { do: smite }

231009(월) 성장

🚤 성장일지 7.0

행복한 이기주의자(웨인 다이어)의 내용에 자극받아 시작하는 소박한 성장기록

살아있는 꽃과 죽은 꽃은 어떻게 구별하는가?<br/> 성장하고 있는 것이 살아 있는 것이다.<br/> 생명의 유일한 증거는 성장이다!

⚛ (7.0)<완전 개편> 파인만 학습법을 알게 된만큼, 성장일지는 정말 그 날의 키워드 중심으로 간단하게 정리하도록 한다.

next 컴포넌트 구성하기

어느정도 프로젝트 시작 전 여러 세팅은 마무리하고 컴포넌트 구성을 하려니 생각보다 많은 고민이 필요했다. 13버전부터는 컴포넌트 별로 클라이언트, 서버 컴포넌트를 분리해서 사용할 수 있게 되었다. 그래서 컴포넌트를 구성할 때 어떤 컴포넌트를 사용할지 고민이 필요했다. 기본적으로는 최대한 SSG로 구성하고 그 뒤에 유저와의 인터렉션이 있는 경우에는 클라이언트 컴포넌트, 데이터가 자주 변경되는 경우에는 SSR로 구성하기로 했다. 물론 그럼에도 헷갈리는 부분들이 존재하기는 한다. 예를 들어, 서버에게 이미지들을 가져와서 그 이미지를 나열하고 그 이미지를 유저가 선택해서 어떤 UI 변경을 준다고 해보자. 이 경우에는 이미지들을 가져오는 부분은 서버 컴포넌트로 두고, 유저가 선택하는 부분은 클라이언트 컴포넌트로 두는 것이 맞는 것 같다.(아직 이 부분은 제대로 구현해보지 않아서 확실하지는 않다. 해봐야알듯..!)

next 유저의 브라우저 설정에 따라 다크모드 적용하기

현재 다크모드 유무와 다크/라이트를 변경하는 토글함수를 context API로 관리하고 있다. 코드는 아래와 같다.

'use client'; import { createContext, useContext, useState } from 'react'; export const ThemeContext = createContext({}); export const ToggleThemeContext = createContext(() => { console.error('Forgot to wrap component in `ThemeProvider`'); }); export const useTheme = () => { return useContext(ThemeContext); }; export const useToggleTheme = () => { return useContext(ToggleThemeContext); }; type Props = { children: React.ReactNode; }; export default function ThemeProvider({ children }: Props) { // NOTE: 현재 유저 브라우저 설정 테마를 가져온다. const isBrowser = typeof window !== 'undefined'; const initialTheme = isBrowser && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; const [theme, setTheme] = useState(initialTheme); const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light'); }; return ( <ThemeContext.Provider value={theme}> <ToggleThemeContext.Provider value={toggleTheme}> <div className={theme}>{children}</div> </ToggleThemeContext.Provider> </ThemeContext.Provider> ); }

그런데 문제는 클라이언트 컴포넌트여도 서버에서 프리렌더링을 하기 때문에 그 때는 window 객체가 undefined인 문제가 발생했다. 그러던 중 next.js에서 제공하는 dynamic을 이용하면 해결할 수 있다는 것을 알게 되었다. 아래와 같이 사용하면 된다. 위의 코드에서 ThemeProvider를 import할 때 dynamic으로 감싸주면 된다.

import dynamic from 'next/dynamic'; const ThemeProvider = dynamic(() => import('components/ThemeProvider'), { ssr: false });

이렇게 되면 서버에서 프리렌더링이 되지 않고 클라이언트에서만 렌더링이 되기 때문에 window 객체가 undefined가 되지 않는다.

그런데... 또다른 문제 발생

처음엔 해결한 줄 알았다. 하... 그런데 문제는 어플리케이션 가장 상위에 ThemeProvider를 감싸두었기 때문에, 그 하위 모든 컴포넌트가 dynamic으로 인한 lazy loading 처리가 되어버린다는 것이다. 즉, 웹 페이지 처음 접속 시 네트워크 탭에서 첫번째 html을 Preview로 보아도 그냥 빈 화면만 보인다. 이러면 Next에서의 SSR(혹은 SSG)의 의미가 사라져버린다...ㅠ 후... useEffect를 사용해봤지만, 그러면 처음에 바로 라이트 모드로 렌더링되었다가 그 이후에 다크 모드로 변경된다. 일단은 initialTheme을 light로 고정해두고, 나중에 다시 고민해봐야겠다.(애초에 서버 렌더링에서 유저의 설정을 알고 렌더링하는 방법이 말이 되나 싶기도 하다.)

react icon with tailwind

정말 별 거 아니지만, react icon의 className에 tailwindcss가 적용된다는 사실...!!!!! 심지어 text- prefix를 붙이면 icon의 content의 색생이 변경되고 bg- prefix를 붙이면 icon의 배경색이 변경된다. 사실 아이콘들 하나하나 찾아가면서 쓰는게 너무 불편하다고 투덜거렸는데 이건 쫌 인정

📝 회고

생각보다 빠르진 않지만 생각보다 재미있넹

참고

undefined

Copyright 2023. all rights reserved by Jayden