Trace 독서 활동 SNS 만들기 - 3

디듀·2026년 1월 28일
post-thumbnail

열심히 블로그를 쓰겠다고 다짐한 지 며칠이나 지났다고, 작심삼일로 끝낼 뻔한 것을 겨우겨우 머릿속에 떠올려 다시 돌아왔다. 사실 블로그 글을 올리지 않는 동안 개발이 조금 진행돼서 오히려 써야 할 내용이 이래저래 쌓여 있는 상황이지만 차근차근 하나씩 해결해 보려고 한다.

우선 오늘은 shadcn/ui가 제공하는 기본적인 기능을 통해 간단하게 구현할 수 있는 라이트/다크모드 테마 설정 기능에 대해서 포스팅해 보려고 한다. 내가 직접 컴포넌트를 만들고, 색상 변수를 지정하고, 설정한 테마에 맞춰서 그것을 노출시키고...... 처음부터 끝까지 다 구현하려면 얼마나 많은 시간이 소요될까? 물론 직접 구현하는 것과, 이미 구현되어 있는 ui 컴포넌트를 사용하는 것은 서로 장단점이 존재하겠지만 (커스터마이징의 유용성이라든지, 복잡성이라든지......) shadcn/ui는 내가 생각하기에는 커스터마이징의 자유도가 높은 편인 것 같다.

개인적으로 가장 큰 장점이자 어쩌면? 진입 장벽으로 느껴질 수 있는 것이 바로 tailwind-css를 사용한다는 점 같은데, 이건 오늘의 주제가 아니니 넘어가고!

테마 설정을 구현하는 것에는 여러 가지 방법이 있겠지만, 요는 동일하다. 바로 html 태그에 'light' 또는 'dark' 클래스를 부여하는 것이다. 간단히 light 클래스를 추가하면 라이트모드가 되고, dark 클래스를 추가하면 다크 모드가 된다. 그 외 나머지 모~든 작업은 shadcn/ui가 처리했으니 걱정 말라구!

그래서 우리가 할 것은 유저로부터 라이트/다크 모드 설정을 받아서 로컬 스토리지에 저장해놓은 뒤 화면에 접속할 때마다 그 값을 꺼내와 설정해 주는 것이다. 나는 context를 생성해서 그 작업을 처리할 예정이다.

우선 theme-context.ts 파일을 생성하여 아래와 같이 코드를 작성한다.

컨텍스트에 담길 값은 theme과, theme을 설정해주는 setTheme 두 가지. ThemeProviderState로 컨텍스트에 담길 상태의 타입을 정의한다.

생성한 컨텍스트에 초기값을 주입하기 위해 createThemeProviderState 함수를 선언하고, createContext 메서드를 호출하여 테마를 저장할 컨텐스트를 생성한다. (그리고 미리 정의한 함수를 통해 초기값을 주입!)

그리고 마지막으로 재사용성을 높이기 위해서 useTheme이라는 커스텀 훅을 생성한다. 매번 컴포넌트 안에서 useContext를 호출하지 않더라도 손쉽게 themeuseTheme을 사용할 수 있게 해준다.

기본적인 준비가 마무리되었다면, 이번에는 provider를 만들 차례!

위에서부터 차근차근 살펴보자면, 먼저 theme을 관리하는 state를 설정하고, 이때 최초의 값은 로컬 스토리지의 값을 쓰거나 존재하지 않는다면 라이트 모드의 값을 쓴다.

그리고 최초 렌더링 및 테마가 변경될 때마다, html 태그의 class를 변경하기 위하여 기본적인 코드를 작성했다. 코드에는 system 테마도 존재하지만 (사용자의 기기 설정을 반영) 일단 내가 만든 UI는 라이트/다크 모드를 토글로 하여 구현했기 때문에 패스.

다음으로는 value를 생성하여 아래 provider에 값을 주입한다. 마지막으로 App.tsx 컴포넌트로 이동하여 아래와 같이 provider를 불러오면 준비 끝.

zustand로 구현해도 되고, 그냥 커스텀 훅으로 만들어서 사용해도 되지만 오랜만에 컨텍스트를 사용해볼 겸 이렇게 구현해 보았다. (사실 검색했을 때 가장 먼저 나오는 게 이 방법이라 그런 것도 있었고......)

이제 설정 메뉴로 가서 useTheme 훅을 가져다 사용하기만 하면 된다.


컨텍스트를 생성하는 파일에서 미리 만들어두었던 훅을 가져와 메뉴의 클릭 이벤트에 붙여본다. 설정한 테마에 따라 아이콘과 텍스트가 다르게 보인다.

요랬는데~!

요래 됐슴당~ shadcn/ui에서 받아온 컴포넌트를 사용하고 + tailwind-css를 통해 스타일링을 하니 따로 뭘 더 설정하지 않아도 각각의 컴포넌트와 요소들이 테마에 따라 적절한 컬러를 가지게 된 것을 볼 수 있다.

참고로 이때 html 태그의 class는 다음과 같이 설정되어 있다.

굿! 완벽하게 구현했으니 이제 다음으로는 tiptap 에디터 사용기로 돌아와볼까 한다!

profile
세상에서 가장 부지런한 사람이 되고 싶은 게으름뱅이

0개의 댓글