서론지난 시간에는 커스텀 커맨드를 만들어 claude.md 문서 최신 동기화 등 다양한 일들을 커맨드 하나로 할 수 있게끔 설정하였다. 또한, 구현, 테스트, 리뷰, 외부 API 이용약관을 감사하는 서브 에이전트들을 만들어 프로젝트에 적용하였다. 이번 포스팅에서는 이 서브 에이전트들을 총 관리 감독하여 병렬적으로 작업을 수행시킬 수 있게 하는 오케스트레이터라는 것을 적용해본 과정을 정리하고자 한다.오케스트레이터란?오케스트레이터는 중앙 LLM이 하나의 거대한 작업을 여러 개의 작은 작업으로 쪼갠 뒤, 워커(서브 에이전트)들에게 위임하고 결과를 종합한다. 이때 각각의 AI 서브 에이전트들에게 역할을 부여하고 병렬적으로 처리하게 할 수 있다. 역할 분담 및 지휘: 메인 오케스트레이터가 전체 프로젝트의 방향을..
전체 글
클로드 코드를 쓰다 보니.. 항상 Claude.md에 규칙 등 현황들만 적어놓고, 서브 에이전트니 오케스트레이터니 그런 것들을 활용해본 적이 없다. 최근 개인 사이드 프로젝트를 하면서 이것저것 할게 많아지다보니 이번 기회에 클로드 코드의 다양한 기능들을 활용하여 생산성을 극대화해보려고 한다. 커스텀 Command 만들기 https://code.claude.com/docs/en/commands Commands - Claude Code DocsComplete reference for commands available in Claude Code, including built-in commands and bundled skills.code.claude.com 클로드 코드의 Command 기능을 통해 세션 내..
서론앞선 글에서 우리는 좋아요 API 요청 -> 이벤트 -> Redis Stream -> Consumer -> ZINCRBY 파이프라인을 완성하였다. 이제 좋아요 토글 API를 요청하게 되면 인기 점수가 +1이 되거나 -1이 될 수 있다. 그런데 여기서 한 가지 문제점이 있는데, Redis Stream(Consumer Group)은 정확히 한 번(exactly-once)이 아니라 적어도 한 번(at-least-once) 발송을 보장한다는 것이다. 이는 즉, 같은 이벤트가 두 번이나 발송될 수 있다는 점이다. 문제는 우리 집계 연산이 ZINCRBY, "이전 값에 더하는" 비멱등 연산이라는 점이다. 좋아요 한 번인데 이벤트가 두 번 처리되면 점수는 +2가 되고, 랭킹이 실제보다 뻥튀기되는 현상이 발생할 ..
서론앞서 엘라스틱 서치를 적용하여 실시간 인기 검색어 조회 기능까지 구현해보았다.이번 포스팅에서는 자동 완성을 어떻게 구현하는지에 대해 정리해보려고 한다. 검색 자동 완성 구현하기현재 엘라스틱 서치 레포지토리의 쿼리문에서 쓰는 multi_match는 단어 단위 매칭이다. 재즈라고 다 쳐야 "재즈 명반"이라는 검색 결과값이 나온다. 자동완성은 재, 재즈, 재즈 처럼 글자를 치는 도중(prefix) 마다 결과가 나와야 하는데, 일반 텍스트 분석은 "재"라는 조각을 색인해두지 않아서 잡히지 않는다. 방법은 접두어 조각(prefix)을 미리 색인해두는 것이라고 하는데, 엘라스틱 서치 8.x 기준 가장 간단하고 한글에도 무난한search_as_you_type 필드 타입을 쓴다고 한다. 이 타입은 색인 시 ..
서론지금까지 만든 것을 쭉 이으면 다음과 같다.ElasticSearch 환경 설정 -> VinylDocument(색인 설계) -> 동기화 전략(Postgres->엘라스틱 서치) 이번 포스팅에서는 본격적으로 ElasticSearch 검색 기능 구현에 대해 정리해보고자 한다. VinylElasticSearchRepository 만들기 엘라스틱 서치도 JPA 방식(JpaRepository)과 마찬가지로 ElasticSearchRepository를 상속하면 기본 CRUD(save, findById, deleteById 등)을 자동으로 얻고, 검색 전용 커스텀 메서드를 추가할 수 있는 구조이다. 아래와 같이 searchByKeyword라는 메서드를 query 어노테이션과 함께 정의했다. public interf..
서론지난 포스팅에서는 엘라스틱 서치와 노리 한국어 형태소 분석기를 설치하고 환경 설정을 마쳤다. 이번 포스팅에서는 인덱스 문서를 통해 검색에 필요한 필드만 색인하도록 처리하는 과정을 정리해보고자 한다. Nori 분석기 설정ES의 기본 standard analyzer는 공백/구두점 기준으로만 토큰을 나누기에 조사가 붙은 형태로 검색하면 한국어 형태소 분석 기능이 없기에 검색 정확도가 떨어진다. 이를 해결하기 위해 nori_tokenizer를 커스텀 analyzer(korean)로 등록해준다. vinyl-settings.jsonSpring Data Elasticsearch에서 @Setting 어노테이션에 인라인으로 설정을 넣을 수도 있지만, analyzer 정의가 늘어나면(동의어 필터, 다른 언어별 ana..
도입 배경Vinyler는 Discogs API 기반의 LP 음반 소셜 플랫폼으로, 사용자가 좋아하는 음반을 찜하고 감상 기록을 남기고 리뷰를 작성하며 유저 간 음악 취향을 공유할 수 있는 서비스이다. 음반 검색 자체는 이미 Discogs API가 제공하고 있어서, 모바일 앱 쪽에서 자체적으로 Discogs API를 호출하여 검색할 수 있다. 하지만 Discogs 검색은 어디까지나 "카탈로그 메타데이터" 검색일 뿐, Vinyler 위에서 쌓인 소셜 데이터 : 몇 명이 찜했는지, 리뷰가 몇 개 달렸는지, 지금 사용자들이 어떤 음반을 많이 찾고 있는지는 전혀 반영하지 못하고 있다. 즉 "찜 많은 순", "리뷰 많은 순" 정렬이나 "실시간 인기 검색어" 같은 기능은 Discogs API로는 원천적으로 구현이 불..
서론최근에 기술면접을 보다가 포트폴리오에 기재해둔 Auto Scaling 구성 관련 내용에서 '무상태성'에 대해 설명해달라는 질문을 받게되었다. 어떠한 개념이 흐릿하게 떠올랐으나, 표현의 한계로 인해 뜸 들이다가 "잘 모르겠다. 더 공부해보겠습니다."라는 답변을 드렸다. 무지함을 반성하는 의미에서 이번 포스팅에서는 '무상태성'이라는 개념에 대해 정리해보고자 한다. 본론무상태성이란? 무상태성이란 서버가 클라이언트의 이전 요청 상태(세션, 로그인 정보 등)를 서버 내부 메모리 등에저장하지 않는 설계 방식을 의미한다. 즉, "각각의 요청은 독립적이며, 서버는 요청을 처리하는 데 필요한 모든 정보를 요청 메시지 그 자체나 외부 저장소(Redis, DB)에서 가져와야 한다"는 원칙이다. Stateful (상태 ..