728x90

PostgreSQL 78

[PostgreSQL] 설치와 접속 Ubuntu apt와 Docker

부제: PostgreSQL을 우분투에 바로 깔거나 도커로 띄워 psql로 접속하기까지# 우분투: 패키지로 설치 (systemd 서비스로 상주)sudo apt update && sudo apt install -y postgresql postgresql-contribsudo systemctl status postgresql # 상태 확인sudo -u postgres psql # postgres 슈퍼유저로 접속psql (16.14 (Ubuntu 16.14-0ubuntu0.24.04.1))Type "help" for help.postgres=#우분투는 apt로 깔면 postgres OS 유저와 동명의 DB 슈퍼유저가 만들어지고 서비스로 상주한다. 그래서 sudo -..

명령어/DB 2026.07.21

[운영] 모니터링을 붙였더니 결함이 나왔다, 그런데 바로 안 고쳤다

부제: 측정이 드러낸 숫자를 곧바로 결함으로 단정하지 않은 이야기모니터링을 붙이는 작업을 했다.목적은 단순했다. 안 보이던 걸 보이게 하는 것.그런데 실측을 시작하자, 모니터링과 무관한 원래부터 있던 것들이 드러났다.PostgreSQL 트랜잭션 롤백율 18.4%정렬·해시가 메모리가 모자라 디스크로 새면서 6일간 임시 파일 19GB, 1,439개로그용 Redis가 메모리 무제한 + 축출 안 함 → 호스트 램이 유일한 한계, 즉 OOM 위험. 게다가 append 로그가 원본 대비 47배로 부풀어 있음숫자만 보면 다 나쁘다.그런데 바로 안 고쳤다.18%는 나쁜 숫자인가롤백율 18%는 언뜻 앱이 에러투성이로 보인다.그런데 롤백은 에러일 때만 생기는 게 아니다.커넥션 풀은 연결을 반납할 때 상태를 리셋하며 롤백한..

Infra 2026.07.16

[백엔드] BE 개발자 없이 시작 느슨한 JSONB 계약 컨텍스트

부제: AI↔백엔드 계약을 맺을 사람이 없어서 어떤 구조든 받게 만든 이야기시스템은 백엔드(BE)가 채워 보내는 사용자 정보를 받아 대화 컨텍스트에 넣는다.그 정보를 어떤 형태로 주고받을지가 문제였다.그리고 이 결정은 기술이 아니라 조직 현실이 정했다.계약할 상대가 없었다프로젝트를 시작할 때 CTO도, 백엔드 개발자도 없었다.AI 서버와 백엔드 사이에 "무슨 필드를 어떤 스키마로 주고받자"는 계약을 맺을 상대가 없었다는 뜻이다.엄격한 스키마를 정하려면 양쪽이 합의하고, 백엔드가 그에 맞춰 개발해야 한다.그럴 사람이 없으니 그 길은 애초에 막혀 있었다.어떤 구조든 받는다그래서 방향을 뒤집었다."스키마를 맞춘다"가 아니라 "어떤 구조가 와도 추가 개발 없이 받는다"로.최소한의 뼈대만 정했다.사용자 정보를 세..

개발 2026.07.14

[RAG] 하이브리드 검색 BM25 벡터 RRF 순위 결합

부제: 키워드 검색과 벡터 검색을 점수 대신 순위로 합친 이유한국어 문서 검색에 두 방식을 같이 썼다.하나는 키워드 검색이다. 형태소로 자른 단어가 문서에 있는지를 본다.다른 하나는 의미 검색이다. 문장을 벡터로 바꿔 뜻이 비슷한 문서를 찾는다.각각 장단이 있어 둘 다 쓰기로 했다. 각 방식에서 상위 50개씩 뽑는다.그다음이 문제였다.두 결과를 어떻게 합치나처음 떠오른 건 점수를 더하는 거였다.키워드 점수와 벡터 점수를 합쳐서 다시 정렬하면 되지 않을까.안 됐다.두 점수는 스케일이 다르다.벡터 유사도는 0에서 1 사이로 얌전한데, 키워드 점수(BM25)는 위로 열려 있고문서·쿼리마다 분포가 제각각이다.그냥 더하면 한쪽이 다른 쪽을 압도해 버린다. 합치는 의미가 없어진다.가중치 튜닝은 답이 아니었다그럼 가..

AI 2026.07.12

