버전 이력
The Real Bali
현재 v1.39 · 2026-05-30 빌드
이 사이트는 발리에서 보고 들은 것들을 한국어로 풀어내는 개인 블로그입니다. Astro 5 + Cloudflare 인프라로 만들어졌고, 모든 글은 GitHub 에 마크다운으로 보관됩니다.
-
Google Search Console + JSON-LD enhancements
airjournal.kr 도메인 GSC 검증 (메타 태그 방식). settings.yaml 의 동적 googleSiteVerification 필드 — BaseLayout 이 자동 렌더. JSON-LD 보강: WebSite + Organization + AboutPage + Person 구조화 데이터. 발리 잔재 정리(alternateName 'The Real Bali' → 'AIRJOURNAL.KR'), SearchAction 제거(/search/ 미존재). robots.txt 도메인 정정.
-
AI 직원 리브랜딩 — 모수(해모수) + SVG 캐릭터 프로필 + about 섹션
가루다(Garuda Indonesia 충돌 해소) → 모수(해모수, 고구려 건국신화 속 하늘의 신). 코드 일괄 리네이밍: aiGaruda → aiMosu, GARUDA_COMMENT → MOSU_COMMENT, garudaComment → mosuComment, ensureGarudaCommentButton → ensureMosuCommentButton. 파일 이동: staff/garuda.yaml → mosu.yaml, prompts/garudaComment.ts → mosuComment.ts, api/ai/garuda-comment.ts → mosu-comment.ts. 22개 파일 변경. SVG 캐릭터 프로필 추가: public/staff/jenny.svg + mosu.svg (단정한 단발 + ID 카드 · 사이드파트 + 견장 + 작은 태양 모티프). About 페이지 'AI 직원' 섹션 추가 — 두 캐릭터 카드 그리드 (모바일 1열, 데스크톱 2열).
-
보안·SEO·UX audit 보강
api-auth.ts ALLOWED_ORIGINS 정리 — bare *.pages.dev 광역 허용 제거(CSRF 위험), 자기 사이트 도메인만 허용. 양 사이트 공통. BaseLayout favicon: 192/512 size icon link + <link rel="shortcut icon" href="/favicon.ico"> 명시 + favicon.ico 파일 추가 → Google 검색 결과 파비콘 노출 보강. 404 페이지: 발리 잔재(/snap/, /photos/) → airline 페이지(/edu/, /terms/, /essays/, /snaps/) 로 교체. Header.astro 의 categories.yaml 자동 append 로직 제거 — 어드민 '메뉴/헤더' 에 명시한 항목만 노출. 어드민 UI 와 헤더 1:1 일치 (양 사이트). bali admin/media SPA collection 라벨 (essays/snaps/... → posts/photos/lens) 수정.
-
항공 용어 갤러리 + YouTube 자동 임베드 + 터미스 OLD 컬렉션
terms 컬렉션에 image + images[] 필드 추가 (스냅과 동일 패턴). 본문 아래 '관련 사진' 섹션 자동 노출, 미디어 관리 페이지에도 인덱싱. middleware 의 📷 여러장 업로드 버튼이 terms 편집 화면에서도 동작. BaseLayout 인라인 스크립트가 본문 안의 단독 YouTube URL(youtube.com/watch?v, youtu.be, shorts) 을 16:9 반응형 iframe 으로 자동 변환. terms·essays·phrases· snaps·edu 본문 컨테이너 적용. 어드민 측 변경 없음. WordPress XML 임포트 글에서 본문이 코드블록(```)으로 잘못 감싸져 한글 긴 줄이 가로 오버플로우 → :global(pre) 에 white-space:pre-wrap + word-break:break-word + max-width:100% 적용 (5개 슬러그 페이지).
-
미디어 관리 어드민 (양 사이트 분리, Cloudinary 통합)
airline + bali 양 사이트에 /admin/media — 글 안에 박힌 모든 이미지·미디어 URL 인덱스 + Cloudinary 통합. 같은 cloud(dctlxip1l) 를 폴더 prefix(airline/, bali/) 로 site 격리. 기능 (5단계 A·B·C·D·E): · A — Cloudinary 고아 미디어 검사 + 일괄 삭제 (Admin API, 사이트 폴더 prefix 필터, cross-site delete 가드, 100개 청크 처리) · B — 외부 URL → Cloudinary 마이그레이션 (signed upload, 사이트별 migrated/ 폴더, 결과 매핑 테이블) · C — 정렬·필터 (사용 횟수, URL 알파벳, '1회만 사용' 필터, 결과 카운터) · D — 라이트박스 (썸네일 클릭 풀사이즈, ←→ 키 순회, Esc 닫기) · E — 일괄 액션 (체크박스, sticky 액션 바, 선택 URL 복사, 사용처 글 일괄 열기) 어드민 사이드바 하단에 '🖼️ 미디어 관리' 링크 자동 주입.
-
IATA RP1008 Business Glossary 일괄 임포트 + 컬렉션 분리
IATA RP1008 (2018) Business Glossary CSV (872개 용어) 일괄 등록 — category iata-glossary, scripts/import-iata-glossary.mjs 로 frontmatter + 본문(원문 + 출처 + 관련) 자동 빌드. 슬러그 충돌 시 -N 접미사. 기존 iata 카테고리(171개) 를 별도 컬렉션 src/content/termsOld 로 분리: 어드민 사이드바에 '항공용어 (OLD)' 그룹 신설. URL 은 /terms/<slug> 로 통일 (slug 페이지에서 두 컬렉션 병합). 슬러그 우선권 swap — 새 IATA Glossary 글이 오리지날 슬러그(예: acars), OLD 글은 -N 접미사로 이동. 또 다른 정리: 164개 IATA 용어 표제어 분리(English (한글) → term=English / meaning=한글), 카테고리 5개 추가(공항서비스/운항/객실/지상/IATA Glossary), 쓰레기 엔트리 3개 삭제.
-
IATA Glossary 한글화 어드민 (gpt-4o, 배치 커밋, 자동 실행)
iata-glossary 카테고리(872개) 영문 정의·본문을 AI 한글 번역 후 GitHub Contents/Trees API 로 자동 커밋하는 어드민 도구. /admin/iata-translate, /api/admin/iata-translate-batch. gpt-4o 모델 + 보수 prompt (확신 없으면 섹션 생략, 헤지 표현, 출처 위조 금지). Git Trees API 로 batch 단위 단일 commit → CF Pages 빌드 큐 폭증 방지. 배치 max 14개 (CF Workers subrequest 50/invocation 제한 고려). 자동 연속 실행 모드 + 실시간 진행률·로그·에러 단계 추적. 본문 구조: 영문/한글 헤더 → 한 문장 번역 → ### 부연 설명(헤지 톤) → ### 언제 마주치나 → ### 자주 헷갈림(선택) → ### 참고 → 인용 박스(원문/번역) → 조건부 디스클레이머. 섹션 라벨 h3 로 변환 + h3 margin-top 32px 로 가독성 강화.
-
어드민 페이지네이션 race condition + UTF-8 인코딩
adminPageSize 가 10인데 페이저는 15로 표시되던 race fix (settings fetch 완료 전 페이저 초기화). _settingsReady 플래그 + 완료 시 재초기화. Worker 의 atob/btoa 가 latin-1 단위라 한글 깨지던 mojibake 해결 → TextEncoder/Decoder 기반 utf8ToBase64 헬퍼로 교체.
-
URL 영문 표준화 + 한글→영문 301 redirect
/전체글/→/archive/, /하루사진/→/photos/, /렌즈/→/snap/, /소개/→/about/ 4개 한글 페이지 경로를 영문으로 통일. 글 상세 슬러그(/posts/*)는 이미 모두 영문이라 변경 없음. public/_redirects 에 한글→영문 301 자동 매핑 → SEO 보존.
-
방명록 (1대1 스레드, 이메일 매치 인증) — Q&A 대체
qna 컬렉션 제거, guestbook (yaml data 컬렉션) 신규. thread 배열로 방문자↔운영자 1대1 대화 스레드. 방문자 답글은 원본 email 매치로 본인 인증 (매직링크 대신 단순 매치 — 발리 블로그 위협 모델에 적합). Cloudflare Worker 에 /guestbook/submit + /guestbook/reply 엔드포인트 신설. utf8ToBase64/base64ToUtf8 헬퍼로 한글 인코딩 안전 처리. 우측 하단 ✍️ 방명록 FAB + /guestbook/ 페이지 ↪ 답글 버튼 모달.
-
운영자 이름 어드민 설정 (operatorName)
siteSettings.operatorName 신규 필드 (default '데우스'). 방명록 답글 라벨, /archive 콜로폰 저자 모두 이 값 사용. 어드민에서 변경 시 양쪽 동시 반영.
-
/changelog/ 버전 이력 페이지
판권면 톤(Stripe Press 스타일) 신규 페이지. changelog.yaml singleton 을 fs+js-yaml 직접 파싱 → 시간순 표시 (유형별 색상 태그). 소개 페이지 풋노트· 푸터 v버전 링크에서 진입.
-
사이트 버전 통합 (footer + changelog + admin)
lib/version.ts 공통 유틸 추출. astro.config.mjs 빌드 시점 계산 → vite define 으로 import.meta.env.SITE_VERSION 주입. 푸터·changelog 페이지·어드민 브랜드 옆 v배지 모두 동일 값 사용. 어드민 배지 클릭 시 /changelog/ 새 탭.
-
카카오페이 데스크톱 QR 후원
카카오페이 송금이 모바일 앱 전용이라 데스크톱에선 동작 안 하던 문제 해소. 어드민에 'kakaoPayQrUpload' 이미지 업로드 필드 추가 → 업로드된 QR 이미지가 데스크톱 사용자 클릭 시 모달로 표시 (폰으로 스캔). 모바일은 기존대로 링크. QR 미등록 시 데스크톱에선 카카오페이 버튼 자동 숨김.
-
인젝트 스크립트 TypeScript 어노테이션 회귀
INJECTION_SCRIPT 템플릿 리터럴 안에 TS 어노테이션 (e: any, as HTMLElement) 이 섞여 들어가 SyntaxError 로 admin DOM 패치 전체가 죽었던 회귀 수정. published chip, Cloudinary 버튼, 맞춤법 버튼, 브랜드 링크 모두 회복.
-
좋아요 토글 + 메타 줄 통합
글 메타에 좋아요 pill 버튼 통합. 클릭 시 ❤️↔🤍 토글, 카운트 ±1.
-
사이트 로고/OG/파비콘 admin 관리
헤더 로고·SNS 공유 이미지·파비콘을 admin에서 URL/이모지로 설정 가능.
-
역사 속 오늘 (인도네시아)
위키 ko/en + OpenAI 번역으로 매일 인도네시아 역사 사건 1건 표시.
-
Obsidian vault 자동 동기화
GitHub Actions로 글 발행/수정/삭제 시 bali-vault repo로 자동 미러. 삭제는 _archived/로 안전 보존. .mdoc → .md 변환 통합.
-
첫 화면 히어로 정보 카드
발리/한국 시간, 날씨, 환율, 다음 축제 D-day, Quick Facts.
저자 항공 이야기 · 편집조수 모수·제니
Astro · Keystatic · Cloudflare · GitHub 으로 만들어짐