개요

Dark Theme 은 기존의 밝은 색 조합으로 이루어진 서비스를 어두운 색의 모드로도 사용할 수 있게 해주는 UX 요소이다.

원래 모바일 앱에서 처음 시작되었지만, 요즘에 Facebook, Naver 등 대형 웹 사이트에서 적용이 되며 웹에서도 유행처럼 번지고 있다.

그리고 이번에 나도 드디어 개인 프로젝트에 Dark Theme 을 적용할 수 있었다.

Dark Theme 을 적용하는 다양한 방법이 있지만 내가 선택한 방법은 CSS 변수를 사용하는 방법이다.

어떻게 기능을 구현하게 되었는지 자세한 과정을 풀어보려 한다.

구현 방법 조사

최근 Dark Theme 이 구현된 사이트를 만날 때 마다 반가운 마음으로 HTML, CSS source 를 살펴 봤다.

그리고 기본적으로 HTML 과 CSS 를 사용해 기능을 구현하며 각각의 역할 이 있다는 것을 알게되었다. 그리고 그 역할을 구현하기 위한 방법을 두 가지씩 찾을 수 있었다.

  • HTML

    역할 : 현재 페이지가 dark 모드인지 light 모드인지 구분한다.

    구현 방법 1 : 상위 HTML 요소의 태그에 dataset 속성으로 구분

    <html data-dark="true">
      <!-- 또는 "false" -->
      ...
    </html>
    

    구현 방법 2 : HTML 요소의 class 명 또는 ID 명으로 구분

    <html class="dark">
      <!-- 또는 "light" -->
      ...
    </html>
    
  • CSS

    역할 : darklight 각 모드에 적용할 style 을 각각 부여한다.

    구현 방법 1 : CSS 선택자로 각 모드를 나타내는 HTML 요소를 구분해 각각의 style 작성

    html.dark .myDiv {
      /* class 명이 `dark` 인 html 태그의 하위에 있는 .myDiv 선택 */
      /* ...style */
    }
    
    html.light .myDiv {
      /* class 명이 `light` 인 html 태그의 하위에 있는 .myDiv 선택 */
      /* ...style */
    }
    
    /* class 가 아니라 `#` 를 사용해 ID 를 선택해도 무관 */
    

    구현 방법 2 : CSS 변수와 var() 함수 사용

    html[dataset="dark"] {
      --bg-color: #333333;
    }
    html[dataset="light"] {
      --bg-color: #ffffff;
    }
    
    .myDiv {
      background-color: var(--bg-color);
    }
    

사실 HTML 의 경우 어떤 방법을 선택하든 코드에 큰 영향을 끼치진 않는다. dataset 속성을 다루느냐 class (또는 id) 를 다루느냐의 차이일 뿐.

중요한 것은 CSS 이다.
어떤 방법을 따르느냐에 따라 작성하는 코드의 모양이 크게 차이나기 때문이다.

기존 웹사이트들을 예시로 각 방법들의 장단점을 파악해봤다.

1. CSS 선택자를 활용한 방법

대표 적용 사이트 : Naver
(HTML 은 방법 1 - dataset 속성 이 사용되었다.)

Naver - Light Theme

Naver - Dark Theme

네이버의 각 Theme 모드 별 화면이다.

특징은 다음과 같다.

  1. <html> 태그에 data-dark 라는 attribute(속성) 를 선언해주고 각각 truefalse 로 구분하고 있다.

    참고로 JavaScript 에서 data-xx 로 이름 붙인 속성에 접근하는 방법은 {해당 html 요소}.dataset.xx 이다.

  2. CSS 는 Light Theme 이 default 로 작성되었고 html[data-dark=true] (<html> 태그 중 data-dark=true 속성이 있는 요소를 지정하는 CSS 선택자)의 하위 컴포넌트들에 대해 스타일을 재선언 해주고 있는 듯 하다.

  3. Theme 모드를 변경할 때 reload 가 발생한다. 이건 왜 이렇게 구현했는지 이해가 잘되지 않는다. 화면이 다시 reset 되는게 UX 면에서 그다지 좋아보이지 않았다. 궁금하긴 하지만 너무 깊게 파고 들만큼 중요한 부분은 아니라고 생각한다. 단순히 ‘CSS 만 변경되는 것이 아닐 수 있겠다’ 고 추측하고 넘어가기로 했다.

