
  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
      <title>Hyo814`s Blog</title>
      <link>https://hyo814-blog.vercel.app/blog</link>
      <description>풀스택 개발자 임효진의 기술 블로그 — 프로젝트 회고, 프런트엔드·백엔드 학습 기록을 정리합니다.</description>
      <language>ko</language>
      <managingEditor>ggamjige8888@naver.com (Hyo814)</managingEditor>
      <webMaster>ggamjige8888@naver.com (Hyo814)</webMaster>
      <lastBuildDate>Fri, 19 Sep 2025 00:00:00 GMT</lastBuildDate>
      <atom:link href="https://hyo814-blog.vercel.app/tags/교통데이터플랫폼/feed.xml" rel="self" type="application/rss+xml"/>
      
  <item>
    <guid>https://hyo814-blog.vercel.app/blog/55개-파일의-회색을-처음-통일했다</guid>
    <title>55개 파일의 회색을 처음 통일했다 — 그때는 대비를 재지 않았다</title>
    <link>https://hyo814-blog.vercel.app/blog/55개-파일의-회색을-처음-통일했다</link>
    <description>입사 다섯 달째, 화면마다 제각각이던 표 정렬과 보조 제목과 회색을 55개 파일에서 한 번에 손봤습니다. 회색은 400을 500으로 올렸는데, 그때는 대비 수치를 재지 않고 눈으로 골랐어요. 1년 뒤 대비 감사를 하면서 같은 회색이 다시 도마에 올랐고, 그날 고른 값이 우연히 기준선과 같았다는 걸 알았습니다.</description>
    <pubDate>Fri, 19 Sep 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>CSS</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/7단계를-박아둔-템플릿이-5단계-환경에서-거짓말을-했다</guid>
    <title>7단계로 박은 절차 안내, 5단계 환경에선 거짓말</title>
    <link>https://hyo814-blog.vercel.app/blog/7단계를-박아둔-템플릿이-5단계-환경에서-거짓말을-했다</link>
    <description>심사 목록 위의 절차 안내가 7단계로 고정돼 있었는데, 이 시스템은 사전인증·인증을 뺀 5단계로도 돕니다. 단계 수는 DB의 프로세스 정의에 있고 화면은 코드에 있어서, 5단계 환경에서는 없는 단계를 그리고 있었어요. 상태와 전이를 걸어 단계 사슬을 만들게 바꿨고, 단계별 역할도 같은 걸음에서 뽑았습니다.</description>
    <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/Semantic-Web</guid>
    <title>시맨틱 웹의 이해 — 공부한 개념이 그대로 실무 도메인이 된 경우</title>
    <link>https://hyo814-blog.vercel.app/blog/Semantic-Web</link>
    <description>RDF, 온톨로지, DCAT, 링크드 데이터 — 교통 데이터 플랫폼을 맡게 되며 급하게 공부했던 시맨틱 웹 개념 정리입니다. 특이한 건 이 공부가 교양으로 끝나지 않았다는 것 — 온톨로지의 클래스·인스턴스·속성·관계가 그대로 시스템의 데이터 모델이 됐고, 그 과정에서 개념과 RDB 사이의 간극도 몸으로 배웠습니다. 정리 뒤에 그 이야기를 붙였습니다.</description>
    <pubDate>Wed, 23 Apr 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/asn1-트리-렌더링-graphviz에서-d3로</guid>
    <title>ASN.1 트리, 서버 PNG 대신 D3로 그린 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/asn1-트리-렌더링-graphviz에서-d3로</link>
    <description>서버에서 graphviz로 PNG를 그려 내려주던 ASN.1 트리를 D3.js 기반 Collapsible Tree로 전환한 과정과 그 이유를 정리합니다. 서버 의존성 제거, 인터랙션, JSON 스키마 설계까지.</description>
    <pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/d3-공용-줌-컨트롤-외부화-회고</guid>
    <title>D3 그래프마다 복붙된 줌 코드를 한 모듈로</title>
    <link>https://hyo814-blog.vercel.app/blog/d3-공용-줌-컨트롤-외부화-회고</link>
    <description>데이터 관계도·워드클라우드·트리맵마다 복붙돼 있던 줌 설정을 공용 모듈 d3ZoomControls.js로 추출하고, 확대/축소/맞춤 버튼과 &quot;최초 1회 fit-to-view&quot;를 표준화한 작업입니다. SVG가 100% 크기일 때 뷰포트 크기를 어떻게 구하느냐가 핵심 함정이었어요.</description>
    <pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/dev의-oid-번호를-운영과-같게-심었다</guid>
    <title>dev 데이터, 번호를 새로 매기면 운영과 어긋난다</title>
    <link>https://hyo814-blog.vercel.app/blog/dev의-oid-번호를-운영과-같게-심었다</link>
    <description>운영 인스턴스 7,083건을 dev에 미러링했더니 OID 검색 화면이 뼈대 9건으로 무너졌습니다. 미러가 OID 문자열은 복사하면서 OID 노드는 안 만들었고, 기존 채번 명령으로 채우면 번호를 새로 매겨 1,489건 중 1,107건이 운영과 어긋났어요. 운영 트리의 번호를 그 자리에 그대로 심는 명령을 따로 만들었습니다. 같은 배치에서 카탈로그에 메시지를 매단 다리는 하루 뒤 운영과 다르다는 이유로 다시 걷었습니다.</description>
    <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/disabled-필드는-cleaned-data에-없다</guid>
    <title>disabled 필드는 cleaned_data에 없다 — 라고 적었는데 Django 문서는 반대였다</title>
    <link>https://hyo814-blog.vercel.app/blog/disabled-필드는-cleaned-data에-없다</link>
    <description>OID 수정 화면에서 상위 항목을 못 바꾸게 parent 필드를 disabled로 뒀더니 저장할 때마다 &quot;유효하지 않은 부모&quot;가 났습니다. clean_parent에 instance에서 부모를 꺼내는 대체 경로를 넣어 막았고, 주석에 &quot;disabled 필드는 cleaned_data에 포함되지 않는다&quot;고 적었어요. 1년 뒤 문서를 다시 읽으니 Django의 disabled는 제출값을 무시하고 initial을 쓴다고 돼 있습니다. HTML의 disabled와 폼 필드의 disabled를 같은 것으로 알고 있던 때의 기록입니다.</description>
    <pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/disabled를-쓰면-왜-안-되는지를-말할-수-없다</guid>
    <title>disabled 버튼에는 툴팁이 뜨지 않는다</title>
    <link>https://hyo814-blog.vercel.app/blog/disabled를-쓰면-왜-안-되는지를-말할-수-없다</link>
    <description>잠긴 버튼에 사유를 title로 달아뒀는데 아무리 호버해도 안 떴습니다. disabled 요소는 마우스·키보드 이벤트를 통째로 죽여서 네이티브 title조차 안 뜬다는 걸 그때 알았어요. aria-disabled로 바꿔 의미만 남기고 클릭은 핸들러에서 막았습니다. 그 다음엔 말풍선이 스크롤 패널에 잘리고, 휠 관성 때문에 떴다 사라지는 문제가 이어졌습니다.</description>
    <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/django-템플릿-공용-매크로와-스크롤-스파이-외부화-회고</guid>
    <title>약관·가이드 페이지의 중복 마크업을 매크로로 걷기</title>
    <link>https://hyo814-blog.vercel.app/blog/django-템플릿-공용-매크로와-스크롤-스파이-외부화-회고</link>
    <description>약관/방침 페이지와 소개·가이드 페이지에 흩어져 있던 마크업 중복을 base 템플릿 + 공용 매크로 + 외부 스크립트로 정리한 회고입니다.</description>
    <pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/django-프로젝트에-d3-시각화-붙이기</guid>
    <title>jQuery 기반 Django 프로젝트에 D3 시각화 얹기</title>
    <link>https://hyo814-blog.vercel.app/blog/django-프로젝트에-d3-시각화-붙이기</link>
    <description>jQuery 기반 Django 프로젝트에 D3.js 시각화를 도입한 경험을 정리합니다. 공통 그래프 유틸 설계, 실데이터 부재 시 샘플 폴백, 줌/중앙정렬 개선 포인트를 다룹니다.</description>
    <pubDate>Sat, 18 Apr 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/django로-설문조사-시스템-처음부터-만들기</guid>
    <title>Django로 설문조사 시스템 처음부터 만들기 — 3-tier 재설계와 PDF 다운로드</title>
    <link>https://hyo814-blog.vercel.app/blog/django로-설문조사-시스템-처음부터-만들기</link>
    <description>common 앱에 섞여 있던 설문조사 모델을 독립 앱으로 분리하고 3-tier 아키텍처로 재설계한 과정, 그리고 weasyprint 기반 PDF 다운로드와 개인정보 마스킹 구현을 정리합니다.</description>
    <pubDate>Sun, 15 Feb 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/handleajaxerror를-다시-고민했다</guid>
    <title>handleAjaxError를 다시 고민했다 — 커밋 두 개 451줄, 들여쓰기를 빼면 120줄</title>
    <link>https://hyo814-blog.vercel.app/blog/handleajaxerror를-다시-고민했다</link>
    <description>트리 화면 셋의 오류 처리를 손보던 오후였습니다. 커밋 둘이 합쳐 600줄 가까이 바뀐 것처럼 보이는데, 공백을 무시하고 보면 120줄이에요. 실제로 한 일은 오류 alert에 어느 요청이 실패했는지 한 줄 붙이기, 관리자 버튼 바인딩을 감싸던 if를 풀기, 세 파일의 버튼 id를 맞추기였습니다. 정작 handleAjaxError 함수 본문은 한 글자도 안 바뀌었습니다.</description>
    <pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/img가-nginx에서-깨졌다</guid>
    <title>./img가 Nginx에서 깨졌다 — 입사 한 달째 첫 배포 환경 차이, 그리고 이름이 같은 함수 둘</title>
    <link>https://hyo814-blog.vercel.app/blog/img가-nginx에서-깨졌다</link>
    <description>입사 한 달째, 로컬에서는 멀쩡하던 아코디언 아이콘이 운영 서버에서 안 떴습니다. 이미지 경로의 ./를 떼서 고쳤는데, 지금 다시 보면 그 수정이 왜 효과가 있었는지 설명이 안 됩니다. 같은 날 오후에는 이름이 같은 전역 함수 둘이 한 페이지에서 부딪히는 것을 잡았어요. 그날 두 가지를 커밋 메시지에 적힌 만큼만 옮깁니다.</description>
    <pubDate>Mon, 12 May 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>인프라</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/iso14817-2-7단계-워크플로우-설계</guid>
    <title>ISO 14817-2로 짠 7단계 심사 상태 머신</title>
    <link>https://hyo814-blog.vercel.app/blog/iso14817-2-7단계-워크플로우-설계</link>
    <description>교통 데이터 플랫폼에 ISO 14817-2의 데이터 개념 라이프사이클을 적용해 기록→제출→사전검증→검증→사전인증→인증→배포의 7단계 상태 머신을 구성한 과정을 정리합니다.</description>
    <pubDate>Tue, 07 Apr 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/its-v2x-표준-정리</guid>
    <title>ITS·V2X 표준 14종은 서로 어떻게 물려 있나</title>
    <link>https://hyo814-blog.vercel.app/blog/its-v2x-표준-정리</link>
    <description>업무상 결제해둔 ITS/V2X 관련 표준 14종(ISO 14817-2, SAE J2735, KS R 1600 시리즈, KS X ISO 14827/15784, ISO TS 19091)을 실제로 읽어보며, 각 표준이 무엇을 규정하고 서로 어떻게 물려 있는지 한 글에 정리합니다.</description>
    <pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/jinja가-캐시-버스터를-컴파일-시점에-굳혔다</guid>
    <title>캐시를 깨려던 필터가 캐시를 만들고 있었다</title>
    <link>https://hyo814-blog.vercel.app/blog/jinja가-캐시-버스터를-컴파일-시점에-굳혔다</link>
    <description>JS를 고치고 새로고침해도 화면이 안 바뀌는데 서버를 다시 띄우면 바뀌는 증상이 있었습니다. 범인은 캐시를 깨라고 만들어 둔 add_hash 필터 자신이었어요. 입력이 전부 상수라 Jinja가 컴파일 시점에 한 번 접어버렸고, 그래서 서버 기동 시각이 URL에 굳어 있었습니다. @pass_context로 접힘을 막고 값을 파일 수정시각으로 바꿨습니다.</description>
    <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/jquery-formset을-넣고-두-달-뒤-인덱스를-직접-다시-매겼다</guid>
    <title>jquery-formset을 넣고 두 달 뒤 인덱스를 직접 다시 매겼다 — 삭제 체크박스를 켠 날과 20가지 시나리오</title>
    <link>https://hyo814-blog.vercel.app/blog/jquery-formset을-넣고-두-달-뒤-인덱스를-직접-다시-매겼다</link>
    <description>워크플로 관리 화면의 인라인 폼셋 12쌍이 전부 can_delete=False였습니다. 5월에 jquery-formset 라이브러리를 넣으면서 삭제를 켰고, 두 달 뒤 항목을 지우고 다시 추가하면 저장이 어긋나서 폼 인덱스를 직접 다시 매기는 함수를 짰어요. 같은 날 저녁에 숨긴 행을 세지 않던 버그를 잡고 시나리오 20개를 커밋 메시지에 남겼습니다. 그 함수는 1년이 지난 지금도 그대로 돌고 있어요.</description>
    <pubDate>Wed, 09 Jul 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/oid-creation-wizard-ux-구현-회고</guid>
    <title>4단계 Creation Wizard UX 구현 회고 — 상태·모드 분리와 완전 종료 문제</title>
    <link>https://hyo814-blog.vercel.app/blog/oid-creation-wizard-ux-구현-회고</link>
    <description>다단계 입력이 필요한 등록 폼에 Creation Wizard 모드와 일반 편집 모드를 분리해서 구현한 과정을 정리합니다. 상태 관리, 트리 연동, &quot;완전 종료&quot; 버그까지.</description>
    <pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/oid-등록-신청-화면이-16초-멈춰-있었다</guid>
    <title>화면 16초 멈춤, 범인은 트리가 아니라 선택 상자</title>
    <link>https://hyo814-blog.vercel.app/blog/oid-등록-신청-화면이-16초-멈춰-있었다</link>
    <description>OID 등록 신청 화면의 상위 OID 트리가 스피너도 없이 빈 상자로 한참 멈춰 있었습니다. 트리 요청은 0.6초에 끝났는데 페이지의 DOMContentLoaded 처리가 16.1초였어요. 같은 폼에 있는 참조 선택 상자가 항목 7,099개를 하나씩 DOM에 붙였고, 페이지 전체를 감시하는 FontAwesome이 그 변경 기록을 처리하느라 메인 스레드를 잡고 있었습니다. 모아서 한 번에 붙이게 바꾸니 0.06초가 됐습니다.</description>
    <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/oid-트리를-jstree에서-조직도로-갈아탔다</guid>
    <title>계층 트리를 가로 조직도로, 네 화면 중 두 곳만</title>
    <link>https://hyo814-blog.vercel.app/blog/oid-트리를-jstree에서-조직도로-갈아탔다</link>
    <description>OID는 번호로 갈라지는 계층인데 세로 목록 트리로는 형제 순서도 계층 폭도 안 읽혔습니다. d3.hierarchy로 가로 조직도를 새로 그렸는데, 네 화면 중 두 곳만 바꿨어요 — 경로 바가 있느냐로 갈랐습니다. 그리고 나서 트리 전체를 다 그리다 SVG가 12,691px가 됐습니다.</description>
    <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/oid-트리를-낮에-고정하고-밤에-되돌렸다</guid>
    <title>드릴다운을 지운 지 일곱 시간 만의 번복</title>
    <link>https://hyo814-blog.vercel.app/blog/oid-트리를-낮에-고정하고-밤에-되돌렸다</link>
    <description>OID 조직도의 드릴다운을 오후 2시에 걷어냈고 밤 9시 45분에 되살렸습니다. 잎을 트리 밖 카드 목록으로 내보낸 뒤 계층이 한 화면에 다 들어오니 드릴다운이 필요 없어 보였는데, 운영 데이터의 표준 가지 아래로 내려갈 길이 통째로 사라졌어요. 되돌리면서 &quot;어느 노드가 카드 버킷인가&quot;를 화면의 추론에서 서버 플래그로 옮겼습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/oid-하나에-표기법-넷</guid>
    <title>OID 하나에 표기법 넷 — 같은 계산이 세 곳에 있었고, 네 번째 표기를 세 곳에 더했다</title>
    <link>https://hyo814-blog.vercel.app/blog/oid-하나에-표기법-넷</link>
    <description>객체 식별자 하나를 점 표기법·ASN.1·IRI·URN 네 가지로 보여 줘야 했습니다. 동료가 만든 세 표기법에 IRI를 넷째로 더했는데, 조상 경로를 이어 붙이는 같은 계산이 모델·매니저·화면 스크립트 세 곳에 있었고 저는 세 곳에 한 줄씩 더 얹었어요. 왜 세 곳인지는 나중에 이해했고, 그때는 걷어내지 않았습니다.</description>
    <pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/open-api-mock에서-실데이터로-provider-추상화</guid>
    <title>mock으로 먼저 만든 API, 실데이터는 스위치 한 줄로</title>
    <link>https://hyo814-blog.vercel.app/blog/open-api-mock에서-실데이터로-provider-추상화</link>
    <description>Open API의 데이터 계층을 처음부터 provider 인터페이스로 추상화해 mock으로 화면·계약을 먼저 굳히고, 실데이터 전환은 OrmDataProvider 골격 + 한 줄 스위치로 분리한 과정을 정리합니다. 미완 활성화가 곧 비공개 데이터 유출이라 fail-closed로 설계한 이야기도 담았어요.</description>
    <pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/open-api-응답-id를-pk에서-uuid로-바꾸며-v1과-v2를-함께-열었다</guid>
    <title>API 응답 id를 UUID로 바꾸며 v2를 따로 연 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/open-api-응답-id를-pk에서-uuid로-바꾸며-v1과-v2를-함께-열었다</link>
    <description>Open API 목록이 내보내던 id는 DB의 pk였습니다. pk는 dev와 운영이 다르고 재적재에 밀리는 값이라, 연계 기관이 저장해 두기엔 맞지 않았어요. 바뀌지 않는 공개 식별자(UUID)를 더하고, 정수 id를 기대하는 기존 호출이 깨지지 않게 /api/v2/를 따로 열어 v1과 함께 운영하기로 했습니다. 같은 뷰를 두 주소에 붙이고, 폐기 예고 헤더와 중지 410을 미들웨어 한 곳에서 내보냈습니다. 같은 날 RDF 안의 주소가 여전히 pk였다는 걸 발견해 다시 고쳤고, 시드와 미러는 아직 UUID를 옮기지 못합니다.</description>
    <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/open-api-정책-토글-캐시와-만료-상태-동기화</guid>
    <title>토글을 바꿔도 TTL이 지나야 반영되던 캐시</title>
    <link>https://hyo814-blog.vercel.app/blog/open-api-정책-토글-캐시와-만료-상태-동기화</link>
    <description>관리자가 오퍼레이션을 토글했는데 TTL이 지나야 반영되던 캐시 갭, 그리고 만료된 토큰의 신청 상태가 &quot;승인됨&quot;으로 남던 stale 문제를 정리합니다. 캐시 즉시 무효화와 진입 시점 sync_expired로 &quot;보이는 상태 = 실제 상태&quot;를 맞춘 이야기예요.</description>
    <pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/open-api-토큰-승인-오클릭-가드와-버튼-그룹화</guid>
    <title>승인 버튼 오클릭을 막는 가장 단순한 가드</title>
    <link>https://hyo814-blog.vercel.app/blog/open-api-토큰-승인-오클릭-가드와-버튼-그룹화</link>
    <description>토큰 신청 검토 화면에서 승인/거절을 우측 정렬 버튼 그룹으로 묶고, 거절 사유를 적어둔 채 승인을 눌러버리는 오클릭에 확인 가드를 넣은 작업입니다. 네 가지 마크업 방식 중 form 속성을 고른 이유와, 커스텀 모달 대신 네이티브 confirm을 남겨둔 판단을 정리해요.</description>
    <pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/pk를-박아둔-e2e-스펙-11개가-한꺼번에-빨개졌다</guid>
    <title>DB pk를 박은 E2E 테스트는 재적재 한 번에 깨진다</title>
    <link>https://hyo814-blog.vercel.app/blog/pk를-박아둔-e2e-스펙-11개가-한꺼번에-빨개졌다</link>
    <description>엑셀 재적재 한 번에 dcat:Catalog의 pk가 35에서 5로 밀렸고, 그 번호를 URL에 박아둔 스펙 11개가 동시에 빨개졌습니다. pk를 URI 조회로 바꾸고, 무엇이 밀리고 무엇이 안 밀리는지 선을 그었습니다. 덤으로 타임아웃 때 원복이 같이 죽어 dev DB가 며칠간 어긋나 있던 것도 잡았어요.</description>
    <pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>테스트</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/playwright-메뉴-136종-qa-스윕</guid>
    <title>기능목록 엑셀을 Playwright로 돌린 메뉴 136종 QA</title>
    <link>https://hyo814-blog.vercel.app/blog/playwright-메뉴-136종-qa-스윕</link>
    <description>납품 문서의 기능목록 엑셀을 JSON으로 뽑아 메뉴 136종을 전부 열어보는 Playwright 스윕을 만들었습니다. 설정을 용도별 3종으로 나눈 이유, SQLite 때문에 워커를 1로 고정한 이유, 그리고 확인 못 한 항목을 스킵으로 남겨둔 게 옳은 선택이었는지까지 적었습니다.</description>
    <pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>테스트</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/sqlite-dev-postgres-prod-charfield-length</guid>
    <title>SQLite에선 통과하고 PostgreSQL에서 터진 CharField(512)</title>
    <link>https://hyo814-blog.vercel.app/blog/sqlite-dev-postgres-prod-charfield-length</link>
    <description>로컬(SQLite)에선 멀쩡히 적재되던 메타데이터 로더가 운영(PostgreSQL)에서만 value too long으로 죽었습니다. 프런트 쪽을 주로 맡다가 모델·마이그레이션을 조금씩 만지기 시작한 입장에서, 원인을 어떻게 좁혀갔고 네 가지 선택지 중 왜 TextField를 골랐는지 정리합니다.</description>
    <pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/sr-only-체크박스-포커스-스크롤-점프-수리</guid>
    <title>토글 한 번에 화면이 튀는 이유 두 가지</title>
    <link>https://hyo814-blog.vercel.app/blog/sr-only-체크박스-포커스-스크롤-점프-수리</link>
    <description>값 유형 토글을 누를 때마다 화면이 튀었습니다. 하나 고쳤는데 증상이 남아서 다시 팠더니 원인이 둘이었어요. sr-only로 숨긴 체크박스가 일으키는 focus scroll, 그리고 tbody 전면 재렌더로 scroll anchoring 기준이 사라지는 문제. 각각 어떤 대안들을 놓고 무엇을 골랐는지, 그리고 &quot;안 튀는 것 같다&quot;를 숫자로 바꾼 검증까지 정리합니다.</description>
    <pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/tailwind-v3에서-v4-css-first-theme-전환-회고</guid>
    <title>Tailwind v4 @theme 전환에서 깨진 것들</title>
    <link>https://hyo814-blog.vercel.app/blog/tailwind-v3에서-v4-css-first-theme-전환-회고</link>
    <description>tailwind.config.js 기반 v3에서 CSS 안에서 @theme로 토큰을 정의하는 v4로 전환하면서 발생한 회귀와 패치 과정을 정리한 회고입니다.</description>
    <pubDate>Sun, 10 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>CSS</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/tailwind-v3에서-v4로-170개-파일을-옮겼다</guid>
    <title>Tailwind v4 전환의 핵심은 설정 파일 삭제였다</title>
    <link>https://hyo814-blog.vercel.app/blog/tailwind-v3에서-v4로-170개-파일을-옮겼다</link>
    <description>v4 전환은 버전을 올리는 일이 아니라 토큰의 원천을 JS 설정에서 CSS로 옮기는 일이었습니다. tailwind.config.js를 지우면서 safelist가 조용히 사라졌고, @layer components에 둔 클래스는 @apply 대상이 아니게 됐고, 마크업에 둔 기본 상태가 컴포넌트 규칙을 이기기 시작했어요. 없던 브레이크포인트를 살리자 8개 화면이 그제야 다열이 됐습니다.</description>
    <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>CSS</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/tv에-연결하니-테두리가-안-보였다</guid>
    <title>TV에 띄우니 테두리가 사라졌다</title>
    <link>https://hyo814-blog.vercel.app/blog/tv에-연결하니-테두리가-안-보였다</link>
    <description>열흘 전 대비 감사에서 회색 테두리 260곳은 장식이라 일부러 안 고쳤습니다. 그런데 고해상도 TV에 HDMI로 확장해 띄우니 표 격자와 카드 테두리가 통째로 사라졌어요. 장식은 gray-500, 관계를 나타내는 연결선은 gray-600으로 94개 파일을 올렸고, 그때 세워 둔 기준이 어디서 틀렸는지를 적습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>CSS</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/workflow-rvs-도입과-철회-회고</guid>
    <title>심사에 &#39;보완 요청&#39; 단계를 넣었다가 뺀 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/workflow-rvs-도입과-철회-회고</link>
    <description>심사 프로세스에 승인/반려 외 제3의 축(보완 요청)을 추가했다가, 상태 머신 복잡도와 UX 혼란을 이유로 철회한 의사결정 과정을 정리합니다.</description>
    <pubDate>Sat, 04 Apr 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/같은-표준데이터를-두-화면이-198건과-134건으로-세고-있었다</guid>
    <title>198건과 134건, 같은 데이터를 다르게 세던 두 화면</title>
    <link>https://hyo814-blog.vercel.app/blog/같은-표준데이터를-두-화면이-198건과-134건으로-세고-있었다</link>
    <description>홈 &quot;데이터 현황&quot; 타일은 198건, 그 타일을 눌러 도착하는 목록 화면은 134건이었습니다. 닷새 전에 &quot;타일이 목록으로 링크하니까 목록에 맞춘다&quot;고 결정하고 주석까지 박아뒀는데도 회귀가 샜습니다. 원인은 결정이 아니라 그 결정을 지킨다던 테스트였어요. 기대값을 상수로 박아둔 정합 테스트는 목록 뷰가 조건을 하나 더 붙여도 계속 초록이었습니다.</description>
    <pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/검색-조건을-바꿀-때-새로고침-대신-조각-9개를-갈아끼웠다</guid>
    <title>새로고침 대신 바뀐 부분만 갈아끼우는 검색 필터</title>
    <link>https://hyo814-blog.vercel.app/blog/검색-조건을-바꿀-때-새로고침-대신-조각-9개를-갈아끼웠다</link>
    <description>필터를 하나 좁힐 때마다 화면이 하얘지고 스크롤이 맨 위로 튀었습니다. 서버와 주소 계약은 그대로 두고, 같은 주소를 fetch로 받아 달라지는 조각 아홉 개만 갈아끼우도록 바꿨어요. 이음매에서 조용히 새던 두 가지를 소리 나게 고쳤고, 응답 순서가 요청 순서와 어긋나는 문제를 사흘 전 데이터 맵에서 잡았던 것과 같은 방식으로 또 잡았습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/검색-화면-시안-넷을-만들었고-여덟-달-뒤-전부-지워졌다</guid>
    <title>검색 화면 시안 넷을 만들었고 여덟 달 뒤 전부 지워졌다 — 시안이 남긴 것과 남기지 못한 것</title>
    <link>https://hyo814-blog.vercel.app/blog/검색-화면-시안-넷을-만들었고-여덟-달-뒤-전부-지워졌다</link>
    <description>입사 넉 달째, 검색 화면이 어떤 모양이어야 할지 정해진 게 없어서 가짜 데이터로 시안 넷을 만들었습니다. 열흘 뒤 팀원이 그중 셋에 실제 데이터를 연결했고, 하나는 끝내 연결되지 않았어요. 여덟 달 뒤 제가 그 앱을 통째로 지웠습니다. 시안이 최종 화면에 무엇을 남겼는지는 코드로 이을 수 없었습니다.</description>
    <pubDate>Fri, 08 Aug 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/검색-화면-하나를-지우면서-파일-36개를-건드렸다</guid>
    <title>화면 하나 지우기, 어려운 건 무엇을 남기느냐</title>
    <link>https://hyo814-blog.vercel.app/blog/검색-화면-하나를-지우면서-파일-36개를-건드렸다</link>
    <description>검색 화면이 둘이었는데 하나로 수렴해서 통합검색을 걷어냈습니다. 2102줄을 지우는 건 쉬웠고, 어려운 건 무엇을 남길지였어요. 호출자가 테스트만 남은 매니저 메서드는 지웠고, 3줄짜리 껍데기 안의 알맹이는 남겼고, 폐지된 화면이 남긴 검색 기록은 집계에서 안 떨어뜨렸습니다.</description>
    <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/검색형-select-복구-searchableselect-회고</guid>
    <title>옵션이 수백 개인 select에 검색 되살리기</title>
    <link>https://hyo814-blog.vercel.app/blog/검색형-select-복구-searchableselect-회고</link>
    <description>클래스 참조 필드처럼 옵션이 수백 개인 select를 스크롤로만 찾던 걸 입력 검색으로 좁히는 검색형 select로 되살린 작업입니다. 라이브러리를 다시 들일지 직접 얹을지부터 정하고, placeholder 잘림·× 해제 안 되는 버그, 그리고 Font Awesome svg 모드가 참조를 유령으로 만드는 함정까지 하나씩 잡았어요.</description>
    <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/게시판-종류를-코드가-아니라-데이터로-뒀다</guid>
    <title>넉 달 전 내가 쓴 &#39;403보다 404&#39; 결론을 어긴 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/게시판-종류를-코드가-아니라-데이터로-뒀다</link>
    <description>FAQ와 1:1 문의를 공지사항 Post 모델 위에 얹었습니다. 게시판 종류를 Category 행으로 뒀더니 게시판 추가가 데이터 한 줄이 됐는데, 대신 &quot;문의&quot;라는 한글 문자열이 코드에 박혔어요. 그리고 넉 달 전 제가 &quot;타인 글은 403보다 404가 안전하다&quot;고 써놓고, 정작 이번 구현은 403으로 냈습니다. 왜 그랬는지 따져봤습니다.</description>
    <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관계도-11개-화면을-렌더러-한-곳에서-바꿨다</guid>
    <title>노드 클릭을 이동에서 선택으로, 화면 11개를 한 번에</title>
    <link>https://hyo814-blog.vercel.app/blog/관계도-11개-화면을-렌더러-한-곳에서-바꿨다</link>
    <description>노드를 클릭하면 곧바로 화면이 떠나서, 이 노드가 뭔지 보려다가 보던 그림을 잃었습니다. 클릭을 선택으로 바꾸고 다음 행동을 우측 패널로 옮겼어요. 공용 렌더러와 공용 본문을 고쳐 공개 6 · 관리자 5, 11개 화면에 한 번에 걸었고, 설정을 템플릿 set에 두면 include로 안 넘어간다는 함정도 같이 정리했습니다.</description>
    <pubDate>Mon, 10 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관계도-연쇄-탐색과-땅콩-모양-노드-겹침</guid>
    <title>노드 두 개가 땅콩처럼 붙은 이유는 forceCenter</title>
    <link>https://hyo814-blog.vercel.app/blog/관계도-연쇄-탐색과-땅콩-모양-노드-겹침</link>
    <description>클래스 3개짜리 화면이 18개 노드로 그려지던 관계도를, 백엔드를 안 건드리고 중심 이동 탐색으로 바꿨습니다. 배치를 힘 시뮬레이션에서 고정 방사 좌표로 뺐더니 이번엔 노드 두 개가 땅콩처럼 붙었어요. 범인은 forceCenter였고, 고정 노드가 있는 그래프에서 왜 그게 겹침을 만드는지 정리했습니다.</description>
    <pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관계도-이웃을-6개씩-펼치기로-했다가-같은-날-폐지했다</guid>
    <title>네 시간 만에 세 번 뒤집힌 관계도 펼치기 결정</title>
    <link>https://hyo814-blog.vercel.app/blog/관계도-이웃을-6개씩-펼치기로-했다가-같은-날-폐지했다</link>
    <description>표준 하나를 중심에 두면 이웃 226개가 한꺼번에 쏟아지던 관계도를 관계·클래스별 그룹 카드로 접었습니다. 그룹을 더블클릭하면 6개씩 펼치기로 하고 패널에 페이저까지 달았는데, 네 시간 뒤 정보 주제라는 2차 단이 들어오면서 6개씩 쪽 넘김을 통째로 걷어냈어요. 같은 날 커밋 둘이 서로를 뒤집는 과정과, 그 사이에 남긴 것·버린 것을 적습니다.</description>
    <pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관리자-방문-통계를-세-번-다시-짜며-고친-집계-버그-둘</guid>
    <title>UTC 날짜 칸 때문에 새벽 방문이 사라지던 통계</title>
    <link>https://hyo814-blog.vercel.app/blog/관리자-방문-통계를-세-번-다시-짜며-고친-집계-버그-둘</link>
    <description>관리자 방문 통계 화면을 9월 15일, 10월 12일, 10월 20일에 세 번 다시 짰습니다. 첫 번째에서는 한 번도 걸리지 않던 디버그 경로 제외 조건과, UTC 날짜로 칸을 만들어 새벽 방문이 사라지던 버그를 찾았습니다. 두 번째에서는 같은 회사의 다른 시스템과 화면을 맞추면서 수집기를 옮기지 않고 조회할 때 규칙을 거는 쪽을 골랐고, 세 번째에서는 서버 모니터링과 한 화면으로 합쳤어요. 10월 집계 함수는 다른 시스템 것을 옮겨 왔고, 9월에 잡은 회귀 사례는 새 테스트에 다시 심었습니다.</description>
    <pubDate>Tue, 20 Oct 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관리자-사이드바-그룹을-열흘-사이-세-번-옮겼다</guid>
    <title>경로 부분 문자열로 메뉴 활성을 판정하면 생기는 일</title>
    <link>https://hyo814-blog.vercel.app/blog/관리자-사이드바-그룹을-열흘-사이-세-번-옮겼다</link>
    <description>관리자 사이드바의 신청·심사 메뉴가 열흘 동안 세 자리를 옮겨 다녔습니다. 도메인별 그룹(제가) → 신청/심사 한 그룹(팀원) → 다시 도메인별 그룹(제가). 옮길 때마다 걸린 건 그룹 이름이 아니라 활성 메뉴 판정이었어요. 판정이 &quot;현재 경로에 이 문자열이 들어 있나&quot;여서, 상위 경로를 가진 메뉴가 하위 화면까지 삼켜 두 그룹이 같이 켜졌습니다. 이 글은 그 판정 위에서 메뉴를 옮기는 비용과, 세 번 바뀐 하위 메뉴 이름 규칙에 대한 기록입니다. 9월 2일 작업을 10월 말 이름 정리까지 묶어 정리했습니다.</description>
    <pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/관리자-화면-12개가-익명에-열려-있었다</guid>
    <title>로그아웃 상태로 열리던 관리자 화면 12개</title>
    <link>https://hyo814-blog.vercel.app/blog/관리자-화면-12개가-익명에-열려-있었다</link>
    <description>로그아웃 상태로 관리자 공지 목록 주소를 열었더니 화면이 그대로 떴습니다. 같은 파일 안의 분류 뷰 다섯은 막혀 있고 공지 뷰 다섯은 안 막혀 있었어요. 게다가 그중 둘은 GET 요청으로 정렬 순서를 저장하고 있었고, except 절의 bare return 때문에 500까지 났습니다. 믹스인을 붙이면서 붙인 권한 선언이 실은 아무도 안 읽는 값이었다는 것도 같이 적었습니다.</description>
    <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/날짜-시간대-변환을-이튿날-서버로-옮겼다</guid>
    <title>날짜 시간대 변환을 이튿날 서버로 옮겼다 — 목록의 JS 변환은 지우고 제출 변환은 넓혔다</title>
    <link>https://hyo814-blog.vercel.app/blog/날짜-시간대-변환을-이튿날-서버로-옮겼다</link>
    <description>settings의 TIME_ZONE이 UTC라 소식지·공지 목록의 날짜가 9시간 어긋나 보였습니다. 첫날 저녁엔 제출할 때 브라우저에서 UTC로 바꾸는 스크립트를 네 필드에만 넣었고, 이튿날 오후엔 목록 세 곳이 innerText를 파싱해 시간대를 바꾸던 JS를 지우고 Jinja 필터가 서울 시간으로 바꾸게 했어요. 시간대 변환이 세 곳에 흩어져 있었다는 걸 그때 처음 봤습니다.</description>
    <pubDate>Tue, 28 Oct 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/날짜-칸을-씌웠더니-옛-값이-지워질-뻔했다</guid>
    <title>날짜 입력칸을 씌우자 기존 값이 지워질 뻔했다</title>
    <link>https://hyo814-blog.vercel.app/blog/날짜-칸을-씌웠더니-옛-값이-지워질-뻔했다</link>
    <description>생성일자·수정일자·발행일자·표준 폐지일자·바이트 크기가 전부 평범한 텍스트칸이었습니다. 그런데 용어를 아무리 들여다봐도 그 슬롯이 날짜인지 알 수가 없었어요. 값 영역이 rdfs:Literal 이거나 아예 비어 있었거든요. CURIE 명단으로 판정하기로 했는데, 날짜칸을 씌우는 순간 꼴이 다른 기존 값이 화면에서 조용히 비워진다는 걸 알았습니다. 저장 한 번이면 그대로 지워지는 값이었어요.</description>
    <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/네임스페이스-색인에-검색칸을-달았다</guid>
    <title>서버를 안 부르는 검색칸, 언젠가 거짓말을 한다</title>
    <link>https://hyo814-blog.vercel.app/blog/네임스페이스-색인에-검색칸을-달았다</link>
    <description>클래스·용어 관리 화면에서 네임스페이스를 고르면 소속 용어가 표로 쭉 나옵니다. 가장 큰 것이 117건인데 찾을 방법이 눈으로 훑는 것뿐이었어요. 목록이 페이지 나눔 없이 통째로 그려져 있어서 서버를 부르지 않고 그려진 행만 걸렀습니다. 대신 &quot;전부 렌더돼 있다&quot;는 전제에 기대는 구현이라, 언젠가 페이지 나눔이 생기면 이 검색칸은 그날부터 거짓말을 합니다.</description>
    <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/네임스페이스-옵션-json에서-db로-전환한-이유</guid>
    <title>&#39;거의 안 바뀐다&#39;던 옵션을 JSON에서 DB로 옮긴 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/네임스페이스-옵션-json에서-db로-전환한-이유</link>
    <description>&quot;거의 안 바뀔 것&quot;이라는 가정으로 정적 JSON에 두었던 네임스페이스 옵션이 실제로는 자주 바뀌고 있었고, 결국 DB 조회로 옮긴 결정과 그 교훈을 정리합니다.</description>
    <pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/데이터-맵에서-세-단계-들어간-자리를-주소에-남겼다</guid>
    <title>드릴다운 위치를 URL에 담아 되돌아오기</title>
    <link>https://hyo814-blog.vercel.app/blog/데이터-맵에서-세-단계-들어간-자리를-주소에-남겼다</link>
    <description>드릴다운으로 세 단계 파고들어간 뒤 상세로 갔다가 돌아오면 늘 맨 처음이었습니다. 탐색 단계를 pushState로 주소에 남겼는데, 그 주소가 상세의 복귀 파라미터로 실려 가면서 서버 필터에 통째로 버려졌어요. 값을 한 번 더 인코딩해 통과시켰고, 복원이 중간에 끊기면 거기까지만 그리고 주소를 화면에 맞췄습니다.</description>
    <pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/동의를-어디서-받을지-정하려고-화면부터-만들었다</guid>
    <title>동의는 어디서 받을까? 답 대신 목업부터</title>
    <link>https://hyo814-blog.vercel.app/blog/동의를-어디서-받을지-정하려고-화면부터-만들었다</link>
    <description>통합로그인 연계에는 약관 동의 단계가 어디에도 없었습니다. 어디서 받을지는 백엔드·기관과 정할 일이라 결정 대신 동의 위치별 목업을 먼저 만들었고, 그중 하나를 실제 가입에 붙이면서 개인정보처리방침의 두 조항이 실제 동작과 어긋나 있던 것을 고쳐 테스트로 묶었습니다. 다만 이 작업은 미리보기 브랜치에 남아 있고, 10월 말까지 다른 브랜치에 들어가지 않았습니다.</description>
    <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/등록-프로세스-안내-중복-카드-플로우-제거-회고</guid>
    <title>안내 화면에서 중복 단계 카드를 들어낸 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/등록-프로세스-안내-중복-카드-플로우-제거-회고</link>
    <description>&quot;있는데 도움 안 되는 정보&quot;가 안내 화면을 어떻게 무겁게 만드는지, 표준데이터/OID 등록 프로세스 안내에서 중복 단계 카드 흐름을 제거하며 깨달은 점을 정리합니다.</description>
    <pubDate>Mon, 04 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/등록된-적-없는-asn1을-파싱하고-있었다</guid>
    <title>테스트 34건 통과, 화면엔 &#39;-&#39;만 서 있던 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/등록된-적-없는-asn1을-파싱하고-있었다</link>
    <description>상세 화면 세 곳의 필드명·M/O·최대 반복이 통째로 `-`로 서 있었습니다. 파서는 멀쩡했고 테스트도 34건 통과했는데, 값을 읽어 오려던 슬롯이 어느 클래스에도 등록돼 있지 않았어요. 출처를 필드 자신의 등록값으로 바꾸고, 줄 세우기도 한 곳이 정하게 모았습니다.</description>
    <pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/링크를-따라간-뒤-돌아오는-길이-어긋났다</guid>
    <title>뒤로가기 이력에 쌓을 것과 덮어쓸 것</title>
    <link>https://hyo814-blog.vercel.app/blog/링크를-따라간-뒤-돌아오는-길이-어긋났다</link>
    <description>상세에서 상세로 두 번 건너가면 목록 버튼이 검색 조건을 통째로 잃었고, 필터를 만질 때마다 뒤로가기 이력이 하나씩 쌓였습니다. 복귀 주소는 받은 것을 그대로 이어달리게 하고, 조건 변경은 덮어쓰고, 화면 안에서 다른 데이터로 건너뛰는 것만 이력에 쌓도록 나눴어요. 기준은 하나입니다. 다른 곳으로 갔나, 같은 화면의 상태가 바뀌었나.</description>
    <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/마이페이지를-뷰부터-url까지-처음-짰다</guid>
    <title>마이페이지를 뷰부터 URL까지 처음 짰다 — 사흘 동안 TemplateView에서 UpdateView까지</title>
    <link>https://hyo814-blog.vercel.app/blog/마이페이지를-뷰부터-url까지-처음-짰다</link>
    <description>입사 여섯 달 만에 템플릿이 아니라 뷰와 URL부터 짠 첫 화면이 마이페이지였습니다. 첫날은 GET만 받는 TemplateView에 값을 박아 넣었고, 이튿날 입력칸을 열었는데 뷰는 여전히 GET만 받았어요. 사흘째에 UpdateView와 PasswordChangeView로 갈아탔고, 손으로 넣은 비밀번호 눈 아이콘이 스크립트가 붙이는 것과 겹쳐 지웠습니다. 그 과정을 커밋 일곱 개로 돌아봅니다.</description>
    <pubDate>Wed, 01 Oct 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/메타클래스-속성-모달에서-인라인-폼으로-전환-회고</guid>
    <title>편집 모달을 걷어내고 인라인 폼으로</title>
    <link>https://hyo814-blog.vercel.app/blog/메타클래스-속성-모달에서-인라인-폼으로-전환-회고</link>
    <description>메타클래스 속성을 편집할 때마다 컨텍스트를 가리던 모달을 들어내고, 트리/리스트 옆 인라인 폼으로 옮긴 결정과 그 결과를 정리합니다.</description>
    <pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/메타클래스-쿼리-최적화-회고</guid>
    <title>데이터가 늘수록 느려지던 목록, 범인은 N+1</title>
    <link>https://hyo814-blog.vercel.app/blog/메타클래스-쿼리-최적화-회고</link>
    <description>항목 수가 늘면서 점점 느려지던 메타클래스 리스트 페이지의 쿼리를 분석하고, select_related/prefetch_related로 정리하면서 의식한 점들을 기록합니다.</description>
    <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/목업-데이터-엑셀-시드-49에서-478개-자동화</guid>
    <title>목업 데이터 49개를 엑셀로 478개까지</title>
    <link>https://hyo814-blog.vercel.app/blog/목업-데이터-엑셀-시드-49에서-478개-자동화</link>
    <description>백엔드 개발 전 mockup 데이터가 49개라서 페이지네이션·검색·필터 검증이 빈약했던 문제를, 엑셀 파일을 입력으로 받는 시드 스크립트를 만들어 478개로 늘린 과정을 정리합니다.</description>
    <pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/목업으로-먼저-짠-open-api의-교체-장치는-한-번도-쓰이지-않았다</guid>
    <title>목업 API에 넣은 교체 장치는 끝내 쓰이지 않았다</title>
    <link>https://hyo814-blog.vercel.app/blog/목업으로-먼저-짠-open-api의-교체-장치는-한-번도-쓰이지-않았다</link>
    <description>6월에 Open API를 목업 데이터로 먼저 짜면서, 나중에 데이터 공급자만 바꾸면 주소·응답 계약·문서는 그대로 간다는 교체 장치를 넣었습니다. 9월에 실제 데이터를 붙일 때 그 장치는 한 번도 쓰이지 않았어요. 바뀐 건 데이터 출처가 아니라 계약 자체였기 때문입니다. 목업 네 종과 교체 장치를 지우고, API의 노출 범위를 공개 화면과 같은 함수에 맡긴 기록입니다.</description>
    <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/밑줄과-정렬은-취향이-아니라-규칙으로</guid>
    <title>이동하는 자리라면 링크여야 한다</title>
    <link>https://hyo814-blog.vercel.app/blog/밑줄과-정렬은-취향이-아니라-규칙으로</link>
    <description>권한 그룹 편집 화면의 라벨이 하이퍼링크로 읽힌다는 제보에서 시작했습니다. 범인은 도움말이 달린 라벨 전부에 실선 밑줄을 주던 CSS 한 줄이었어요. 밑줄을 떼는 김에 반대 방향도 찾았습니다 — 링크처럼 생겼는데 링크가 아니라서 새 탭도 키보드 포커스도 죽어 있던 자리들이요. 이튿날에는 같은 화면들의 표 정렬을 잡으면서, 정렬을 정하는 건 값의 가짓수가 아니라 값의 성격이라는 규칙을 문서에 박았습니다.</description>
    <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/버튼-기본값이-w-full이었다</guid>
    <title>예외가 61곳이면 기본값이 틀린 것이다</title>
    <link>https://hyo814-blog.vercel.app/blog/버튼-기본값이-w-full이었다</link>
    <description>이 프로젝트의 모든 button은 base 레이어에서 w-full을 물려받고 있었습니다. 그래서 버튼을 놓는 자리마다 w-auto로 되돌리고 있었고, 그게 61곳이었어요. 기본값을 글자 폭으로 뒤집고 되돌리기를 전부 지웠습니다. 예외가 규칙보다 많으면 규칙이 틀린 겁니다.</description>
    <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>CSS</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/범위-필터-두-축을-배타에서-교집합으로-바꿨다</guid>
    <title>나란히 놓인 필터 둘, 배타 대신 교집합으로</title>
    <link>https://hyo814-blog.vercel.app/blog/범위-필터-두-축을-배타에서-교집합으로-바꿨다</link>
    <description>표준데이터 검색의 카탈로그·개념체계 범위 필터는 둘 중 하나만 걸리는 배타 규칙이었습니다. 아코디언을 한 번에 하나만 여는 화면에서 나온 규칙이라, 두 조건이 함께 실린 주소는 화면이 표현할 수 없는 상태로 보고 서버가 카탈로그만 남겼어요. 필터를 목업대로 셀렉트 한 줄로 바꾸자 사정이 뒤집혔습니다. 두 칸이 나란히 서면 하나를 고를 때 옆 칸이 스스로 비는 쪽이 설명할 수 없는 동작이 됩니다. 규칙을 교집합으로 바꾸면서 서버 판정과 테스트 단언을 같이 옮겼고, 검색 폼에 되살리는 조건은 그 판정을 따라 방향이 뒤집혔습니다.</description>
    <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/북마크-버튼-하나에-바라는-상태와-공개-범위를-실었다</guid>
    <title>북마크 버튼은 뒤집지 말고 원하는 상태를 보낸다</title>
    <link>https://hyo814-blog.vercel.app/blog/북마크-버튼-하나에-바라는-상태와-공개-범위를-실었다</link>
    <description>표준데이터 검색 카드·상세, OID 카드에 북마크 버튼을 달고 마이페이지에서 모아 보게 했습니다. 버튼은 뒤집기 대신 바라는 상태를 보내고, 저장할 수 있는 범위와 마이페이지에 보이는 범위를 공개 화면과 같은 모집단 함수로 묶었어요. 비로그인에게도 버튼을 보여 주되 CSRF 토큰은 로그인 사용자에게만 싣고, 카드 클릭과 겹치는 버튼은 캡처 단계에서 받았습니다. 테스트 8건과 함께, dev SQLite에서 난 500에 다시 보내기를 붙인 한계도 적었습니다.</description>
    <pubDate>Tue, 27 Oct 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/분류-칩-하나를-네-번-갈아엎었다</guid>
    <title>URL 값 0이 falsy라 &#39;미분류&#39;가 &#39;전체&#39;가 됐다</title>
    <link>https://hyo814-blog.vercel.app/blog/분류-칩-하나를-네-번-갈아엎었다</link>
    <description>표준데이터 목록에 분류 칩을 붙이는 데 나흘간 네 번 갈아엎었습니다. 3분류 → 4분류 → 문자 코드를 숫자로 → 미분류 칩 추가. 마지막에 &quot;미분류&quot;의 저장 코드가 0인데 &quot;전체&quot;도 0을 쓰고 있어서, 미분류를 고르면 전체가 나오는 문제를 만났어요. falsy 하나 때문에 URL 값과 저장 코드를 갈라야 했습니다.</description>
    <pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/분류체계-메타클래스-트리-공통-로직-헬퍼-추출-회고</guid>
    <title>두 트리 화면의 중복 코드를 헬퍼 4개로</title>
    <link>https://hyo814-blog.vercel.app/blog/분류체계-메타클래스-트리-공통-로직-헬퍼-추출-회고</link>
    <description>두 페이지가 따로 들고 있던 jstree 옵션과 이벤트 핸들러를 비교해 차이가 거의 없음을 확인하고, 공통 헬퍼 4종으로 추출한 리팩토링 회고입니다.</description>
    <pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/분류체계-화면에서-목록-단계를-없앴다</guid>
    <title>SKOS 트리에서 자식은 거꾸로 찾아야 한다</title>
    <link>https://hyo814-blog.vercel.app/blog/분류체계-화면에서-목록-단계를-없앴다</link>
    <description>분류체계는 목록 → 상세 두 단계였는데, 목록이 하는 일이 &quot;트리 하나 고르기&quot;뿐이었습니다. 트리 하나로 합치면서 자식 개념을 정방향 링크로 찾다가 트리와 다른 집합이 나왔어요. 저장된 트리플은 자식이 선언한 skos:broader 하나뿐이라, 자식을 찾으려면 역방향으로 가야 했습니다. 이어서 같은 역관계 때문에 관계도 라벨이 포개지던 것도 잡았습니다.</description>
    <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/비동기-관계-피커-prefill-값-소실-수리</guid>
    <title>건드리지 않은 값이 저장하면 사라지는 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/비동기-관계-피커-prefill-값-소실-수리</link>
    <description>편집 화면에서 아무것도 건드리지 않고 저장만 눌렀는데, 이미 선택돼 있던 값이 빈 값으로 저장되는 버그가 있었습니다. 세 가지 해결책을 놓고 고민한 끝에 &quot;값은 동기, 라벨만 비동기&quot;로 나누는 씨앗 패턴을 골랐어요. 에러 로그가 남지 않는 조용한 데이터 소실을 어떻게 재현하고 잡았는지 정리합니다.</description>
    <pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/빨갛게-남아-있던-e2e-25건-중-코드-회귀는-1건이었다</guid>
    <title>실패한 e2e 25건 중 진짜 회귀는 1건</title>
    <link>https://hyo814-blog.vercel.app/blog/빨갛게-남아-있던-e2e-25건-중-코드-회귀는-1건이었다</link>
    <description>Playwright 전체 스위트가 235 통과 · 25 실패 · 11 skip인 채로 한동안 있었습니다. 25건을 하나씩 열어 갈라 보니 코드 회귀 1 · 데이터 없음 4 · 나머지는 화면과 데이터를 못 따라간 낡은 스펙이었어요. 빨간불이 오래 쌓이면 진짜 회귀가 그 안에 묻힙니다. 같은 날 선택자가 사라져 영영 건너뛰던 스펙, 저장한 뒤에 건너뛰어 데이터를 남기던 스펙도 함께 고쳐, 다시 돌린 274건이 실패 0으로 끝났습니다.</description>
    <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>테스트</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/상세-화면을-목업에-맞추며-하루에-세-번-뒤집었다</guid>
    <title>목업을 따라가며 하루에 세 번 뒤집은 결정</title>
    <link>https://hyo814-blog.vercel.app/blog/상세-화면을-목업에-맞추며-하루에-세-번-뒤집었다</link>
    <description>표준데이터 상세를 목업 구성으로 옮기는 날, 오전에 넣은 카드 표제 순서를 한 시간 뒤 뒤집었고, 일주일 전에 단 필드명 링크를 걷어냈고, 그래프에서 관계를 추론하던 코드를 슬롯 라벨로 대체했습니다. 뒤집은 것마다 왜 처음 판단이 틀렸는지를 문서에 남겼어요. 그 기록을 결정별로 옮깁니다.</description>
    <pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/서버-혼자서는-끝낼-수-없는-초기-상태가-셋-남았다</guid>
    <title>서버 렌더링만으로 끝나지 않는 초기 상태 셋</title>
    <link>https://hyo814-blog.vercel.app/blog/서버-혼자서는-끝낼-수-없는-초기-상태가-셋-남았다</link>
    <description>9월 4일에 신청 화면 한 곳의 &quot;펼쳐졌다 접히는&quot; 깜빡임을 서버가 hidden을 달아 내보내는 방식으로 고쳤습니다. 2주 뒤 같은 원인을 아코디언·목차 전체의 규약으로 넓혀 7개 구획과 목차 첫 칸에 적용했는데, 그 과정에서 서버가 그리는 것만으로는 끝나지 않는 초기 상태가 세 가지 나왔습니다. 서버와 JS가 같은 목록을 따로 들고 있어야 하는 활성 클래스, 서버로 오지 않는 URL 해시, 그리고 부분 템플릿이 알 수 없는 &quot;페이지의 첫 항목&quot;입니다.</description>
    <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/선반영이-드러낸-도메인-문제-두-케이스</guid>
    <title>화면을 먼저 만들자 드러난 도메인 문제 두 가지</title>
    <link>https://hyo814-blog.vercel.app/blog/선반영이-드러낸-도메인-문제-두-케이스</link>
    <description>프론트엔드가 먼저 만들어둔 두 작업이 각각 &quot;심사 전 무분별 취소&quot;와 &quot;OID 트리 방향 역전 필요&quot;라는 도메인 문제를 드러낸 과정과, 어떻게 결정·정리했는지에 대한 회고입니다.</description>
    <pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/속성-range-클래스-참조와-데이터-유형-분리</guid>
    <title>한 컬럼에 섞인 두 의미, FK 둘로 쪼개기</title>
    <link>https://hyo814-blog.vercel.app/blog/속성-range-클래스-참조와-데이터-유형-분리</link>
    <description>속성의 range가 CharField 하나였습니다. xsd:string 같은 데이터 유형과 클래스 이름이 같은 칸에 문자열로 들어가 있었어요. FK 두 개 + 상호배타 제약으로 쪼개면서, 왜 단일 FK나 Generic FK로 가지 않았는지, 그리고 데이터 마이그레이션 스크립트 없이 로더 재적재만으로 과거 오적재를 정정한 방법을 정리합니다.</description>
    <pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/스피너-하나-넣으려다-jquery를-두-번-실을-뻔했다</guid>
    <title>로딩 스피너는 장식이 아니라 로드 순서 문제</title>
    <link>https://hyo814-blog.vercel.app/blog/스피너-하나-넣으려다-jquery를-두-번-실을-뻔했다</link>
    <description>관계도와 데이터 맵은 응답을 기다리는 동안 빈 캔버스였습니다. 트리 화면이 쓰던 waitMe를 그대로 가져다 덮으려 했는데, 그 플러그인이 jQuery에 붙어 있다는 사실 하나 때문에 세 가지가 연달아 걸렸어요. jQuery를 한 번 더 실으면 앞의 플러그인이 지워지고, defer로 실으면 그림 자체가 안 그려지고, 켠 스피너를 끌 때는 캔버스가 이미 다른 객체로 바뀌어 있었습니다.</description>
    <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/승인-시각이-승인한-때가-아니었다</guid>
    <title>default=timezone.now는 승인 시각이 아니다</title>
    <link>https://hyo814-blog.vercel.app/blog/승인-시각이-승인한-때가-아니었다</link>
    <description>신청 처리 이력에 찍힌 승인·반려 시각이 실제로 처리한 때보다 한 단계 앞이었습니다. 심사 액션 행은 대기 상태로 미리 깔리는데, timestamp의 default가 행을 만들 때 한 번 찍히고 완료 처리에서는 갱신되지 않았거든요. 타임라인이 이 값으로 정렬까지 하고 있어서 승인이 그 승인을 낳은 심사 의견보다 위에 설 수 있었습니다. 완료 처리 시점에 시각을 다시 찍고, 대기 행을 한 시간 전으로 밀어 둔 뒤 확인하는 테스트를 붙였습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/승인될-때까지-아무것도-만들지-않기</guid>
    <title>승인될 때까지 아무것도 만들지 않기</title>
    <link>https://hyo814-blog.vercel.app/blog/승인될-때까지-아무것도-만들지-않기</link>
    <description>신청서에서 엘리먼트·프레임·메시지를 직접 쓸 수 있게 했는데, 신청 시점에 만들어 버리면 반려된 신청의 찌꺼기가 목록에 남습니다. 작성분을 JSON 초안 한 칸에 두고 승인 시점에 자식부터 순서대로 재생하게 했어요. 그러다 초안 JSON이 PostgreSQL btree 색인 상한 2704바이트에 걸려 INSERT가 통째로 실패했습니다.</description>
    <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/시각을-찍는-자리를-서버-한-곳으로-모았다</guid>
    <title>반대로 어긋난 두 시각, 원인은 TIME_ZONE 한 줄</title>
    <link>https://hyo814-blog.vercel.app/blog/시각을-찍는-자리를-서버-한-곳으로-모았다</link>
    <description>역할 배정 상세 화면에 2026-09-09 16:47:55.613497+00:00 이 그대로 찍혀 있었습니다. 반대로 설문 관리 화면은 제출일시를 서버 포맷으로 옮기자마자 9시간 앞선 값을 보여 줬어요. 증상이 반대인데 원인은 하나였습니다. 시간대를 서버가 바꾸는지 브라우저가 바꾸는지가 화면마다 달랐거든요. TIME_ZONE을 KST로 옮기고 화면 변환 경로를 전부 지운 뒤 표기를 두 형식으로 통일했습니다. 한 시간짜리 작업이었는데, 이 선택지는 11개월 전 글이 &quot;검토하지 않았다&quot;고 적어 둔 것이었습니다.</description>
    <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/신청-항목-셋-중-한-건이면-제출</guid>
    <title>조건이 단계를 넘나들면 안내도 단계 밖에</title>
    <link>https://hyo814-blog.vercel.app/blog/신청-항목-셋-중-한-건이면-제출</link>
    <description>표준데이터 신청서는 메시지 한 건을 반드시 써야 제출됐습니다. 엘리먼트만, 프레임만 내는 신청도 있어서 조건을 &quot;셋 중 최소 한 건&quot;으로 풀었어요. 판정은 팀원이 한 입구로 묶어 둔 함수 안의 조건만 바꾸면 됐는데, 정작 어려웠던 건 안내를 어디에 두느냐였습니다. 조건이 세 단계를 가로지르는데 안내는 한 단계 조각 안에 있어서 다른 단계에서 항목을 넣어도 낡은 채 남았거든요. 그리고 같은 규칙을 말하는 자리가 네 곳이었는데, 한 곳이 75분 늦게 따라왔습니다.</description>
    <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/신청서-단계-구획이-로딩-중에-전부-보였다</guid>
    <title>펼쳐졌다 접히는 신청서, 310ms의 틈</title>
    <link>https://hyo814-blog.vercel.app/blog/신청서-단계-구획이-로딩-중에-전부-보였다</link>
    <description>OID 등록 신청 화면을 열면 여섯 구획이 다 펼쳐졌다가 한 박자 뒤에 하나로 접혔습니다. 접는 일을 DOMContentLoaded의 스크립트가 하는데, 그 앞에 d3를 동기로 싣고 있어 첫 페인트와의 틈이 310ms였어요. 서버가 첫 단계 말고는 hidden을 달아 내보내고 d3를 defer로 돌렸습니다. 같은 구조인 표준데이터 신청은 틈이 1ms라 안 보였을 뿐이었습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/신청서-항목-모달에서-후보-조회-20회를-2회로-줄였다</guid>
    <title>체크박스 2,178개와 조회 20번을 띄우던 모달</title>
    <link>https://hyo814-blog.vercel.app/blog/신청서-항목-모달에서-후보-조회-20회를-2회로-줄였다</link>
    <description>등록 신청서의 항목 모달이 화면 4.1개 길이였습니다. 재 보니 67%가 체크박스 상자였고, 한 번 여는 데 체크박스 2,178개를 그리고 후보 조회가 20번 나갔어요. 후보가 많은 슬롯만 접힌 검색칸으로 바꾸고, 접힌 슬롯은 펼칠 때 조회하게 해서 2회로 줄였습니다.</description>
    <pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/심사가-끝난-신청서를-보며-등록하는-화면을-만들고-끝까지-돌려-봤다</guid>
    <title>끝까지 돌려 본 QA 12건, 새 화면 탓은 셋</title>
    <link>https://hyo814-blog.vercel.app/blog/심사가-끝난-신청서를-보며-등록하는-화면을-만들고-끝까지-돌려-봤다</link>
    <description>표준데이터 신청서가 원장과 분리된 뒤로는, 심사가 끝나면 등록관리자가 신청서 팝업과 관리 화면을 나란히 띄워 놓고 손으로 옮겨 적어야 했습니다. 그 사이를 한 화면으로 잇는 &quot;신청서 기반 등록&quot;을 만들었어요. 그리고 신청 → 7단계 심사 → 등록 → 공개까지 역할별 계정으로 실제로 끝까지 돌려 보니, 걸린 QA 소견 12건 중 새 화면 자체의 문제는 셋이었고, 절반(6건)은 새 화면이 아니라 그 앞 신청·심사 화면에서 나온 문제였습니다.</description>
    <pubDate>Wed, 30 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/안내-캡처-34장을-두-번에-나눠-다시-찍었다</guid>
    <title>화면을 고치면 매뉴얼 캡처가 낡는다</title>
    <link>https://hyo814-blog.vercel.app/blog/안내-캡처-34장을-두-번에-나눠-다시-찍었다</link>
    <description>이용안내는 화면 캡처 수십 장으로 설명하는 문서라, 화면을 고칠 때마다 통째로 낡습니다. 9월에 두 번, 이용안내만 34장을 다시 찍었어요. 촬영은 Playwright 스펙이 대신 하지만 자동화되는 건 셔터뿐이고 무엇을 찍을지·무엇이 찍히면 안 되는지는 사람이 정해야 했습니다. 사용자 안내에 싣는 역할을 넷으로 줄인 기준, 디버그 툴바가 그림에 찍힌 사고, 앞 촬영이 남긴 데이터가 다음 캡처를 오염시킨 일을 정리합니다.</description>
    <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>테스트</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/없는-pk로-들어가면-404가-아니라-500이-났다</guid>
    <title>get_object를 덮으면 404 처리도 같이 사라진다</title>
    <link>https://hyo814-blog.vercel.app/blog/없는-pk로-들어가면-404가-아니라-500이-났다</link>
    <description>관리자 상세·수정 화면 여덟 개가 없는 pk를 받으면 500을 냈습니다. 쿼리를 미리 로드하려고 get_object()를 덮으면서 404 처리 없이 .get(pk=)를 직접 불렀거든요. 덮어야 했던 건 &quot;무엇을 가져오나&quot;가 아니라 &quot;어떤 쿼리셋에서 가져오나&quot;였습니다. 여덟 뷰를 get_queryset()으로 옮기니 78줄이 26줄이 됐고, 제네릭 뷰가 원래 하던 404 처리가 돌아왔습니다. 같은 함정이 남은 화면 네 곳은 아직 그대로입니다.</description>
    <pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/없는-관계를-prefetch하고-있었다</guid>
    <title>없는 관계를 prefetch하고 있었다 — 다운로드 4종을 죽인 한 단어</title>
    <link>https://hyo814-blog.vercel.app/blog/없는-관계를-prefetch하고-있었다</link>
    <description>카탈로그 PNG 다운로드가 500을 뱉어서 들어갔는데, 원인은 성능 최적화라고 믿고 있던 prefetch_related의 인자 하나였습니다. Dataset에 없는 관계명이라 QuerySet 평가 시점에 AttributeError가 났고, 지연 평가 때문에 선언부가 아니라 버튼 클릭에서 터졌어요. 같은 파일 안에서 따옴표 표기가 갈려 grep이 한쪽만 잡은 이야기와, AST로 인자 478건을 전수 대조한 기록입니다.</description>
    <pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/엑셀-2단-병합-헤더-워크북-리더와-4패스-로더</guid>
    <title>pandas가 못 읽는 2단 병합 헤더 엑셀 읽기</title>
    <link>https://hyo814-blog.vercel.app/blog/엑셀-2단-병합-헤더-워크북-리더와-4패스-로더</link>
    <description>엑셀 3개를 읽던 로더 3개를 워크북 1개를 읽는 로더 1개로 합쳤습니다. pandas가 못 읽는 2단 병합 헤더를 openpyxl로 직접 평탄화하고, 시트 순서 의존을 없애려고 유형별 4패스로 나눴어요. 853행에서 중복 6건이 나왔는데 그 승자 규칙에 아직 구멍이 남아 있다는 얘기까지 적었습니다.</description>
    <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/연결할-표준데이터가-목록에-안-보인-이유</guid>
    <title>연결할 표준데이터가 목록에 안 보인 이유 — 관계에서 거꾸로 뽑던 후보를 전체 조회로</title>
    <link>https://hyo814-blog.vercel.app/blog/연결할-표준데이터가-목록에-안-보인-이유</link>
    <description>OID 관리 화면에서 표준데이터를 연결하려는데 후보 목록에 없는 것이 있었습니다. 후보를 OID-표준데이터 관계 테이블에서 거꾸로 뽑고 있어서, 아직 어디에도 연결되지 않은 표준데이터는 나올 수 없었어요. 동료가 닦아 둔 REST 기반 위에 처음으로 엔드포인트 하나를 팠고, 같은 날 오후 설정 객체를 통째로 덮어써서 주소를 잃어버린 것도 고쳤습니다.</description>
    <pubDate>Mon, 22 Dec 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/용어-하나를-96개-파일-667곳에서-바꿨다</guid>
    <title>용어 667곳을 바꾸며 일부러 남긴 세 곳</title>
    <link>https://hyo814-blog.vercel.app/blog/용어-하나를-96개-파일-667곳에서-바꿨다</link>
    <description>화면에서 쓰는 용어가 분류체계에서 개념체계로 바뀌었습니다. 템플릿·뷰·매니저·폼·JS·e2e·문서까지 96개 파일 667곳을 치환했는데, 정작 중요한 판단은 어디서 멈출지였어요. 코드 식별자·URL·DB 데이터 값 세 곳은 일부러 안 건드렸고, 그 대가로 코드와 화면이 서로 다른 말을 하게 됐습니다.</description>
    <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/운영-2732건이-92948px-캔버스를-만들었다</guid>
    <title>2,732건이 만든 92,948px짜리 캔버스</title>
    <link>https://hyo814-blog.vercel.app/blog/운영-2732건이-92948px-캔버스를-만들었다</link>
    <description>데이터 맵에서 클래스 타일을 눌렀더니 인스턴스 2,732개를 부채꼴로 세로로 쌓아 캔버스가 92,948px이 됐습니다. 목록으로 보내는 대신 이름 접두어로 묶음 단을 끼웠고, 한 글자씩만 깊어지는 사슬을 같은 단에 미리 펼쳐 최악 경로를 3클릭으로 줄였어요. 같은 날 두 번 방식을 바꿨고, 이튿날 붙인 핵심어 탭은 그날 저녁에 다시 뺐습니다.</description>
    <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/운영-pdf에서-한글이-통째로-빠졌다</guid>
    <title>맥에선 멀쩡하던 PDF, 운영에선 한글이 사라졌다</title>
    <link>https://hyo814-blog.vercel.app/blog/운영-pdf에서-한글이-통째로-빠졌다</link>
    <description>등록 신청 작성 예시 PDF를 만들어 올렸더니 운영에서 한글이 한 글자도 안 찍혔습니다. 템플릿이 지정한 글꼴이 윈도우와 맥 것이라 우분투에는 아무것도 안 걸렸고, 맥에서는 시스템 글꼴이 잡혀 정상으로 보였어요. 서버 글꼴에 기대지 않고 저장소의 Pretendard를 @font-face로 문서에 심었고, 운영 설정에서 글꼴 파일을 찾는지 테스트로 잠갔습니다. 2월부터 있던 설문 PDF 두 종도 같은 길을 지나게 됐습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/운영-전에-정해-달라고-적어-둔-목록을-기본값으로-닫을-수-있는-만큼-닫았다</guid>
    <title>아직 안 정해진 운영 값을 기본값으로 닫기</title>
    <link>https://hyo814-blog.vercel.app/blog/운영-전에-정해-달라고-적어-둔-목록을-기본값으로-닫을-수-있는-만큼-닫았다</link>
    <description>Open API를 넘기면서 &quot;운영 전에 백엔드가 정해 줘야 할 것&quot;을 인수인계 문서에 적어 두었습니다. 그중 값을 정할 사람이 나중에 바꿀 수 있는 기본값으로 닫을 수 있는 일을 10월 28일에 했어요. 틀린 키로 계속 부르면 끝없이 쌓이던 접근 로그에 보존 기간과 정리 명령을 붙였고, 정해지지 않은 어휘 주소는 고치는 대신 배포 점검이 경고하게 했고, 프록시 뒤 호스트 설정은 기본값으로 켜 두었습니다. 값을 정하는 일은 그대로 남아 있고, 그 경계도 같이 적었습니다.</description>
    <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/워드클라우드가-통째로-안-그려졌다</guid>
    <title>tojson을 백틱으로 감싸면 안 되는 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/워드클라우드가-통째로-안-그려졌다</link>
    <description>데이터 통계 화면의 워드클라우드 세 탭이 전부 빈 채로 떴습니다. 서버가 내려준 JSON을 템플릿 리터럴 안에 넣고 JSON.parse로 다시 읽고 있었는데, 값에 든 줄바꿈을 리터럴이 먼저 실제 줄바꿈으로 바꿔 parse가 죽고 렌더 함수 전체가 멈춘 거였어요. tojson은 그 자체로 JS 리터럴이라 그냥 놓으면 됩니다.</description>
    <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/워드클라우드를-검색어-빈도로-개편</guid>
    <title>아무도 안 묻는 질문에 답하던 워드클라우드</title>
    <link>https://hyo814-blog.vercel.app/blog/워드클라우드를-검색어-빈도로-개편</link>
    <description>ASN.1 노드 단어를 세어 서버에서 PNG로 그려주던 워드클라우드를, 통합검색 검색어를 세어 클라이언트에서 그리는 화면으로 바꿨습니다. 화면의 성격을 &quot;무엇이 등록됐나&quot;에서 &quot;무엇을 찾았나&quot;로 옮긴 결정과, 같은 집계를 두 군데 두는 바람에 같은 검색어가 화면마다 다른 비율로 보이게 된 이야기입니다.</description>
    <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/워크플로우-엔진-데이터베이스-설계</guid>
    <title>워크플로우 엔진 DB 설계를 공부하고, 실제로 지으면서 바꾼 것들</title>
    <link>https://hyo814-blog.vercel.app/blog/워크플로우-엔진-데이터베이스-설계</link>
    <description>Exception Not Found의 워크플로우 엔진 DB 설계 8부작을 정리하고, 그 설계를 실제 표준데이터 심사 워크플로우로 구현하면서 무엇을 그대로 따랐고 무엇을 바꿨는지 대조했습니다. 참조 설계가 스스로 지적한 한계 하나는 구현 단계에서 피해갈 수 있었고, 하나는 그대로 남았어요.</description>
    <pubDate>Thu, 24 Apr 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/이용안내-아코디언에서-캐러셀로-전환-회고</guid>
    <title>이용안내를 아코디언에서 캐러셀로</title>
    <link>https://hyo814-blog.vercel.app/blog/이용안내-아코디언에서-캐러셀로-전환-회고</link>
    <description>표준데이터·OID·아키텍처·Open API 4개 이용안내 탭을 아코디언에서 캐러셀로 통일한 작업입니다. 네 가지 UI 후보를 놓고 캐러셀을 고른 근거, 감수하기로 한 트레이드오프(페이지 내 검색 불가), 그리고 탭마다 복붙돼 있던 인라인 매크로를 공유 파티얼 하나로 합친 이야기예요.</description>
    <pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/인기-검색어를-주석-처리했다</guid>
    <title>인기 검색어를 주석 처리했다 — 하드코딩 단어 목록을 석 달 반 만에 내렸다</title>
    <link>https://hyo814-blog.vercel.app/blog/인기-검색어를-주석-처리했다</link>
    <description>홈 화면에 인기 검색어 칩 다섯 개를 달았습니다. 실제로는 템플릿에 박아 둔 단어 다섯 개였어요. 석 달 반 뒤 &quot;명확한 기준이 있어야 한다&quot;는 메시지와 함께 주석 처리했습니다. 실제 검색 기록으로 세는 화면은 그로부터 여덟 달 뒤에야 생겼습니다. 값의 출처를 못 답하는 채로 화면부터 그린 기록입니다.</description>
    <pubDate>Sat, 15 Nov 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/인스턴스-트리를-가상-스크롤로-옮겼다</guid>
    <title>노드 수천 개짜리 jsTree를 가상 스크롤로</title>
    <link>https://hyo814-blog.vercel.app/blog/인스턴스-트리를-가상-스크롤로-옮겼다</link>
    <description>관리 화면의 jsTree가 클래스 하나에 인스턴스 수천 건을 매달고 있었습니다. 오후에 더 보기 노드를 고치고, 스크롤 자동 적재까지 갔다가, 저녁에 창 하나만 DOM에 두는 가상 스크롤로 확정했어요. 창 밖은 padding으로 높이만 세우는데, 그 여백을 인라인이 아니라 우리가 소유한 style 규칙으로 줘야 했고, jsTree 펼침 애니메이션은 꺼야 했습니다.</description>
    <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/저장-뒤-돌아올-자리를-주소에-남겼다</guid>
    <title>저장 뒤 돌아올 자리를 주소에 남겼다 — ?selected_node=의 첫 판</title>
    <link>https://hyo814-blog.vercel.app/blog/저장-뒤-돌아올-자리를-주소에-남겼다</link>
    <description>속성을 편집하고 저장하면 트리 화면이 늘 첫 노드로 돌아갔습니다. 성공 주소에 ?selected_node=를 붙여 편집하던 클래스로 돌아오게 했어요. 이틀 뒤 저녁에 setTimeout과 no-cache 헤더를 넣었다가 두 시간 뒤 전부 지우고 페이지 새로고침으로 바꿨습니다. 그때 만든 파라미터 이름이 1년 뒤에도 그대로 쓰입니다.</description>
    <pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/저장이-터진-선택자와-새로고침해야-반영되던-구성</guid>
    <title>오래 떠 있는 화면이 틀리는 두 가지 방식</title>
    <link>https://hyo814-blog.vercel.app/blog/저장이-터진-선택자와-새로고침해야-반영되던-구성</link>
    <description>인스턴스 관리 화면에서 같은 날 41분 간격으로 두 가지를 고쳤습니다. 하나는 객체 슬롯이 있는 데이터를 저장하면 TypeError가 나면서 저장이 통째로 죽던 것이고, 하나는 다른 화면에서 구성 속성 순서를 바꿔도 이미 열려 있는 탭은 옛 순서로 계속 그리던 것이었어요. 원인은 달랐지만 둘 다 &quot;이 화면이 한 번 정해 둔 것을 계속 믿는다&quot;는 같은 자리에서 나왔습니다.</description>
    <pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/정본-파생캐시-동기화-signal-fanout</guid>
    <title>고쳤는데 목록은 옛날 값, 시그널로 캐시 다시 잇기</title>
    <link>https://hyo814-blog.vercel.app/blog/정본-파생캐시-동기화-signal-fanout</link>
    <description>인스턴스를 수정해도 목록·다운로드·RDF는 옛 값을 보여줬습니다. 링크 시점에 한 번 복사하고 끝이었거든요. 캐시 제거·조회 시 재계산·쓰기 시 시그널 세 안을 놓고 마지막을 고른 이유와, 감사 로그가 폭발하지 않게 bulk_update로 일부러 시그널을 우회한 트레이드오프를 정리합니다.</description>
    <pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/제출-단계-칩에-스튜어드가-찍혀-있었다</guid>
    <title>같은 칸을 두 사람이 반대로 읽었다</title>
    <link>https://hyo814-blog.vercel.app/blog/제출-단계-칩에-스튜어드가-찍혀-있었다</link>
    <description>심사 진행 띠의 &quot;제출&quot; 칸에 데이터 스튜어드가 적혀 있었습니다. 제출하는 사람은 신청자인데요. 칩을 그 단계로 들어오는 전이의 역할로 바꿨는데, 두 시간 뒤 팀원이 반대 방향으로 되돌렸습니다. 둘 다 맞는 읽기였고, 화면이 그 뜻을 말하지 않은 게 진짜 문제였어요. 결론을 낸 건 코드가 아니라 칸에 한 줄 더 붙인 설명과 회귀 테스트였습니다.</description>
    <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/중복-쿼리라고-뺀-열을-닷새-뒤-되돌렸다</guid>
    <title>중복 쿼리라고 뺀 열을 닷새 뒤 되돌렸다 — 측정 없이 뺐고, 측정 없이 되돌렸다</title>
    <link>https://hyo814-blog.vercel.app/blog/중복-쿼리라고-뺀-열을-닷새-뒤-되돌렸다</link>
    <description>카탈로그 관리 폼의 표준데이터 표에서 분류체계 열을 뺐다가 닷새 뒤 &quot;운영에서 이상 없어서&quot; 되돌렸습니다. 뺄 때는 동료의 진단을 따랐고, 되돌릴 때도 쿼리를 세지 않았어요. 그런데 되돌린 열은 그 사이에 뒷받침하던 프로퍼티가 지워져서 두 달 동안 빈 칸이었습니다. 입사 다섯 달째, ORM을 배우면서 화면을 고치던 때의 기록입니다.</description>
    <pubDate>Wed, 24 Sep 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/창-밖-노드를-고르면-트리가-맨-위로-돌아갔다</guid>
    <title>가상 스크롤 밖 노드를 고르면 트리가 맨 위로 튄다</title>
    <link>https://hyo814-blog.vercel.app/blog/창-밖-노드를-고르면-트리가-맨-위로-돌아갔다</link>
    <description>인스턴스 트리를 가상 스크롤로 바꾼 뒤로, 이름을 고쳐 저장하면 선택이 풀리고 트리가 클래스 맨 위로 가는 증상이 있었습니다. 여드레 뒤에야 고쳤는데, 이름을 안 바꾼 저장은 멀쩡해서 간헐적으로 보였어요. 원인은 트리 갱신이 첫 창만 다시 받는다는 것이었고, 같은 전제를 쓰는 자리를 전수로 훑었더니 선택은 하는데 화면 밖에 그리는 곳이 네 군데 더 있었습니다.</description>
    <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/처음-만든-트리를-열흘-만에-통째로-다시-짰다</guid>
    <title>처음 만든 트리를 열흘 만에 통째로 다시 짰다 — 템플릿 안 550줄이 어디서 무너졌나</title>
    <link>https://hyo814-blog.vercel.app/blog/처음-만든-트리를-열흘-만에-통째로-다시-짰다</link>
    <description>입사 두 달째에 메타데이터 클래스 트리를 처음 만들었습니다. 템플릿 하나에 스크립트 550줄을 넣었고, 공개 화면에는 같은 것을 한 벌 더 넣었어요. 아흐레 뒤 스크립트를 파일로 빼면서 노드를 고를 때마다 페이지를 통째로 이동하게 만들었다가, 다음날 그걸 걷어내고 트리를 목록 화면으로 옮겼습니다. 첫 판이 어디서 무너졌는지를 커밋 셋으로 되짚습니다.</description>
    <pubDate>Fri, 20 Jun 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/탭-이름을-이틀-만에-되돌렸다</guid>
    <title>화면의 낱말은 문구가 아니라 도메인 계약이다</title>
    <link>https://hyo814-blog.vercel.app/blog/탭-이름을-이틀-만에-되돌렸다</link>
    <description>9월 7일에 셋째 탭을 &quot;개념체계&quot;에서 &quot;개념 탐색&quot;으로 바꿨고, 이틀 뒤 되돌렸습니다. 같은 날 필터 칸 이름도 &quot;정보 주제&quot;에서 &quot;개념체계&quot;로 돌아왔어요. 되돌리면서 선택지 구조도 한 단으로 폈는데, 이틀 전에 넣었던 정렬 하나가 그 과정에서 조용히 같이 빠졌습니다. 같은 주에 서비스 소개 문구와 홈 목록 표제도 손봤고, 세 자리 모두 화면의 낱말이 가리키는 대상과 어긋나 있던 자리였습니다.</description>
    <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/탭의-전체는-조건-없음이-아니라-합집합이었다</guid>
    <title>&#39;전체&#39; 탭은 조건 없음일까, 합집합일까</title>
    <link>https://hyo814-blog.vercel.app/blog/탭의-전체는-조건-없음이-아니라-합집합이었다</link>
    <description>카탈로그 탭과 개념체계 탭이 하루 사이에 카탈로그 카드 목록에서 다시 표준데이터 목록으로 돌아왔습니다. 그러자 첫 칸의 &quot;전체&quot;가 무슨 뜻인지가 문제가 됐어요. 조건 없음이면 카탈로그 밖 데이터까지 세고, 첫 뿌리 하나면 나머지 뿌리가 안 보입니다. 뿌리 전부의 합집합으로 정했는데, 그 결정을 내리기 11분 전에는 첫 뿌리 하나로 커밋해 둔 상태였습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/토큰을-만드는-길이-세-갈래였다-사용자당-1개를-한-관문에서-지키기</guid>
    <title>사용자당 토큰 1개, 발급 경로 셋을 한 관문으로</title>
    <link>https://hyo814-blog.vercel.app/blog/토큰을-만드는-길이-세-갈래였다-사용자당-1개를-한-관문에서-지키기</link>
    <description>Open API 토큰은 관리자 직접 발급, 발급 신청 승인, 관리용 REST API 세 곳에서 만들어지고 있었고, 셋 다 그 사용자에게 이미 유효한 토큰이 있는지 보지 않았습니다. &quot;사용자당 유효 토큰 1개&quot; 규칙을 세 곳에 따로 넣지 않고 발급 함수 하나로 모은 뒤, 동시 발급을 막는 잠금은 새로 만들지 않고 계정 삭제가 쓰던 잠금을 같은 순서로 잡았습니다. 만료일을 바꿔 만료 토큰을 되살리는 네 번째 길도 같은 관문에 걸었습니다.</description>
    <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/트리-뿌리를-이름으로-찾다가-id로-바꿨다</guid>
    <title>트리 뿌리를 이름으로 찾다가 id로 바꿨다 — 식별자를 처음 고른 날</title>
    <link>https://hyo814-blog.vercel.app/blog/트리-뿌리를-이름으로-찾다가-id로-바꿨다</link>
    <description>분류체계 그래프 화면이 뿌리 노드를 이름으로 찾고 있었습니다. 트리 JSON의 id는 enumerate 인덱스였고, 주소에는 이름이 실렸어요. 둘 다 pk로 바꿨는데, 함수 계약을 바꾸면서 호출하는 쪽 두 곳을 놓쳐 15분 동안 화면이 깨졌습니다. 그날은 &quot;이름보다 pk&quot;까지만 알았고, pk도 밀린다는 건 1년 뒤에 알았습니다.</description>
    <pubDate>Thu, 19 Jun 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>Django</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/트리에서-뺀-신청-상태-표시를-일주일-뒤-되살렸다</guid>
    <title>트리에서 뺀 신청 상태 표시를 일주일 뒤 되살렸다 — 지운 커밋 해시를 커밋 메시지에 적었다</title>
    <link>https://hyo814-blog.vercel.app/blog/트리에서-뺀-신청-상태-표시를-일주일-뒤-되살렸다</link>
    <description>OID 트리 노드 이름 뒤에 [신청중] 같은 상태를 붙이던 코드를 76줄 지웠다가 일주일 뒤 되살렸습니다. 되살린 커밋 메시지에 지운 커밋의 해시를 &quot;깃 참고&quot;로 적어 뒀어요. 그런데 되살린 건 같은 것이 아니었습니다. 워크플로 상태 대신 모델 필드, 모두에게 대신 관리자에게만. 35분 뒤엔 공용 파서에서 빼서 화면 전용 후처리로 옮겼습니다.</description>
    <pubDate>Mon, 29 Dec 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/트리플을-우리말-문장으로-읽는다</guid>
    <title>RDF 트리플을 우리말 문장으로 읽기</title>
    <link>https://hyo814-blog.vercel.app/blog/트리플을-우리말-문장으로-읽는다</link>
    <description>온톨로지 옆 패널의 관계 목록은 무엇과 이어졌는지는 말하는데 그 이음이 무슨 뜻인지는 안 말합니다. 트리플을 주어·서술어·목적어 문장으로 풀었어요. 기계 틀 하나로는 뜻이 안 잡혀 술어 18종의 문장을 손으로 다듬었고, 조사는 받침을 세서 골랐습니다. 서버는 한 줄도 안 고쳤습니다.</description>
    <pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/파일-33개를-한-커밋에-넣었다</guid>
    <title>파일 33개를 한 커밋에 넣었다 — 제목은 한 가지 일이라고 말하고, 안에는 다섯 가지가 있었다</title>
    <link>https://hyo814-blog.vercel.app/blog/파일-33개를-한-커밋에-넣었다</link>
    <description>입사 석 달째, 파일 33개에 1,228줄을 더하고 823줄을 지운 커밋을 올렸습니다. 제목은 스크립트 하나를 바꿨다는 한 줄이었어요. 지금 세어 보니 그 안에 이름 바꾸기, 새 모듈 다섯, 인라인 스크립트 분리, 설정 변경, 뷰 정리가 같이 들어 있었습니다. 그중 하나는 두 달 뒤 팀원이 지웠고, 하나는 1년 뒤 버그로 돌아왔습니다.</description>
    <pubDate>Thu, 17 Jul 2025 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/팔레트에-없는-색은-조용히-안-칠해진다</guid>
    <title>팔레트에 없는 색은 조용히 안 칠해진다 — 색 클래스 142곳 정리와 대비 감사</title>
    <link>https://hyo814-blog.vercel.app/blog/팔레트에-없는-색은-조용히-안-칠해진다</link>
    <description>토큰에 없는 색 이름은 빌드 오류가 아니라 그냥 안 칠해집니다. 그렇게 죽어 있던 클래스 142곳을 토큰으로 바꾸고, 다시 들어오면 빌드를 세우는 가드를 붙였어요. 이어서 팔레트 안에 있는 색들의 명도 대비를 재봤더니 회색 스케일이 통째로 한 칸 밝아 입력 경계와 회색 글자가 기준 미달이었습니다. 못 고치기로 한 35곳도 이유와 함께 적었습니다.</description>
    <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/페이지-자동-캡쳐-스크립트-만들기</guid>
    <title>Tailwind 업그레이드 전에 만든 화면 자동 캡처</title>
    <link>https://hyo814-blog.vercel.app/blog/페이지-자동-캡쳐-스크립트-만들기</link>
    <description>Tailwind 메이저 업그레이드를 앞두고 시각 회귀를 잡기 위해 Playwright 기반 페이지 캡쳐 스크립트를 만든 경위와, 그 과정에서 만난 작은 어려움들을 정리합니다.</description>
    <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>테스트</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/편집-중-트리를-누르면-입력이-사라졌다</guid>
    <title>확인 창에서 &#39;취소&#39;를 눌러도 입력이 날아간 이유</title>
    <link>https://hyo814-blog.vercel.app/blog/편집-중-트리를-누르면-입력이-사라졌다</link>
    <description>인스턴스를 편집하다 왼쪽 트리의 다른 노드를 누르면 입력한 게 전부 날아갔습니다. confirm으로 되묻는 것까지는 쉬웠는데, &quot;취소&quot;를 눌러 선택을 되돌리는 그 동작이 다시 select 이벤트를 쏴서 결국 화면이 지워졌어요. 이어서 같은 화면의 e2e가 간헐 실패하던 것도 jstree refresh()가 비동기라는 같은 뿌리였습니다.</description>
    <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>JavaScript</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/표준데이터-고정컬럼에서-인스턴스-기반-모델로-전환</guid>
    <title>개정마다 마이그레이션하던 고정 컬럼 모델 버리기</title>
    <link>https://hyo814-blog.vercel.app/blog/표준데이터-고정컬럼에서-인스턴스-기반-모델로-전환</link>
    <description>표준 메타데이터가 개정될 때마다 마이그레이션을 찍어야 했던 고정 컬럼 모델을, 메타클래스 인스턴스 기반으로 전환한 설계 기록입니다. JSONField·고정 컬럼 유지를 포함한 세 가지 안을 놓고 왜 EAV에 가까운 구조를 골랐는지, 리터럴 값과 객체 참조를 왜 다른 테이블로 나눴는지, 그리고 두 모델을 한동안 동시에 살려둔 전환 전략을 정리했어요.</description>
    <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/표준데이터-구조를-깊이마다-한-번씩만-읽었다</guid>
    <title>재귀 구조를 깊이당 쿼리 한 번으로 그리기</title>
    <link>https://hyo814-blog.vercel.app/blog/표준데이터-구조를-깊이마다-한-번씩만-읽었다</link>
    <description>메시지가 무엇으로 이뤄졌는지 보려면 상세를 계속 타고 들어가야 했습니다. 전체를 좌→우 계층 트리 한 장으로 그리는 전용 뷰어를 만들었어요. 재귀 구조인데 쿼리는 깊이당 한 번이고, 순환은 자르되 잘랐다고 화면에 적습니다. 같은 날 오전에 넣은 디스플레이 유형 하나를 오후에 걷어낸 이야기도 같이 적었습니다.</description>
    <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/표준데이터-통계-대시보드-개수에서-인사이트로-회고</guid>
    <title>개수 대신 품질을 묻는 통계 대시보드</title>
    <link>https://hyo814-blog.vercel.app/blog/표준데이터-통계-대시보드-개수에서-인사이트로-회고</link>
    <description>총 등록 수·상태 분포만 보여주던 통계 대시보드를, 생애주기·완성도·최근 업데이트·인기 항목 중심으로 다시 짠 작업입니다. &quot;ACT 개수&quot;가 아니라 &quot;완성형(고품질) 데이터가 얼마나 되나&quot;를 묻도록 지표를 바꾼 이야기예요.</description>
    <pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>시각화</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/필수-여부-체크박스를-3단계-의무-수준으로</guid>
    <title>서버는 아직 불리언인데 화면은 세 단계로</title>
    <link>https://hyo814-blog.vercel.app/blog/필수-여부-체크박스를-3단계-의무-수준으로</link>
    <description>구성 속성의 &quot;필수 여부&quot;를 선택·권장·필수 3단계로 바꿨습니다. 서버 필드는 아직 불리언이라 권장은 화면에만 남는 반쪽짜리인데, 그걸 알면서 먼저 한 이유를 적었습니다. 이어서 표시 순서를 드래그로 바꾸게 만들고, 그 과정에서 이틀 전에 넣은 정렬 버튼을 스스로 지웠습니다.</description>
    <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/필수-플래그-전역에서-클래스별-관계로</guid>
    <title>플래그를 잘못된 테이블에 달아 뒀다</title>
    <link>https://hyo814-blog.vercel.app/blog/필수-플래그-전역에서-클래스별-관계로</link>
    <description>속성에 달려 있던 is_mandatory를 클래스-속성 관계 행으로 옮긴 작업입니다. 같은 속성이 클래스마다 필수/선택으로 갈리는데 전역 플래그로는 표현할 수 없었어요. 이관 마이그레이션을 짜다 PostgreSQL의 pending trigger events에 걸렸고, 제약을 백필보다 먼저 만드는 순서로 풀었습니다.</description>
    <pubDate>Fri, 24 Jul 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>설계</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/필터-선택지-옆-건수를-어느-모집단으로-셀-것인가</guid>
    <title>필터 옆 건수, 어디서 세야 0건이 안 될까</title>
    <link>https://hyo814-blog.vercel.app/blog/필터-선택지-옆-건수를-어느-모집단으로-셀-것인가</link>
    <description>통합 검색의 카탈로그·개념체계 칸을 셀렉트에서 접이식 트리 드롭다운으로 바꾸고 선택지마다 건수를 붙였습니다. 건수는 &quot;고르면 몇 건이 나오나&quot;인데, 지금 걸린 조건 안에서 세면 고른 항목만 남고 나머지는 전부 0건이 돼요. 세는 모집단에서 범위 조건을 뺐고, 체크 즉시 조회하던 걸 같은 날 패널을 닫을 때 한 번으로 바꿨습니다.</description>
    <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/홈-화면의-준비-중-타일을-지웠다</guid>
    <title>&#39;준비 중&#39; 타일 뒤에서 엉뚱한 걸 세고 있었다</title>
    <link>https://hyo814-blog.vercel.app/blog/홈-화면의-준비-중-타일을-지웠다</link>
    <description>홈 &quot;데이터 현황&quot;에 물리 아키텍처만 &quot;준비 중&quot;으로 있었습니다. 데이터를 붙이려고 기존 집계 함수를 열어보니 ASN.1 데이터셋을 세고 있었어요. 화면이 말하는 것과 다른 것을 세고 있었던 겁니다. 같이 정리한 퀵메뉴에서는 카드 폭을 flex-1로 두면 안 되는 이유를 만났습니다.</description>
    <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

  <item>
    <guid>https://hyo814-blog.vercel.app/blog/화면이-없어진-기능을-설명하고-있었다</guid>
    <title>소개 페이지가 없어진 기능을 설명하고 있었다</title>
    <link>https://hyo814-blog.vercel.app/blog/화면이-없어진-기능을-설명하고-있었다</link>
    <description>서비스 소개 페이지가 &quot;상세검색·기관·유형·태그 필터&quot;를 설명하고 있었는데, 그 필터는 진작 없어졌습니다. 도입 배경은 4차 산업혁명·D.N.A·ICBM 같은 몇 년 지난 문구였고요. RFP와 연차보고서를 근거로 다시 썼습니다. 같은 축에서 읽기 전용 화면의 &quot;필수 *&quot; 표기도 걷어냈는데, 그건 이틀 전 제가 적은 규칙을 뒤집는 일이었습니다.</description>
    <pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate>
    <author>ggamjige8888@naver.com (Hyo814)</author>
    <category>기술노트</category><category>UI</category><category>교통데이터플랫폼</category>
  </item>

    </channel>
  </rss>
