Blogspot은 무료고 Google 인프라에서 돌아가니까 속도와 안정성은 보장된다. 문제는 기본 테마가 전부 일반 블로그 느낌이라는 것이다. 개발자·엔지니어 블로그로 쓰기엔 분위기가 맞지 않았다. 그래서 XML 테마를 처음부터 작성해서, 다크 배경에 터미널 감성이 나는 UI를 만들었다.
Blogspot의 테마는 XML 기반이라 처음엔 낯설지만, 본질은 HTML/CSS/JS에 Blogspot 전용 태그(b:if, data:post.title 등)가 섞인 구조다. 이 구조를 이해하면 거의 모든 걸 커스텀할 수 있다.
전체 색상을 CSS Custom Properties(변수)로 관리한다. 배경은 거의 검정에 가까운 #050810을 베이스로, 시안(#00f5ff)과 퍼플(#7b2fff)을 액센트 컬러로 사용했다. 강조가 필요한 곳에는 핑크(#ff3d71)와 골드(#ffd60a)를 포인트로 넣는다.
변수로 관리하면 나중에 색상 톤을 바꾸고 싶을 때 변수 값만 수정하면 전체 사이트에 반영된다. 일일이 찾아서 바꿀 필요가 없다.
| 역할 | 색상 | 용도 |
|---|---|---|
| 배경 | #050810 | 전체 배경, 카드 배경 |
| 메인 액센트 | #00f5ff | 링크, 강조, 글로우 효과 |
| 서브 액센트 | #7b2fff | 그라데이션, 보조 강조 |
| 하이라이트 | #ff3d71 | 경고, 중요 표시 |
| 골드 | #ffd60a | 배지, 특별 강조 |
본문과 코드에는 JetBrains Mono를 사용한다. 모노스페이스 폰트 중에서 가독성이 가장 좋고, 코드와 일반 텍스트를 동시에 쓰는 기술 블로그에 잘 맞는다. 제목에는 Syne을 사용해서 본문과 시각적 차이를 뒀다. Google Fonts에서 무료로 쓸 수 있다.
CSS Grid 기반 2컬럼 레이아웃이다. 왼쪽 본문 + 오른쪽 사이드바(360px 고정) 구조로, 태블릿(960px 이하)에서는 사이드바를 숨기고 1컬럼으로 전환한다.
데스크톱에서 마우스를 움직이면 시안색 글로우 커서와 링이 따라다닌다. requestAnimationFrame으로 부드러운 추적 애니메이션을 구현했고, 링크나 버튼 위에 올리면 커서가 확대되면서 색상이 바뀐다.
중요한 점은 터치 디바이스에서는 아예 초기화하지 않는다는 것이다. 모바일/태블릿에는 마우스 커서가 없으니까, 터치 디바이스를 감지하면 커서 관련 JS를 실행하지 않아서 배터리와 성능을 절약한다. CSS에서도 600px 이하에서 display: none으로 이중 안전장치를 걸었다.
페이지 배경에 두 가지 효과가 깔려 있다. 첫째, ::before pseudo-element로 미세한 격자 패턴을 그린다. 터미널 느낌을 내는 핵심 요소다. 둘째, ::after로 우상단에 보라색 그라디언트 오브를 띄워서 은은하게 움직이게 했다. 둘 다 pointer-events: none이라 사용자 인터랙션을 방해하지 않는다.
홈 목록 페이지에서 포스트 카드가 스크롤에 따라 fade-in되면서 올라오는 효과를 적용했다. IntersectionObserver로 뷰포트 진입을 감지하고, 진입하면 opacity와 transform을 변경한다. 글 상세 페이지에서는 이 애니메이션을 비활성화해서 읽기에 방해되지 않게 했다.
이 블로그의 가장 독특한 기능이다. 홈페이지에서 실제로 명령어를 입력하고 결과를 볼 수 있는 터미널이 내장되어 있다.
터미널 자체는 별도의 HTML/CSS/JS 파일로 만들어서 GitHub Pages에 호스팅했다. 블로그에는 iframe으로 삽입한다. 왜 이렇게 분리했냐면, Blogspot 테마 XML 안에 복잡한 터미널 코드를 넣으면 유지보수가 불가능해지기 때문이다. 분리하면 터미널만 독립적으로 수정·배포할 수 있다.
iframe 삽입 시 한 가지 문제가 있었다 — iframe이 페이지 스크롤을 가로채서 사용자가 페이지를 내리다가 터미널 영역에서 멈추는 현상이다. 이걸 해결하기 위해 기본적으로 pointer-events: none으로 비활성화해두고, 사용자가 직접 클릭하면 활성화되는 오버레이 방식을 적용했다.
| 명령어 | 기능 |
|---|---|
help | 명령어 목록 표시 |
whoami | 블로그 주인 정보 |
ls / cd / cat | 가상 파일시스템 탐색 |
neofetch | 시스템 정보 (ASCII 아트) |
ps aux / df -h | 가상 프로세스·디스크 정보 |
git log | 실제 블로그 최신 포스트 실시간 조회 |
open <번호> | git log 결과에서 포스트 열기 |
contact | 연락처 정보 |
clear | 화면 지우기 |
가장 까다로웠던 부분이다. git log를 입력하면 실제 블로그 최신 글 목록이 git commit 형태로 출력된다. 해시값은 랜덤 생성이지만, 제목·날짜·URL은 실제 데이터다.
기술적으로는 Blogspot의 피드 API를 호출해서 최근 포스트를 가져온다. 문제는 GitHub Pages(iframe)에서 Blogspot 도메인으로 요청하면 CORS가 차단된다는 것이었다. 이걸 JSONP 방식으로 우회했다 — script 태그를 동적으로 생성하면 CORS 제약을 받지 않는 점을 이용한 것이다.
실제 터미널처럼 느끼게 하려고 여러 기능을 넣었다. Tab 키로 명령어·파일명 자동완성, 방향키로 이전 명령어 히스토리 탐색, 하단 힌트바에 클릭 가능한 추천 명령어, 상태바에 실시간 업타임 카운터까지. 처음 접속하면 Kubernetes·Terraform·ArgoCD 부팅 시퀀스 애니메이션이 재생되면서 터미널이 열린다.
데스크톱에서는 히어로 섹션 아래에 iframe으로 직접 보여주지만, 모바일에서는 다른 접근을 택했다. 작은 화면에 iframe을 그대로 넣으면 사용성이 떨어지기 때문에, 대신 우하단에 플로팅 버튼(>_)을 배치했다. 버튼을 누르면 전체화면 모달로 터미널이 열리고, 닫기 버튼으로 종료한다. 모달은 배경 블러 효과가 깔리고, iframe은 모달 오픈 시점에 lazy load해서 초기 페이지 로딩에 부담을 주지 않는다.
블로그 글을 작성할 때마다 매번 CSS를 새로 만들 수 없으니, 전용 CSS 클래스 시스템을 만들어두고 재사용한다. .eol- 접두사가 붙은 클래스들이 그것이다.
| 클래스 | 용도 |
|---|---|
.eol-post | 포스트 본문 전체를 감싸는 래퍼 |
.eol-h2 / .eol-h3 / .eol-h4 | 제목 — 좌측 보라→시안 그라데이션 보더 |
.eol-terminal | 터미널 스타일 코드 블록 (빨/노/초 점 3개) |
.eol-arch | 아키텍처 다이어그램 (모노스페이스 프리포맷) |
.eol-table | 다크 테마 테이블 (가로 스크롤 지원) |
.eol-info / .eol-warn / .eol-success | 정보/경고/성공 알림 박스 |
.eol-summary | 요약 박스 (글 상단/하단) |
.eol-faq-item | FAQ 질문-답변 블록 |
이 클래스들은 테마 CSS에도 반응형 규칙이 들어가 있고, 글 자체 CSS에도 @media 쿼리가 내장되어 있어서 모바일에서도 깨지지 않는다. 테이블과 코드 블록은 overflow-x: auto로 가로 스크롤이 가능하고, iOS에서는 -webkit-overflow-scrolling: touch로 관성 스크롤을 지원한다.
헤더는 스크롤해도 상단에 고정되는 sticky 방식이다. 배경에 backdrop-filter: blur(20px)를 적용해서, 스크롤 시 뒤에 깔린 콘텐츠가 유리처럼 블러되는 효과를 준다. 불투명 배경 대신 블러를 쓰면 시각적으로 가볍고, 콘텐츠 위치를 인지하는 데도 도움이 된다.
960px 이하에서 가로 메뉴를 숨기고 햄버거 메뉴로 전환한다. 햄버거를 누르면 풀스크린 오버레이가 열리면서 메뉴 링크와 검색 폼이 표시된다. 모바일에서는 사이드바가 숨겨지기 때문에, 검색 폼을 오버레이 안에 넣어서 접근성을 보완했다. 글 상세 페이지에서는 뒤로가기 버튼도 자동으로 표시된다.
글 상세 페이지에서 본문의 h2, h3 태그를 자동으로 스캔해서 목차를 생성한다. 제목이 3개 미만이면 목차가 의미 없으니 숨기고, 3개 이상일 때만 표시한다. h3는 들여쓰기 처리해서 계층 구조를 나타내고, 클릭하면 해당 섹션으로 앵커 스크롤된다.
접기/펼치기 기능도 있어서, 목차가 길 때는 접어두고 필요할 때만 펼칠 수 있다.
홈페이지에서 스크롤을 내리면 다음 포스트가 자동으로 로드된다. Blogspot의 JSON 피드 API를 활용해서 timestamp 기반 커서 페이지네이션을 구현했다. IntersectionObserver로 하단을 감지하면 다음 포스트를 요청하고, 더 이상 글이 없으면 "모든 글을 불러왔습니다" 메시지를 표시한다.
| 브레이크포인트 | 대상 | 주요 변경 |
|---|---|---|
| 960px 이하 | 태블릿 | 사이드바 숨김, 1컬럼 전환, 햄버거 메뉴 활성화 |
| 768px 이하 | 태블릿 세로 | 터미널 폰트 축소, 테이블 가로 스크롤 |
| 600px 이하 | 모바일 | 패딩/폰트 전면 축소, iframe 터미널 숨기고 FAB으로 전환, 커스텀 커서 비활성화 |
단순히 화면 크기만 보는 게 아니라, 터치 디바이스인지 감지해서 불필요한 기능을 끈다. 커스텀 커서는 터치 디바이스에서 JS 초기화 자체를 스킵하고, 터미널 폰트는 vw 단위를 써서 화면 너비에 비례하게 조절한다. 긴 출력이 화면을 뚫고 나가지 않도록 word-break와 overflow-wrap도 적용했다.
| 영역 | 기술 |
|---|---|
| 플랫폼 | Google Blogger (Blogspot) |
| 호스팅 | Google 서버 + GitHub Pages (터미널) |
| 마크업 | Blogger XML 템플릿 + HTML5 |
| 스타일 | CSS3 (Custom Properties, Grid, Flexbox, Media Query, vw 단위) |
| 스크립트 | Vanilla JavaScript (ES5 호환) |
| 폰트 | Google Fonts (JetBrains Mono, Syne) |
| 피드 연동 | Blogspot Atom/JSON API + JSONP |
| 반응형 | 3단계 브레이크포인트 (960px, 768px, 600px) |
| 성능 최적화 | 터치 디바이스 커서 스킵, iframe lazy load, IntersectionObserver |
b:if, data:post 등)로 동적 데이터를 활용하면 된다. 다만 빌드 도구가 없어서 프레임워크는 쓰기 어렵고, Vanilla JS로 작업해야 한다./feeds/posts/default?alt=json)를 활용한다. timestamp 기반 커서로 페이지네이션하고, IntersectionObserver로 하단 도달을 감지해서 다음 포스트를 자동 로드한다. 외부 라이브러리 없이 순수 JS로 구현했다.