콘텐츠로 이동

2026-11-11 (수)

오늘 요약 - 대시보드 다운로드를 sqlway 직접 질의 + Parquet 기본으로 바꿨고, 학습 일지 자동화를 처음부터 끝까지 만들었다. 새로 익힌 것은 Blob, 파티션 교체, claude -p, commit과 push의 구분, Parquet과 CSV의 차이. - 가장 오래 헷갈린 것은 "큰 파일을 받으면 브라우저 메모리가 차는가"(3번). 메모리를 쓰는지는 받는 방식(<a href>냐 fetch→blob이냐)에 달려 있었다.

🗂️ 오늘의 세션 (4개)

시간 프로젝트 무엇을 했나
08:54~14:25 disaster-dashboard 할 일 정리, 다운로드·오버뷰 작업
09:32~16:37 Dtonic 학습 일지 자동 정리 환경 구축
14:31~16:06 dhub2-manager (기술 질문 없음) 재난 과제 문서 검토와 PR
16:26~16:59 dhub2-manager #3561 도구 인자 타입 문제 해법

🛠️ 오늘 한 작업

1. 할 일 정리와 다운로드 방식 점검 (disaster-dashboard · 08:54~11:00)

  • 배경: 남은 할 일 7가지를 다시 봤다. 그중 2번(다운로드 형식)과 4번(presigned URL)은 시니어가 "브라우저 메모리가 찬다"고 한 말에서 나온 과제였다.
  • 진행:
  • 2번과 4번은 둘 다 "파일을 어디서, 누가 만드느냐"에 답해야 해서 같이 설계하는 게 좋다는 설명을 들었다.
  • 지금 대시보드는 네 곳 모두 <a href download>라서 브라우저 메모리를 거의 쓰지 않는다는 걸 확인했다. fetch→blob 방식과 비교했다.
  • 시니어의 걱정은 토큰을 헤더로 보내느라 blob으로 받는 구조를 상정한 것일 가능성이 높다고 정리했다.
  • SSO 방식을 코드로 확인했다. OIDC Authorization Code + PKCE로 로그인한 뒤 토큰은 버리고 서버가 서명한 쿠키 세션만 남긴다.
  • 메모리 문제가 없으니 2·4번을 뒤로 미뤘다. 미룬 이유, 나중에 바꿀 때 조심할 점, 시니어에게 확인할 질문을 메모리에 남겼다.
  • 11:00에 운영 빌드를 직접 띄워 받아 봤다. dhub SSO를 적용해도 <a href download> 방식을 그대로 쓸 수 있다.
  • 결과: 다운로드 메모리 걱정은 정리됐다. 실제 배포 환경(HTTPS 등)에서의 확인은 남았다.

2. 학습 일지 자동화: 실행 구조와 GitHub 연결 (Dtonic · 09:32~11:30)

  • 배경: Claude와 나눈 대화를 자동으로 md로 정리해서, 출퇴근길에 "내가 뭘 몰랐나"를 폰으로 보고 싶었다.
  • 진행:
  • 저장소를 비교했다. 갤럭시 폰이라 git + GitHub 앱으로 정했고, 웹 화면은 보류했다. 비용은 들이지 않기로 했다.
  • 클라우드 실행도 검토했다. 대화 원본이 대화한 컴퓨터에만 있어서 완전히 클라우드로만 할 수는 없다.
  • Mac 18시 실행과 클라우드 18시 실행을 비교했다. 차이는 "18시에 노트북이 깨어 있느냐" 하나였다. 노트북 교체는 차이가 아니라고 Claude가 정정했다. Mac 18시 + 구독 토큰으로 정했다.
  • 커밋이 어디에 됐는지 물었다. remote 없이 로컬에만 commit된 상태였다.
  • HTML 아티팩트도 검토했다. GitHub는 HTML을 화면으로 보여 주지 않아서 md(A안)를 유지했다.
  • 개인 GitHub용 SSH 키를 만들어 연결하고 첫 push를 했다. claude setup-token으로 1년짜리 토큰을 발급해 Keychain에 넣고 동작을 확인했다.
  • 세션 없는 날은 일지가 안 생기는 것, 수동 실행 명령도 확인했다.
  • 야근을 반영하려고 18시 1차 정리 + 자정 최종 정리로 바꿨다. 18시 이후 대화가 없으면 자정 실행은 넘어간다.
  • 결과: 오늘부터 자동으로 돈다.

