Developer StroyHouse LIST

Recent Story

RAG를 활용한 LLM 서비스 구축

STEP 32 - 셀프호스팅 LLM으로 RAG 구축하기

셀프호스팅 LLM으로 RAG 구축하기 - vLLM과 Ollama지난 글까지 운영·거버넌스 파트를 마무리했습니다. 지금까지 다룬 모든 LLM 호출은 OpenAI 같은 외부 API를 전제로 했습니다. 이번 글부터는 LLM 인프라 심화 파트로 넘어가서, 외부 API 대신 LLM을 직접 서버에 올려 운영하는 셀프호스팅 방식을 다룹니다.1. 왜 셀프호스팅을 고려하게 되는가지난 비용 모니터링 글에서 다룬 것처럼, 트래픽이 늘어날수록 외부 API 비용은 계속 누적됩니다. 또한 보안이 중요한 도메인에서는 문서와 질문이 외부 서버로 나가는 것 자체가 부담일 수 있습니다.[외부 API 방식]장점: 인프라 관리 불필요, 최신 모델 즉시 사용 가능단점: 트래픽 비례 비용, 데이터가 외부로 전송됨[셀프호스팅 방식]장점: 데이터..

RAG를 활용한 LLM 서비스 구축

STEP 31 - RAG에서 민감정보 보호하기

개인정보(PII) 마스킹 처리 - RAG에서 민감정보 보호하기지난 글에서 문서의 만료와 폐기를 관리하는 라이프사이클 정책을 다뤘습니다. 이번 글에서는 운영·거버넌스 파트의 마지막 주제로, 문서 안에 포함된 개인정보(PII)가 검색과 답변 과정에서 그대로 노출되지 않도록 마스킹하는 방법을 정리합니다.1. RAG에서 PII 노출이 왜 특히 위험한가일반 DB 조회는 필요한 컬럼만 SELECT하면 되지만, RAG는 문서 청크 전체를 통째로 LLM에 넘기고, 그 내용이 그대로 답변에 녹아들 수 있습니다.문서 원본: "김철수(주민번호 900101-1******, 010-1234-5678)님은 2024년 3월 입사하여 개발팀에 배속되었습니다."질문: "개발팀에 언제 입사한 사람 있어?"LLM 답변: ..

성능 최적화

성능 최적화 STEP 32 - CQRS 패턴으로 명령과 조회의 책임 분리

