크롬 개발자 도구 perfomance탭 알아보기

크롬의 개발자도구의 성능분석 탭을 사용해보자.
다음 문서의 예시를 따라 진행하였다.

동작원리

성능 분석은 웹페이지를 녹화하고 분석하는 방식으로 진행된다.

시작하기

성능(Perfomance)탭은 크롬 개발자도구에 있다.

다음과 같은 순서로 시작할 수 있다.

  1. 개발자 도구를 열고 perfomance탭에 들어간다.

성능 탭

  1. 예제를 신행하고 싶을 경우 다음 링크를 시크릿 모드에서 연다. 크롬 익스텐션이 성능 측정에 노이즈를 발생시킬 수 있기 때문이다.

  2. 시작한다.

    • 초기 랜더링부터 분석 하고싶은 경우 새로고침 버튼을 누르면 된다.
    • 혹은 성능을 분석하고 싶은 시점 전에 녹화버튼을 누르면 된다.
    • stop버튼을 눌러 녹화를 중지할 수 있다.
    • 너무 길게 녹화할 필요 없이 3~4초 정도 녹화하면 된다.

모바일 CPU 시뮬레이션

모바일 기기는 데스크탑이나 노트북에 비해 CPU의 성능이 좋지않다.
CPU의 성능을 일부러 저하시켜 모바일 환경에서의 시뮬레이션을 할 수 있다.

  1. 성능 탭에서 스크린샷(screenshot)이 활성되어있는지 확인한다.
  2. 캡쳐 설정(톱니바퀴)를 클릭한다.
  3. 아래의 CPU제한없음에서 CPU에 제한을 준다.
    예시에선 2배 제한을 줬지만 예전 아티클인지 4배 8배만 남아있어서 4배 제한을 주었다.

모바일 시뮬레이션

결과 분석

위의 시작하기에서 얻은 결과를 분석해보자.

분석 결과

초당 프레임 분석

애니메이션의 성능을 측정하는 주요 지표는 초당 프레임수(FPS)이다.
사용자들은 애니메이션이 60 FPS로 실행될 때 행복하다.

  1. FPS 차트
    빨간색 막대를 볼 때마다 Framerate가 저하된다는 의미이다.
    녹색 막대가 높을수록 FPS가 높다.

    FPS 차트

  2. CPU 차트
    CPU 차트의 색상은 그림에서 아래의 요약탭의 색상과 일치한다.
    색칠이 되어있을 수록 CPU를 사용했다는 의미이다.
    장시간 색칠되어있을 경우 최적화가 필요하다는 의미이다.
    CPU 차트

FPS,CPU 차트 위에 마우스를 올리면 해당 시점의 스크린샷을 보여준다.

  1. 프레임
    프레임
    마우스를 올리면 특정 프레임에 대한 FPS를 보여준다.
    위 사진과 Frame 영역의 색이 다른 건 사각형 수를 조절했기 때문이다.

    • 실시간 FPS 추정치
      ctrl+shift+p를 누르고 FPS 추정치를 확인할 수 있다.
      실시간 FPS 추정치

    다음과 같이 실시간으로 FPS 추정치를 보여준다.

병목 현상 찾기

  1. 요약 탭

    • 선택한 이벤트가 없는 경우 활동 내역을 보여준다.
    1. 사각형 수가 없는 경우
      유휴상태가 많고 작업이 여유로움을 알 수 있다.

    사각형 수가 없는 경우

    1. 사각형 수가 많은 경우
      사각형 수가 늘어날 수록 랜더링에 대부분의 시간이 쓰이는 것을 알 수 있다.

    사각형 수가 많은 경우

    1. 사각형 수가 많은 경우+ 최적화
      여전히 랜더링에 대부분의 시간이 쓰이지만
      애니메이션을 담당하는 스크립트에서 작업시간을 줄였음을 알 수 있다.

    최적화를 해줄 경우

  2. 기본 탭
    특정 프레임을 클릭하고 기본탭을 열어 시간 경과에 따른 메인스레드의 활동도를 볼 수 있다.
    각 막대는 이벤트이며 막대의 길이가 길 수록 오래 걸렸다는 것을 의미한다.
    또한 막대가 쌓인 것은 아래의 이벤트가 위의 이벤트를 발생 시켰다는 의미이다.
    기본 탭

    또한 이벤트를 클릭하여 단일 이벤트에 대한 정보를 확인할 수도 있다.
    기본 탭 단일 이벤트

    호출 스택을 통해 이벤트를 발생시킨 소스코드 또한 확인할 수 있다.

    이벤트를 발생시킨 소스코드