3. H3 정규화 데이터셋 고르기와 파이프라인 통합 (disaster-dashboard · 10:01~10:44)

  • 배경: 대시보드에 동기화할 정규화 데이터셋을 고를 새 태그를 정하려다, 태그 대신 열로 거를 수 있는지 보게 됐다.
  • 진행:
  • h3_r9 하나가 아니라 공통 열 전체를 보면 태그 기준과 똑같은 20개가 골라졌다.
  • "정규화했다"는 필드를 새로 만들자고 했는데, normalized_at이 이미 있어서 필요 없었다.
  • H3 정규화 파이프라인이 두 개인 이유를 확인했다. 기능은 같고, 추가할 때 기존 것을 건드리지 않으려고 따로 만든 것이었다.
  • 하나(norm_spatiotemporal)로 합쳤다. 원천 하나가 실패해도 나머지는 갱신하게 했다. 실행 후 20개가 모두 다시 써졌고 행 수와 내용 지문이 같은 것을 확인한 뒤 옛 파이프라인을 지웠다.
  • 쓰기 방식(전체 교체·파티션 교체)과 upsert를 물었다. 데이터셋 upsert는 아직 플랫폼에서 안 되고, 누적은 원천 쪽 책임이라는 답을 들었다.
  • 결과: 파이프라인은 하나로 정리됐다. 원천 수집에 일정이 없어서 아직 이력이 쌓이지 않는 문제가 남았다.

4. 날짜 슬라이더 커밋과 오버뷰 페이지 (disaster-dashboard · 10:41~14:25)

  • 배경: 지도에 모든 데이터를 한 번에 보여 줄 오버뷰 페이지를 구상했다. 시니어가 말한 "데이터를 누르면 어느 셀인지 보여 주기"도 가능한지 봤다.
  • 진행:
  • 관측값과 건물 같은 정적 정보는 나눠서 보여 주는 게 맞다고 의견을 모았다.
  • 데이터를 누르면 셀을 보여 주는 기능은 행마다 위치 열이 있어서 가능하다는 답을 들었다.
  • 날짜 슬라이더를 먼저 커밋했다(893a320).
  • "우와 포인트"를 묻자 Claude가 기존 상세 지도에 재생과 3D 기둥을 붙이기 시작했다. 자동 재생은 우와 포인트가 아니라고 보고 오버뷰 페이지를 새로 만들게 방향을 바꿨다.
  • /overview를 만들었다. 출처가 다른 데이터를 같은 H3 셀 위에 겹쳐 보여 준다. 시험 156개를 통과했다.
  • 진한 셀이 "데이터가 많은 곳"이지 "위험한 곳"이 아니라는 점을 짚었다. 위험도 모델은 우리 소관이 아니라서, 레이어를 따로 보여 주는 방식으로 바꿔 봤다. 마음에 안 들어서 셀 표시로 되돌렸다.
  • 행 개수 대신 침수흔적 안의 재난 지표 값을 셀 색으로 쓰는 방안을 제안받았다.
  • 결과: 오버뷰 페이지는 셀 표시로 유지한다. 셀 색에 쓸 재난 지표는 다음에 정한다.

