pnpm ERR_PNPM_OUTDATED_LOCKFILE — CI 배포 실패 진단과 해결

Render에서 배포가 터졌다. 에러 메시지는 짧고 명확했지만 원인은 생각보다 다양했다. ERR_PNPM_OUTDATED_LOCKFILE Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/apps/legal_audit_web/package.json Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile" Failure reason: specifiers in the lockfile don't match specifiers in package.json: * 1 dependencies were added: @ios26_design_system/svelte-inertia@^1.0.0 로컬에서는 잘 됐는데 CI에서만 죽는 전형적인 패턴이다. 원인과 해결법을 기록해둔다. ...

2026-04-02 00:00 · 4분 소요 · Seunghan

JANDI 채팅방 크롤링 — AngularJS 가상 스크롤 SPA를 Puppeteer로 전수 수집한 삽질기

왜 JANDI 채팅방을 크롤링해야 했나 한국거래소(KRX)에서 증권사 담당자들과 소통하는 채널로 JANDI 메신저를 사용하고 있다. “[KRX] 거래시간 연장 및 장애대응 실시간 채팅"이라는 채팅방에서 400여 명의 증권사 담당자들이 질문하고, KRX 측이 답변하는 구조다. 문제는 이 Q&A 내역을 체계적으로 관리할 방법이 없다는 것이었다. JANDI에는 메시지 읽기 API가 없고, Outgoing Webhook은 시작 키워드가 필수라서 모든 메시지를 수신할 수 없다. 결국 브라우저 자동화로 직접 크롤링하는 수밖에 없었다. JANDI의 기술 스택이 만든 함정 JANDI 웹앱은 AngularJS 기반 SPA(Single Page Application)다. 열어보면 URL이 https://next-it.jandi.com/app/#!/room/34791415 같은 해시 라우팅을 쓰고 있다. 이게 크롤링에 어떤 영향을 주는지 처음엔 몰랐다. ...

2026-03-31 00:00 · 7분 소요 · Seunghan

Mole로 맥 190GB 정리한 후기 — 개발자 맥에 쌓인 캐시의 실체

개발하다 보면 디스크가 어느 순간 꽉 찬다. Xcode 빌드하다 용량 부족 에러가 뜨고, Docker 이미지 pull이 실패하고, npm install이 ENOSPC를 뱉는다. 저장소 확인해보면 “시스템 데이터"가 수백 GB를 차지하고 있는데, 정작 뭐가 그렇게 큰지 알 수가 없다. CleanMyMac 같은 도구가 있지만 연 9만원짜리 구독이고, 개발자 특화 캐시는 잘 못 잡는다. 그러다 GitHub에서 34K 스타를 받은 오픈소스 CLI 도구 Mole을 발견했다. 설치부터 190GB 정리까지의 실전 기록을 남긴다. Mole이 뭔가 Mole은 대만 개발자 tw93이 만든 macOS 시스템 정리 CLI 도구다. Shell 79%와 Go 21%로 작성됐고, MIT 라이선스다. ...

2026-03-30 00:00 · 7분 소요 · Seunghan

Render 배포 실패 두 가지 — npm lockfile dev 플래그와 DATABASE_URL 소켓 오류

Render에서 배포가 갑자기 안 되기 시작했다. 한 번도 아니고 두 번 연속으로, 서로 다른 이유로. 첫 번째는 Vite 빌드에서 패키지를 못 찾는다는 에러, 두 번째는 Rails 서버가 PostgreSQL에 소켓으로 연결하려다 죽는 오류였다. 둘 다 원인을 찾기까지 상당히 헤맸다. 첫 번째 오류: Cannot find package 'vite-plugin-ruby' 빌드 로그에 이런 에러가 찍혔다. failed to load config from /opt/render/project/src/.../vite.config.ts error during build: Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite-plugin-ruby' imported from vite.config.ts vite-plugin-ruby는 분명히 package.json의 dependencies에 들어있었다. devDependencies가 아니라 dependencies에. ...

2026-03-30 00:00 · 4분 소요 · Seunghan

배포는 됐는데 앱이 죽는다 — Solid Queue가 Puma를 끌고 내려간 이야기

Render에 Rails 앱을 새로 배포했다. 빌드는 성공했고 “Deploy live” 메시지도 떴다. 그런데 몇 분 뒤 대시보드에 이런 메시지가 반복됐다. Instance failed: wcvg7 Application exited early while running your code. 증상 파악 Render 로그를 뒤지니 이런 흐름이 보였다. SolidQueue::Configuration#ensure_configured_processes ← 여기서 에러 → exit 1 → "Detected Solid Queue has gone away, stopping Puma..." → Puma 종료 → 인스턴스 실패 Puma가 죽은 게 아니었다. Solid Queue가 먼저 죽고, Puma가 그걸 감지해서 스스로 내려간 것이었다. ...

