DevInsight

개발하며 겪은 판단을 적어요

DevInsight Archive

전체 글

최근 발행한 분석과 실무 기술 글을 시간순으로 모았습니다.

Tools

eslintrc를 버리고 flat config로 갈아탈 때 조용히 무너지는 지점들

eslintrc에서 flat config로 전환할 때 가장 많이 무너지는 지점은 규칙이 아니라 플러그인 호환성과 설정 병합 순서다. 문자열 기반 extends가 사라지고 객체 배열로 바뀌면서 플러그인 등록 방식, ignores 처리, 에디터 연동이 모두 달라진다. 이 글은 실제 마이그레이션에서 조용히 실패하는 지점을 짚고, 무엇을 먼저 옮기고 무엇을 버려야 하는지 판단 기준을 제시한다.

#ESLint#flat config#마이그레이션#린트
AI

검색이 자꾸 엉뚱한 문서를 물어올 때 임베딩보다 먼저 의심해야 할 것

RAG 검색 품질이 오르지 않을 때 임베딩 모델이나 벡터 DB를 먼저 의심하기 쉽지만, 정작 원인은 문서를 기계적으로 잘라 문맥을 조각내는 청크 분할에 있다. 고정 길이 분할, 문장 중간 절단, 표와 제목 분리 같은 흔한 실수가 재현율을 어떻게 망치는지 사례와 함께 짚고, 청크 크기와 오버랩을 문서 구조에 맞게 조정하는 방법, 검색 품질을 측정하는 실용 지표까지 정리한다.

#RAG#청크 분할#검색 품질#임베딩
Frontend

use client 한 줄로 갈리는 서버와 클라이언트, 번들 크기부터 상태 관리까지 흔들린다

Next.js App Router에서 'use client' 한 줄이 서버·클라이언트 영역을 가르면 번들 크기, 데이터 페칭, 상태 관리 전략이 전부 흔들린다. 경계를 잘못 그으면 번들 비대화와 중복 페칭이 뒤늦게 한꺼번에 터진다. 이 메모는 계층별 책임과 데이터 소유권을 기준으로 경계를 다시 그리는 판단 원칙과, 이미 잘못 그어진 경계를 리팩터링하는 우선순위를 정리한다.

#React#Next.js#Server Components#Client Components
Tools

2,731개의 타입 에러와 마주했던 한 주, strict 옵션을 끄고 켜는 사이의 현실

TypeScript strict 계열 옵션을 한 번에 켜면 수천 개의 타입 에러가 쏟아져 작업이 멈추기 십상이다. 실제 프로젝트 사례를 바탕으로 옵션별 변경 난이도와 영향 범위를 비교해 어떤 순서로 켜는 것이 안전한지, 어디까지 자동으로 고치고 어디를 수동으로 봐야 하는지 단계적 로드맵으로 정리했다.

#TypeScript#strict 모드#타입 안정성#레거시 코드
Backend

작은 서비스도 버틸 수 있는가, 폴링 한계와 큐 도입 시점의 판단 기준

작은 서비스에서 DB 폴링으로 작업을 처리하다 보면 스루풋이 급격히 떨어지고 레이턴시가 늘어나는 신호가 나옵니다. 이 글에서는 폴링 기반 처리가 감당해야 하는 한도를 분석하고, 큐 시스템 도입이 필요한 시점의 구체적 판단 기준을 제시합니다. 단순히 '트래픽이 늘었다'는 증상이 아니라 시스템 자체의 포화 상태를 어떻게 인지하고 대응할지, 도입 후 새겨야 하는 운영 체크포인트까지 함께 다룹니다.

#메시지 큐#폴링#백엔드 아키텍처#Redis
Backend

웹훅은 믿지 말고, 시그니처로 검증하라

웹훅 수신부는 외부의 불신을 전제로 설계해야 한다. 재전송과 처리 지연, 심지어 위조 시도까지 뒤따르는 불안정한 요청을 믿으면 안 되기에, 시그니처 검증과 멱등 처리, 재전송 ID 추적, 지연 시 큐잉 판단 등 수신부 설계에서 빼먹기 쉬운 요소를 모두 챙겨야 비로소 안정적 수신이 시작된다. 특히 재전송은 멱등키 없이 또다시 도착해도 중복 처리되지 않도록, 지연이 길어지면 즉시 큐에 넣어 처리를 미루어야 한다는 점을 잊지 말자

#webhook#signature-verification#idempotency#retry-handling
DevOps

캐시 적중률 98%인데 배포판은 왜 자꾸 구버전일까