5. 다운로드를 sqlway 직접 질의와 Parquet 기본으로 전환 (disaster-dashboard · 11:30~13:47)

  • 배경: 미뤘던 다운로드 형식 과제로 돌아왔다. 메타데이터 PG를 설계한 것도 원래 필터를 걸어 Parquet으로 받으려던 것이었다.
  • 진행:
  • 필터를 걸어 Parquet으로 받는 구조와 흐름을 정리했다.
  • Parquet과 CSV를 실제로 재 봤다. Parquet이 전송·디스크·서버 처리에서 모두 앞섰다. CSV는 gzip을 켜면 전송 시간만 비슷해졌다.
  • 지금 CSV는 sqlway에 바로 묻지 않고 매니저를 거친다는 걸 확인했다. 두 경로를 비교했다.
  • 작은 질의는 차이가 수십 ms라서 매니저 경유를 유지하고, 큰 다운로드만 sqlway 직접으로 가기로 했다. 매니저가 느린 이유는 1,000행씩만 주는 상한 때문이었다.
  • 다운로드를 sqlway 직접 질의로 바꾸고 Parquet을 기본으로 했다. 시험 152개를 통과했고 hub-dev 실제 데이터로 받아 봤다.
  • 받기 단추를 스플릿 버튼(왼쪽 Parquet, ▾로 CSV)으로 바꿨다.
  • 카드 레이아웃을 정리했다. 상세 미리보기 버튼을 없애고 카드 전체를 눌러 이동하게 했으며 호버를 넣었다. 위치 배지를 제목 줄 오른쪽 끝으로 옮기고 이름을 "구 단위"·"셀 단위"로 바꿔 화면 전체 용어를 "셀"로 맞췄다.
  • 결과: 기능과 UI 변경은 끝났다. 시험도 통과했다.

6. 학습 일지 형식 다듬기와 트러블슈팅 기능 (Dtonic · 11:31~16:37)

  • 배경: 작업 2에서 만든 자동화의 결과물을 실제로 뽑아 보며 형식을 맞췄다.
  • 진행:
  • push 없이 미리보기를 만들었다. 토큰 사용량을 기록하게 했고 모델을 Opus로 통일했다.
  • 질문 배경, 한글 주제 파일, 참고 링크, 세션 목록을 넣었다.
  • 세션이 길거나 많을 때 생길 문제를 물었다. 재료를 걸러 내도 15%밖에 안 줄어서(Claude가 정정), 질문만 남기는 방식으로 바꿨다. 재료가 18%로 줄었다. 키워드로 학습 질문을 고르는 기준은 쓸 만하지 않아서 Claude가 판단하게 했다.
  • 11-09로 돌려 보니 일시적인 상황 질문이 섞여 있었다. 상황 질문은 빼고, 반복해서 물은 질문은 그 밑의 개념으로 묶고, 약점 칸을 따로 두는 v2가 나왔다. 한 번만 물은 개념도 주제 파일로 만들게 했다.
  • "오늘 한 작업" 칸을 넣었다. 비용은 10~12% 늘 것으로 계산했다. 한글 참고 자료를 우선하고 Mermaid 그림 규칙도 넣었다.
  • 어려워한 개념만 더 길게 쓰는 안은 복잡해져서 품질이 떨어질까 봐 단계를 나누지 않기로 했다. v4로 11-09·11-10을 바꿔 push했다.
  • 트러블슈팅 폴더 기능을 추가하고 비용을 줄이는 방법 두 가지를 적용했다. 10-27로 시험해 파일 2개가 잘 나온 것을 확인하고 push했다.
  • 결과: 이 구조로 확정했다. 며칠 써 볼 예정이다.

7. 재난 과제 문서 검토와 PR (dhub2-manager · 14:31~16:06)

  • 배경: 이 브랜치의 재난 과제 문서 작성 지침(README §9)을 기준으로 산출 문서 두 개를 검토했다. 국토부 시설물 관리시스템 분석 보고서 v0.6, 데이터 수집 통합 프로토타입 설계서 v0.7이다.
  • 진행:
  • HWPX를 먼저 고치고 MD를 HWPX에서 다시 만들어 맞췄다.
  • 특허를 낼 예정이라 내부 로직을 빼게 했다. 6곳, 18곳, 42건으로 범위를 넓혀 가며 "어떻게 동작하는가"를 걷어 내고, 계층별로 구성 요소와 기술 이름만 남겼다. 특정 임베딩 모델 이름도 뺐다.
  • 고치는 중에 v0.7이 한글에서 열리지 않았다. 원인을 찾아 고쳤다(아래 문제 1).
  • v0.6에는 플랫폼 로직이 없다는 걸 확인했다. 새 기준으로 마지막 점검을 했고 v0.7의 [그림 1] 하나가 남았다.
  • MD 5개를 지우고 HWPX에서 다시 만들었다.
  • 새 브랜치에 변경을 옮겼다. Claude가 만든 내부 메모 파일은 지웠다. 두 설계서·표준안을 v1.1로 바꾸고, 제출한 단계보고서 외의 옛 작업본을 지웠다.
  • 결과: PR #4440을 올렸다.

