본문 바로가기

Development/Web (HTML, CSS)

나의 마크다운 블로그 포스트 작성 루틴

image-20241114181354148

블로그 포스트를 작성할 때, 글의 구조와 가독성, 강조 효과 등을 적절히 표현하기 위해 Markdown을 활용한다. 키보드만으로 빠르게 콘텐츠를 구성할 수 있어 효율적이며, 작성한 글을 블로그에 복사해 붙여 넣었을 때 웹에서도 동일하게 볼 수 있는 장점이 있다. 여러 종류의 에디터 중 Typora를 선택한 이유와 이미지를 다루는 방법, 강조 스타일, 마크다운 다이어그램 등을 다루는 과정을 소개한다.


마크다운 작성과 에디터 선택

Notion은 개인적인 메모나 자료 정리에 탁월한 도구이지만, 블로그 포스트 작성에서는 Typora를 선택하였다. Typora는 실시간 미리보기를 제공하며, 작성 즉시 최종 모습을 확인할 수 있다는 장점이 있다. 또한 사진 자료의 자동 업로드를 지원해 이미지 경로 문제를 최소화하며, 문법이 기억나지 않을 때도 빠르게 툴팁을 이용해 작성할 수 있다.

  1. 자동 이미지 업로드 지원: Markdown 문서 내의 이미지 경로 문제를 해결하여 이미지 깨짐을 방지한다.
  2. 실시간 미리보기: Markdown 문법이 적용된 모습을 즉시 확인할 수 있다.
  3. 문법 툴팁 지원: 다양한 문법 툴팁이 있어 필요한 요소를 손쉽게 삽입 가능하다.

크게 위와 같은 이유로 Typora를 선택하였으며, 그 외에도 여러 에디터를 써본 결과 사용자화할 수 있는 정도와 심플함의 적당한 균형도 한몫했다.


이미지 첨부와 자동 업로드 설정

Markdown에서 이미지를 첨부하면 로컬 경로가 문서에 저장되기 때문에 웹에 업로드한 후에도 이미지가 표시되지 않는 문제가 발생한다. 수동으로 블로그에 이미지를 일일이 첨부할 수도 있지만 이는 번거로울 뿐만 아니라 alt 속성 입력 등의 추가 작업을 요하므로 비효율적이다.

Typora는 다양한 이미지 업로드 옵션을 제공하여 이미지 경로 문제를 해결할 수 있다. 이와 같은 기능이 없던 시절, Jekyll과 같은 Github 블로그를 고려해보았지만, 기존 블로그를 유지하면서 해결책을 찾기로 결정했다. Typora의 이미지 자동 업로드 설정은 다음 블로그 링크에서 참고할 수 있다. Typora 이미지 업로드시 GitHub로 업로드


강조 표시를 위한 Callout 스타일링

중요한 내용이나 유용한 팁을 강조하기 위해 Callout을 활용하는데, 이는 Markdown 문법의 인용문을 변형해 다양한 스타일로 구현할 수 있다. 예를 들어 [!TIP], [!WARNING]과 같은 키워드를 활용하여 글에 따라 구분되게 강조할 수 있다. Typora 내에서는 미리보기를 통해 이 강조 스타일을 확인할 수 있어 작업이 편리하다.

하지만 내가 사용하는 블로그 호스팅 서비스인 티스토리에서는 모든 Markdown 문법을 지원하지 않기 때문에 Callout 기능이 제대로 표현되지 않는 문제가 있었다. 이를 해결하기 위해, 직접 JavaScript와 CSS를 커스텀 작성하여 티스토리에서도 Callout이 올바르게 표시되도록 했다. 아래는 내가 설정한 JavaScript와 CSS 코드 예시이다.

JavaScript 코드

Callout을 Markdown 문법으로 작성한 후, 각 Callout을 div 요소로 변환하여 아이콘과 색상으로 강조하는 스크립트이다.

<!-- 콜아웃 변환 스크립트 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
  const blockquotes = document.querySelectorAll('blockquote');

  blockquotes.forEach(blockquote => {
    const paragraphs = blockquote.querySelectorAll('p');
    let calloutType = null;
    let calloutContent = '';

    paragraphs.forEach(paragraph => {
      const textContent = paragraph.textContent.trim();
      if (!textContent || textContent === '\u200B') return;

      if (!calloutType) {
        const calloutMatch = textContent.match(/^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]/i);
        if (calloutMatch) {
          calloutType = calloutMatch[1].toUpperCase();
          const remainingContent = paragraph.innerHTML.replace(/^\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*/i, '').trim();
          if (remainingContent) calloutContent += remainingContent;
        }
      } else {
        calloutContent += paragraph.outerHTML;
      }
    });

    if (calloutType) {
      const icons = {
        'NOTE': '<i class="fa-solid fa-note-sticky"></i>',
        'TIP': '<i class="fa-solid fa-lightbulb"></i>',
        'IMPORTANT': '<i class="fa-solid fa-circle-exclamation"></i>',
        'WARNING': '<i class="fa-solid fa-triangle-exclamation"></i>',
        'CAUTION': '<i class="fa-solid fa-bolt"></i>'
      };

      const calloutContainer = document.createElement('div');
      calloutContainer.classList.add('callout', calloutType.toLowerCase());

      const calloutTitle = document.createElement('div');
      calloutTitle.classList.add('callout-title');
      calloutTitle.innerHTML = `${icons[calloutType]} ${calloutType.charAt(0)}${calloutType.slice(1).toLowerCase()}`;

      const calloutBody = document.createElement('div');
      calloutBody.classList.add('callout-content');
      calloutBody.innerHTML = calloutContent;

      calloutContainer.appendChild(calloutTitle);
      calloutContainer.appendChild(calloutBody);

      blockquote.parentNode.replaceChild(calloutContainer, blockquote);
    }
  });
});
</script>