2026-03-10 00:00 · 3분 소요 · Seunghan

Hugo 블로그 AdSense 승인 안 되는 이유 — 콘텐츠가 아니라 구조 문제였다

Google AdSense에 사이트를 등록했는데 상태가 “준비 중"에서 멈춰 있었다. 글은 80개 넘게 있는데 왜 승인이 안 되는 걸까? 조사해보니 콘텐츠 양의 문제가 아니라 사이트 구조의 문제였다. 이 글에서는 Hugo + PaperMod 블로그에서 AdSense 승인 확률을 높이기 위해 실제로 수정한 내용을 정리한다. 현황 진단 AdSense 신청 후 거절되는 주요 사유는 크게 3가지다: 거절 사유 의미 가치가 별로 없는 콘텐츠 글이 독창적이지 않거나 AI 생성물 그대로 게시자 콘텐츠가 없는 화면에 광고 빈 페이지나 정책 페이지에 광고 코드가 삽입됨 준비 중 필수 페이지 누락, 사이트 구조 미비 내 블로그는 세 번째 — “준비 중” 상태였다. 글 수는 충분했지만 구조적인 결함이 있었다. ...

2026-03-08 00:00 · 3분 소요 · Seunghan
Render Deploy Debugging

Render 배포 실패 디버깅 — DB 업그레이드부터 Gemfile 누락까지 10개 에러 연속 격파

오늘 Rails 앱 배포가 build_failed로 떨어졌다. 처음엔 단순한 에러 하나겠지 싶었는데, 고칠 때마다 새 에러가 튀어나왔다. 결국 10개의 에러를 순서대로 해결하고 나서야 live 상태가 됐다. 연속 디버깅의 기록을 남긴다. 배경 Render에서 Rails 8 + Inertia.js + Svelte 5 조합 웹 서비스를 운영 중이다. 어느 날 대시보드를 보니 최신 배포가 build_failed 상태. 로그를 열었다. 에러 1: DB 연결 실패 — ActiveRecord::ConnectionNotEstablished bin/rails aborted! ActiveRecord::ConnectionNotEstablished: connection to server at "10.x.x.x", port 5432 failed: Connection refused Tasks: TOP => db:migrate 빌드 스크립트에서 db:migrate를 실행하는 순간 PostgreSQL 연결이 거부됐다. 트리거를 보니 service_resumed — 서비스가 재개(resume)된 것이었다. ...

2026-03-07 00:00 · 5분 소요 · Seunghan
Render Multi Service Error Fix Deploy

Render 6개 서비스 에러 일괄 점검 & 수정 — Stoplight, FK 제약, Puma 7, Solid Stack 삽질 기록

Render에 올려둔 Rails 서비스 6개가 전부 각자 다른 에러를 토해내고 있었다. 하나씩 로그를 까보니 공통 패턴도 있고, 프로젝트마다 고유한 문제도 있었다. 한 세션에서 전부 수정하고 배포까지 마친 과정을 정리한다. 전체 상황 Render API로 서비스 6개의 로그를 일괄 조회했다. 각 서비스에 SSH로 하나씩 들어가서 로그를 보는 대신, Render의 REST API를 활용하면 로컬 터미널에서 모든 서비스의 로그를 한꺼번에 스크립트로 수집할 수 있다. 이번 점검에서 확인된 결과는 다음과 같았다: 서비스 주요 에러 서비스 A ERB 문법 에러로 500 (이미 커밋됐지만 미배포) 서비스 B Stoplight Light#run 블록 에러 + Telegram 파싱 에러 서비스 C solid_cache_entries 테이블 누락 서비스 D PG::UndefinedColumn + solid_cache 누락 서비스 E PG::DuplicateTable sessions + Sentry 초기화 에러 서비스 F TaskCleanupJob FK 위반 + Puma deprecated 경고 공통 패턴: Rails 8의 Solid Stack (SolidCache, SolidQueue, SolidCable) 초기 설정 문제가 여러 프로젝트에서 반복됐다. Render의 무료/스타터 플랜에서 단일 PostgreSQL 인스턴스를 여러 Rails 컴포넌트가 함께 사용하는 구성이 원인이었다. ...

2026-02-24 00:00 · 10분 소요 · Seunghan
Rails Solidqueue Render Manual Assignment

Rails 8 + SolidQueue Render 배포 삽질 3연타 — 테이블 누락, AI 담당자, 수동 배정

