앞의 장들에서 우리는 Haystack과 Python 기반의 지능형 애플리케이션을 보았다. Python이 데이터 과학자들의 총애를 받는 언어 프레임워크인 것은 사실이지만, 해법을 짓는 데 다른 프레임워크가 필요한 시나리오도 있다. 떠오르는 또 하나의 대중적 언어 프레임워크가 Java다. Java는 Python보다 빠르고, 다양한 데이터 소스와의 통합을 매끄럽게 제공하며, Spring Framework와 함께 웹 기반 애플리케이션을 짓는 데 가장 많이 쓰이는 언어다. 이 목적을 위해, 이어지는 몇 장에 걸쳐 LLM과 Neo4j에 기초한 지능형 애플리케이션을 짓는 방법을 본다.
또 하나. 지금까지 우리는 지능형 검색 애플리케이션을 짓는 데 LLM의 능력을 활용하는 일에 집중해 왔다. 그러나 그것은 한 측면일 뿐이다. LLM은 더 나은 추천 시스템에 동력을 공급하는 지식그래프의 구축과 활용에서도 훌륭한 도구가 될 수 있다. 이 장에서 우리는 추천 시스템이 무엇이고 개인화된 추천이 왜 중요한지 이해한다. 추천 시스템의 전통적 규칙 기반 접근을 간략히 짚고 그 결함도 이야기한다. 그런 다음 LangChain4j와 Spring AI 프레임워크를, 그리고 이들이 지능형 추천 시스템 구축을 어떻게 뒷받침하는지를 소개한다.
기술 요건
이 장은 개인화된 추천에 집중하고 LangChain4j·Spring AI 프레임워크를 소개하는 장이므로, 특별한 기술 요건은 없다. 다만 Spring 애플리케이션이 처음이라면 Spring Boot 가이드로 몸을 풀어 둘 수 있다. 이어지는 장들에서 내장 웹 프레임워크를 갖춘 Spring Boot 애플리케이션을 쓸 것이기 때문이다. 시스템에 Java도 설치되어 있어야 하며, 다가올 장들을 위해서는 Java 17 또는 19를 권장한다.
(:Section {n: 1})-[:EXTENDS]->(:Capability)
지능형 애플리케이션을 위한 Neo4j의 확장 능력
이전 장들에서 우리는 좋은 검색 애플리케이션을 짓는 데 LLM과 Neo4j를 썼다. 지식그래프가 지능형 검색 애플리케이션에 훌륭한 문맥을 제공하는 것은 사실이지만, 그것은 개인화된 추천 애플리케이션의 위대한 토대이기도 하다. 데이터에서 지능을 추출하고, 기본적인 흐름 기반 분석을 넘어서는 더 낫고 더 지능적인 애플리케이션을 지으려면, 그래프 데이터베이스의 능력 그 이상이 필요하다. 데이터베이스로서 Neo4j의 능력들이 더 나은 애플리케이션 구축을 돕는 지점이 바로 여기다. 그 능력들의 일부를 나열하면 이렇다.
- 확장성Neo4j는 샤딩(sharding)으로 연합 그래프(federated graph)를 구성해 대규모 데이터셋을 감당하는 큰 그래프를 짓게 해 준다. 비용을 최소화하면서 데이터 성장과 비즈니스 요구에 맞춰 확장된다. 복합 데이터베이스 문서에서 더 읽을 수 있다.
- 보안Neo4j는 역할(role)을 지렛대 삼아 데이터 보안을 가능케 한다. 누가 데이터베이스를 읽고 쓸 수 있는지 같은 상위 수준의 보안 역할이 있고, 역할에 기초해 어떤 데이터를 읽을 수 있는지 정의하는 더 세밀한 보안 제어도 제공한다. 이 접근으로, 배정된 역할에 따라 한 사용자는 그래프의 이쪽을, 다른 사용자는 저쪽을 보게 만들 수 있다. 인증·인가 문서에서 더 읽는다.
- 유연한 배포 아키텍처Neo4j의 클러스터링 아키텍처는 수평 확장으로 더 많은 읽기 볼륨을 감당하고, 읽기를 서버별로 지역화해 데이터가 자라도 소유 비용을 최소화하는 여러 배포 옵션을 제공한다. 클러스터링 소개를 참고한다.
- GDS 알고리즘Neo4j Graph Data Science 알고리즘은 연결된 데이터에서 숨은 통찰을 풀어낸다. 경로 탐색, 노드 유사도, 중심성(centrality), 커뮤니티 탐지부터 링크 예측·노드 분류 같은 기계학습 측면까지 아우른다. GDS 문서에서 더 읽는다.
- 벡터 인덱스Neo4j는 임베딩을 인덱싱해 유사 노드를 조회하고, 이어서 그래프 순회를 활용해 더 정확한 결과를 제공하는 벡터 인덱스 능력을 갖췄다. 벡터 인덱스 문서를 참고한다.
그래프 데이터베이스로서 Neo4j는 연결된 데이터와의 작업을 쉽게 만들며, 위의 능력들은 연결된 데이터 너머로 나아가 확장 가능하고 복잡한 지능형 애플리케이션을 짓도록 우리를 돕는다.
검색 시스템과 추천 시스템의 차이를 더 읽고 싶다면 다음 글들이 도움이 된다.
What's the difference between search and recommendation · How are search and recommendations the same, and how are they different?
다가오는 장들에서 우리는 이 Neo4j 능력들을 활용해 지능형 추천 시스템을 짓는다. 그 전에, 추천 엔진이 무엇이고 개인화가 지능형 추천 시스템 창조를 어떻게 도울 수 있는지부터 논하자.
(:Section {n: 2})-[:PERSONALIZES]->(:Recommendation)
추천의 개인화
추천 시스템(recommendation system)은 사용자의 구매·검색 선호에 기초해 상품을 추천하는 애플리케이션이다. 이 개념은 상품 배치에 국한되지 않는다. 의료 진단과 치료에서도 쓰인다. 환자가 약물에 어떻게 반응하는지, 어떤 치료 순서가 더 효과적인지 이해하는 데 추천이 도움을 주는 식이다. 데이터가 자라고 구할 수 있는 상품의 수가 늘수록, 사용자 행동을 이해하고 가장 개인적인 추천을 제공하는 능력은 점점 더 중요해진다. 개인화된 경험을 짓는 데 쓸 수 있는 전략들이 있다.
사용자 프로필 구축
사용자 행동을 이해해 맞춤 프로필을 만든다. 행동 패턴에는 일정 기간 사용자가 수행한 거래의 순서나 발생한 이벤트의 결과가, 나이·인종·성별 같은 다른 속성과 함께 포함될 수 있다. 이 측면들로 사용자를 여러 그룹으로 분할(segment)하고 그룹별 프로필을 만든다.
맥락적 지원 제공
프로필이 갖춰지면 더 의미 있고 맥락적인 지원이 가능해진다. 마지막으로 산 상품에 기초한 구매 추천일 수도, 현재 치료 수준과 증상에 기초한 다음 약물 추천일 수도 있다. 마지막 이벤트만이 아니라 다른 사용자 속성까지 고려해 더 직접적인 지원을 제공한다.
셀프서비스 경험 제공
필요할 때의 맥락적 지원과 더불어, 추천을 이용해 더 만족스러운 셀프서비스 경험도 제공할 수 있다. 사용자가 추천에 고려될 특성들을 직접 바꿀 수 있어야 한다. 이벤트에 대한 반응 방식이 사용자에 맞게 조정되는 시스템이 되는 것이다.
피드백의 통합
앞의 전략들을 모두 이용하면 긍정적·부정적 피드백 양쪽을 통합할 수 있다. 시스템이 개별 사용자의 요구에 필요한 만큼 적응하게 된다.
개인화된 추천의 이점은 무수하다. 현재 보고 있는 것에 기초해 다음 상품을 제안하고, 사용자 행동에 기초해 인센티브를 제공하고, 브랜드 평판을 끌어올리고, 환자의 치료 요법을 최적화하고, 신약을 더 효율적으로 마케팅하고, 공급망 프로세스를 개선하고, 최적의 배송 경로를 결정한다. 이 맞춤 제안들은 기업이 고객에게 더 적절하고 강렬한 경험을 배달하게 해 준다. 추천 시스템의 다른 흥미로운 용례로는 매출 신장, 공급망 관리, 환자 여정 매핑이 있다.
이제 추천 시스템의 전통적 규칙 기반 접근을, 그리고 그것이 왜 지능적이고 개인화된 추천 시스템을 짓기에 충분치 않은지를 살펴본다.
전통적 접근의 한계
전통적으로 추천 시스템은 규칙 기반 시스템(rule-based system)을 썼다. 주어진 데이터 입력에 기초해 일련의 규칙을 실행함으로써 결정을 내리는 시스템이다. 논리는 단순할 수도, 필요에 따라 매우 복잡할 수도 있다. 특정 지역에서 1,000달러를 넘는 신용카드 거래는 자동으로 거절된다는 규칙이 단순한 예라면, 작은 거래가 성공한 직후 더 큰 거래가 시도될 때 거절한다는 규칙은 조금 더 복잡한 예다. 규칙 기반 시스템이 적용하는 규칙은 대개 두 종류다. 정적 규칙(static rule)은 수동으로 구성된다. 일단 자리 잡으면 매우 효율적으로 작동하고 시스템은 그것을 충실히 실행한다. 최소한의 자원으로 빠른 응답이 필요할 때 좋고, 입력에 따라 값을 돌려주는 case 문처럼 단순할 수 있다. 동적 규칙(dynamic rule)은 정교한 규칙 엔진이다. 다음 결정이 현재 결정 트리가 놓인 상태와 다음 데이터 입력에 의존하는 시나리오다.
- 일관성 — 행동이 한결같아, 주어진 입력에 대해 같은 출력을 보장한다.
- 확장 — 데이터와 복잡성을 수월하게 감당하며 매우 잘 확장된다.
- 효율 — 소모 자원과 시스템 비용의 측면에서 매우 효율적이다.
- 유지·관리 — 짓고 유지하기 쉬우며, 그 덕분에 관리도 쉽다.
- 복잡성 — 올바르게 다루지 않으면 비즈니스 요구가 늘어남에 따라 꽤 복잡해질 수 있다. 복잡성이 더해지면 대부분의 이점이 서서히 사라지기 시작한다.
- 완고함 — 새로운 유형의 데이터와 시나리오에 적응하기에 시스템이 너무 경직되어 있다. 새 시나리오를 식별해도, 코딩과 구성에 시간이 너무 걸려 효과를 보지 못할 수 있다.
- 비즈니스 적응성 — 자라나는 비즈니스 요구와 요건에 시스템을 적응시키는 데 지나치게 많은 노력이 들 수 있다.
규칙 기반 시스템의 전형적 용례는 사기 방지와 사이버보안이다. 단순하고 짓기 쉬운 시스템이지만, 보다시피 비즈니스 요구가 진화하면 규칙 기반 시스템에 기대는 우리는 제한된 선택지에 갇힌다. 새로운 데이터 포인트와 데이터 복잡성에 적응해 좋은 추천을 위한 더 나은 문맥을 제공하는 지능형 애플리케이션의 구축이 그만큼 더 중요해진다. 변하는 환경과 데이터, 새 요건에 빠르게 적응하는 시스템이어야 한다. 그래프 데이터베이스로서의 Neo4j와 그 주변 기술 스택이 지능형 추천 시스템 구축을 돕는 지점이 바로 여기다. 어떻게 돕는지 알아보자.
(:Section {n: 3})-[:INTRODUCES]->(:JavaFramework)
Neo4j의 LangChain4j와 Spring AI 프레임워크
지능형 애플리케이션을 지으려면 Neo4j 주변에서 구할 수 있는 여러 프레임워크를 활용할 수 있다. 지능형 추천 시스템이라는 특정 용례를 위해, 우리는 Java 프레임워크인 Spring AI와 LangChain4j를 들여다본다.
LangChain4j
Python의 인기 프레임워크 LangChain에서 영감을 받아, Java로 LLM 애플리케이션을 짓는 프레임워크. LLM API의 Java 통합을 단순화하는 것이 목표이며, LangChain·Haystack·LlamaIndex 등의 개념을 혼합한 API에 자신만의 맛을 더해 복잡한 애플리케이션을 짓는다.
- 통합 API — OpenAI, Google Gemini 같은 LLM 제공자들은 저마다 독자적 API를 가진다. Neo4j·Pinecone·Milvus 같은 벡터 스토어도 임베딩 저장·검색을 위한 자체 API를 제공한다. LangChain4j는 이 모든 API의 복잡성을 감추는 통합 API로 개발을 쉽게 만든다.
- 포괄적 툴박스 — LangChain 커뮤니티가 식별해 온 다양한 패턴·추상화·기법이 바로 쓸 수 있는 패키지로 담겨 개발을 급가속한다. 저수준 프롬프트 템플릿, 채팅 메모리 관리, AI 서비스, RAG의 예제들이 들어 있고, 대부분 다른 애플리케이션에 쉽게 통합된다.
- 15개 이상의 LLM 제공자 — 단순한 API로 LLM 제공자를 애플리케이션에 통합해 쉽게 쓴다 (언어 모델 통합).
- 20개 이상의 벡터 스토어 — 생성된 임베딩을 저장하고 질의하는 벡터 스토어 API를 제공한다 (임베딩 스토어).
- AI 서비스 — LLM 제공자·벡터 스토어와 직접 상호작용하는 저수준 API가 일부 시나리오에는 너무 낮을 수 있어, LLM·벡터 스토어·임베딩 모델·RAG를 하나의 파이프라인으로 통합하는 고수준 API 흐름도 제공한다. AI Services라 불리며, 다가올 장들에서 사용한다.
- RAG — RAG의 인덱싱 단계와 검색 단계를 모두 지원하고, RAG 기능을 쉽게 시작하게 하는 Easy RAG 기능이 있다 (RAG 튜토리얼).
Spring AI
LangChain4j와 LlamaIndex에서 영감을 받았다. LangChain4j가 단순 Java 애플리케이션과 Spring 애플리케이션을 함께 지원한다면, Spring AI는 Spring Framework와의 작동에 최적화되어 있다. Spring에 정통한 사람이라면 LLM 애플리케이션을 더 빠르고 쉽게 개발할 수 있다는 뜻이다.
- 왜 유리한가 — Spring Framework는 다양한 데이터베이스에 접속하는 여러 모듈과, 수많은 개발자가 쓰는 잘 정의된 코딩 패턴을 제공한다. 이 새 기능 덕분에 개발자들이 AI 애플리케이션을 빠르게 채택하고 짓기가 매우 쉬워진다.
- LLM 프롬프트 템플릿 — LLM을 쉽게 통합하는 단순한 API를 제공한다.
- 임베딩 모델 — 구성(configuration)만으로 다양한 임베딩 모델 엔진을 통합해 벡터 임베딩을 생성한다.
- 벡터 스토어 — 벡터 스토어의 저장·질의를 위한 단순한 API를 제공하며, Neo4j·Pinecone·Milvus 같은 다양한 벡터 스토어에 구성 기반으로 쉽게 접속한다.
- RAG — LLM 프롬프트 템플릿, 임베딩 모델, 벡터 스토어를 사슬로 엮어(chain) 효과적인 RAG 애플리케이션을 지을 수 있다.
LangChain4j와 Spring AI 두 프레임워크 모두 LLM 채팅 모델, 프롬프트 템플릿, 임베딩 모델, 벡터 스토어와 통합하는 핵심 API를 제공한다. 그 시스템들과 대화하는 저수준 API에 더해, RAG 프레임워크 API 같은 고수준 API로 더 정교한 애플리케이션의 구축도 쉽게 만든다.
왜 Java 기반 프레임워크인가
Neo4j와 함께 일할 수 있는 Python 프레임워크는 많다. 그러나 Java 프레임워크를 쓰는 애플리케이션도 많다. 이 프레임워크들은 다양한 데이터 소스에 접속하는 수단을 제공하고, 복잡한 애플리케이션을 짓는 데 쓸 수 있는 다양한 패키지를 지렛대 삼는다.
이 프레임워크들은 Neo4j 같은 다양한 벡터 스토어와, Amazon Bedrock, Azure OpenAI, Google Gemini, Hugging Face, OpenAI 같은 복수의 LLM 제공자를 지원한다. LLM을 위한 입력 포매팅과 출력 파싱 같은 단순한 과업부터 채팅 메모리, 도구(tools), RAG 같은 더 복잡한 기능까지, 고수준 AI 능력을 제공한다. 이 능력들을 Neo4j와 결합하면 더 복잡한 애플리케이션을 짓기가 쉬워진다. LLM으로 그래프 특징(경로 등)의 임베딩을 생성하고, 그것을 유사도·커뮤니티 탐지 알고리즘으로 노드를 세그먼트로 묶는 그래프 강화의 기초로 삼는 식이다. 이 세분화(segmentation)가 다음 수준의 추천과 여타 측면의 토대가 된다. Neo4j의 GenAI 생태계는 neo4j.com/labs/genai-ecosystem에서 더 읽을 수 있다.
(:Section {n: 4})-[:ARCHITECTS]->(:GraphRAG)
Neo4j GenAI 생태계 속 지능형 추천 시스템의 조감
LLM/RAG 원리 위에 지어진 추천 시스템이 Neo4j GenAI 생태계 안에서 어떻게 작동하는지 보자(그림 7.1).
이 프레임워크들의 기능을 지렛대 삼아 지식그래프가 뒷받침하는 RAG 애플리케이션을 지을 수 있다. 이 아키텍처에서 우리는 Spring AI 앱으로 그래프를 증강해 더 개인적인 추천을 제공할 수 있게 만든다.
또한 RAG를 위해 이 아키텍처는 벡터 인덱스와 그래프 순회를 함께 활용해 응답을 증강할 수 있다. 두 세계의 최선을 취해 더 정확한 응답을 얻는 것이다. 이 개념이 Graph RAG다. 지식그래프는 AI 모델 상호작용에 더 정확한 응답, 풍부한 문맥, 그리고 설명 가능성(explainability)을 가져다준다. Neo4j는 LangChain4j와 Spring AI에 통합되어 벡터 스토어이자 그래프 데이터베이스로서 LLM 응답을 증강할 수 있다.
요약
이 장에서 우리는 지능형 애플리케이션 구축을 돕는 Neo4j의 능력들을 보았고, 이 애플리케이션들이 제공하는 개인화가 왜 유용한지, 기존의 규칙 기반 애플리케이션과 어떻게 다른지를 살폈다. Spring AI와 LangChain4j가 무엇이고, 지능형 애플리케이션을 짓는 그들의 능력이 무엇인지도 들여다보았다.
다음 장인 8장에서는 H&M 데이터셋으로 지능적이고 개인화된 추천을 지원하는 그래프 데이터 모델을 만들고, 추천 제공을 목표로 이 데이터를 그래프 데이터 모델에 적재하는 방법을 본다. 이 책의 9장은 이 지능형 추천 시스템을 Spring AI·LangChain4j 프레임워크와 통합할 수 있게 해 줄 것이다.