5.x에서 2026.xx로: 왜 버전 체계를 바꿨나
Neo4j는 2026년부터 캘린더 버전(Calendar Versioning, CalVer)으로 전환했다. 2026년 1월부터 2026.01.0, 2026.02.0 형식을 사용한다. 7월 2일 공개된 2026.06.0이 이 글 작성 시점의 최신 버전이다.
시맨틱 버저닝(SemVer)에서 CalVer로의 전환은 단순한 숫자 변경이 아니다. SemVer에서 메이저 버전 번호(5.x)는 이론적으로 하위 호환성 단절을 의미한다. 실제로 Neo4j 5.x 계열은 5.1부터 5.26까지 이어지며 호환성 관리가 복잡해졌다.
CalVer는 릴리스 시점을 버전 번호에 내장한다. 2026.06.0은 "2026년 6번째 릴리스"다. 운영자 입장에서의 실질적 변화:
- 업그레이드 주기 예측 가능: 매달 한 번 릴리스가 원칙이므로, 패치 일정을 사전에 수립할 수 있다.
- LTS 구분 명확화: Neo4j 5.26은 2028년 6월까지 지원되는 LTS 버전으로 유지된다. 새 CalVer 라인에서도 주기적으로 LTS를 지정할 예정이다.
- 드라이버 호환성 주의:
2026.xx시리즈는 Java 드라이버 6.x 이상을 권장한다. 기존 드라이버 4.x 이하와의 호환성이 종료됐다.
2026.05.0과 2026.06.0의 핵심 변화
두 릴리스는 큰 방향에서 일관된 흐름을 갖는다. 그래프 DB의 AI 실용화다. 벡터 검색 성능 강화, 생성형 AI와의 Cypher 통합, 대규모 임포트 안정성 개선이 주요 축이다.
벡터 인덱스: 바이너리 양자화 GA
Neo4j 2026.05.0에서 이진 양자화(Binary Quantization, BQ)가 정식 출시(GA)됐다. 이전에는 스칼라 양자화(Scalar Quantization, SQ)만 GA였다.
양자화 종류와 트레이드오프
| 설정 | 방식 | 메모리 절감 | 리콜(Recall) | 적합한 용도 |
|---|---|---|---|---|
NONE | 원본 FP32/FP64 보관 | 기준 (1×) | 최대 | 소규모 고정밀 검색 |
SCALAR (기본값) | INT8 근사 변환 | ~4× | 높음 | 범용 프로덕션 |
BINARY | 부호 비트만 보관 | ~32× | 중간 | 대규모 후보 필터링 |
-- 새 인덱스 생성 시 양자화 방식 지정
CREATE VECTOR INDEX movieEmbeddings
FOR (m:Movie) ON (m.embedding)
OPTIONS {
indexConfig: {
`vector.dimensions`: 1536,
`vector.similarity_function`: 'cosine',
`vector.quantization.type`: 'BINARY'
}
}Hi-Fidelity Quantization(HFQ) 프리뷰 (2026.06.0)
BQ는 메모리를 극도로 절약하지만 리콜이 저하된다. HFQ는 이 문제를 2단계 검색으로 해결한다.
- 후보 검색 단계: 바이너리 양자화 벡터로 빠르게 상위 N개 후보를 찾는다.
- 재순위 단계: 후보 N개에 대해 원본 전정밀도(full-precision) 벡터로 점수를 재계산해 최종 k개를 반환한다.
이 방식은 BQ의 메모리 효율과 원본 정밀도 검색 품질을 동시에 추구한다. 설정은 vector.default_search_expansion_factor로 확장 배수를 제어한다. BINARY 기본값은 2.0이며, SCALAR는 1.5, NONE은 1.0이다.
GenAI Cypher 함수: 그래프 DB에서 직접 LLM을 호출하다
2026.05.0에서 추가된 GenAI 함수들은 Neo4j를 외부 AI 파이프라인 없이도 RAG 워크플로우를 완성할 수 있는 환경으로 바꾼다.
텍스트 청킹과 토큰 계산
-- 대용량 문서를 LLM 컨텍스트 한도에 맞게 청크 분리
MATCH (d:Document)
WITH d,
ai.text.chunkByTokenLimit(d.content, 512, {model: 'gpt-4o-mini'}) AS chunks
UNWIND chunks AS chunk
CREATE (c:Chunk {text: chunk, documentId: d.id})
CREATE (d)-[:HAS_CHUNK]->(c)ai.text.chunkByTokenLimit(text, limit, config): 텍스트를 토큰 한도에 맞게 분리한다. 자연 경계(줄바꿈 → 공백 순서)를 우선 사용해 청크를 만든다.
ai.text.countToken(text, config): 텍스트의 토큰 수를 반환한다. LLM 비용 사전 추정, 컨텍스트 한도 초과 여부 체크에 사용한다.
구조화 출력 생성
-- 노드 속성에서 LLM으로 구조화 정보 추출
MATCH (a:Article)
WHERE a.summary IS NULL
WITH a,
ai.text.aggregateStructuredCompletion(
collect(a.content),
"이 기사들의 핵심 주제와 감정 분석을 JSON으로 반환하세요",
{schema: {topics: "string[]", sentiment: "string"}},
{model: 'gpt-4o-mini'}
) AS analysis
SET a.summary = analysis.topics[0],
a.sentiment = analysis.sentimentai.text.aggregateCompletion(): 여러 텍스트를 하나의 LLM 호출로 집계한다. ai.text.aggregateStructuredCompletion(): 집계 결과를 스키마에 맞는 구조화 JSON으로 반환한다.
GenAI 함수의 운영 고려사항
- 외부 API 비용: 각 함수 호출은 설정된 LLM 제공자에게 API 요청을 발생시킨다. 쿼리 볼륨이 클 때 예기치 않은 비용이 생길 수 있다.
- 지연 증가: LLM API 호출 지연(수백 ms~수 초)이 Cypher 쿼리 전체 지연에 추가된다. 프로덕션 경로에서는 배치 사전 처리를 권장한다.
- 네트워크 격리 환경: 온프레미스 배포에서 외부 LLM API 접근이 차단된 경우 로컬 모델 엔드포인트(Ollama, LM Studio)를 설정할 수 있다.
DISJOINT BY: 병렬 임포트의 데드락 방지
대량 데이터 임포트에서 CALL {} IN CONCURRENT TRANSACTIONS는 성능상 유리하지만, 여러 트랜잭션이 같은 노드를 동시에 수정하면 데드락이 발생한다. 특히 관계(Relationship) 임포트 시 양쪽 끝 노드를 잠그는 순서가 달라질 때 생긴다.
2026.05.0에서 실험적(experimental)으로, 2026.06.0에서 GA로 출시된 DISJOINT BY 절이 이 문제를 해결한다.
세 가지 사용 방식
-- 1. 명시적 선언: 이 컬럼 값으로 배치를 분리
CALL {
WITH row
MATCH (a:Person {id: row.from}), (b:Person {id: row.to})
CREATE (a)-[:KNOWS]->(b)
} IN CONCURRENT TRANSACTIONS OF 1000 ROWS
DISJOINT BY (row.from, row.to)
-- 2. 자동 추론: 실행 계획을 분석해 충돌 방지 기준 자동 결정
CALL {
WITH row
MATCH (a:Person {id: row.from}), (b:Person {id: row.to})
CREATE (a)-[:KNOWS]->(b)
} IN CONCURRENT TRANSACTIONS OF 1000 ROWS
DISJOINT BY AUTO
-- 3. 비활성화: 기존 동작과 동일 (데드락 가능성 있음)
CALL { ... } IN CONCURRENT TRANSACTIONS OF 1000 ROWS
DISJOINT BY NONEDISJOINT BY (expr, ...)는 지정한 표현식 값이 겹치지 않는 행들만 같은 배치에 묶는다. 예를 들어 DISJOINT BY (row.from, row.to)를 지정하면, 같은 from 또는 to 값을 가진 행들은 서로 다른 배치로 분리된다. 동시에 같은 노드를 수정하는 트랜잭션이 없으므로 데드락이 제거된다.
DISJOINT BY AUTO는 실행 계획 분석을 통해 충돌 가능한 변수를 자동으로 감지한다. 쿼리 복잡도가 높거나 충돌 패턴을 수동으로 파악하기 어려울 때 유용하다.
함께 도입된 배치 스케줄링 설정
dbms.cypher.transactions.default_subquery_batch_strategy값: default (기본) | none | auto
이 설정은 서버 전체 기본값을 지정한다. 개별 쿼리에서 CYPHER transactionBatchStrategy=auto 힌트로 재정의할 수 있다.
ABAC: 속성 기반 접근 제어에 네이티브 사용자 태그 추가
2026.06.0에서 네이티브 사용자(native database user)가 ABAC 규칙에서 사용할 수 있는 태그를 가질 수 있게 됐다.
이전에는 ABAC 정책이 LDAP 등 외부 인증 제공자에서 가져온 속성에 의존했다. 이제 Cypher에서 직접 사용자 태그를 설정하고 정책을 작성할 수 있다.
-- 사용자에게 태그 부여
ALTER USER alice SET TAGS ['region:apac', 'tier:premium']
-- ABAC 정책에서 태그 활용
GRANT READ {*} ON GRAPH data TO `role:premium-reader`
WHERE abac.native.user_tags() CONTAINS 'tier:premium'이 기능은 멀티-테넌트 그래프 DB 운영에서 외부 LDAP 인프라 없이도 세밀한 데이터 접근 제어를 구현할 수 있게 한다.
Cypher 언어 개선: ACYCLIC 경로와 문자열 함수
ACYCLIC 경로 명시
-- GPM 구문으로 비순환 최단 경로 탐색
MATCH ANY SHORTEST ACYCLIC (start:City)-[:CONNECTS*]->(end:City)
WHERE start.name = '서울' AND end.name = '부산'
RETURN pathACYCLIC 키워드를 SHORTEST 경로 연산자와 함께 사용하면, 같은 노드를 두 번 방문하지 않는 경로만 반환한다. 이전에는 Cypher에서 순환 방지를 위해 복잡한 조건을 수동으로 작성해야 했다.
새 문자열 함수 (2026.05.0)
RETURN string.indexOf('Hello World', 'World') -- 6
RETURN string.join(['a', 'b', 'c'], '-') -- "a-b-c"
RETURN string.regexReplace('abc123', '\d+', '#') -- "abc#"string.indexOf(), string.join(), string.regexReplace()가 추가됐다. 기존 indexOf(), apoc.text.join(), apoc.text.regsub()의 네이티브 대체다. APOC 플러그인 의존성을 줄이는 방향의 일환이다.
CDC 개선: txCommitTime 컬럼 추가
-- CDC 현재 커서 조회 (2026.06.0에서 txCommitTime 추가)
CALL db.cdc.current() YIELD id, txCommitTime
RETURN id, txCommitTimedb.cdc.current()가 이제 txCommitTime 컬럼을 반환한다. CDC 소비자가 다운스트림 지연을 측정하거나 특정 시점의 변경 로그를 추적할 때 트랜잭션 커밋 시각이 필요했다. 이전에는 이 정보를 CDC 스트림 외부에서 별도로 얻어야 했다.
운영자 체크리스트
2026.05/06 업그레이드 전 확인 사항
- 드라이버 버전: Java 드라이버 6.0.5+, Python 드라이버 5.x로 업그레이드했는가?
- 5.x → 2026.xx 이관 경로: Neo4j 5.26(LTS)에서 직접 이관 가능. 5.26 미만이면 5.26 경유 권장.
- 기존 벡터 인덱스: 생성 당시
vector.quantization.type이 지정되지 않은 인덱스는 기본값 SCALAR가 적용된다. 명시적으로 재생성하지 않아도 되지만, BQ로 마이그레이션하려면 새 인덱스를 생성하고 기존 데이터를 재임포트해야 한다. - GenAI 함수 사용 시 API 키:
neo4j.conf에 LLM 제공자 API 키 설정이 필요하다. Vault 또는 환경 변수 인젝션을 사용할 경우 서버 시작 전에 주입되는지 확인한다. - ABAC 정책 검토: native user tags를 사용하는 경우 기존 LDAP 기반 정책과 충돌하지 않는지 역할-태그 매핑을 문서화한다.
벡터 인덱스 운영 기준
소규모(~100만 벡터): vector.quantization.type = SCALAR
대규모(1000만+ 벡터): vector.quantization.type = BINARY + HFQ 활성화 검토
정밀도 우선: vector.quantization.type = NONEHFQ가 GA가 되면 대규모 그래프 + 벡터 혼합 검색에서 BQ와 NONE 사이의 좋은 선택지가 될 것이다. 현재는 프리뷰이므로 프로덕션에 적용 전 충분한 리콜 측정이 필요하다.
요약
| 항목 | 변화 |
|---|---|
| 버전 체계 | SemVer 5.x → CalVer 2026.xx (매달 릴리스) |
| Binary Quantization | 2026.05.0에서 GA; ~32× 메모리 절감, 리콜 감소 |
| Hi-Fidelity Quantization | 2026.06.0 프리뷰; BQ 후보 + 원본 정밀도 재순위 |
| GenAI Cypher 함수 | ai.text.chunk/count/aggregate — Cypher 안에서 LLM 호출 |
| DISJOINT BY | 2026.05 실험 → 2026.06 GA; 병렬 임포트 데드락 방지 |
| ABAC 네이티브 태그 | 2026.06 GA; LDAP 없이 사용자 기반 속성 접근 제어 |
| CDC txCommitTime | 2026.06; 변경 이벤트에 커밋 시각 포함 |
Neo4j 2026 계열의 방향은 뚜렷하다. 그래프 구조와 벡터 검색을 하나의 쿼리에서 결합하고, LLM과의 통합을 Cypher 레이어에서 네이티브로 지원하는 것이다. 칼럼형 OLAP 엔진들이 벡터와 전문 검색을 통합하는 것과 같은 흐름이 그래프 DB에서도 진행 중이다.
References
- Neo4j 2026 Changelog (GitHub Wiki)
- Release 2026.06.0 · neo4j/neo4j (GitHub)
- Neo4j 2026.05.0 and 2026.06.0 Release Notes (Neo4j)
- Vector indexes — Cypher Manual
- Neo4j GenAI Plugin — Count tokens and chunk text
- Neo4j GenAI Plugin — Functions and Procedures
- CALL {} IN CONCURRENT TRANSACTIONS — Cypher Manual
- Neo4j Supported Versions