프론트엔드 개발에 도움되는 사이트 모음

HTML

CSS

CSS Validation

Palate

Gradient

Font

Icon

optimization

  • PageSpeed

    페이지의 성능을 검사하고 개선해야할 사항을 알려준다. 한글을 지원한다.
    https://pagespeed.web.dev/

hexo + icarus 블로그 lighthouse 성능지표 개선하기

블로그의 성능면에서 개선할 것이 없나 고민하던 중 크롬에서 제공하는 성능지표인 lightouse 분석을 하고 개선하기로 하였다.

lighthouse

내 블로그의 lighthouse 점수이다.
퍼포먼스쪽이 처참하다.
어차피 다 수정해야겠지만 빨간 권장사항들을 먼저 수정하기로 하였다.
lighthouse 점수

적절한 이미지 size 사용하기

첫 번째 권장사항이다. 적절한 크기의 이미지를 사용하라는 지침이다.
나는 블로그에 사진을 업로드 할 때 따로 이미지의 크기를 지정해주지 않아 리페인트 작업에 많은 리소스를 사용한 것 같다.
또한 png파일들을 주로 사용하다보니 이미지의 크기가 큰 것도 영향이 있었다.

Serve images that are appropriately-sized to save cellular data and improve load time.
lighthouse 이미지 개선

정적 이미지 사용하기

현재 나는 깃허브 issue를 이용해 이미지를 관리하고 있다.
또한 이미지 형식이 png라 많은 리소스를 사용한다.
이를 수정해주었다.

source에 postimage라는 폴더를 새로 만들어주었다.

폴더구조

정적파일을 생성할 떄에 source안의 폴더들은 public안에도 생성된다.

정적파일 폴더구조

이 작업들을 하나씩 다 해야한다..

이미지의 크기 명시하기

이미지는 파일 자체의 크기도 크고 이미지 사이즈를 명시하지 않으면 리페인트 작업에 리소스를 사용하게 된다.
이미지 태그를 사용하여 사이즈를 명시하고 이미지를 불러주었다.

수정 전

