본문 바로가기
728x90
반응형

전체 글332

조회 트래픽으로 랭킹을 채운다 연무장(전투 연습) 기능을 만들면서, 랭킹 데이터를 어디에, 어떻게 쌓을지 고민이 길었습니다. 배치로 한 번에 채우는 분포 집계와 달리, 연무장은 유저가 리플레이를 볼 때마다 한 줄씩 늘어납니다. 그래서 세 번째 SQLite 파일을 두고, 조회 API 두 번으로 “스텁 → 채우기”를 나눴습니다.왜 세 번째 DB인가이전에 분포 집계 테이블을 주 DB에서 분리했을 때의 교훈은 단순했습니다. 쓰기 성격이 다른 데이터는 파일을 나눕니다. 그때는 “파일을 나누면 writer가 둘”이었습니다. 지금은 writer가 셋입니다.파일역할채우는 방식project.db검색·세션·프로필요청 시 upsert, 배치 재조회project_distribution.db유저 분포 집계cron 배치project_battle_practic.. 2026. 8. 30.
Rust + SQLite 백엔드, 인프라 대신 경계를 나누다 Rust 백엔드에 계층을 들이되, Postgres는 넣지 않은 이유GeekNews에 올라온 Rust와 PostgreSQL로 확장 가능한 백엔드 서비스 구축하기를 읽고, 개인 프로젝트 백엔드에 적용할 수 있는 것만 골라 반영했다. 결론부터 말하면, 글의 핵심은 Postgres나 작업 큐가 아니었다. HTTP / 서비스 / 저장소를 나누고, 프레임워크와 SQL과 비즈니스 규칙을 서로 묶지 않는 것이었다. 그 경계만 가져와 단일 크레이트 안에서 정리했다.출발점개인 프로젝트 백엔드는 이미 글이 권하는 스택에 가까웠다.런타임 tokio, HTTP는 axum + tower-http, 외부 호출은 reqwest관측성은 tracing인메모리 캐시는 mokaDB는 SQLite + sqlx문제는 스택이 아니라 역할이 한 .. 2026. 8. 23.
SQLite는 한 번에 하나만 쓴다 — Writer 직렬화와 집계 DB 분리 개인 프로젝트 백엔드는 Rust(Axum) + SQLite입니다. 캐릭터 검색, 경험치 히스토리, 로그인 세션처럼 요청마다 짧게 쓰는 OLTP와, 유니온 랭킹을 긁어 월드·직업·유니온 구간 인구를 다시 만드는 배치 집계가 한 프로세스에 공존합니다. 처음엔 db 파일 하나면 충분해 보였습니다. 트래픽이 붙고 집계 배치가 커지자 문제가 분명해졌습니다. SQLite의 writer는 하나인데, 웹 요청의 짧은 INSERT와 집계의 긴 DROP/INSERT가 같은 락을 놓고 줄을 섭니다. 이 글은 그때 넣은 두 가지 장치를 정리합니다.앱 레벨 writer 직렬화집계 전용 DB 분리SQLite가 실제로 막아 주는 것WAL(Write-Ahead Logging)을 켜면 읽기는 쓰기와 겹칠 수 있습니다. 그래도 writ.. 2026. 8. 16.
Node.js + NestJS 입문서 오늘은 Node.js + NestJS 입문서 에 대해 리뷰해보고자 합니다. 읽게 된 계기최근 기업 공고들을 살펴보면서, Java뿐만 아니라 Python, TS를 요구하는 공고들이 많아졌습니다. 그 중, TS에 관심이 생겨 인프런에서 교육을 시청했었습니다. 그러던 와중, 많은 기업들에서 TS 백엔드로 사용하고 있는 NestJS에 대한 책이 있어 읽어보게 되었습니다.리뷰책을 처음 봤을때, 저는 단순히 Node.js에 대해 설명하고 Nest.js에 대해 설명할거라고 생각했습니다. 그러나, 해당 책에서는 다음과 같은 순서로 설명합니다.Node.js에 대한 기초 지식 및 활용HttpClient를 활용한 서버 구현npm 패키지 매니저에 대한 설명express라는 백엔드 프레임워크를 활용한 구현서버에서 사용하는 S.. 2026. 7. 30.
Tokio 생태계에 등장한 새로운 웹 풀스택 프레임워크, Topcoat 최근에 tokio 생태계에 새로운 녀석이 등장했습니다. 바로 Topcoat이라는 웹 풀스택 프레임워크입니다.Topcoat이란?Topcoat는 서버 중심 렌더링으로, 서버에서 HTML 조각을 렌더링하고 메타데이터로 "반응형 지시문"을 추가하는 방식으로 더해집니다. (HTMX와 유사) Topcoat로 만든 "hello wolrd"앱 입니다.#[tokio::main]async fn main() { topcoat::start(Router::builder().discover().build()).await.unwrap();}#[page("/")]async fn home() -> Result { view! { .. 2026. 7. 26.
메이플스토리 통계 서비스를 만들며 겪은 시행착오 개인 프로젝트를 진행하면서 겪었던 거에 대하여 작성해보고자 합니다. 현재 메이플스토리의 모든 캐릭터들에 대한 정보들을 가지고, 이에 대한 통계를 보여주는 페이지를 구현하고자 했습니다.어떻게 했는데?초기 구상로직은 검색된 유저들에 대한 정보를 기록하는 db에서 서버별, 레벨별로 select로 데이터를 가져와서 처리하고자 했습니다. 그렇게 구현하니 db에서 데이터를 정리해서 가져오는데 6분 정도의 시간이 소요되었습니다. 해당 부분은 문제가 있다고 생각이 들어 해당 데이터들을 미리 저장해두는 db를 구현하고 이에 데이터를 저장하도록 했습니다.현재까지 로직검색된 유저들에 대한 정보를 가지고 있는 db에 원하는 부분 데이터는 where 조건걸고 가져옴가져온 데이터를 화면에 보여줌보여지는데 필요한 정보들만 있는 D.. 2026. 7. 19.
Bun은 왜 RIIR를 선택했을까 Bun이라고 Node.js의 대안으로 나온 프로젝트가 있었습니다. 해당 프로젝트는 Zig라는 언어로 이루어져 있었고, 많은 관심을 받은 상태였습니다. 그러던중, 어느 날 하나의 PR이 올라옵니다. Zig로 이루어진 프로젝트를 Rust로 재포팅한다는 pr이였습니다. 바로 GeekNews에 올라왔고, 많은 관심이 쏠리게 되었습니다. bun이 왜 Zig에서 Rust로 언어를 바꾸게 되었고, 이로 인해 어떤 이득을 얻게 되었는지에 대하여 다뤄보고자 합니다.왜 언어를 바꾸게 되었는가?Bun은 esbuild의 JavaSciprt, TypeSciprt 트랜스파일러를 Go에서 Zig로 라인 단위 포팅한 프로젝트로 출발했습니다. 2021년 4월 16일에 저수준 제어와 성능 지향 설계에 매료되어 Zig를 사용하여작성되었습.. 2026. 7. 12.
Rust 서버 성능 개선을 위해 병목부터 측정해봤습니다 이번에는 각 API들이 얼마만큼의 시간을 소비하고, 어디서 가장 많은 시간을 소비하는지 측정하기 위하여 개인 프로젝트에 해당 시스템을 도입했습니다. 이에 대한 내용에 대해 적어볼까 합니다.왜서버 성능 향상을 위해, 어느 시점에 가장 많은 시간을 소요하는지, 이에 대한 해결책을 찾아보고자 해당 시스템을 도입하게 되었습니다. 현재 서버는 서버 -> nexon open api / DB -> 서버 -> 클라이언트 구조를 기본적으로 가지고 있습니다. 여기서 어느 시점에 가장 오래걸리는지 확인하기 위하여 다음과 같이 구간을 나누었습니다.Nexon open apiDBLogicRest apiCache어떻게?현재 사용중인 tracing-subscriber을 활용하였습니다. 가장 먼저 해당 로직은 release모드가 아닌.. 2026. 7. 5.
NDC 오프라인 2일차 후기 이번 NDC(NEXON DEVELOPERS CONFERENCE)에 2일차로 신청해서 방문했었다. 오프라인을 통해 NDC에 참여했던 후기에 대해 적어보고자 합니다.내가 미소녀 목소리를 만들 수 있을 리 없잖아, 무리무리! (※무리가 아니었다?!) - SBV2 오픈소스를 활용한 한국어/일본어 TTS 모델 개발기가장 먼저 1994홀에서 내가 미소녀 목소리를 만들 수 있을 리 없잖아, 무리무리! (※무리가 아니었다?!) - SBV2 오픈소스를 활용한 한국어/일본어 TTS 모델 개발기라는 주제로 9년차 개발자 김명지님께서 이야기해주셨습니다. 일본어 전용 TTS 모델인 Style-Bert-Vites2를 활용해서 개발을 진행했다고 했는데, 모델명에서 익숙한 BERT라는 내용이 들어가서 혹시 연관이 있나? 하고 듣기 .. 2026. 6. 24.
728x90
반응형