의존성 캐시와 빌드 캐시, 매트릭스 전략은 CI 실행 시간을 반으로 줄이지만 무효화 기준을 잘못 잡으면 오래된 패키지가 그대로 빌드를 통과시키는 예상 밖의 사고로 돌아온다. 이 글은 캐시가 실제로 빌드를 깨뜨리는 구체적인 상황들을 짚고, 잠금 파일·해시 입력·매트릭스 키 설계에서 무효화 시점을 정확히 읽는 원칙을 정리해 캐시를 안전하게 쓰는 기준을 제시한다.

#GitHub Actions#CI/CD#캐시 전략#빌드 최적화
Data

만들어 둔 인덱스를 쿼리가 외면하는 순간들, EXPLAIN으로 사인을 읽는 법

인덱스를 만들어도 EXPLAIN에 풀스캔이 찍히는 일은 흔하다. 함수로 감싼 컬럼, 타입 불일치, LIKE의 선행 와일드카드, 낮은 선택도라는 네 가지 패턴이 쿼리와 인덱스 사이의 연결을 끊는다. 이 글은 각 패턴이 실행 계획을 어떻게 왜곡하는지 실제 예시로 짚고, EXPLAIN 해석부터 원인 확정까지 원인을 좁혀 고치는 절차를 정리한 결정 메모다.

#PostgreSQL#EXPLAIN#인덱스#풀스캔
Frontend

폰트가 보이기 전에 페이지는 이미 흔들리고 있다

한글 웹 폰트는 글리프 하나당 용량이 커서 로딩을 지연시키고, 폰트가 늦게 뜰수록 CLS 지표가 요동친다. 이 글에서는 subset으로 글리프를 걸러내고 preload 타이밍을 잡고 font-display 전략을 고르는 과정을 실제 수치와 함께 살펴본다. Next.js의 next/font가 자체적으로 처리하는 일과 처리하지 않는 일을 구분해, 퍼포먼스 예산을 넘지 않으면서 텍스트가 안정적으로 렌더링되는 폰트 파이프라인을 설계하는 방법을 다룬다.

#웹 폰트#CLS#Core Web Vitals#Next.js
Tools

any 지옥에서 strict로 승급한 어느 프로젝트의 사투기

느슨하게 태어난 TypeScript 프로젝트에서 strict를 하루아침에 켜면 수백 개의 에러가 쏟아진다. 이 글은 신규 기능 개발과 버그 수정 틈새에서 strict 계열 옵션을 하나씩 켠 실제 진행 기록으로, 옵션별 난이도와 효과를 따져 최적의 적용 순서를 정리했다. any 소탕 순서부터 strictNullChecks, noImplicitAny까지 실무에서 겪은 장애와 회귀를 함께 담았다.

#TypeScript#strict#strictNullChecks#noImplicitAny
DevOps

200 OK는 무중단 배포를 지켜주지 않는다

무중단 배포가 실패하는 지점은 서버가 다운된 순간이 아니라, 헬스체크가 형식적인 200을 돌려주는 순간이다. 준비가 덜 된 신버전으로 트래픽이 몰리고 장애는 배포가 끝난 뒤에야 폭발한다. readiness와 liveness를 DB·Redis·메시지 큐 같은 실제 의존성 상태와 연결하는 방법, 탐지 지연을 줄이는 체크 주기, 그리고 어떤 지표에서 롤백을 눌러야 하는지 기준을 함께 정리한다.

#무중단배포#헬스체크#롤링배포#블루그린배포
AI

문서를 잘게 쪼갤수록 답이 멀어지는 이유

청크 크기와 분할 기준 하나가 임베딩 벡터의 품질을 좌우한다. 잘못 자르면 유사도 검색이 문맥이 끊긴 반쪽짜리 조각만 반환해 정답이 산산조각 나는데, 크게 자른다고 해결되지도 않는다. 자주 저지르는 분할 실수의 원리를 짚고, 검색 재현율과 응답 완결성을 함께 보는 실용적인 평가 지표까지 정리했다. 후보 조각 검증, 컨텍스트 회수 전략, 기준별 실험 방법을 바로 파이프라인에 적용할 수 있게 구성했다.

#RAG#청크 분할#임베딩#벡터 검색
Tools

node_modules를 두 번 지운 뒤에야 패키지 매니저를 다시 봤다

패키지 매니저 선택은 설치 속도, 디스크 사용량, 유령 의존성이라는 세 축이 서로 맞물려 움직인다. 단독 저장소에선 대충 선택해도 문제가 드물지만, 모노레포로 넘어가면 hoisting 방식 차이가 CI 시간과 디스크 폭발로 그대로 드러난다. npm·pnpm·yarn이 각각 의존성을 저장하고 공유하는 구조를 비교하고, 팀 규모와 모노레포 성숙도라는 실제 조건에 맞춰 도구를 고르는 판단 흐름을 정리했다.

#패키지매니저#pnpm#npm#yarn
AI