1
![lighthouse 개선](https://user-images.githubusercontent.com/79688915/144422469-6fc049ec-191b-4ca1-ae0e-d667723971d2.png)

수정 후

1
<img src="/postimage/hexo_icarus_블로그_성능지표_개선하기/성능.png" alt="lighthouse 개선" width="650" height="300px">

해결 방안

lighthouse 개선

hexo SEO 적용하기

지난 글들에 이어 블로그에 SEO를 적용해보았다.

크롤링 개선

  • description

    게시글마다 description을 추가해주었다.
    1
    2
    3
    4
    5
    6
    7
    8
    ---
    title: SEO 알아보기(2)
    date: 2021-11-30 16:15:36
    tags: [seo]
    description: GOOGLE 검색 센터를 통해 검색엔진 최적화(SEO)에 대해 더 자세하게 알아보자.
    category: [seo]
    toc: true
    ---

호환성 검사

블로그의 HTML을 검사하였다.

HTMl 검사

<meta>태그가 있다.
HTMl 검사

./theme/icarus/layout/common/head.jsx

1
2
3
4
5
{
meta && meta.length ? <MetaTags meta={meta} /> : null;
}

<title>{getPageTitle(page, config.title, helper)}</title>;

다만 이 부분은 hexo 내부 로직이라 혹시나 발생할 사이드이펙트 때문에 수정하지는 않았다.

검색엔진에 등록하기

검색엔진에 내 사이트 정보를 등록하였다. 안 하여도 되지만 조금 더 빨리 크롤링 된다고 한다.
등록 뒤에도 며칠 기다려야 한다..! 사이트마다 어떻게 등록했는지는 사진을 찍어두지 못하였다.

  • 네이버 웹마스터 도구 에서 사이트를 등록하였다. 등록 후엔 간단 체크로 체크해볼 수 있다. 사이트맵과 rss제출도 할 수 있다.

    ./theme/icarus/layout/common/head.jsx 소유권을 인증하는 <meta>태그를 삽입하였다.

    1
    <meta name="naver-site-verification" content="...">
  • Google

    구글 서치 콘솔에도 등록하였고, 사이트맵과 rss제출도 할 수 있다.

    ./theme/icarus/layout/common/head.jsx 소유권을 인증하는 <meta>태그를 삽입하였다.

    1
    <meta name="google-site-verification" content="...">
  • daum

    다음 검색 등록은 rss제출과 사이트맵 제출을 요구하지 않았다.

플러그인

hexo에선 SEO적용을 돕는 여러 플러그인을 지원한다.
나는 아래와 같은 플러그인을 적용하였다.

  • hexo-autonofollow

    hexo-autonofollow는 블로그 내의 <a>태그마다 자동으로 nofollow 속성을 추가해주는 플러그인이다.
    사이트와 연관되지 않은 url들의 크롤링을 막는 기능을 한다.

    다음과 같이 설치할 수 있다.

    1
    npm install hexo-autonofollow --save

    _config.yml 파일에 다음과 같이 적용한다.

    1
    2
    3
    4
    5
    nofollow:
    enable: true
    exclude: //제외할 호스트
    - exclude1.com
    - exclude2.com
  • hexo-generator-seo-friendly-sitemap

    hexo-generator-seo-friendly-sitemap은 자동으로 sitemap을 생성해주는 플러그인이다.

    다음과 같이 설치할 수 있다.

    1
    npm install hexo-autonofollow --save

    _config.yml 파일에 다음과 같이 적용한다.

    1
    2
    3
    4
    sitemap:
    path: sitemap.xml //sitemap의 경로
    tag: false
    category: false
  • hexo-generator-seo-friendly-sitemap

    hexo-generator-seo-friendly-sitemap은 자동으로 sitemap을 생성해주는 플러그인이다.

    다음과 같이 설치할 수 있다.

    1
    npm install hexo-autonofollow --save

    _config.yml 파일에 다음과 같이 적용한다.

    1
    2
    3
    4
    sitemap:
    path: sitemap.xml //sitemap의 경로
    tag: false
    category: false
  • hexo-generator-feed

    hexo-generator-feed은 자동으로 RSS 피드를 생성해주는 플러그인이다.

    다음과 같이 설치할 수 있다.

    1
    npm install hexo-generator-feed --save

    _config.yml 파일에 다음과 같이 적용한다.

    1
    2
    3
    4
    feed:
    type: rss2 //rss
    path: rss2.xml //경로
    limit: 20 //url수
  • hexo-generator-robotstxt

    hexo-generator-robotstxt은 자동으로 robots.txt를 생성해주는 플러그인이다.

    다음과 같이 설치할 수 있다.

    1
    npm install hexo-generator-robotstxt --save

    _config.yml 파일에 다음과 같이 적용한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    feed:
    robotstxt:
    useragent: "*"
    disallow:
    - /one_file_to_disallow.html
    - /2nd_file_to_disallow.html
    - /3rd_file_to_disallow.html
    allow:
    - /one_file_to_allow.html
    - /2nd_file_to_allow.html
    - /3rd_file_to_allow.html
    sitemap: /sitemap.xml

ref

hexoplugin

마무리

SEO작업을 마무리 하였고, 결과 반영까지 기다리는 중이다..!
최소 5일정도 걸린다고 하니 그 떄까지 기다려보고 문제가 있으면 다시 수정해보아야겠다.

SEO 알아보기(2)

지난글에 이어서 SEO에 대해서 더 자세하게 정리하려 한다.

Google 검색 센터의 advanced를 참고하였다.

사이트맵

사이트맵은 사이트의 중요한 페이지를 Google에 알려주는 방법이다. 사이트맵은 다음과 같이 접근할 수 있는 url과 업데이트 빈도등의 정보를 제공한다. 사이트맵을 사용할 경우 Google에서 크롤링할 페이지를 찾고 우선순위로 지정한다.

내 블로그의 사이트맵이다. 접근할 수 있는 url 정보와 업데이트 정보를 저장하고 있다.
사이트맵

사이트맵

RSS피드

사이트의 최신 컨텐츠를 제목과 본문을 포함한 xml파일이다.
검색엔진은 RSS 피드를 주기적으로 재방문하여 크롤링한다.

내 블로그의 RSS피드이다. 제목을 포함한 컨텐츠 정보를 저장하고 있다.
사이트맵

robots.txt

크롤러가 사이트에서 엑세스 할 수 있는 URL을 검색엔진 크롤러에 전달하는 파일이다. 콘텐츠가 크롤링 서버에 문제를 일으킬 수 있는 경우 사용한다.

일반적으로 다음과 같이 작성된다.
참고로 모든 url은 암시적으로 허용된다.
allow 명령어는 disallow 명령어를 재정의 하는데에 사용된다.

robots.txt

1
2
3
4
5
6
7
8
9
10
// 전부 차단하는 예시
User-agent:*
Disallow: /

//Googlebot과 AdsBot의 크롤링을 허용하는 예시
User-agent:Googlebot
User-agent:AdsBot-Goggle
Allow: /article //구글 봇과 AdsBot에 /article 크롤링 허용

Sitemap: '사이트맵 url' //사이트맵 정보

브라우저 호환성 고려하기

브라우저마다 웹사이트 해석방식이 다르다.
개별 브라우저 작업에 의존하지 않도록 해야한다.

  • 가능한 많은 브라우저에서 작동하는지 테스트하기

    모양과 기능이 어떻게 작동하는지 확인해야한다.

  • 올바르고 오류가 없는 HTML 작성하기

    유효한 HTML과 CSS를 이용하여 작성한 다음 테스트를 거쳐야한다. 아래서 언급할 검사도구를 이용해 쉽게 검사할 수 있다.

  • 문자 인코딩 지정

    페이지의 텍스틀 랜더링할 문자 인코딩을 지정해야한다.
    <head>에 아래 내용을 추가해주면 된다. utf-8 기준이다.

    1
    <meta charset="utf-8" />
  • 누구나 사용할 수 있는 기술 적용하기

    flash나 activex와 같은 지원되지 않는 기술을 피해야한다.

브라우저 호환성 검사도구

Nu HTML Checker
w3c CSS Validation Service

SEO 알아보기(1)

블로그에 SEO를 적용하는 도중 GOOGLE 검색 센터에서 제공하는 SEO관련 문서를 읽고 정리해보았다.

검색 엔진의 작동방식

  1. 크롤링

  • 크롤러를 이용해 웹을 검색하여 신규 또는 업데이트 된 페이지를 찾는다.
    그 후발견된 페이지의 주소(또는 페이지 URL)을 큰 목록에 저장한다.
  1. 색인 생성

  • 크롤링을 통해 파악한 페이지를 방문하여 각 페이지에 관한 정보를 분석한다.
    페이지의 콘텐츠, 이미지, 동영상 파일을 분석하여 어떤 페이지인지 파악한다.
    이 정보는 데이터베이스에 저장된다.
    이 과정은 HTMl 파일을 분석하여 진행된다.
    만약 HTML 파일에 내용이 없고 js파일을 통해서만 수정하는 경우 위 작업이 어려울 수 있다.
  1. 검색 결과 게재

  • 검색 시 사이트마다 내부 알고리즘을 통해 최적의 검색결과를 선정한다.

SEO(Search Engine Optimization)

  • 검색엔진의 작동원리를 이용하여 검색결과에 잘 노출되도록 하는 과정이다.
  1. 크롤링 개선하기

  • 페이지가 올바르게 표시되는지도 기준이다.
    페이지의 모든 이미지와 기타 요소가 바르게 랜더링되는지 확인해야한다.
    위 작업은 모바일 친화성 테스트에서 할 수 있다.

  • 사이트맵을 이용하기
    홈페이지 내부에서 중요한 정보와 페이지들에 연결될 수 있도록 구성해야한다.
    혹은 관련 url을 모두 제공해주는 사이트맵(xml)파일을 만들어서 구글에 제공하는 방법도 있다.

  • GOOGLE 웹마스터 가이드라인 잘 지키기
    광고링크, 구매한 링크, 댓글에 포함된 링크등은 GOOGLE에서 수집하지 않는다.
    이런 링크들은 <a>태그에 nofollow 속성을 추가하서 크롤링을 막을 수 있다.

  1. 색인 생성 개선하기

    콘텐츠 파악이 쉽도록 해야한다.
  • 페이지 제목은 짧고 의미있게 만들어야 한다.
    <head>요소 내에 <title> 태그를 꼭 사용해야 한다.
    반복되는 텍스트나 상용구 텍스트는 스팸처리 될 수 있다.

  • 페이지의 주제를 전달하는 페이지 제목을 사용한다.

  • 메타 설명 태그를 사용해야 한다.

    메타 태그는 검색엔진에 페이지의 내용을 요약해서 전달해준다. 스니펫으로 사용될 수 있기 때문에 추가하는것이 권장된다. 메타 설명 태그는 컨텐츠를 정확하게 요약 해야한다.
  • 강조해야할 내용의 경우 표제 태그를 사용해야 한다.
    <em>이나 <strong>태그를 사용하는 것이 권장된다.

  • 이미지나 비디오의 경우 alt(대체 텍스트)를 꼭 적어준다.
    텍스트를 통해 주석을 달아야 검색엔진이 이해하기가 더 쉽다.

  1. 검색 결과 게재 개선하기

  • 빠르게 로드되는 모바일 친화적인 페이지를 만들어야 한다.
    반응형 웹이 권장된다.

  • 유용한 컨텐츠를 포함하고 최신 상태로 유지한다.

  • GOOGLE 웹마스터 가이드라인을 따른다.

마무리

다음 게시글에선 고급 검색엔진 최적화와 내가 어떤 부분에 최적화를 적용했는지 적어보려고 한다.

관련 사이트

구글 모바일 친화성 테스트
네이버 사이트 간단 체크

ref

구글 검색센터
네이버 서치어드바이저
hexo plugin

카탈로그 수정

카탈로그의 위치를 수정하였다.

카탈로그는 아래 사진의 오른쪽에 저렇게 목차가 나오고 클릭할 경우 해당 부분으로 이동하는 위젯이다.

image

처음엔 카탈로그가 왼 쪽에 있고 고정되지 않아, 글의 목차와 내용을 간략하게 보려고 할 경우 카탈로그가 존재하는 위치까지 이동해주어야 했다.

카탈로그를 오른쪽에 배치하고 고정되도록 만들기로 하였다.

코드 살펴보기

개발자 도구를 열어 카탈로그에 position: fixed와 position:sticky를 추가해주었다.

왼쪽에 있는 다른 위젯들과 겹쳐 가독성이 상당히 안 좋았다.

레이아웃의 html을 살펴보았다.

image

게시글이 작성된 부분의 css이다.

1
"column order-2 column-main is-9-tablet is-9-desktop is-9-widescreen"

왼 쪽부터 클래스명의 order-1, order-2 등으로 레이아웃을 정하는 듯 하였다.

또한 is-9-tablet 과 같은 클래스는 기기마다 차지할 크기를 알려주는 클래스명이다.

개발자도구에서 클래스명이 column 상위 태그에 다음과 같은 HTML을 추가해 보았다.

1
<div class="column order-3 column-main is-9-tablet is-9-desktop is-9-widescreen">hihi</div>

성공적으로 추가되었다.
image

레이아웃 수정하기

성공한 줄 알았으나 실제 카탈로그에 적용하니 레이아웃 밖으로 나갔다 ㅠ

클래스명을 살펴보니 클래스명을 통해 설정한 레이아웃과 위젯의 비율이 오버한 것 같았다.

nav-bar를 아래의 영역은 hexo\themes\icarus\layout\layout.jsx에서 관리된다.

총 column의 합이 12가 되도록 수정해주어야 한다.

columncount가 1일 경우 12 2일 경우 9 3일 경우 8을 사용하도록 수정해주었다.

image

위젯 수정하기

hexo\themes\icarus\layout\common\widgets.jsx또한 수정해주었다.

우측에 카탈로그를 추가하게 되면 column count가 왼쪽 위젯 게시글 오른쪽 위젯으로 3이 된다.

위에서 3일경우 8을 사용하도록 수정해주었기 때문에 3일때의 위젯의 레이아웃 비율을 2를 사용하여 합이 총 12(8+2+2)가 되도록 수정해주었다.

image

sticky 적용하기

개발자 도구를 열고 position:sticky를 적용하니 잘 되지 않았다ㅠ

widgets.jsx 파일을 살펴보니 is-sticky라는 클래스명이 있었다. 이를 개발자도구에 적용하니 제대로 작동하였다.

파일에서 찾아서 수정하려하니 생각보다 어려웠다.

그러던 중 widgets.jsx 파일을 살펴보니 columncount가 3이면 제일 오른쪽에 있는 모듈을 보이지 않게 해주는 함수를 찾았다.

내 경우 오른쪽에는 카탈로그 밖에 없고, 오른쪽에 다른 위젯이 있을 경우 겹치거나 보이지 않아서 가독성이 좋지 않다.

그래서 이부분에 is-sticky를 추가해주었다.

image

완성본

카탈로그

정상적으로 작동하게 되었다..!

hexo+ icarus 다크모드 구현하기

나는 다크모드를 아주 애용한다.

다크모드를 적용하며 유익한 경험이여서 글로 작성해두려고 한다.

hexo + icarus 작동원리

우선 hexo + icarus의 원리부터 알아야한다.

아래에 작성할 모든 디렉터리는 hexo루트 폴더 기준이다.

루드 디렉토리의 내부 파일을 수정한다.

그 후 정적파일인 public 폴더를 생성하고 배포하면 사이트에 반영되는 구조이다.

1
hexo generate --deploy

커스텀 디자인을 하기 위해선 이 ./themes 폴더를 수정해야한다.

버튼 만들기

./themes/icarus/layout/common 폴더엔 icarus의 여러 요소들의 jsx파일이 작성되어있다.

hexo\themes\icarus\layout\common\navbar.jsx파일에서 검색버튼 옆에 버튼을 만들었다.

1
<button type="button" id="changeModeButton" class="navbar-item" />

버튼을 커스텀하기

./themes/icarus/include/style 폴더엔 여러 css들이 작성되어있다.

확장자가 styl인데 기존에 작성된 파일을 보니 들여쓰기로 depth를 관리하는 듯 했다.

그리고 이 파일들은 ./themes/source/css/style.styl에서 모두 import되고 이를 빌드하여 ./public/css에 하나의 css파일을 생성한다.

./themes/icarus/include/style/navbar.styl 파일에 다음과 같은 내용을 추가하였다.

1
2
3
4
5
6
#changeModeButton {
background: none;
border: none;
cursor: pointer;
font-size: 2rem;
}