성능 최적화 32편 - CQRS 패턴으로 명령과 조회의 책임 분리하기21편에서는 읽기 전용 Replica로 조회를 분리했고, 28편에서는 검색을 위해 Elasticsearch에 별도로 데이터를 동기화했습니다. 사실 이 둘은 모두 CQRS(Command Query Responsibility Segregation)라는 더 큰 개념의 부분적인 적용이었습니다. 이번 글에서는 이 패턴을 정식으로 정리하고, 언제 어디까지 적용해야 하는지를 다룹니다.1. CQRS란CQRS는 데이터를 변경하는 작업(Command)과 조회하는 작업(Query)을, 서로 다른 모델로 완전히 분리하는 패턴입니다.[기존 방식 - 하나의 모델]Order 엔티티 하나로 저장도 하고, 조회도 하고, 목록도 뽑고, 통계도 냄[CQRS - 모델 분리..

성능 최적화

성능 최적화 STEP 31 - Caffeine + Redis로 멀티 레벨 캐싱 구성하기

성능 최적화 31편 - Caffeine + Redis로 멀티 레벨 캐싱 구성하기3편에서 Redis로 캐싱 전략을, 14편에서 캐시 스탬피드 방지를 다뤘습니다. 그런데 아무리 Redis가 빨라도, 결국 네트워크를 한 번 거쳐야 합니다. 이번 글에서는 애플리케이션 서버 안에 로컬 캐시를 두고 Redis와 함께 계층화해서, Redis 조회조차 줄이는 멀티 레벨 캐싱을 정리합니다.1. Redis만으로도 부족할 수 있는 이유Redis 캐싱을 적용하면 DB 조회는 확실히 줄어들지만, 여전히 매 요청마다 네트워크를 통해 Redis에 접근해야 합니다.[DB 직접 조회] 평균 30ms[Redis 조회] 평균 1~2ms (네트워크 왕복 포함)[로컬 메모리 조회] 평균 0.01ms 이하숫자만 보면 Redis도 이미 ..

RAG를 활용한 LLM 서비스 구축

STEP 30 - 문서 라이프사이클 관리

문서 라이프사이클 관리 - 만료와 폐기 정책지난 글에서 재해 복구 전략을 다루며 원본 문서 보관의 중요성을 강조했습니다. 그런데 문서를 안전하게 보관하는 것 못지않게 중요한 문제가 하나 더 있습니다. 시간이 지나면서 더 이상 유효하지 않은 문서가 벡터 DB에 그대로 남아, 오히려 잘못된 답변의 원인이 되는 상황입니다. 이번 글에서는 문서의 만료와 폐기를 체계적으로 관리하는 방법을 정리합니다.1. 오래된 문서가 왜 문제가 되는가RAG는 검색된 문서를 그대로 근거 삼아 답변하는 구조이기 때문에, 폐기된 정책이나 만료된 규정이 벡터 DB에 남아있으면 그 내용을 그대로 사실처럼 답변에 포함시킵니다.질문: "재택근무는 몇 회까지 가능해?"벡터 DB에 남아있는 문서들:- (2023년 작성, 폐기됨) "재택근무는 주..

RAG를 활용한 LLM 서비스 구축

STEP 29 - RAG 시스템 재해 복구(DR) 전략

RAG 시스템 재해 복구(DR) 전략지난 글에서 벡터 DB를 파티셔닝과 샤딩으로 확장하는 방법을 다뤘습니다. 규모가 커진 시스템일수록 장애가 났을 때 피해도 커지기 마련입니다. 이번 글에서는 벡터 DB나 LLM API 제공사에 장애가 발생했을 때 RAG 서비스를 어떻게 지속시킬지, 재해 복구(DR) 전략을 정리합니다.1. RAG 시스템의 장애 지점은 어디인가지금까지 다룬 RAG 파이프라인을 장애 관점에서 다시 살펴보면, 장애가 날 수 있는 지점이 생각보다 여러 곳에 흩어져 있습니다.[문서 적재 경로]원본 문서 저장소 → 벡터 DB (pgvector)[질의응답 경로]임베딩 API → 벡터 DB → Reranker API → LLM API이 중 하나라도 장애가 나면 전체 답변이 실패할 수 있습니다. 특히 임..

성능 최적화

성능 최적화 STEP 30 - Transactional Outbox 패턴

성능 최적화 30편 - Transactional Outbox 패턴으로 이벤트 발행 신뢰성 확보하기29편에서 Saga 패턴을 다루며, 각 서비스가 로컬 트랜잭션을 커밋한 뒤 이벤트를 발행해 다음 단계로 넘어간다고 설명했습니다. 그런데 여기엔 숨겨진 문제가 하나 있습니다. DB 커밋과 이벤트 발행이 하나의 원자적 작업이 아니라는 점입니다. 이번 글에서는 이 문제(Dual Write Problem)와, 이를 해결하는 Transactional Outbox 패턴을 정리합니다.1. Dual Write Problem - 두 시스템에 동시에 쓸 수 없다11편에서 봤던 주문 완료 로직을 다시 보겠습니다.@Transactionalpublic void completeOrder(Long orderId) { Order o..

성능 최적화

성능 최적화 STEP 29 - Saga 패턴으로 트랜잭션 처리하기

성능 최적화 29편 - Saga 패턴으로 여러 서비스에 걸친 트랜잭션 처리하기11편 Kafka, 23편 서킷 브레이커, 28편 Elasticsearch 동기화까지, 시스템이 여러 서비스로 나뉜 구조를 계속 다뤄왔습니다. 그런데 정작 가장 근본적인 질문 하나를 남겨뒀습니다. 주문, 결제, 재고가 각각 다른 서비스와 다른 데이터베이스에 있다면, 하나의 트랜잭션으로 묶을 수 없는 이 작업들을 어떻게 안전하게 처리할까요? 이번 글에서는 이 문제를 푸는 Saga 패턴을 정리합니다.1. 단일 데이터베이스에서는 당연했던 것같은 데이터베이스 안에서는 @Transactional로 여러 작업을 하나로 묶고, 하나라도 실패하면 전부 롤백시킬 수 있었습니다.@Transactionalpublic void createOrder(..

Top 10 Story

데이터베이스

DATABASE SEMI PROJECT - MOVIE RANK DATA

★ MOVIE RANK DATA https://movie.naver.com/movie/sdb/rank/rmovie.naver 랭킹 : 네이버 영화 영화, 영화인, 예매, 박스오피스 랭킹 정보 제공 movie.naver.com 현재 네이버 영화에 있는 순위 목록을 크롤링 하여, 1. 개념적 모델링 2. 논리적 모델링 3. 물리적 모델링 4. DDL 생성 5. DML 생성 6. SELECT 검증 순으로 진행하였다. ■ STEP 1. 데이터 크롤링 현재 랭킹에 있는 정보와 영화 상세 정보들을 크롤링 하여 excel에 종합하였다. 컬럼은 총 21 컬럼으로, 1위 ~ 50위에 위치하는 영화들을 가져왔다. 1. 순위 2. 제목 3. 개봉년도 4. 관람객 평점 5. 평론가 평점 6. 네티즌 평점 7. 개요 8. 장르..

깃허브

깃허브 초기 셋팅하기

★ 깃(Git) 설치 먼저 설치하기 위해서 깃(Git) 홈페이지(https://git-scm.com/)에 들어가야 한다. 깃(Git) 홈페이지에 들어오시면 'Latest source Release'라는 부분에 'Download for Windows'를 클릭하셔서 설치할 수 있고, 설치 과정은 계속 다음(또는 Next)을 눌러주면 된다. 보통 윈도우 데스크탑 설치는 64-bit Git for Windows Setup을 설치하면 된다. 설치 완료 ★ 설치 완료 후 Git Bash를 클릭하여 실행한다. (!!사용자명과 이메일 주소는 깃허브의 등록사항과 같아야한다) git config -- global user.name "사용자명" git config --global user.email "아이디@이메일주소" g..

성능 최적화

성능 최적화 STEP 28 - Elasticsearch로 검색 성능 개선하기

성능 최적화 28편 - Elasticsearch로 검색 성능 개선하기5편에서 인덱스를 다루며 LIKE '%검색어%'처럼 앞쪽에 와일드카드가 붙는 검색은 일반 B-Tree 인덱스로는 처리할 수 없고, 검색 전용 엔진 도입을 고려해야 한다고 짚었습니다. 이번 글에서는 그 대안인 Elasticsearch를 도입해 검색 성능을 개선하는 방법을 정리합니다.1. RDB의 LIKE 검색이 느린 이유를 다시 보기select * from products where name like '%무선 이어폰%';%검색어% 형태는 인덱스를 활용하지 못해 테이블 전체를 훑는 풀 스캔이 발생합니다. 상품이 수백만 건이라면, 검색할 때마다 전체 테이블을 스캔해야 해서 응답 시간이 데이터량에 비례해 계속 느려집니다. 게다가 "무선이어폰"(..

RAG를 활용한 LLM 서비스 구축

STEP 15 - 임베딩 모델 교체 시 벡터 데이터 마이그레이션하기

임베딩 모델 교체 시 벡터 데이터 마이그레이션하기지난 글에서 RAG 챗봇에 캐싱과 비동기 처리를 적용해 트래픽에 대응하는 방법을 다뤘습니다. 서비스를 운영하다 보면 언젠가 한 번은 마주치는 이슈가 있습니다. 더 성능 좋은 임베딩 모델이 나오거나, 비용 절감을 위해 다른 모델로 바꿔야 할 때입니다. 이번 글에서는 임베딩 모델을 교체할 때 왜 기존 벡터를 그대로 쓸 수 없는지, 그리고 어떻게 안전하게 마이그레이션하는지 정리합니다.1. 왜 임베딩 모델을 바꾸면 벡터를 다시 만들어야 하는가임베딩은 모델마다 벡터 공간 자체가 다릅니다. 같은 문장이라도 모델이 다르면 완전히 다른 좌표에 매핑되기 때문에, 서로 다른 모델로 만든 벡터끼리는 비교 자체가 의미가 없습니다."재택근무는 주 2회까지 가능합니다"text-em..

RAG를 활용한 LLM 서비스 구축

STEP 13 - Spring Boot에 RAG 연동하기

Spring Boot에 RAG 연동하기 - 실전 서비스 아키텍처 설계지금까지는 Python 스크립트로 임베딩, 검색, LangChain 파이프라인을 실습했습니다. 하지만 실제 서비스는 백엔드가 Spring Boot로 돌아가는 경우가 많습니다. 이번 글에서는 지금까지 다룬 RAG 개념을 Spring Boot 서비스에 실제로 연동하는 아키텍처와 구현 방법을 정리합니다.1. 전체 아키텍처 그림RAG를 Spring Boot에 붙이면 다음과 같은 흐름으로 요청이 처리됩니다.[문서 적재 흐름]관리자 문서 업로드 API → DocumentService (청킹) → EmbeddingModel (임베딩 변환) → VectorStore (pgvector 테이블 저장)[질의응답 흐름]사용자 질문 API → ChatS..

RAG를 활용한 LLM 서비스 구축

STEP 11 - 답변 품질을 측정하는 방법

RAG 시스템 평가하기 - 답변 품질을 측정하는 방법지난 글에서 Reranking으로 검색 정확도를 끌어올리는 방법을 다뤘습니다. 그런데 검색과 답변 생성 단계를 아무리 잘 구축해도, "지금 이 RAG 시스템이 실제로 잘 동작하고 있는가"를 객관적으로 판단할 방법이 없다면 개선 방향을 잡기 어렵습니다. 이번 글에서는 RAG 시스템을 정량적으로 평가하는 방법을 정리합니다.1. 왜 RAG는 평가가 특히 어려운가일반적인 분류 모델은 "정답이 맞았는가 틀렸는가"로 명확하게 평가할 수 있습니다. 하지만 RAG는 평가해야 할 지점이 여러 단계로 나뉘어 있습니다.질문 → [검색 단계] 관련 문서를 잘 찾아왔는가? → [생성 단계] 찾아온 문서를 바탕으로 답변을 잘 만들었는가?검색은 잘했는데 답변 생성에서 문서..

RAG를 활용한 LLM 서비스 구축

STEP 5 - 벡터 DB의 필요성

벡터 유사도 검색은 어떻게 동작하는가 - 벡터 DB의 필요성지난 글에서 텍스트를 임베딩 벡터로 변환하고, 코사인 유사도로 두 벡터가 얼마나 비슷한지 계산할 수 있다는 걸 다뤘습니다. 이번 글에서는 이 유사도 계산을 실제 서비스 규모에서 어떻게 빠르게 수행하는지, 그리고 왜 벡터 DB라는 별도의 저장소가 필요한지 정리합니다.1. 문서가 적을 땐 그냥 다 비교하면 되지 않을까문서가 몇십 개 수준이면, 사용자 질문 벡터를 저장된 모든 문서 벡터와 하나씩 비교해도 문제가 없습니다.질문 벡터 vs 문서1 벡터 → 유사도 계산질문 벡터 vs 문서2 벡터 → 유사도 계산질문 벡터 vs 문서3 벡터 → 유사도 계산...→ 가장 높은 유사도 순으로 정렬이 방식을 Brute-force(전수 비교) 검색이라고 부릅니다. 문..

RAG를 활용한 LLM 서비스 구축

STEP 32 - 셀프호스팅 LLM으로 RAG 구축하기

셀프호스팅 LLM으로 RAG 구축하기 - vLLM과 Ollama지난 글까지 운영·거버넌스 파트를 마무리했습니다. 지금까지 다룬 모든 LLM 호출은 OpenAI 같은 외부 API를 전제로 했습니다. 이번 글부터는 LLM 인프라 심화 파트로 넘어가서, 외부 API 대신 LLM을 직접 서버에 올려 운영하는 셀프호스팅 방식을 다룹니다.1. 왜 셀프호스팅을 고려하게 되는가지난 비용 모니터링 글에서 다룬 것처럼, 트래픽이 늘어날수록 외부 API 비용은 계속 누적됩니다. 또한 보안이 중요한 도메인에서는 문서와 질문이 외부 서버로 나가는 것 자체가 부담일 수 있습니다.[외부 API 방식]장점: 인프라 관리 불필요, 최신 모델 즉시 사용 가능단점: 트래픽 비례 비용, 데이터가 외부로 전송됨[셀프호스팅 방식]장점: 데이터..

RAG를 활용한 LLM 서비스 구축

STEP 18 - 권한 기반 RAG 접근 제어

권한 기반 RAG 접근 제어 - 사용자마다 다른 문서만 검색되게 하기지난 글에서 멀티턴 대화형 RAG를 구현하면서, 다음 주제로 권한에 따라 검색 대상을 제한하는 접근 제어를 예고했습니다. 실제 사내 챗봇이나 멀티테넌트 서비스에서는 모든 사용자가 모든 문서에 접근해서는 안 되는 경우가 많습니다. 이번 글에서는 RAG 검색 단계에 권한 필터링을 적용하는 방법을 정리합니다.1. 왜 RAG에서 접근 제어가 특히 중요한가일반적인 API는 데이터를 조회할 때 WHERE 절 하나로 권한을 걸면 되지만, RAG는 벡터 검색을 거쳐 문서 내용이 그대로 LLM 프롬프트에 들어가고, 그 내용이 답변에 노출됩니다. 권한 필터링을 빠뜨리면 검색 결과뿐 아니라 최종 답변에까지 남의 정보가 그대로 새어나갈 수 있습니다.[권한 필..

RAG를 활용한 LLM 서비스 구축

STEP 10 - 검색 정확도를 높이는 방법

검색 정확도를 더 높이는 방법 - Reranking지난 글에서 LangChain으로 RAG 파이프라인을 처음부터 끝까지 구축해봤습니다. 그런데 실제로 서비스를 운영하다 보면, 벡터 검색만으로는 항상 "가장 적절한" 문서가 상위에 오지는 않는다는 걸 발견하게 됩니다. 이번 글에서는 이 문제를 보완하는 Reranking(재정렬) 기법을 정리합니다.1. 벡터 검색만으로 충분하지 않은 이유벡터 검색은 코사인 유사도라는 하나의 기준으로만 문서를 정렬합니다. 그런데 유사도가 높다고 해서 항상 질문에 가장 적합한 답인 것은 아닙니다.질문: "재택근무 승인은 누가 하나요?"벡터 검색 결과 (유사도 순)1위 (0.81) "재택근무는 팀장 승인 하에 주 2회까지 가능합니다."2위 (0.79) "재택근무 신청은 인사 시스템..

IT의 큰손
Developer Story House