[디버깅] user thread 완전복제 재현 원본 오염 방지

부제: 운영 버그를 원본을 건드리지 않고 재현하기특정 유저, 특정 대화에서만 나는 버그가 있다.재현하려고 그 유저에게 채팅을 한 번 쏘면, 그 순간 메모리·요약·체크포인트가 바뀐다.상태가 오염돼서 두 번째 디버깅은 이미 다른 조건이 된다.원본에 쏘면 오염된다손으로 재현 데이터를 만들 수도 없었다.수백 개의 대화 스레드에 분석 기록까지 누적된 상태를,픽스처 코드로 흉내 내는 건 사실상 불가능하다.그래서 방향은 하나였다.원본과 똑같은 상태의 사본을 만들고, 실험은 사본에서 한다.복제의 정의부터 못 박았다.모든 기본 키(PK)와 외래 키(FK)만 새로 생성하고,나머지 컬럼은 JSONB든 임베딩이든 파일이든 타임스탬프든 바이트 그대로 복사한다.즉 ID만 빼면 원본과 구별이 안 되는 사본이다.복제 범위는 손으로 ..

Infra 2026.07.09

[백엔드] 다국어 챗봇 타임존 단일 소스 LLM 컨텍스트 오염

부제: 사용자 시간대를 어디에 두고, 프롬프트엔 왜 안 넣었나다국어 챗봇이 제대로 답하려면 사용자별로 두 값이 있어야 한다.하나는 응답 언어(language), 하나는 현지 시각(timezone)이다.언어가 틀리면 엉뚱한 말로 답하고, 시간대가 어긋나면 "지금 몇 시"·"오늘"이 틀린다.문제는 이 두 값이 어디에 저장되고 어떻게 프롬프트에 들어가느냐였다.두 가지 결함정리하다 보니 시간대에서 결함이 두 개 보였다.첫째, 소스가 흩어져 있었다.채팅·프롬프트는 device.timezone을 읽고, 유휴 요약 잡은 settings.timezone을 읽었다.한쪽에만 값이 저장된 유저는 서브시스템마다 시간대가 달랐다.둘째, 시간대 문자열이 대화에 새어 들어갔다.프롬프트를 만들 때 device 정보를 통째로 블록에..

AI 2026.07.09

[백업] restic DB 백업 용량 최소화 복원 자동검증

부제: 6GB 백업을 월 0.9GB로 줄이고 매일 복원까지 확인한 이야기DB를 백업하려고 보니 덩치가 컸다.그런데 뜯어보니 대부분은 굳이 백업할 필요가 없는 데이터였다. 그 이야기다.문제이 서비스는 LangGraph로 대화 상태를 checkpoint에 저장한다.agent가 추론 턴을 한 번 돌 때마다 그 시점의 전체 상태를 스냅샷으로 남긴다. 과거 step으로 되돌아가는 time-travel을 위해서다.그러다 보니 한 스레드에서 대화가 100번 오가면 step 버전이 100개 쌓인다.checkpoint 테이블만 약 6GB였는데, 그중 98%가 이 step 이력이었다.재해 복구 관점에서 진짜 필요한 건 각 스레드의 최신 상태 하나뿐이다. 나머지 옛 step은 되감기 같은 고급 기능에나 쓰인다.결정 — 최신..

Infra 2026.07.08

[RAG] PostgreSQL 한국어 전문검색 MeCab 형태소 분석

부제: "약"을 검색하면 "약을"이 안 걸리던 문제한국어 문서 검색을 붙이는데, 기본 전문검색이 영 엉뚱하게 걸렸다.결국 언어 특성에 맞는 토크나이저를 고르는 게 일의 절반이었다.문제PostgreSQL 기본 전문검색(tsvector, simple 토크나이저)은 공백으로 단어를 나눈다.영어는 단어 사이가 공백이라 이게 통하는데, 한국어는 다르다."오늘 약을 먹었어요"공백 토큰화 → ["오늘", "약을", "먹었어요"]사용자가 "약"을 검색하면 약을이라는 덩어리와는 안 맞는다.한국어는 어근에 조사·어미가 달라붙는 구조라 공백으로 자르면 "약 + 을"이 통째로 하나가 돼버린다.영어식 어근 추출(stemming)도 답이 아니다. 그건 접사가 떨어지는 영어 형태에나 맞는 방식이라 결합형인 한국어엔 형태소 분석이 ..

AI 2026.07.08
728x90