다음은 장점과 단점이다.

  • 장점
    IE 에서도 Dark Theme 을 사용할 수 있다.
    CSS 선택자는 IE 에서도 문제없이 지원되기 때문이다.
    IE 사용률이 높은 한국의 대표 포털사이트인 Naver 가 CSS 선택자로 Dark theme 을 구현한 이유이지 않을까 싶다.

  • 단점
    CSS 에서 html[data-dark=true] 의 하위 요소들을 하나하나 재지정해가며 style 을 작성해야한다.

    예를 들어,

    /* Light Theme 영역 */
    #header {
      /* style... */
    }
    
    #main {
      /* style... */
    }
    
    /* Dark Theme 영역 */
    html[data-dark="true"] #header {
      /* style... */
    }
    html[data-dark="true"] #main {
      /* style... */
    }
    .
    .
    .
    
    

    HTML 요소들을 하나하나 새로 지정하며 dark theme 에서 변경될 style 을 작성해줘야한다.
    컴포넌트 트리가 깊어지면 정확히 어떤 컴포넌트의 style 을 변경해줄지도 하나하나 선택해야하므로 꽤나 복잡한 작업이 될 것이다.

    내가 적용할 사이트 또한 컴포넌트가 적지 않기 때문에 분명 엄청난 양의 반복 작업이 될 것 같았다. 물론 Naver 에선 내가 떠올리지 못한 smart 한 방법으로 작성했겠지만, 난 떠올릴 수 없었다..

2. CSS 변수와 var() 함수 사용

대표 적용 사이트 : Overreacted 블로그
(HTML 은 방법 2 - class 명으로 구분 이 사용되었다.)

Overreacted 는 Facebook React 팀의 개발자 Dan Abramov 님 의 개인 기술 블로그이다.
우연히 알게된 이 블로그에서도 Dark Theme 을 찾을 수 있었다.

Dan's blog - Light Theme

Dan's blog - Dark Theme

이 블로그의 Dark Theme 구현 특징은 아래와 같다.

  1. <body> 태그의 classdarklight 모드를 구분하고 있다.

  2. prefix -- 가 붙은 CSS 변수를 사용하고 있다.

  3. css transition 을 적용해 색 전환이 부드러워 UX 면에서 뛰어나다.

Facebook 웹사이트 또한 이런 방식으로 Dark theme 을 구현했다.

다음은 장점과 단점이다.

  • 장점
    CSS 변수를 사용해 각 Theme 에 따라 변수의 값만 변경해주었다. 즉, 하위 html 요소들을 재지정하며 style 을 다시 작성할 필요가 없다.
    그리고 가독성 높은 CSS code 를 작성할 수 있다.

  • 단점
    CSS 변수와 var() 함수 문법은 IE 에서 지원하지 않는다.

Cross Browsing (IE)

이제 위의 두 방법이 CSS 문법의 IE 지원여부로 나뉜다는 것을 알고 있다.
그럼 위 웹사이트들은 IE 에서 어떻게 서비스하고 있는지 알아보자.

1. Naver

Naver - IE

CSS 선택자를 이용한 Naver 는 IE 에서도 똑같이 Dark Theme 기능을 사용할 수 있었다.

2. Facebook

Facebook - IE

CSS 변수와 var() 함수 를 이용한 Facebook 은 구 버전 UI 를 서비스하고 있다.
Dark Theme 기능은 Chrome 등 modern browser 에서 확인할 수 있는 새 버전의 UI 에서만 제공된다.

3. Overreacted

Dan's blog - IE

마찬가지로 CSS 변수와 var() 함수 를 이용한 Overreacted 블로그는 IE 에서 색이 완전히 깨져버렸다. 개인 블로그라 사실 Cross-browsing 까지 신경쓸 필요는 없었을 것이다.

React 프로젝트에 적용하기

나는 CSS 변수와 var() 함수를 사용한 방법 으로 프로젝트에 Dark Theme 을 구현하기로 했다. 이유는 아래와 같다.

  • CSS 변수를 사용해보고 싶었다.
  • 유지보수성이 뛰어난 CSS Code 를 작성할 수 있다.

글이 너무 길어져 직접 작성한 코드는 다음 글에 기록했다. [다음 글 링크]

출처