전체 글

개 발 자 로 살 아 남 기
· TIL
멀티플레이어 미니 FPS 만들기 2편(운영편)전체 흐름코드 정리(상수 중앙화) → 멀티룸(로비) → EC2 배포 → 맵 권위화 → 자연 지형 → 아레나 확장 → 밤하늘 → rubber-banding 진단 진행 방식이 기본편과 달랐다. 기본편 보러가기기본편 단계에서는 한 단계씩 내가 직접 검증하며 구현했고,여기는 클로드코드로 에이전트 파이프라인(architect → implementer → reviewer → qa)으로 굵직한 작업 단위를 처리했다.Part 1 - 상수/매직넘버 중앙화무엇 / 왜서버 전반에 흩어진 매직넘버를 단일 소스로 모았다. 핵심은 숨은 결합을 드러내는 것.예를 들어 틱 레이트 TICK_HZ=30과 물리 timestep=1/30은 반드시 같아야 하는데 따로 떨어져 있었다.스폰 높이 0...
· TIL
멀티플레이어 미니 FPS 만들기 1편(기본편)어두운 아레나에서 손전등으로 앞을 비추며 페인트볼로 눈싸움하는, 최대 3인용 웹 FPS를 0에서 끝까지 만든 기록.과정을 잊지 않고자 기록하는, 남이 읽기엔 불친절한 기록물.결과물배포: https://eunoh.top/tests/mini-fps백엔드: 권위 게임 서버 (Node + ws, Rapier 물리, 30Hz 틱)프론트: 클라이언트 (Next 16 / React 19 / three.js · R3F · drei)어떤 게임인가컨셉: 총기 난사가 아니라 눈싸움/페인트볼. 페인트볼이 포물선을 그리며 날아가고, 회피가 가능하다.분위기: 거의 검정에 가까운 아레나. 각 플레이어는 손전등을 들고 앞을 비춘다. 어둠 속에서 다른 사람의 손전등 불빛이 휘청거리며 움직이..
· TIL
Vercel → AWS 마이그레이션 마스터 플랜Next.js 앱을 Vercel에서 AWS(ECS Fargate)로 옮기는 작업을,처음부터 끝까지 어떻게 설계하고 진행했는지의 압축 기록.다음에 같은 일을 할 때 코드 디테일이 아니라 순서·결정·함정 중심으로 펼쳐보기 위한 노트.1. 무엇을, 왜Next.js Vercel 배포시, RDS 와 직접 붙어야 할 경우 any-open을 피할 수 없다.RDS any-open 하지 않으려면 돈내고 Vercel static ip를 쓰거나 aws 이전이 필요하다.대상: Next.js 16 앱 (App Router, RSC, Better Auth, Prisma 7)출발: Vercel (Edge + Vercel Build, 환경변수 UI 입력)도착: AWS ECS Fargat..
· TIL
비개발 팀에게 RDS 조회 환경을 안전하게 전달하기1. 배경HQ 마케터와 기획자가 내부 데이터를 직접 확인해야 하는 상황이 있었다.다만 이들은 SQL이나 개발 환경에 익숙하지 않았고, RDS를 직접 노출하거나 관리자 계정을 공유하는 방식은 보안상 적절하지 않았다.그래서 다음 조건을 만족하는 방식을 구성했다.RDS는 외부에 직접 공개하지 않는다.Bastion EC2를 통해서만 접근한다.HQ 전용 DB 계정은 SELECT 권한만 가진다.비개발자는 복잡한 SSH 명령어를 직접 입력하지 않는다.Windows 환경에서도 실행 가능해야 한다.Claude Desktop의 MCP Postgres 서버에서 사용할 수 있어야 한다.2. 최종 아키텍처HQ Windows PC ↓ PowerShell SSH Tunnelloc..
· TIL
Nemotron Personas — 임베딩 기반 페르소나 검색 시스템 구현 회고한 줄 요약NVIDIA Nemotron 한국어 페르소나 데이터셋 100만 건을 OpenAI 임베딩으로 벡터화하고,pgvector + HNSW로 의미 검색 시스템을 구축한 뒤,NestJS API + Next.js 프론트로 광고 도메인 페르소나 검색기를 만든 프로젝트.만든 것배포: https://personas.eunoh.top (API), https://eunoh.top/tests/personas (UI)관측성: https://grafana.eunoh.top (Cloudflare Zero Trust로 보호)최종 스택[Next.js 프론트] ↓ [NestJS API (홈 우분투 서버)] ↓ ├─→ [OpenAI text-embed..
· TIL
관측성 처음 세팅해본 회고0. 시작 vs 끝 시점의 멘탈 모델시작 시점의 멘탈 모델"관측성 = 슬랙으로 알림 받는 것""알림 받으면 로그는 어디서 보지...?"→ 알림은 단편적이고 컨텍스트가 없었음. 서버 SSH 들어가서 journalctl, docker logs 뒤지는 게 일과.메트릭/로그/트레이스의 차이를 모름. 그냥 "로그"가 전부였음.OTel이라는 단어는 들어봤지만 "텔레메트리가 대체 어디로 어떻게 가는지" 감이 없었음.끝 시점의 멘탈 모델관측성은 "증상을 보고 → 원인을 파고들 수 있는 환경"이다.증상: request rate, error rate, latency p95/p99 같은 메트릭원인: 그 시점 로그, 그 요청의 trace알림은 "심각도와 맥락을 담아" 받는 것. 단순 에러 발생이 아니..
· TIL
pgvector + HNSW 검색 시스템 설계 후기0. 시작 vs 끝 시점의 멘탈 모델시작 시점의 멘탈 모델pg_trgm + GIN 같은 거 해봤으니 pgvector도 비슷하게 인덱스 만들고 WHERE + ORDER BY 하면 될 거 같다끝 시점의 멘탈 모델HNSW는 일반 인덱스와 본질이 다르다. "사전 그래프"여서 필터와 결합되는 순간 옵티마이저의 path 선택 문제가 발생.옵티마이저는 데이터 분포 보고 케이스별로 옳은 선택을 하고 있다 (Path A vs Path B).우리가 할 일은 ef_search 같은 힌트로 후보 풀 크기를 조절하는 것.100만건 적재는 INSERT가 아니라 COPY. 라운드트립 vs 단일 스트림 차이.1. 호스팅 결정: Supabase / Railway / 로컬 Docker후..
0. 벡터 임베딩 처음 구현해본 후기1. 임베딩의 본질 — "특정 모델만의 좌표계"시작 시점의 멘탈 모델"어깨너머로 본 벡터 임베딩. 1536차원이라는데 대체 그게 무슨 차원이라는 거지?"끝 시점의 멘탈 모델인간이 1536차원 배열을 보고 의미를 읽을 수는 없다.대신 "두 벡터의 거리가 얼마나 가까운가"가 의미적 유사도를 표현한다.더 중요한 깨달음: 임베딩은 "절대적 의미 좌표계"가 아니라 특정 모델만의 좌표계다.text-embedding-3-small의 좌표 ≠ BGE-M3의 좌표두 벡터를 비교하려면 같은 모델로 만들어야만 한다.→ 인덱싱한 모델과 검색 시 쓰는 모델이 반드시 같아야 한다!차원 수(1536, 3072 등)는 "표현 해상도". 높을수록 미세한 의미 차이를 담을 수 있지만, 저장·연산 비용..
· TIL
HuggingFace 데이터셋 처음 다뤄본 후기0. 시작 vs 끝 시점의 멘탈 모델시작 시점의 멘탈 모델데이터셋 = HF에서 다운받는 거.parquet은 잘 모르겠지만 좋다고 들었다.100만건이면 어떻게 다뤄야 하지...끝 시점의 멘탈 모델데이터 탐색은 "5단계 체크리스트"로 표준화됨parquet의 컬럼 지향 의미를 어느정도,, 이해100만건도 두렵지 않아!! 면 좋겠지만 아직 무섭다..1. 다운로드: streaming vs full download선택: full download → 로컬 parquet이유:데이터 탐색 단계에서는 같은 데이터를 여러 번 다른 각도로 들여다봐야 함.streaming은 일회성 순회에 최적화되어 있어서 탐색에 부적합.언제 streaming이 맞나:데이터가 디스크에 안 들어갈 때..
· TIL
Nemotron Personas 프로젝트 함정 노트이 프로젝트를 진행하면서 직접 부딪혀 알게 된 함정들.미래의 내가 같은 증상을 만났을 때 키워드로 찾을 수 있도록 정리.임베딩임베딩 모델은 인덱싱과 검색에 같은 걸 써야 한다 (좌표계 일관성)증상: 다른 모델로 임베딩한 두 벡터를 비교하면 의미적으로 가까운 것도 멀게 나옴원인: 임베딩 좌표계는 모델별로 다름. text-embedding-3-small의 (1536차원) 좌표 ≠ BGE-M3의 좌표. 차원 수가 같다고 해도 다른 좌표계.해결: 인덱싱한 모델과 검색 시 쓰는 모델을 동일하게 고정. 모델 변경 시 전체 재임베딩.메모: 어깨너머로 봤을 땐 "한 번 차원 좌표계를 만들면 다 똑같이 쓰는 줄" 알았던 게 오개념.쿼리와 문서의 길이/형식 비대칭 → 유사..
adminisme
elseif