8. #3561 Gemma 도구 인자 타입 문제 해법 검토 (dhub2-manager · 16:26~16:59)

  • 배경: 10-27에 겪은 vLLM Gemma 도구 인자 문자열 변환 422 문제를 이슈 #3561로 정식 해결하려 했다.
  • 진행:
  • Claude가 B안(매니저 공용 코어에서 검증 직전에 정해진 칸의 문자열을 숫자·불리언으로 되돌리기)을 권했다. A안(스키마 힌트)은 단독 해법으로 부족하다고 봤다.
  • 원인을 다시 정리했다. Gemma는 타입을 맞게 쓰고, vLLM이 스키마에 안쪽 타입이 없는 payload 값을 문자열로 남긴다.
  • 다른 LLM에 주는 영향은 지금 거절되던 값에만 작동하니 작다고 확인했다.
  • "True"를 다룬 이전 PR #2735·#3790을 찾았다. 그와 반대 방향이 아니냐는 물음에, 같은 원칙이라 오히려 설득 근거가 된다는 답을 들었다.
  • 함수를 만들어 scratchpad에서 실제 매니저 모델로 확인했다. 저장소는 고치지 않았다.
  • 결과: 최적안은 "Create 모델 스키마를 따라 되돌리는 B"를 공용 코어에 넣고 A는 하지 않는 것이다. 구현과 PR은 남았다.

🔧 오늘 해결한 문제

1. HWPX 문서 수정 후 한글에서 열리지 않음 (→ 작업 7)

  • 증상: 한글 밖에서 v0.7 HWPX의 글자를 고친 뒤 한글에서 파일이 안 열렸다. 예전에 겪은 문제와 같았다.
  • 원인 → 해결: 문단의 줄 배치 정보(<hp:linesegarray>)가 글이 짧아진 뒤에도 옛 줄 시작 위치를 가리키고 있었다. 글자가 바뀐 문단에서 이 정보를 지우자 해결됐다. 한글은 열 때 줄 배치를 다시 계산한다.
  • 👉 HWPX 수정 후 한글에서 열리지 않음

🧠 부족했던 개념

1. 브라우저 파일 다운로드와 Blob 메모리 · 🔁 3번 물음

  • 어떻게 드러났나: 작업 1에서 presigned URL을 왜 쓰는지 다시 따지다가 물었다(→ 작업 1). 처음엔 "presigned URL이면 브라우저 메모리를 많이 쓰나"를 물었다. 다음엔 <a href>와 blob 방식을 비교해 달라고 다시 물었고, 끝으로 "blob이 뭐고 왜 메모리에 올리나"를 물었다.
  • 헷갈린 점: 메모리 사용이 파일이 어디서 오느냐(서버냐 S3냐)에 달렸다고 생각했다. 실제로는 누가 받느냐(다운로드 관리자냐 페이지 JS냐)에 달려 있었다.
  • 핵심:
  • <a href download>는 브라우저의 다운로드 관리자가 받는다. 받은 조각을 바로 디스크에 쓰니 10GB 파일도 메모리가 거의 늘지 않는다.
  • fetch()→res.blob()은 응답을 끝까지 다 받아 하나의 Blob으로 합친다. 페이지 JS는 샌드박스 때문에 디스크에 직접 쓸 수 없어서 그 사이 메모리에 쌓아 둔다.
  • Blob은 크기가 정해진 "바이트 덩어리" 객체다. createObjectURL로 blob: 주소를 만들어 저장하거나 미리볼 때 쓴다.
  • 비유: href는 택배를 바로 창고로, blob은 거실에 다 쌓아 둔 뒤 창고로 옮긴다.
  • 👉 브라우저 다운로드와 Blob 메모리

