<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>블로그 on Physical AI 드림팀</title><link>https://ditis3g.github.io/tags/%EB%B8%94%EB%A1%9C%EA%B7%B8/</link><description>Recent content in 블로그 on Physical AI 드림팀</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Thu, 02 Jul 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ditis3g.github.io/tags/%EB%B8%94%EB%A1%9C%EA%B7%B8/index.xml" rel="self" type="application/rss+xml"/><item><title>블로그 글을 숏폼 영상으로 자동 변환해서 유튜브에 올리기까지</title><link>https://ditis3g.github.io/posts/2026-07-02-blog-to-shorts/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0900</pubDate><guid>https://ditis3g.github.io/posts/2026-07-02-blog-to-shorts/</guid><description>&lt;p&gt;블로그에 정리해 둔 글을 그냥 두기 아까워서, &lt;strong&gt;글 하나를 60초짜리 세로형 교육용 숏폼 영상으로 만들고 유튜브에 자동으로 올리는 파이프라인&lt;/strong&gt;을 만들었다. 목표는 세 가지였다. (1) 글을 어떻게 영상 구성으로 바꿀 것인가, (2) 그걸 자동으로 할 수 있는가, (3) 실제 영상 파일로 인코딩해 저장·업로드까지 되는가. 결론부터 말하면 셋 다 된다. 비전공자도 따라올 수 있게, 개념과 내가 헤맨 지점 위주로 정리한다.&lt;/p&gt;
&lt;h2 id="전체-그림-먼저"&gt;전체 그림 먼저
&lt;/h2&gt;&lt;p&gt;파이프라인은 이렇게 흐른다. 각 단계는 뒤에서 하나씩 풀어 쓴다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;블로그 글(.md)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ① 글을 &amp;#34;장면 대본&amp;#34;으로 압축 (AI가 요약)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;장면 JSON
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ② 나레이션 음성 만들기 (TTS, 무료 한국어)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ③ 장면 화면(이미지) 만들기 (HTML 또는 Pillow)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ④ 이미지 + 음성 → 영상으로 합치기 (ffmpeg)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;숏폼 mp4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ⑤ 유튜브 업로드 (YouTube API)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;유튜브 Shorts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;이 전체를 매일 일정 시간에 자동으로 도는 스케줄로 걸어두는 게 마지막 단계다.&lt;/p&gt;
&lt;h2 id="준비물-무료-도구-네-가지"&gt;준비물: 무료 도구 네 가지
&lt;/h2&gt;&lt;p&gt;돈 드는 건 없다. 전부 무료다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; — 파이프라인을 묶는 접착제 역할.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ffmpeg&lt;/strong&gt; — 이미지와 음성을 합쳐 mp4로 &lt;strong&gt;인코딩&lt;/strong&gt;(영상 파일로 만드는 것)하는 도구. 영상 자동화의 핵심.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;edge-tts&lt;/strong&gt; — 글자를 사람 목소리로 읽어주는 &lt;strong&gt;TTS&lt;/strong&gt;(Text To Speech). Microsoft의 무료 한국어 음성을 API 키 없이 쓸 수 있다. &lt;code&gt;ko-KR-SunHiNeural&lt;/code&gt;(여성) 같은 목소리가 꽤 자연스럽다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;화면 만드는 도구&lt;/strong&gt; — 두 가지를 다 만들어 비교했다. 뒤에서 설명한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Windows라면 ffmpeg는 &lt;code&gt;winget install Gyan.FFmpeg&lt;/code&gt;, 나머지는 &lt;code&gt;pip install&lt;/code&gt;로 끝난다.&lt;/p&gt;
&lt;h2 id="-글을-장면-대본으로-쪼개기"&gt;① 글을 &amp;ldquo;장면 대본&amp;quot;으로 쪼개기
&lt;/h2&gt;&lt;p&gt;블로그 글은 길다. 60초 숏폼에는 한국어로 대략 320~380자밖에 못 담는다. 그래서 글을 통째로 넣을 수 없고 &lt;strong&gt;핵심만 압축&lt;/strong&gt;해야 하는데, 이 요약·재구성이야말로 AI(LLM)가 제일 잘하는 일이다.&lt;/p&gt;
&lt;p&gt;글을 다음처럼 &lt;strong&gt;5개 장면&lt;/strong&gt;으로 나눈 대본(JSON 형식)으로 바꾼다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;후킹&lt;/strong&gt; (0&lt;del&gt;3초): 강한 한 줄로 시선 잡기 (&amp;ldquo;최신 AI 모델, 외우지 마세요&amp;rdquo;)
2&lt;/del&gt;4. &lt;strong&gt;핵심 카드&lt;/strong&gt;: 한 장에 한 개념. 짧은 문장 3개 + 나레이션&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;마무리&lt;/strong&gt;: 결론 한 줄 + &amp;ldquo;전체 글은 블로그에서&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;각 장면에는 화면에 띄울 글자와, 성우가 읽을 나레이션이 따로 들어간다. 블로그 글의 제목·소제목·표가 자연스럽게 후킹·핵심 카드·계보 도표로 대응된다는 점이 좋았다.&lt;/p&gt;
&lt;p&gt;한 가지 팁: 나레이션에서 영어 약어는 한글 발음으로 적어야 TTS가 제대로 읽는다. &lt;code&gt;VLA&lt;/code&gt;는 &amp;ldquo;브이엘에이&amp;rdquo;, &lt;code&gt;AI&lt;/code&gt;는 &amp;ldquo;에이아이&amp;quot;처럼. 숫자도 &amp;ldquo;96%&amp;ldquo;보다 &amp;ldquo;구십육 퍼센트&amp;quot;로 적으면 자연스럽다.&lt;/p&gt;
&lt;h2 id="-나레이션-음성-만들기"&gt;② 나레이션 음성 만들기
&lt;/h2&gt;&lt;p&gt;장면별 나레이션 문장을 edge-tts에 넣으면 mp3가 나온다. 명령 한 줄이면 된다. 이 음성의 &lt;strong&gt;길이&lt;/strong&gt;를 재서, 나중에 그 장면 화면을 그 시간만큼 보여주면 화면과 목소리가 자동으로 맞는다.&lt;/p&gt;
&lt;h2 id="-화면-만들기-두-가지-방법"&gt;③ 화면 만들기: 두 가지 방법
&lt;/h2&gt;&lt;p&gt;세로형(9:16, 유튜브 Shorts 규격)의 카드 이미지를 장면마다 만든다. 두 방식을 다 만들어 비교했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A안 — HTML/CSS로 만들고 캡처&lt;/strong&gt;: 웹페이지처럼 예쁘게 꾸민 뒤 브라우저로 스크린샷을 찍는다. 한글 타이포와 표·도표가 훨씬 깔끔하다. 교육용에 유리해서 이걸 채택했다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B안 — Pillow(파이썬 그림 라이브러리)로 직접 그리기&lt;/strong&gt;: 브라우저가 필요 없고 가볍다. 담백한 스타일.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;여기서 초보가 꼭 만나는 문제 하나. &lt;strong&gt;자막이 화면 폭을 넘어 줄이 깨진다.&lt;/strong&gt; 글자 길이가 글마다 다르니 고정 폰트 크기로는 안 된다. 그래서 &amp;ldquo;한 줄에 들어갈 때까지 폰트 크기를 자동으로 줄이는&amp;rdquo; 로직을 넣었다. 이러면 어떤 글이 와도 자막이 깔끔하게 한 줄로 맞는다.&lt;/p&gt;
&lt;h2 id="-영상으로-합치기-ffmpeg"&gt;④ 영상으로 합치기 (ffmpeg)
&lt;/h2&gt;&lt;p&gt;장면마다 &lt;code&gt;이미지 + 그 장면 음성&lt;/code&gt;을 붙여 짧은 클립을 만들고, 클립들을 순서대로 이어 붙이면 하나의 mp4가 된다. 페이드 인 같은 효과도 ffmpeg 옵션으로 넣을 수 있다. 60초 영상이 1~2MB로 가볍게 나온다.&lt;/p&gt;
&lt;h2 id="-유튜브-자동-업로드-여기가-진짜-삽질-구간"&gt;⑤ 유튜브 자동 업로드: 여기가 진짜 삽질 구간
&lt;/h2&gt;&lt;p&gt;영상 만드는 것보다 &lt;strong&gt;유튜브에 자동으로 올리는 인증 과정&lt;/strong&gt;이 훨씬 까다로웠다. 공식 방법은 &lt;strong&gt;YouTube Data API + OAuth 인증&lt;/strong&gt;이다. 초보가 순서대로 만나는 함정을 그대로 적어둔다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Cloud에서 API 사용 설정 + OAuth 클라이언트(데스크톱 앱) 만들기.&lt;/strong&gt; 다운로드한 인증 파일(&lt;code&gt;client_secret.json&lt;/code&gt;)이 &lt;code&gt;&amp;quot;installed&amp;quot;&lt;/code&gt;로 시작하면 데스크톱 앱(정상), &lt;code&gt;&amp;quot;web&amp;quot;&lt;/code&gt;이면 잘못 만든 것.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;앱 이름에 &amp;ldquo;Google&amp;rdquo;·&amp;ldquo;YouTube&amp;rdquo; 같은 상표명을 넣으면 안 된다.&lt;/strong&gt; 정책상 거부된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;프로덕션&amp;quot;으로 올리면 오히려 막힌다.&lt;/strong&gt; 유튜브 업로드는 민감한 권한이라 프로덕션 상태에선 구글 정식 심사를 통과해야 한다. 개인용이면 &lt;strong&gt;&amp;ldquo;테스트&amp;rdquo; 상태로 두고 내 계정을 테스트 사용자로 추가&lt;/strong&gt;하는 게 답이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;확인하지 않은 앱&amp;rdquo; 경고는 차단이 아니다.&lt;/strong&gt; 테스트 모드에선 이 경고가 정상이다. &lt;code&gt;고급 → (앱이름)(으)로 이동&lt;/code&gt;을 눌러 통과하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;youtubeSignupRequired&lt;/code&gt; 오류 = 유튜브 채널이 없다는 뜻.&lt;/strong&gt; 인증은 됐는데 그 구글 계정에 채널이 없으면 올릴 곳이 없다. youtube.com에서 채널을 먼저 만들면 해결된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;테스트 모드는 토큰이 약 7일마다 만료된다.&lt;/strong&gt; 자동화가 일주일에 한 번쯤 끊기므로, 주 1회 인증 명령을 한 번 다시 실행해 토큰을 갱신해 줘야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;참고로 무료 사용량은 하루 10,000 유닛이고 업로드 1건이 1,600 유닛이라, &lt;strong&gt;하루 약 6개까지&lt;/strong&gt; 올릴 수 있다. 매일 몇 개면 충분하다.&lt;/p&gt;
&lt;h2 id="매일-자동-실행-규칙을-정하다"&gt;매일 자동 실행: 규칙을 정하다
&lt;/h2&gt;&lt;p&gt;마지막으로 위 전체를 &lt;strong&gt;Windows 작업 스케줄러&lt;/strong&gt;에 매일 오후 3시로 걸었다. 규칙은 이렇게 정했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;게시된 글만&lt;/strong&gt; 대상 (초안 제외).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;블로그 메이킹&amp;rdquo; 카테고리는 제외&lt;/strong&gt; (지금 이 글처럼 블로그 만들기 자체를 다룬 글은 영상으로 안 만든다).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;오래된 글부터 순서대로 하루 2개&lt;/strong&gt;씩 처리. 이미 처리한 글은 기록해 두고 다시 만들지 않는다.&lt;/li&gt;
&lt;li&gt;밀린 글이 다 소진되면, 그다음부터는 새로 올라온 글을 자동으로 집어 처리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="한-줄-정리"&gt;한 줄 정리
&lt;/h2&gt;&lt;p&gt;블로그 글을 숏폼으로 바꾸는 핵심은 &lt;strong&gt;&amp;ldquo;긴 글을 5개 장면으로 압축하는 AI 단계&amp;rdquo;&lt;/strong&gt; 와 &lt;strong&gt;&amp;ldquo;이미지+음성을 ffmpeg로 합치는 인코딩&amp;rdquo;&lt;/strong&gt; 이고, 진짜 난관은 영상 제작이 아니라 &lt;strong&gt;유튜브 OAuth 인증(테스트 모드·채널 생성·토큰 만료)&lt;/strong&gt; 이다. 이 셋만 넘으면 매일 자동으로 도는 숏폼 공장이 완성된다.&lt;/p&gt;
&lt;h2 id="실제-결과물--이-글이-이렇게-숏폼이-됐다"&gt;실제 결과물 — 이 글이 이렇게 숏폼이 됐다
&lt;/h2&gt;&lt;p&gt;아래 원본 글 하나가, 위에서 설명한 파이프라인을 거쳐 60초짜리 세로 영상으로 자동 변환됐다. 긴 글이 어떻게 5개 장면으로 압축됐는지 원본과 나란히 보면 감이 온다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;원본 글&lt;/strong&gt;: &lt;a class="link" href="https://ditis3g.github.io/posts/2026-07-01-study/" &gt;피지컬 AI, 최신 모델을 외우지 말고 &amp;lsquo;흐름&amp;rsquo;을 읽어라&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결과 숏폼&lt;/strong&gt;: 이 파이프라인으로 처음 업로드한 영상 (아래)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="video-wrapper"&gt;
 &lt;iframe loading="lazy" 
 src="https://www.youtube.com/embed/LQcLLUg-Jew" 
 allowfullscreen 
 title="YouTube Video"
 &gt;
 &lt;/iframe&gt;