버튼에 로직 추가하기

./themes/source/js 폴더엔 여러 js파일들이 있다.

이는 ./themes/icarus/layout/common/scripts.js에서 한 번에 모아서 ./public/index.js에 작성된다.

여기에 다크모드 버튼 관련 파일을 작성하였다.

페이지에 접속 시 로컬스토리지를 확인하고 darkMode가 true일경우 html의 body에 darkMode 태그를 추가하고 버튼의 모양을 달 모양으로 해주었다.

값이 존재하지 않을경우 버튼의 모양을 해 모양으로 해주었다. 기본 값은 다크모드의 미적용이기 때문에 따로 처리를 해주진 않았다.

그리고 버튼에 이벤트를 등록해주었다.

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
31
32
33
34
35
36
37
const darkModeButton = document.querySelector("#changeModeButton");

function init() {
loadDarkModeData();
darkModeButton.addEventListener("click", clickEvent);
}

const loadDarkModeData = () => {
const data = localStorage.getItem("darkMode");
const body = document.querySelector("body");
if (data === "true") {
darkModeButton.innerText = "🌙";
body.classList.add("darkMode");
} else {
darkModeButton.innerText = "🌞";
}
};

const setDarkMode = () => {
const body = document.querySelector("body");
if (body.classList.contains("darkMode")) {
darkModeButton.innerText = "🌞";
body.classList.remove("darkMode");
localStorage.setItem("darkMode", false);
} else {
darkModeButton.innerText = "🌙";
body.classList.add("darkMode");
localStorage.setItem("darkMode", true);
}
};