토큰이 흐르는 동안 화면은 왜 산산조각나는가

SSE로 LLM 응답을 토큰 단위로 흘려보내며 화면에 그리는 순간, 마크다운 문법은 중간에 깨지고 중단 요청은 제대로 전달되지 않으며 토큰마다 렌더링이 버벅인다. 이 글은 스트리밍 UI에서 실제로 부딪히는 마크다운 파싱 붕괴, abort 처리와 에러 복구, 렌더링 성능 문제를 실패 사례 순서로 훑고, 부분 렌더링과 버퍼 축적을 최소화하는 백프레셔 방식 등 검증된 해결책을 정리한다.

#SSE#스트리밍#LLM#마크다운 파싱
DevOps

이미지를 얇게 만들수록 빌드가 비대해지는 역설

Next.js/Node.js 컨테이너를 multi-stage 빌드와 standalone 출력으로 최적화하다 보면 용량은 80% 줄었는데 빌드 시간은 되레 늘고, 캐시 무효화로 매 배포마다 의존성을 새로 내려받는 경우가 생긴다. 이 글은 무엇을 줄여야 하고 무엇은 절대 건드리면 안 되는지를 가르는 기준을 결정 메모 형식으로 정리하고, 최적화가 역효과를 내는 지점을 짚는다.

#Docker#Next.js#Node.js#multi-stage 빌드
Security

토큰이 로그인을 기억한다는 착각

JWT와 서버 세션은 취향 문제가 아니라 로그아웃 즉시성, 토큰 탈취 대응, 확장 방식까지 전부 갈라놓는 구조적 선택이다. refresh token 회전과 재사용 감지, 세션 저장소 운영 부담, 로그아웃 처리의 어려움을 실제 구현 사례를 기준으로 비교하며, 무상태의 매력과 상태의 안전함 사이에서 서비스 특성에 맞는 판단 기준을 세우는 방법을 정리한다.

#JWT#세션#refresh token#인증
Data

1번 조회가 100번이 되는 순간

에러 로그에는 남지 않으면서 DB 부하만 조용히 키우는 N+1 쿼리. ORM이 연관 엔티티를 개별 SELECT로 쪼개는 구조적 원인부터, 실행 로그와 계측 데이터에서 폭주 지점을 특정하는 순서, 그리고 연관 데이터의 수와 변동성에 따라 eager loading과 배치 조회를 나누는 판단 기준까지 실전 절차 순으로 담았다. 쿼리 개수 자체보다 트레이드오프를 보는 관점이 핵심이다.

#N+1#ORM#JPA#쿼리 최적화
Frontend

next/image sizes 한 줄이 LCP를 0.5초 당긴다

LCP 개선을 위해 무작정 이미지를 압축하고 CDN을 도입하기 전에, next/image의 sizes 속성과 priority 플래그가 실제로 어떤 영향을 미치는지 정량적으로 이해해야 한다. 이 글은 next/image 설정값이 LCP에 미치는 영향을 실제 코드 레벨에서 분석하고, 이미지 CDN이 진짜 필요한 상황과 불필요하게 최적화를 도입했다가 역효과를 보는 사례까지 함께 다룬다.

#LCP#이미지최적화#next-image#CoreWebVitals
DevOps

INFO, WARN, ERROR만으로는 부족하다

console.log에서 JSON 로그로 가는 건 시작일 뿐이다. 로그 레벨을 모호하게 정의하면 알람이 무의미해지고, 스키마 없이 쌓은 로그는 검색조차 불가능하다. 마스킹을 미루면 개인정보가 로그 플랫폼에 그대로 노출된다. 급증하는 로그 비용도 간과할 수 없다. 이 글은 로그 레벨 기준, 공통 필드, 마스킹, 비용 거버넌스 등 구조화 로깅 도입 전에 반드시 정해야 할 결정들을 기록한다.

#구조화로깅#로그레벨#observability#DevOps
Security

시크릿은 매번 같은 길로 도망친다

환경변수와 시크릿이 유출되는 가장 흔한 세 가지 경로인 클라이언트 번들 포함, 로그 출력, 실수로 인한 커밋을 분석한다. 각 경로별 사고 패턴과 조기 탐지를 위한 도구 설정, 그리고 유출 확인 시 즉시 실행해야 할 키 롤링과 로그 감사까지 실전 대응 루틴을 제시한다. NEXT PUBLIC API KEY=sk live ...

#환경변수#시크릿관리#보안사고#API키유출
Data

데이터는 반드시 낡는다. 그리고 그 사실을 받아들일 때 진짜 설계가 시작된다.