오늘 Rails 8 기반 ITSM 시스템을 Render에 배포하면서 연속으로 삽질을 했다. 각각 원인이 달랐지만 사슬처럼 연결된 문제들이었다. 배포 로그를 보고 디버깅하고, 코드를 고치고, 새로운 문제를 발견하는 과정을 기록해 둔다. 이 글에서 다루는 스택은 Rails 8.1, SolidQueue 1.3.1, Puma, PostgreSQL이고 배포 환경은 Render.com이다. 삽질 1 — Application exited early with SolidQueue 증상 Render 배포 로그에 빌드는 성공인데 실행하자마자 죽는다. ==> Build successful 🎉 ==> Deploying... ==> Running 'bundle exec puma -C config/puma.rb' [87] Puma starting in cluster mode... [87] * Preloading application ==> Application exited early Build successful 메시지가 나왔으니 빌드 단계는 정상이다. 문제는 실행 단계다. Puma 프로세스가 시작조차 못 하고 종료된다. ...

2026-01-06 00:00 · 7분 소요 · Seunghan
Rails Ruby3 Kwargs Dispatch Integration Debug

하루 종일 삽질한 것들 — Ruby 3.0 kwargs, Docker env, NAS 크론, SSH 특수문자

AI 에이전트가 Rails API 서버를 호출해서 티켓을 자동 배정하는 디스패처를 만들었다. 로직 자체는 간단한데 붙이는 과정에서 예상치 못한 곳에서 계속 막혔다. 하루 동안 7개의 서로 다른 버그를 순서대로 만났고, 각각은 사소하지만 연속으로 터지니 꽤 피로했다. 비슷한 스택을 쓰는 사람에게 도움이 됐으면 해서 기록해 둔다. 1. Ruby 3.0 kwargs 분리 — render_success(key: val) 가 왜 터지나 가장 오래 고생한 것. Rails 컨트롤러에서 응답 헬퍼를 이렇게 호출했다: render_success(tickets: tickets_list, pagination: pagination_data) 서버 로그에 찍힌 에러: ...

2026-01-02 00:00 · 7분 소요 · Seunghan
Rails Denormalized Cache Vs Count Query

Rails 비정규화 캐시 컬럼과 COUNT 쿼리 불일치: 씨드 데이터가 0%를 만들었을 때

Rails 앱에 데모용 씨드 데이터를 직접 삽입했는데, 화면에서 모든 퍼센트가 0% 로 표시되는 상황을 만났다. 서버 로그도 깨끗하고, 데이터는 DB에 분명히 들어가 있는데, 숫자만 안 나온다. 상황 투표 기능이 있는 Rails 앱이다. 선택지(Choice)마다 득표 수를 보여주는 화면이 있고, 전체 투표수 대비 퍼센트를 계산해서 프로그레스 바와 숫자로 표시한다. 데모를 보여줘야 해서 외부 API에서 실시간 데이터를 가져와 씨드 데이터로 넣었다. 방식은 간단했다. # 씨드 데이터: 컬럼을 직접 업데이트 choice.update_column(:vote_count, 4712) pick.update_column(:total_votes, 6536) DB를 직접 조회하면 숫자가 잘 들어가 있다. 그런데 화면에서는: ...

2025-12-16 00:00 · 4분 소요 · Seunghan
Rails8 Deploy Lessons

Rails 8 첫 배포에서 마주친 5가지 문제: 보안, 마이그레이션, 호환성

Rails 8 프로젝트를 처음 클라우드 서비스에 배포하면서 하루 동안 연속으로 5가지 문제를 만났다. 각각 독립적인 문제처럼 보였지만, 하나를 고치면 다음 문제가 드러나는 패턴이었다. 특히 Rails 8에서 새로 도입된 Solid Suite의 멀티 DB 구조는 기존 Rails 개발자에게도 낯선 부분이 많았다. 시간 순서대로 마주친 문제와 해결 과정을 기록한다. 1. 공개 저장소에 민감한 파일이 들어간 경우 증상 배포 전 보안 점검을 하다가 git 히스토리에 민감한 파일이 포함된 것을 발견했다. 현재 HEAD에는 없더라도 과거 커밋에 남아있으면 누구나 조회할 수 있다. ...

2025-11-11 00:00 · 6분 소요 · Seunghan
Rails Missing Migration Sessions Table

Production DB에 테이블이 없다: schema.rb와 migration 파일 불일치 사고

회원가입, 로그인이 전부 안 된다는 제보를 받았다. 앱에서는 “예상하지 못한 오류가 발생했습니다"만 반복. 증상 회원가입 시도 → 500 Internal Server Error 로그인 시도 → 동일하게 500 Health check API → 200 OK, DB 연결 정상 서버는 살아있고 DB도 연결되어 있는데, 인증 관련 기능만 전멸. 조사 과정 1단계: 서버 상태 확인 SSH로 접속해서 Rails 환경 확인. rails runner "puts Rails.env" # => production rails runner "puts User.count" # => 13 서버 정상, DB 연결 정상, 유저 데이터도 존재. ...