const clickEvent = () => {
setDarkMode();
console.log(localStorage.getItem("darkMode"));
};

init();

그리고 ./themes/icarus/layout/common/scripts.js에 아래 내용을 추가해주었다.

정확히 어떤 구조인지는 모르지만 main.js가 이런 식으로 작성되어 있길래 똑같이 적었다.

defer는 script로딩시 버튼이 없으면 안되기 때문에 추가해주었다.

1
<script src={url_for("/js/darkmode.js")} defer></script>

다크모드 css 추가하기

다음으로 darkmode.styl 파일을 작성해주었다.

처음 보는 확장자명이기도 했고 ./themes/include/style에 작성할지 ./themes/source/css에 작성할지 고민되었다.

고민끝에 include폴더는 컴포넌트마다의 css를 작성하는 느낌이 강해서 ./themes/source/css/darkmode.styl에 작성하였다.

css는 개발자 도구를 여러 하나하나 클래스명을 확인하며 적어주었다.

빌드과정에서 압축될 것이여서 하나씩 풀어 적었다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
body.darkMode
background-color: #171717;
color:#F9F9F9;
.navbar ,& .navbar-menu
background-color: #444444;
section,article,.card{
background-color: inherit;
color:inherit;
}
& .navbar-item
color:#F9F9F9;
&:hover{
color:#3273dc;
background-color:#393E46;
}
& .menu-list>li *{
color:rgba(255,255,255,0.9);
}