TTL과 태그 기반 무효화, stale-while-revalidate를 언제 선택해야 하는지 구체적인 판단 기준을 제시한다. 캐시로 인한 데이터 불일치를 비즈니스 관점에서 어디까지 용인할지 결정하는 프레임워크와 무효화 비용을 최소화하는 실전 패턴을 함께 다룬다. 사용자 프로필 페이지에서 '최근 구매 목록'이 3초 전 데이터를 보여주고 있다.

#캐시무효화#TTL#stale-while-revalidate#캐시전략
Tools

ESLint Flat Config 마이그레이션 실패 일지와 살아남는 체크리스트

ESLint 9의 flat config로 넘어가면서 extends가 사라지고, 플러그인 호환성 문제, VS Code ESLint 확장과의 설정 불일치, 글로벌 변수 선언 방식 변화 등 현장에서 마주치는 장애물을 해결 순서대로 정리한다. 삽질을 줄이는 실전 체크리스트. 2025년 4월, ESLint 9가 정식 릴리스되면서 파일은 deprecated 경고를 넘어 아예 무시되기 시작했다.

#ESLint#flat config#eslintrc#마이그레이션
Backend

1년 동안 DB 테이블로 큐 대신 쓰면서 내가 놓친 것들

DB 폴링 기반 작업 처리로 버틸 수 있는 한계와 Redis·메시지 큐 도입을 결정해야 하는 실전 신호, 그리고 큐를 도입할 때 따라오는 운영 부담을 사례 중심으로 정리한다. DB 테이블 하나로 작업 큐를 대신한 지 1년이 지났다. 처음엔 "언젠가 Redis나 RabbitMQ를 도입해야지"라고 생각했지만, 그 언젠가는 오지 않았다.

#메시지 큐#Redis#BullMQ#DB 폴링
AI

AI 에이전트는 서버에서 태어났지만 브라우저에서 산다

대부분의 AI 에이전트가 여전히 서버에서 오케스트레이션을 돌리고 있지만, 브라우저가 가진 런타임 맥락과 WebGPU·WebLLM의 발전이 이 판도를 바꾸고 있다. 서버 중심과 브라우저 네이티브 아키텍처의 지연 시간, 개인정보 보호, 비용, 확장성을 비교하며 왜 지금 이 전환이 중요한지 분석한다.

#AI 에이전트#브라우저 AI#WebLLM#AI 오케스트레이션
Frontend

TypeScript 설계 부채를 숫자로 드러내고 CI가 대신 막게 하라

타입스크립트 프로젝트에서 CK 메트릭(WMC, DIT, NOC, CBO, RFC, LCOM)을 측정하는 CLI 도구 Artie-lens를 활용해 CI 파이프라인에 설계 품질 게이트를 구축하는 방법을 다룬다. 코드 복잡도와 결합도가 임계치를 넘으면 자동으로 빌드를 실패시켜 기술 부채 누적을 사전에 차단하는 실전 가이드.

#TypeScript#CK메트릭#설계품질#CI/CD
AI

로컬 AI가 당신 대신 HTML을 쓰는 시대, 마크다운은 초안으로 충분하다

로컬 AI 에이전트가 마크다운, CSV, JSON 등 다양한 입력을 75가지 디자인 템플릿과 9가지 출력 형식으로 변환해 완성된 HTML을 즉시 생성하는 패러다임을 다룬다. API 키 없이 Claude Code, Cursor 등 기존 CLI 세션을 재활용하며 원클릭으로 여러 소셜 플랫폼에 배포할 수 있다.

#AI 에이전트#HTML 자동 생성#로컬 LLM#Claude Code
Backend

메모리를 대신 관리해주는 쾌락과 고통의 세계

가비지 컬렉션은 현대 프로그래밍 언어가 거의 예외 없이 채택한 자동 메모리 관리 기술이지만, 그 내부는 대부분의 개발자에게 블랙박스다. 2판으로 돌아온 이 핸드북은 지난 60년간 축적된 GC 연구의 정수를 집대성한다. 단순한 mark-sweep에서 병렬·동시·실시간 컬렉터까지, GC가 어떻게 진화해왔고 오늘날 어떤 선택지를 제공하는지 한 권으로 조망한다.

#garbage collection#memory management#JVM#runtime internals
DevOps

프론트엔드 개발자가 배포에서 벗어나는 순간

Vercel이 'Develop. Preview. Ship.'으로 압축한 것은 단순한 마케팅 문구가 아니다. 로컬 개발부터 프로덕션 배포까지 원클릭으로 연결하는 경험은 프론트엔드 개발 문화를 재정의하고 있다. 이 글에서는 Vercel이 만들어낸 배포의 투명화와 그 이면에 있는 기술적 트레이드오프, 그리고 팀이 겪는 현실적인 도전을 짚어본다.

#Vercel#프론트엔드#배포#CI/CD