2. 작업 스케줄링: 로컬 cron과 클라우드 실행 · 🔁 2번 물음

  • 어떻게 드러났나: 학습 일지를 매일 18시에 자동으로 돌리는 구조를 정하다가 물었다(→ 작업 2). "노트북을 바꾸면 안 되니 클라우드에서 못 하나"를 먼저 물었고, 이어서 두 실행 위치가 어떻게 다른지 다시 물었다.
  • 헷갈린 점: 클라우드 예약 작업도 내 Mac의 파일을 읽을 수 있다고 봤다. 그리고 노트북 교체가 두 방식을 가르는 차이라고 생각했다.
  • 핵심:
  • 예약 작업(cron, macOS는 launchd)은 그 컴퓨터가 깨어 있을 때 돈다. 잠들어 있으면 다음에 깨어날 때 실행된다.
  • 클라우드(GitHub Actions 등)는 컴퓨터가 꺼져 있어도 돌지만, 올라와 있는 데이터만 볼 수 있다. 로컬에만 있는 재료는 누군가 먼저 올려 줘야 한다.
  • 노트북 교체는 스크립트를 repo에 두면 어느 쪽이든 git clone + 설치로 복구된다. 실제 차이는 실행 시각에 기계가 켜져 있느냐다.
  • 👉 cron 예약 실행과 클라우드 실행

3. 데이터 쓰기 방식: 덮어쓰기·파티션·upsert · 🔁 2번 물음

  • 어떻게 드러났나: H3 정규화 파이프라인을 합치다가 코드의 쓰기 방식을 봤다(→ 작업 3). "파티션 교체가 뭐냐"를 물었고, 이어서 "누적되는 정보는 upsert로 저장할 방법이 없나"를 물었다.
  • 헷갈린 점: 정규화 결과를 전체 교체하면 이력이 사라질 거라고 걱정했다. 이력을 지키는 책임이 원천과 파생 결과 중 어디에 있는지를 구분하지 못했다.
  • 핵심:
  • 파티션은 열 값(예: dataset_id, 날짜)에 따라 파일을 폴더별로 나눠 둔 칸이다.
  • 전체 교체(overwrite)는 표 전체를 바꾼다. 파티션 교체는 새 결과에 든 파티션만 바꾸고 나머지는 둔다. append는 뒤에 붙인다. upsert는 키가 있으면 고치고 없으면 넣는다.
  • 원천이 날짜 파티션이나 append로 쌓이면, 원천 전체를 읽어 다시 쓰는 파생 결과는 전체 교체만 해도 이력이 다 들어간다. 규칙을 바꿔도 과거를 다시 계산할 수 있다는 장점도 있다.
  • 👉 데이터 쓰기 방식과 upsert

4. API 중간 계층 경유와 직접 질의 비교 · 🔁 2번 물음

  • 어떻게 드러났나: Parquet 다운로드 구조를 정하다가 지금 CSV가 매니저를 거친다는 걸 알게 됐다(→ 작업 5). 두 경로의 차이를 물었고, 이어서 "sqlway 직접이 모든 면에서 나아 보이는데 매니저를 거칠 필요가 있나"를 물었다.
  • 헷갈린 점: 중간 계층을 속도를 늦추는 한 단계로만 봤다. 그 계층이 대신 지켜 주는 것(권한, 상한, 공식 계약)을 놓쳤다.
  • 핵심:
  • 중간 계층(API 서버·게이트웨이)은 이름을 실제 자원으로 바꾸고, 권한을 확인하고, 질의를 검증하고, 행 수 상한을 강제하고, 내부 오류 문구를 가린다.
  • 한 단계 더 거치는 비용은 보통 수십 ms다. 느렸던 진짜 이유는 계층 자체가 아니라 1,000행 상한 때문에 여러 번 나눠 물은 것이었다.
  • 그래서 작은 질의는 공식 API로, 큰 파일 전송처럼 상한이 걸리는 곳만 직접 경로로 나눠 쓴다. 직접 경로는 보호 장치를 우리가 직접 걸어야 하고 내부 주소가 바뀌면 멈출 위험이 있다.
  • 👉 API 중간 계층 경유와 직접 질의