& .menu-list a:hover{
color:#3273dc;
background-color:#393E46;
}

& .menu-list a.is-active{
background:#141010;
}
& .is-active
color:#3273dc;
& article
& > * {
color:rgba(255,255,255,0.7);
};
& h1,h2,h3,h4,h5,h6{
color:rgba(255,255,255,0.9);
}
& .article-meta{
color:rgba(255,255,255,0.38);
}
& .card-content
& > * {
color:rgba(255,255,255,0.7);
};

& .title, .location{
color:rgba(255,255,255,0.9);
}

& .menu{
color:rgba(255,255,255,0.7);
}

& .level-start{
color:rgba(255,255,255,0.7);
}

& .menu-label{
color:rgba(255,255,255,0.9);
}

& .tag{
background:#444444;
color:rgba(255,255,255,0.7);
}
.searchbox-container
background:#444444;
.searchbox-input, .searchbox-close{
background:#444444;
color:rgb(255,255,255);
}
.footer{
background:#444444;
}
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #abb2bf;
background: #282c34;
}

.hljs-comment,
.hljs-quote {
color: #5c6370;
font-style: italic;
}

.hljs-doctag,
.hljs-keyword,
.hljs-formula {
color: #c678dd;
}

.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
color: #e06c75;
}

.hljs-literal {
color: #56b6c2;
}