&lt;/div&gt;
</description></item><item><title>PaperMod에서 Stack 테마로 갈아타며 배운 것들</title><link>https://ditis3g.github.io/posts/2026-06-30-study-2/</link><pubDate>Tue, 30 Jun 2026 00:00:00 +0900</pubDate><guid>https://ditis3g.github.io/posts/2026-06-30-study-2/</guid><description>&lt;p&gt;블로그 테마를 PaperMod에서 Stack(&lt;code&gt;CaiJimmy/hugo-theme-stack&lt;/code&gt;)으로 교체했다. 색은 무채색(zinc) 톤으로, 폰트는 Pretendard로 커스텀했다. 단순히 &amp;ldquo;옷 갈아입기&amp;quot;로 끝나는 작업이 아니라 글 메타데이터와 자동화 prompt까지 한 사이클로 묶어야 일이 닫힌다는 걸 새삼 느꼈다. 헤맸던 지점 위주로 정리한다.&lt;/p&gt;
&lt;h2 id="테마-붙이고-config에서-처음에-헤매는-것들"&gt;테마 붙이고 config에서 처음에 헤매는 것들
&lt;/h2&gt;&lt;p&gt;Stack은 submodule로 붙인다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git submodule add https://github.com/CaiJimmy/hugo-theme-stack themes/hugo-theme-stack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;GitHub Actions로 빌드한다면 &lt;code&gt;checkout&lt;/code&gt; 단계에 &lt;code&gt;submodules: recursive&lt;/code&gt; 옵션이 있어야 테마가 같이 받아진다. 이게 없으면 로컬에선 멀쩡한데 배포 빌드만 깨진다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hugo.toml&lt;/code&gt;은 길지만, 처음에 발목 잡히는 건 세 가지뿐이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;mainSections = [&amp;quot;posts&amp;quot;]&lt;/code&gt;&lt;/strong&gt; — Stack 기본값은 단수형 &lt;code&gt;&amp;quot;post&amp;quot;&lt;/code&gt;다. 우리 폴더가 &lt;code&gt;posts/&lt;/code&gt;라면 이걸 명시하지 않으면 홈에 글이 한 개도 안 뜬다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;sidebar.avatar&lt;/code&gt;는 문자열 한 줄로.&lt;/strong&gt; &lt;code&gt;{enabled=..., src=...}&lt;/code&gt; 같은 중첩 테이블을 쓰면 빌드 에러가 난다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메뉴 아이콘은 실재하는 파일명으로.&lt;/strong&gt; &lt;code&gt;themes/.../assets/icons/&lt;/code&gt;에 실제로 있는 이름이어야 한다. &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;처럼 없는 이름을 쓰면 빌드가 fail한다. &lt;code&gt;archives&lt;/code&gt;, &lt;code&gt;categories&lt;/code&gt;, &lt;code&gt;tag&lt;/code&gt;, &lt;code&gt;hash&lt;/code&gt;, &lt;code&gt;home&lt;/code&gt; 정도가 안전하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="커스텀의-90는-customscss-한-파일에서-끝난다"&gt;커스텀의 90%는 custom.scss 한 파일에서 끝난다
&lt;/h2&gt;&lt;p&gt;Stack은 자기 &lt;code&gt;style.scss&lt;/code&gt; 마지막에 &lt;code&gt;@import &amp;quot;custom.scss&amp;quot;;&lt;/code&gt;를 박아둔다. 그래서 우리 사이트의 &lt;code&gt;assets/scss/custom.scss&lt;/code&gt;만 만들면 별도 설정 없이 자동으로 끼워져 컴파일된다. 이게 Stack 커스텀의 핵심이다.&lt;/p&gt;
&lt;p&gt;이 파일에서 한 일은 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;색 변수(&lt;code&gt;--body-background&lt;/code&gt;, &lt;code&gt;--accent-color&lt;/code&gt;, &lt;code&gt;--card-background&lt;/code&gt; 등)를 라이트/다크 모두 zinc 톤으로 override. 다크 모드는 &lt;code&gt;:root[data-scheme=&amp;quot;dark&amp;quot;]&lt;/code&gt; 블록에서 따로 잡는다.&lt;/li&gt;
&lt;li&gt;Pretendard를 &lt;code&gt;@import url(...)&lt;/code&gt; CDN으로 불러오고 &lt;code&gt;--base-font-family&lt;/code&gt;를 교체. Stack 기본 폰트인 Lato는 한글 글리프가 없어서 시스템 fallback으로 떨어지면 글자가 둔탁해진다.&lt;/li&gt;
&lt;li&gt;카드 타이틀을 2.2rem → 1.9rem으로 줄이고 &lt;code&gt;letter-spacing: -0.01em&lt;/code&gt;. 한글은 영문보다 자간을 살짝 좁히는 쪽이 균형이 맞는다.&lt;/li&gt;
&lt;li&gt;본문에 &lt;code&gt;word-break: keep-all; overflow-wrap: anywhere;&lt;/code&gt; — 한국어가 어절 단위로 줄바꿈되어 훨씬 깔끔해진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="가장-큰-함정-카테고리-배지의-inline-style"&gt;가장 큰 함정: 카테고리 배지의 inline style
&lt;/h2&gt;&lt;p&gt;제일 오래 잡아먹은 건 카테고리/태그 배지였다. Stack은 카테고리·태그마다 hash로 색을 자동 생성해서 &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; 태그에 &lt;strong&gt;inline style&lt;/strong&gt;로 직접 박는다. inline style은 외부 CSS를 이기기 때문에, SCSS로 그냥 덮어쓰면 먹지 않는다.&lt;/p&gt;
&lt;p&gt;해결은 &lt;code&gt;!important&lt;/code&gt;로 강제하는 것이다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nc"&gt;.article-category&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.article-tags&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;card-background-selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;card-text-color-secondary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;이걸 안 하면 사이트 전체는 무채색인데 카테고리 배지만 알록달록하게 튄다.&lt;/p&gt;
&lt;h2 id="글-메타데이터와-자동화-prompt까지-함께-손보기"&gt;글 메타데이터와 자동화 prompt까지 함께 손보기
&lt;/h2&gt;&lt;p&gt;Stack 사이드바의 카테고리 위젯이 살아나려면 각 글의 frontmatter에 &lt;code&gt;categories:&lt;/code&gt;가 있어야 한다. 기존 글들은 PaperMod 시절이라 &lt;code&gt;tags:&lt;/code&gt;만 있어서 위젯이 비어 있었다. 그래서 모든 글에 카테고리를 VLA / 피지컬 AI / 메타 3개 분류로 채워 넣었다.&lt;/p&gt;
&lt;p&gt;여기서 멈추면 다음 날 새로 생기는 글에서 같은 문제가 반복된다. 그래서 매일 밤 자동 초안을 만드는 &lt;code&gt;prompt-instructions.txt&lt;/code&gt;에도 categories 지시를 추가했다. 이제 다음 날부터 새 글은 자동으로 올바른 분류에 들어간다. 테마 교체를 글 메타데이터·자동화 prompt까지 한 사이클로 묶어야 일이 닫힌다는 게 이 작업의 교훈이다.&lt;/p&gt;
&lt;p&gt;작업 흐름에서 챙긴 팁도 적어둔다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;별도 브랜치에서 작업.&lt;/strong&gt; main은 머지 시점까지 건드리지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로컬에서 &lt;code&gt;hugo server&lt;/code&gt;를 띄워두고&lt;/strong&gt; SCSS를 고치면 hot reload된다. 확인할 때마다 GitHub Pages에 push하지 말 것.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;배포 후 옛 모양으로 보이면 십중팔구 브라우저 캐시다.&lt;/strong&gt; &lt;code&gt;Ctrl+Shift+R&lt;/code&gt;이나 시크릿 창으로 먼저 확인하자. 빌드 자체를 의심하기 전에 &lt;code&gt;curl&lt;/code&gt;로 라이브 CSS에 새 규칙이 들어갔는지 보는 게 더 빠르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="한-줄-정리"&gt;한 줄 정리
&lt;/h2&gt;&lt;p&gt;Stack 테마 교체의 핵심은 &lt;code&gt;custom.scss&lt;/code&gt; 한 파일과 inline style을 이기는 &lt;code&gt;!important&lt;/code&gt;이며, 테마 변경은 글 메타데이터와 자동화 prompt까지 한 사이클로 묶어야 비로소 끝난다.&lt;/p&gt;</description></item></channel></rss>