5. LLM 도구 호출 인자의 타입 변환 · 🔁 2번 물음

  • 어떻게 드러났나: #3561 해법을 듣고 "Gemma가 dhub의 타입을 못 받는 걸로 아는데 무슨 소리냐"며 요약을 부탁했다(→ 작업 8). 원인을 이해한 뒤에도 "어떻게 바꾼다는 건지 한 번에 이해가 안 간다"고 다시 물었다.
  • 헷갈린 점: 잘못이 모델(Gemma)에 있다고 생각했다. 실제로는 중간의 서빙 계층(vLLM) 파서가 타입을 살리지 못한 것이었다.
  • 핵심:
  • 일부 모델은 도구 호출을 JSON이 아닌 자기 표기로 쓴다. 서빙 계층의 파서가 이를 JSON으로 옮길 때 일단 모든 값을 문자열로 두고, 도구 스키마에 타입이 적힌 칸만 되돌린다.
  • 스키마에 "아무 객체"로만 적힌 칸(payload)의 안쪽 값은 문자열로 남는다. true가 "true"가 되어 검증에서 422로 거절된다.
  • 고치는 방법은 스키마에 안쪽 타입을 적어 주기(파서에 의존) 또는 받는 쪽이 검증 직전에 되돌리기(서빙 방식과 무관)다.
  • 👉 LLM 도구 호출 파서와 타입 복원

6. SSO 로그인과 쿠키 세션 유지

  • 어떻게 드러났나: 시니어의 "브라우저 메모리" 걱정이 헤더 토큰 구조에서 나왔을 수 있다는 설명을 듣고, "SSO로 바꾸면 실제 문제가 되느냐"를 물었다(→ 작업 1).
  • 헷갈린 점: SSO를 쓰면 브라우저가 토큰을 헤더로 보내야 한다고 봤다. SSO는 로그인 방식일 뿐이고, 로그인 뒤 세션을 어떻게 유지하느냐는 따로 정한다는 점을 몰랐다.
  • 핵심:
  • 서버가 있는 앱은 보통 SSO(OIDC) 결과를 서버가 받아 서명한 쿠키 세션으로 바꾼다. 쿠키는 <a href> 요청에도 자동으로 실린다.
  • 서버 없는 SPA는 브라우저 JS가 토큰을 들고 Authorization 헤더로 보낸다. <a href>는 헤더를 못 붙여서 fetch→blob으로 받게 된다.
  • 다른 도메인 API를 직접 부를 때는 쿠키가 안 실릴 수 있다(SameSite, 도메인 설정). 이럴 때 주소에 인증이 담긴 presigned URL이 대안이 된다.
  • 👉 SSO 로그인과 쿠키 세션

7. git 로컬 커밋과 원격 저장소

  • 어떻게 드러났나: Claude가 "commit까지 끝났다"고 하자, 아직 새 repo를 연결하지 않았는데 어디에 커밋했냐고 물었다(→ 작업 2).
  • 헷갈린 점: commit이 곧 GitHub에 올리는 것이라고 생각했다.
  • 핵심:
  • commit은 변경을 내 컴퓨터의 .git 기록에 남긴다. 네트워크를 쓰지 않는다.
  • push는 그 기록을 remote(GitHub 등)로 보낸다. remote가 연결돼 있어야 된다.
  • git init만 하면 로컬 저장소만 생긴다. 나중에 remote를 연결하면 첫 push 때 쌓인 커밋이 한꺼번에 올라간다. 올리기 전에는 얼마든지 고칠 수 있다.
  • 👉 git commit과 push, 원격 저장소