위 코드는 인용문(blockquote)을 자동으로 Callout 스타일로 변경하며, 각 Callout 유형별로 아이콘을 표시할 수 있게 만든다. 다음과 같이 markdown 양식으로 작성한 4가지 callout에 대해 custom div를 만들어 강조 표시할 수 있고, font awesome icon을 사용하였다.

> [!NOTE]
> 이것은 노트 콜아웃입니다.

> [!TIP]
> 이것은 팁 콜아웃입니다.

> [!IMPORTANT]
> 이것은 중요한 콜아웃입니다.

> [!WARNING]
> 이것은 경고 콜아웃입니다.

> [!CAUTION]
> 이것은 주의 콜아웃입니다.

CSS 코드

CSS로 각 Callout의 색상과 스타일을 지정하여 Callout이 더욱 눈에 띄도록 설정했다. 다크 모드와 라이트 모드에 따라 배경색을 다르게 설정하여 사용자 환경에 맞추도록 했다.

/* 콜아웃 공통 스타일 */
.callout {
  border-radius: 4px;
  padding: 16px;
  margin: 16px 0;
  border-left: 6px solid;
  background-color: rgba(249, 249, 249, 0.8); /* 기본 배경색 투명도 적용 */
}

.callout-title {
  font-weight: bold;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
}

.callout-title i {
  margin-right: 8px;
}

.callout-content {
  margin: 0;
}

/* 콜아웃 타입별 스타일 */
/* 각 콜아웃의 배경색을 rgba()로 변경하여 투명도 적용 */
.callout.note {
  background-color: rgba(231, 244, 255, 0.8);
  border-color: #1e90ff;
}

.callout.note .callout-title {
  color: #1e90ff; /* 파란색 */
}

.callout.tip {
  background-color: rgba(231, 255, 241, 0.8);
  border-color: #28a745;
}

.callout.tip .callout-title {
  color: #28a745; /* 초록색 */
}

.callout.important {
  background-color: rgba(246, 215, 255, 0.8);
  border-color: #c507ff;
}

.callout.important .callout-title {
  color: #c507ff; /* 보라색 */
}

.callout.warning {
  background-color: rgba(255, 243, 205, 0.8);
  border-color: #fd7e14;
}

.callout.warning .callout-title {
  color: #fd7e14; /* 주황색 */
}

.callout.caution {
  background-color: rgba(253, 236, 234, 0.8);
  border-color: #dc3545;
}

.callout.caution .callout-title {
  color: #dc3545; /* 빨간색 */
}
/* 
.callout p {
    color: black !important;
} */

/* 다크 모드 - 콜아웃 배경색 */
[data-theme="dark"] .callout.note {
  background-color: #2b3e50;
  border-color: #79b7ff;
}

[data-theme="dark"] .callout.tip {
  background-color: #243f2e;
  border-color: #76d392;
}

[data-theme="dark"] .callout.important {
  background-color: #3c2a4d; /* 보라색 배경으로 변경 */
  border-color: #a371f7;     /* 보라색 계열의 테두리 색상 */
}

[data-theme="dark"] .callout.warning {
  background-color: #4a3924;
  border-color: #ff9d4d;
}

[data-theme="dark"] .callout.caution {
  background-color: #4a252c;
  border-color: #ff6b82;
}

결과

이렇게 구현된 Callout 스타일은 티스토리 블로그에서도 다음과 같이 보인다.

image-20241114175608996


다이어그램과 그래프 작성

Typora는 mermaid와 같은 확장 문법을 지원하여 다양한 다이어그램과 그래프를 손쉽게 작성할 수 있다. 예를 들어, 복잡한 흐름을 설명하는 플로우 차트나 상태도를 단 몇 줄의 코드로 그릴 수 있어 매우 유용하다. 다이어그램을 그릴 때는 직접 드로잉 툴을 사용할 필요 없이 다음과 같은 코드만으로 표현할 수 있다.

graph LR
A[시작] --> B{결정}
B -->|예| C[진행]
B -->|아니오| D[중지]
C --> E[종료]

image-20241114181045733

관련 문법에 대한 자세한 내용은 이 블로그에서 확인할 수 있다.


티스토리 업로드 자동화

한 가지 아쉬운 점은 티스토리가 글쓰기 API를 지원 종료하면서 블로그 자동 업로드 기능까지 단단히 구현하려 했으나 힘들어졌다.

대신 selenium을 이용해 업로드 하는 스크립트를 조만간 작성하고자 한다.

이가 없으면 잇몸으로