2025-10-18 00:00 · 4분 소요 · Seunghan
Multi Landing Page Netlify Workflow

앱 랜딩 페이지 8개를 하나의 저장소로 관리하는 법

앱을 여러 개 만들다 보면 각각 랜딩 페이지가 필요해진다. 저장소를 8개 따로 만들면 관리 비용이 8배가 된다. 반대로 하나로 완전히 묶으면 배포가 복잡해진다 — 어느 페이지 하나를 수정해도 전체가 재배포되고, 실수 하나가 전체를 망가뜨릴 수 있다. 두 극단 사이에서 찾은 구조가 저장소 1개 + Netlify 사이트 N개다. 코드 관리는 한 곳에서, 배포는 서비스별로 완전히 독립적으로. 이 글은 그 구조의 세부 사항, 각 결정의 이유, 그리고 규모가 커져도 유지보수할 수 있게 만드는 패턴들을 정리한 것이다. ...

2025-10-11 00:00 · 7분 소요 · Seunghan
Hugo Blog Multi Site Management

Hugo 블로그 3개를 하나의 폴더에서 관리하는 구조

Hugo 블로그를 목적별로 3개 운영하고 있다. 개발 블로그 — 개발 삽질 기록, 기술 문서 (이 블로그) [앱명] 홈페이지 — 앱 소개 + 업데이트 블로그, 다국어(ko/en) 개인 블로그 — 비개발 글 각각 역할이 달라서 분리했지만, 관리는 한 곳에서 하고 싶었다. 처음엔 별도 저장소로 나눴다가 결국 단일 디렉토리 아래 모아두는 구조로 정착했다. 이 글은 그 구조와 각 블로그의 설정 방식을 정리한 것이다. 왜 Hugo인가 정적 사이트 생성기 중 Hugo를 선택한 이유는 단순하다. 빠르다. 수백 개의 포스트도 1초 내에 빌드된다. Go 바이너리 하나로 동작하기 때문에 의존성 관리 부담도 없다. Node.js 기반 도구처럼 node_modules가 수백 MB씩 쌓이지 않는다. ...

2025-10-08 00:00 · 8분 소요 · Seunghan
Domain Projects Dev Guide

멀티 도메인 정적 사이트 운영 개발 가이드

개요 여러 개의 정적 사이트(랜딩 페이지 + 블로그)를 단일 디렉토리에서 관리하는 구조와 배포 워크플로우를 정리한 문서입니다. 개인 블로그, 앱별 랜딩 페이지, 다국어 블로그 등 성격이 다른 여러 사이트를 운영할 때 발생하는 실무적인 문제들과 그 해결책을 다룹니다. 정적 사이트는 서버 부담이 없고, 배포가 빠르며, CDN 캐싱 효율이 높아 소규모 개인 프로젝트와 앱 마케팅 페이지에 이상적입니다. 그러나 여러 사이트를 동시에 운영하면 배포 방식이 사이트마다 달라져 혼란이 생기기 쉽습니다. 이 가이드는 각 사이트 유형별 배포 전략을 명확히 구분하고, 반복 작업을 자동화하는 방법을 설명합니다. ...

2025-09-13 00:00 · 7분 소요 · Seunghan

Rails에서 Slack 메시지 렌더링하기 — HTML 엔티티, 이모지, mrkdwn, whitespace-pre-wrap 함정까지

Slack 채널 데이터를 Rails 앱에 넣고 그대로 뷰에서 뿌려봤더니, 화면이 온통 &gt;와 :raised_hands:로 도배되어 있었다. 이모지는 텍스트 그대로, 볼드는 별표 그대로, 링크는 꺾쇠 그대로. 거기에 whitespace-pre-wrap CSS가 붙은 말풍선에서는 ERB 들여쓰기까지 렌더링돼서 모든 메시지가 들여쓰기된 것처럼 보였다. 이 글에서는 Slack 메시지를 Rails에서 제대로 렌더링하기 위해 겪은 삽질과 해결 과정을 정리한다. Slack 메시지 포맷의 특성 Slack은 자체 마크업 언어인 mrkdwn을 사용한다. Markdown과 비슷하지만 문법이 다르다. 포맷 Slack mrkdwn Markdown 볼드 *bold* **bold** 이탤릭 _italic_ *italic* 취소선 ~strike~ ~~strike~~ 인용문 > 줄 시작 > 줄 시작 (동일) 코드 `code` `code` (동일) 링크 <url|label> [label](url) 멘션 <@U123>, <!everyone> 없음 공식 문서(docs.slack.dev)에 따르면, Slack API를 통해 메시지를 가져올 때 세 가지 문자가 HTML 엔티티로 인코딩된 상태다: ...

2025-03-25 00:00 · 7분 소요 · Seunghan
개인정보처리방침 이용약관 면책조항 문의