8. CLI 비대화형(headless) 실행

  • 어떻게 드러났나: 자동 정리 스크립트에 계속 나오던 claude -p가 뭔지 물었다(→ 작업 2).
  • 헷갈린 점: 평소 쓰는 대화형 Claude Code와 예약 작업에서 부르는 Claude가 어떻게 다른지 몰랐다.
  • 핵심:
  • -p(--print)는 질문 하나를 받아 처리하고 결과를 출력한 뒤 종료하는 headless 모드다. 스크립트, cron, CI에서 쓴다.
  • 물어볼 사람이 없으니 권한 확인은 미리 허용한 것만 실행된다. 모델·로그인·요금은 대화형과 같다.
  • 자동화에서는 모델 지정, 대화 기록 안 남기기(--no-session-persistence), hook·MCP 끄기, 도구 제한 같은 옵션으로 실행 범위를 좁혀 둔다.
  • 👉 CLI headless 실행과 claude -p

9. 로그인 토큰과 API 키의 차이

  • 어떻게 드러났나: 예약 작업용으로 claude setup-token 토큰을 발급하다가, 이걸 API 토큰처럼 쓸 수 있냐고 물었다(→ 작업 2).
  • 헷갈린 점: "토큰"이면 다 API 호출에 쓸 수 있는 키라고 생각했다.
  • 핵심:
  • OAuth 로그인 토큰은 사람 대신 프로그램이 그 계정으로 로그인한 상태를 쓰게 한다. 구독 한도 안에서 공식 앱(Claude Code)용으로 쓴다.
  • API 키는 개발자용 자격증명이다. 직접 만든 앱이나 SDK에서 쓰고 사용량만큼 과금된다.
  • 둘 다 유출되면 남이 내 권한을 쓴다. 파일이나 repo가 아니라 Keychain 같은 비밀 저장소에 두고, 값을 대화나 로그에 남기지 않는다.
  • 👉 OAuth 로그인 토큰과 API 키

10. Parquet과 CSV 파일 형식 비교

  • 어떻게 드러났나: sqlway 직접 질의로 받는 구조를 정리한 뒤, Parquet과 CSV 중 성능이 좋은 쪽을 물었다(→ 작업 5).
  • 헷갈린 점: 형식 차이가 전송 시간에만 있다고 봤다. 디스크, 서버 처리, 받은 뒤 분석까지 차이가 나는 건 몰랐다.
  • 핵심:
  • Parquet은 열 단위로 저장하고 압축(ZSTD 등)하며 열 타입을 보존한다. 실측에서 9만 행이 4.5MB, CSV는 74.2MB였다.
  • CSV는 gzip 전송 압축을 켜면 받는 시간은 비슷해진다. 하지만 받은 뒤엔 풀려서 크고, 모든 값이 글자라 다시 해석해야 한다.
  • CSV의 장점은 엑셀에서 바로 열린다는 것 하나다. 그래서 보통 "Parquet 기본, CSV 선택"으로 둔다.
  • 👉 Parquet과 CSV 형식 비교

11. LLM 컨텍스트 길이 한계

  • 어떻게 드러났나: 일지 형식을 다듬다가, 세션이 너무 많거나 길면 요약에 문제가 생기냐고 물었다(→ 작업 6).
  • 헷갈린 점: 입력이 길면 "다 안 들어가서" 실패할 거라고만 생각했다. 실제 위험은 품질 저하, 시간 초과, 사용량 한도 쪽이었다.
  • 핵심:
  • 긴 입력을 조각으로 나누면 조각끼리 맥락이 끊긴다. 앞 조각의 요약을 다음 조각에 넘겨 보완한다.
  • 컨텍스트에 다 들어가도 한 번에 너무 많이 넘기면 뒤쪽을 얕게 다루는 경향이 있다. 턴이 늘수록 앞 내용을 다시 읽어서 시간과 비용도 는다.
  • 근본 대책은 넣는 재료 자체를 줄이는 것(필요한 부분만 추리기)과 작업을 나누는 것이다.
  • 👉 LLM 컨텍스트 길이와 긴 입력