.hljs-string,
.hljs-regexp,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
color: #98c379;
}

.hljs-built_in,
.hljs-class .hljs-title {
color: #e6c07b;
}

.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-type,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
color: #d19a66;
}

.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-title {
color: #61aeee;
}

.hljs-emphasis {
font-style: italic;
}

.hljs-strong {
font-weight: bold;
}

.hljs-link {
text-decoration: underline;
}


그리고 ./themes/source/css/style.styl에 import 해주었다.

1
@import './darkmode.styl'

정리

전체적인 로직은 다음과 같다.

  1. body.darkMode의 하위 태그들에 적용이 되도록 여러 css를 작성해둔다.
  2. 첫 접속시에 로컬스토리지에 darkMode 관련 값이 저장되어있는지 확인하고 알맞은 처리를 해준다. 새로고침시에 상태가 유지되게 하기 위함이다.
  3. 버튼 클릭시 다크모드가 적용되도록 이벤트를 추가해준다.(body태그에 darkMode 클래스를 toggle하도록)

완성본

다크모드가 적용될 경우 적용되지 않을경우의 버튼이 다르고 글자 색과 배경 색도 다르다.

다크모드 미적용 다크모드 적용

느낀 점

  1. styl 확장자 파일을 작성해보았다.
    • Stylus CSS파일이라고 하는데, 작성해보니 의외로 굉장히 편하였다.
  2. REACT가 아닌 jsx로 작성되어 이러한 파일들을 중앙에서 제어하여 빌드시 html을 만드는 과정에 대한 이해가 늘었다.
    • jsx문법을 이용하여 컴포넌트 단위로 파일을 작성하고 관리하는 것이 얼마나 가독성이 좋은지 다시 한 번 느꼈다.
  3. 역시 다크모드가 눈이 편하다
    • 다크모드가 최고다 ㅠ

