Jun Kang 👋

  • AI와 빅데이터로 건설업계의 디지털 혁신을 이끄는 (주)산군의 Jun Kang입니다. 대규모 데이터 처리, DB 최적화, 확장 가능한 시스템 구축에 관심이 많으며, 개발팀의 건강하고 지속 가능한 성장 문화를 만들어가고 있습니다.
  • 주요 관심사: Backend Development, Cloud Computing, DevOps, Database, AI, 개발 문화 형성

[LLM] Vertex AI를 쓰기 전에 걸어 둘 비용 가드레일 — 예산 알림과 토큰 할당량

LLM API를 서비스에 붙이면 비용이 트래픽보다 빨리 는다. 대부분은 기능을 붙이는 데 집중하느라 비용 쪽 설정을 나중으로 미룬다. 그런데 GCP에서 Vertex AI를 쓰기 시작할 때 기본 상태를 열어 보면, 막혀 있는 것이 거의 없다. 예산은 없고, 토큰 할당량은 사실상 무제한이다. 처음에 걸어 둘 것은 네 가지다. 순서대로 예산 알림, 토큰 할당량, 프로젝트 분리, 인증 점검이다. 각각이 막는 것과 못 막는 것이 다르니 하나만 걸고 안심하면 안 된다. 비용은 어디서 불어나나 LLM 과금은 입력 토큰과 출력 토큰을 따로 센다. 단가는 출력이 더 비싼 경우가 많아서 출력 길이부터 의심하게 되는데, 실제로 먼저 불어나는 건 입력인 경우가 많다. 입력은 코드가 조용히 늘리기 쉽다. ...

2026-11-03 · 5 분 · Jun Kang

[PostgreSQL] 배치마다 반복되는 집계는 Materialized View로 빼라

검색 색인, 데이터 동기화, 리포트 적재처럼 테이블을 조금씩 읽어서 다른 곳으로 보내는 배치가 있다. 이런 배치의 쿼리가 유난히 느리고, 필요한 인덱스는 다 있는데도 EXPLAIN ANALYZE가 끝나지 않는다면 쿼리 모양부터 볼 만하다. 배치마다 같은 집계를 처음부터 다시 하고 있을 가능성이 크다. 이 경우 집계를 Materialized View(MV)로 빼고 FROM 절만 바꾸면 된다. 분 단위가 초 단위로 줄어드는 일이 흔하다. 다만 결과가 원본과 정말 같은지 검증하는 단계와, MV를 언제 갱신할지 정하는 단계를 건너뛰면 안 된다. ...

2026-11-03 · 5 분 · Jun Kang

[PostgreSQL] 파티셔닝하면 못 하게 되는 것들 — 유니크, 외래키, 행 이동

파티셔닝 시리즈 마지막이다. 앞의 두 편이 얻는 것이었다면 이번 편은 잃는 것이다. 파티셔닝을 결정하기 전에 이 목록을 보고 감당할 수 있는지 판단하는 게 맞다. 유니크 제약은 파티션 키를 포함해야 한다 가장 먼저 부딪히는 벽이다. CREATE TABLE orders ( id bigint, created_at timestamptz NOT NULL, PRIMARY KEY (id) ) PARTITION BY RANGE (created_at); ERROR: unique constraint on partitioned table must include all partitioning columns DETAIL: PRIMARY KEY constraint on table "orders" lacks column "created_at" which is part of the partition key. 이유는 구조에 있다. 유니크 인덱스는 파티션마다 따로 만들어진다. 8월 파티션의 인덱스는 8월 파티션 안에서만 중복을 검사한다. id = 100이 8월에도 있고 9월에도 있는지는 아무도 검사하지 않는다. 그래서 PostgreSQL은 처음부터 허용하지 않는다. ...

2026-09-24 · 5 분 · Jun Kang

[PostgreSQL] 시간 기반 파티션 운영 — DELETE 없이 데이터 버리기

지난 편에서 파티셔닝의 확실한 이득은 프루닝보다 데이터를 파티션째 버리는 데 있다고 썼다. 이번 편은 그 운영 이야기다. 시간으로 나눈 파티션을 어떻게 만들고, 어떻게 떼어내고, 어디서 사고가 나는지. 파티션은 미리 있어야 한다 행이 들어올 때 그 값에 맞는 파티션이 없으면 실패한다. ERROR: no partition of relation "orders" found for row DETAIL: Partition key of the failing row contains (created_at) = (2026-10-01 00:00:00+00). 10월 1일 자정에 10월 파티션이 없으면 그 순간부터 모든 INSERT가 이 에러다. 월 초 자정에 장애 나는 전형적인 경로다. ...

2026-09-23 · 4 분 · Jun Kang

[PostgreSQL] 파티셔닝이 성능을 올리지 않는 경우

“테이블이 커서 파티셔닝했다"는 말을 자주 듣는다. 그리고 그 뒤에 “그런데 안 빨라졌다"가 따라오는 경우도 자주 본다. 파티셔닝은 쿼리를 빠르게 하는 기능이 아니다. 조건에 맞는 파티션만 읽게 하는 기능이다. 그 조건이 안 갖춰지면 이득은 없고 비용만 남는다. 파티션 프루닝 주문 테이블을 월별로 나눴다고 하자. CREATE TABLE orders ( id bigint, created_at timestamptz NOT NULL, ... ) PARTITION BY RANGE (created_at); CREATE TABLE orders_2026_08 PARTITION OF orders FOR VALUES FROM ('2026-08-01') TO ('2026-09-01'); CREATE TABLE orders_2026_09 PARTITION OF orders FOR VALUES FROM ('2026-09-01') TO ('2026-10-01'); 이 쿼리는 9월 파티션 하나만 읽는다. ...

2026-09-22 · 4 분 · Jun Kang