12. 스키마 기반 입력 검증과 타입 변환

  • 어떻게 드러났나: B안 흐름을 이해한 뒤, payload가 "아무 객체"로 오는데 dhub가 어느 칸이 불리언인지 어떻게 아냐고 물었다(→ 작업 8).
  • 헷갈린 점: 바깥에 보여 주는 스키마(모델에게 보내는 설명서)와 내부 검증 규칙이 같은 정보라고 생각했다.
  • 핵심:
  • 내용이 종류마다 다른 칸은 겉 모델에서 dict[str, Any]처럼 느슨하게 적는다. 대신 옆의 종류 필드(resource_type)를 보고 안쪽을 검사할 모델을 고른다(판별자 방식).
  • "불리언이어야 하는데 문자열"이라고 거절할 수 있다는 것 자체가 타입을 안다는 뜻이다.
  • 그래서 검증에 쓰는 같은 타입 정보로 검증 직전에 "true"→true, "2"→2로 되돌리는 단계를 넣을 수 있다. "yes"처럼 애매한 값은 그대로 두어 검증에서 거절되게 한다.
  • 👉 스키마 기반 입력 검증과 타입 변환

🩹 오늘 드러난 약점

  • 데이터가 어느 계층을 거쳐 어디에 쌓이는지 그려 보지 않고 결론부터 물었다 — 근거: Blob 메모리(3번), 매니저 경유와 직접 질의(2번), vLLM 타입 변환(2번) 모두 "어느 단계가 무엇을 하느냐"를 몰라서 되물었다 → 다음에: 질문하기 전에 요청 → 계층 → 저장 위치를 한 줄 화살표로 먼저 써 본다.
  • 남의 주장을 그 전제와 함께 확인하지 않았다 — 근거: 시니어의 "브라우저 메모리가 찬다"를 지금 구조에도 맞는 말로 받아들였다. 실제로는 헤더 토큰 + blob 구조에서만 맞았다 → 다음에: 우려를 들으면 "어떤 구조를 상정했나"를 먼저 묻는다.
  • 비슷한 이름의 기본 개념 경계가 흐렸다 — 근거: commit과 push, 로그인 토큰과 API 키, 대화형과 -p 실행을 같은 것으로 봤다 → 다음에: 새 용어는 "무엇과 다른가"를 한 줄로 적어 둔다.
  • 이력과 책임의 위치를 구분하지 못했다 — 근거: 정규화 결과에 upsert가 필요하다고 봤다. 누적은 원천 쪽 책임이었다 → 다음에: 데이터를 저장할 때 "원천인가, 다시 계산할 수 있는 결과인가"부터 정한다.

🧪 복습 퀴즈

1. <a href download>와 fetch()→res.blob() 중 큰 파일에서 탭이 죽을 수 있는 쪽은? 이유는?

답 보기 `fetch`→`blob` 쪽이다. `res.blob()`은 응답을 끝까지 다 받아 하나로 합치는데, 페이지 JS는 디스크에 직접 쓸 수 없어서 그동안 메모리에 쌓아 둔다. ``는 다운로드 관리자가 받은 조각을 바로 디스크에 쓴다.

2. dataset_id로 파티션된 표에 강우량 결과만 쓸 때, 전체 교체와 파티션 교체의 결과는 어떻게 다른가?

답 보기 전체 교체는 표에 강우량만 남기고 나머지를 지운다. 파티션 교체는 강우량 파티션만 바꾸고 다른 파티션(예: 교통량)은 그대로 둔다.

3. 도구 스키마에 payload가 "아무 객체"로만 적혀 있을 때, vLLM을 거친 nullable: true는 어떻게 되고 받는 쪽은 어떻게 되돌릴 수 있나?

답 보기 파서가 타입을 모르는 칸이라 `"true"`(문자열)로 남는다. 받는 쪽은 `resource_type`으로 안쪽 검증 모델을 알고 있으니, 그 타입 정보로 검증 직전에 `"true"`를 `true`로 되돌린다.