아쉬운 점

  1. 구현을 하고 보니 코드블록이나 위젯에는 다크모드가 적용이 안 되었다.
    • 이것도 개발자 도구를 이용하여 css를 까보고 수정해야겠다.
  2. 모바일에서 레이아웃이 아쉽다.
    • 버튼을 추가하다보니 상단바에 스크롤바가 생겼다.
    • 이것도 수정해보아야겠다. 레이아웃에 손을 대거나 전체적으로 크기를 줄이는 방향으로 갈 것 같다.
    • 모바일
  3. 정신없이 작업하고 복기하며 메모하다보니 빠진 부분이 있을까봐 걱정된다.
    • 다음부턴 간략한 개요든지 사진을 틈틈히 찍어두어야겠다 ㅠ

+++ 수정

다크모드를 끄고 게시글에 접근시 다크모드가 적용되는 버그가 있었다.
로컬스토리지에 데이터가 string으로 저장되는데 if(data)의 형태로 확인해서 발생한 버그였다.

1
2
3
4
5
6
7
8
9
10
const loadDarkModeData = () => {
const data = localStorage.getItem("darkMode");
const body = document.querySelector("body");
if (data) {
darkModeButton.innerText = "🌙";
body.classList.add("darkMode");
} else {
darkModeButton.innerText = "🌞";
}
};

위 부분을 다음과 같이 변경하였다.

1
2
3
4
5
6
7
8
9
10
const loadDarkModeData = () => {
const data = localStorage.getItem("darkMode");
const body = document.querySelector("body");
if (data === "true") {
darkModeButton.innerText = "🌙";
body.classList.add("darkMode");
} else {
darkModeButton.innerText = "🌞";
}
};

hexo+icarus 위젯 삭제하고 댓글 기능 추가하기

위젯 없애기

블로그 내에서 표시되는 위젯들은 루트디렉토리의 _config.icarus.yml에서 수정 가능하다.

수정하려면 윗줄의 -를 포함하여 다음 -까지 위젯 관련 정보들을 지워주면 된다.
주석 줄에 있어서 -도 주석인 줄 알고 안 지웠더니 빌드에 실패하였다.
나는 카테고리나 태그같은 게시글 관련 위젯 말고는 전부 지워주었다.

위젯 윗부분에 donation도 삭제 해주었다.

1
2
3
4
- # 주석
position: ''
type: ''
(...)
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
31
32
33
34
35
36
37
# Table of contents widget configurations

- # Where should the widget be placed, left sidebar or right sidebar
position: right
type: toc
# Whether to show the index of each heading
index: true
# Whether to collapse sub-headings when they are out-of-view
collapsed: true
# Maximum level of headings to show (1-6)
depth: 3

# Recommendation links widget configurations

# Categories widget configurations

- # Where should the widget be placed, left sidebar or right sidebar
position: left
type: categories

# Recent posts widget configurations

- # Where should the widget be placed, left sidebar or right sidebar
position: left
type: recent_posts

# Archives widget configurations

- # Where should the widget be placed, left sidebar or right sidebar
position: left
type: archives

# Tags widget configurations

- # Where should the widget be placed, left sidebar or right sidebar
position: left
type: tags

댓글 기능 추가

disqus를 이용하였다.

사용방법이 무척 간단하다.

  1. disqus 접속한다.

    홈페이지
  2. I want to instal …를 클릭한다.

    선택 페이지
  3. 웹사이트 명을 입력해준다.
    이 정보는 shortname에 사용된다.
    아래의 shortname을 복사해둔다.

    설정하기
  4. Basic 요금제를 구독한다.

    무료 요금제를 고른다.
  5. Universal Code를 선택한다.

    목록에 없다 ㅠ
  6. icarus엔 shortname만 필요하다.
    configure를 눌러 다음으로 가고 정보를 입력해준다.
    website URL을 채워주면 된다.

    정보를 입력한다.
  7. 정책을 골라준다.
    큰 차이점은 basic은 비로그인 댓글도 허용하고
    strict는 로그인 댓글만 허용한다.
    다만 google, twitter, facebook 자동로그인을 사용할 수 있다.
    나는 strict을 골라주었다.

    정책
  8. dismiss를 누르고 hexo 루트디렉토리의 _config.icarus.yml 파일을 수정한다.

    1
    2
    3
    4
    5
    6
    comment:
    type: disqus
    # Disqus shortname
    shortname: "shortname"
    # Donate plugin configurations
    # https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Donation/
  9. 변경사항을 적용한다.

1
hexo clean & hexo generate --deploy & git add . & git commit -m "메시지" & git push origin main
  1. 변경사항이 적용되었음을 확인할 수 있다..!