티스토리 뷰
본 포스팅은 프로젝트 회고를 목적으로 작성되었습니다.
프로젝트 결정 계기
예전부터 꿈꿔왔던 나의 블로그 만들기를 실행할 수 있을 때가 드디어 찾아왔다고 생각합니다. 외계어 같던 html과 css도 이제 어느정도 적응되었고, react도 이정도면 입문은 떼고 초보로 나아갈 때인 것 같습니다.
그래서인지 최근에는 UI에 관심이 많이 생기고 있습니다. 물론 개발자로서 사용자의 편의를 우선시하는 것은 중요하지만, 일단 나의 편의부터 갖추고 싶다는 생각 때문입니다. 최근 보는 UI 포스팅 중 가장 좋아하는 포스팅은 다크모드에 관한 것입니다. 제가 가장 좋아하는 기능이기 때문입니다.
다크 모드 UI 디자인 팁 7가지 | 요즘IT
우리는 하루 중 거의 10시간을 디지털 화면 앞에 앉아 있습니다. 다양한 앱, 웹사이트, 디지털 기기의 눈부신 발전으로 인해 우리의 삶은 더욱 편리해졌죠. 하지만 그 결과 우리 모두 여러 건강
yozm.wishket.com
다크모드의 UI 컬러
다크모드에선 컬러를 어떻게 사용해야 할까요? | 다크모드는 사용자를 위해 있어야해요 다크모드를 지원해야 하는 이유는 사용자에게 좋은 경험을 제공하기 위해서예요. 다크모드 OS UI 사용 유
brunch.co.kr
블로그를 제작한다면, 꼭 다크모드 기능을 넣고 싶습니다. 아무래도 핵심 기능은 아니다보니 후순위로 밀릴테지만요. 그 날을 기약하며 간단하게 다크모드 프로젝트를 진행해보았습니다.
다크모드
다크모드는 UX를 개선하는 중요한 기능 중 하나입니다. 현대인은 밝은 화면을 볼 일이 점점 많아지고 있는데 다크모드가 눈의 피로를 줄여주기 때문입니다. 더군다나, 밝은 화면을 유지하는 데 비해 검은색 배경은 훨씬 더 적은 전력을 소비합니다.
제게 가장 중요한 이유는 UI 디자인 측면에서 다크모드가 들어가면 모던하고 세련된 느낌을 자아낼 수 있다는 점입니다. 특정 브랜드는 그러한 분위기를 강조하기 위해 다크모드를 기본으로 채택하는 경우도 있습니다.
선행연구
[React] 다크모드 구현하기 🌝🌚
리액트로 다크모드 구현하기 다크모드는 다양한 브랜드들과 웹 사이트에서 이제는 거의 필수라고 봐도 될 정도로 흔하게 적용되는 기능 중 하나이다. 나 역시 휴대폰, 노트북, 채팅 어플 등에서
jeongeum1202.tistory.com
리액트 다크모드 구현하기 feat. styled-components & context API
사용자 경험을 최상으로 이끌어주는 디자인 트렌드 다크모드 UI.애플, 구글, 인스타그램, 페이스북 등 세계적인 브랜드들이 이 다크모드 기능을 애용하기 시작하며 UI/UX에 필수적인 기능 중 하나
velog.io
이 프로젝트 역시 TypeScript로 마이그레이션하였지만, 이전 프로젝트와 달리 큰 비지니스 로직이 없기 때문에 어렵지 않게 마이그레이션할 수 있었습니다.
프로젝트 진행
사실 다크모드는 css적 요소가 훨씬 강한 기능이라고 생각합니다. 최대한 이 프로젝트에서 새로운 것을 얻어가고 싶어 전역 상태라이브러리와 CSS 변수를 이용해보았습니다.
많은 선행 프로젝트에서 자바스크립트로 직접 스타일을 변경하는 JS-in-CSS 방식을 사용하였으나, 이 방식은 프로젝트의 크기가 커질수록 런타임에 오버헤드를 더합니다. 이 부분에 관해 다음 포스팅을 참고하면 좋을 것 같습니다.
(번역) 우리가 CSS-in-JS와 헤어지는 이유
원문: https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b
junghan92.medium.com
따라서, CSS Variables 방식만을 이용해 제작해보려고 했습니다.
CSS Variables 방식만을 채택하려했기 때문에, 파일구조는 비교적 단순합니다.
App.tsx
const themeState = atom({
key: 'themeState',
default: 'light',
});
const DarkMode = () => {
const [theme, setTheme] = useRecoilState(themeState);
useEffect(() => {
document.body.setAttribute('data-theme', theme);
}, [theme]);
themeState는 현제 테마를 저장하는 atom입니다. 기본 값은 light며, DarkMode 컴포넌트는 themeState의 상태를 가져와 다크 모드나 라이트 모드로 변경합니다.
하지만 클릭이벤트가 일어나면 어떻게든 모드가 변경되어야하는데, js 폴더에서 css 파일을 건들이지 않고 구현하는 방법을 고안하지 못해 결국 setAttribute 함수를 사용하고 말았습니다.
data-theme 속성을 통해 다크모드를 적용한다면, CSS에서 미리 테마별로 스타일을 정의해두었을지라도 JS가 UI 스타일링에 간접적으로 개입하게 됩니다. 그렇다면 이것을 JS-in-CSS를 피했다고 볼 수 있을까요?
저는 이게 충분히 JS와 CSS의 결합을 나타내며, JS-in-CSS 패턴에 속한다고 생각합니다.
return (
<div className='center'>
<p className='cute'>
나의 작고 귀여운 {theme === 'light' ? '라이트' : '다크'} 모드
</p>
<div className='emotion'>
현재 기분은 {theme === 'light' ? '🌝' : '🌚'} 이다
</div>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
테마 변경
</button>
</div>
);
};
export default DarkMode;
그래도 다음 프로젝트가 기다리고 있으니 나머지 jsx 파일도 완성해보았습니다.
index.css
:root {
--light-background: #f0f0f0;
--light-color: #333;
--dark-background: #232425;
--dack-color: e0e0e0;
--button-color: #fff;
--button-hover-color: #555;
--dark-button-background: #444;
--dark-botton-color: #f5f5f5;
--dark-hober-background: #666;
--emotion-light: #d1a23f;
--emotion-dark: #4cf3c1;
}
body[data-theme='light'] {
background-color: var(--light-background);
color: var(--light-color);
}
body[data-theme='dark'] {
background-color: var(--dark-background);
color: var(--dack-color);
}
button {
background-color: var(--light-color);
color: var(--button-color);
border: none;
padding: 12px 24px;
font-size: 1rem;
cursor: pointer;
border-radius: 25px;
margin-top: 20px;
}
button:hover {
background-color: var(--button-hover-color);
transform: scale(1.05);
}
body[data-theme='dark'] button {
background-color: var(--dark-button-background);
color: var(--dark-botton-color);
}
body[date-theme='dark'] button:hover {
background-color: var(--dark-hober-background);
}
.center {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
text-align: center;
}
p,
div {
margin: 5px 0;
font-size: 1.3rem;
line-height: 1.6;
}
.cute {
font-weight: bold;
}
.emotion {
color: var(--emotion-light);
font-size: 1.5rem;
}
body[data-theme='dark'] p,
body[data-theme='dark'] div {
background-color: rgba(0, 0, 0, 0.2);
}
body[data-theme='dark'] .emotion {
color: var(--emotion-dark);
}
이건 CSS 파일입니다. 무척 간단한 다크모드를 CSS Variables로 구현하니, 오히려 코드 재사용성에 도움이 되기보다 복잡함만 취하게 된 것 같은 느낌이 있었습니다. 색을 재활용할수록 빛을 발하는 방식이니, 조금 더 복잡한 프로젝트에서 도움될 것 같은 방식이라고 생각합니다.
TypeScript로 마이그레이션
마이그레이션은 너무 간단한 프로젝트라 해줄 것이 없었습니다. 굳이 타입을 명시할 수 있었지만, 이미 타입추론이 완전히 되어있어 굳이 다룰 일이 없었습니다. 나름 TypeScript 토이 프로젝트였는데 아쉽습니다😬
회고
해당 프로젝트에서 가장 중점에 두었던 부분은 JS를 사용하지 않고 CSS Variables만 이용해 다크모드를 구현하는 것이었습니다. 하지만 setAttribute를 이용하는 순간 간접적으로 JS를 이용하게 되는 것이었죠. 회고록을 작성하며 이 부분을 알았기 때문에, 온전히 CSS만을 이용해 다크모드를 구현하는 것이 힘들지 않을까하는 결론이 나왔습니다.
만약 미디어쿼리를 이용해, 시스템 테마 설정에 의해 다크모드를 구현하는 것은 온전한 CSS Variables로만 가능하지만 클릭 이벤트로 다크모드를 제어하는 순간 JS 요소는 배제할 수 없을 것 같다는 결론이 났습니다.
다음에는 현업에서 다크모드를 구현할 때 JS-in-CSS를 사용하는지, 다크모드 정도의 가벼운 기능이라면 오버 헤드를 감내할만한 수준인지에 대한 추가 학습을 진행해보겠습니다.
해당 프로젝트 진행 과정이 담긴 깃허브 링크입니다.
GitHub - mindaaaa/react-ts-dark-mode: React + TypeScript Dark Mode Toggle
React + TypeScript Dark Mode Toggle. Contribute to mindaaaa/react-ts-dark-mode development by creating an account on GitHub.
github.com
'Oops, All Code! > 📝 Study Notes' 카테고리의 다른 글
[React+TS] 달력 기반 투두 리스트로 확장, UI/UX와 상태 관리의 조화 (0) | 2024.11.11 |
---|---|
[React+TS] 투두리스트와 다크모드 결합을 통해 알아본 타입 좁히기 (0) | 2024.11.04 |
React 순차적 계산기: TypeScript로 마이그레이션 (0) | 2024.09.22 |
소프트웨어공학 과제로 역할 분담하기 (0) | 2024.09.19 |
[Conventional Commits] 커밋 메시지 작성 가이드 (0) | 2024.09.02 |
- Total
- Today
- Yesterday
- react
- 트러블슈팅
- 프로토타입
- 플리마켓운영
- 대학생팝업스토어
- 플리마켓후기
- 서평
- 프론트엔드
- 경험플리마켓
- 코딩테스트
- js
- 일급객체
- 도서추천
- 소사벌
- javascript
- 카드뉴스
- 비즈플리마켓
- 프리코스
- 도서리뷰
- 회고
- 카페추천
- 타입좁히기
- 책추천
- 어휘력
- 우아한테크코스
- 소사벌맛집
- typescript
- 대학생플리마켓
- 어른의어휘공부
- 안성스타필드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |