← Back to Home

Neo4j와 Spring Boot 시작하기

Neo4j와 Spring Boot 시작하기

Neo4j는 연결된 데이터를 다루는 데 특화된 그래프 데이터베이스다. Spring Data Neo4j는 Spring Boot와 자연스럽게 통합되어, 익숙한 Spring 패턴으로 그래프 데이터를 다룰 수 있게 해준다.

1. 의존성

pom.xml에 Spring Data Neo4j 스타터를 추가한다:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

Gradle의 경우:

implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'

2. 설정

application.yml에서 연결을 설정한다:

spring:
  neo4j:
    uri: bolt://localhost:7687
    authentication:
      username: neo4j
      password: your-password

로컬 개발 환경에서는 Docker로 Neo4j를 실행할 수 있다:

docker run -d \
  --name neo4j \
  -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/your-password \
  neo4j:5

7474 포트는 브라우저 인터페이스, 7687은 Bolt 프로토콜 연결용이다.

3. 노드 정의

@Node로 엔티티 클래스를 만든다:

@Node
public class Person {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String name;
    private Integer age;
 
    @Relationship(type = "FRIEND_OF", direction = Direction.OUTGOING)
    private List<Person> friends = new ArrayList<>();
 
    // constructors, getters, setters
}

@Relationship 어노테이션은 그래프의 엣지를 정의한다. 방향이 중요한데, OUTGOING은 이 사람이 친구를 가지고 있음을, INCOMING은 다른 사람들이 이 사람을 친구로 여긴다는 것을 의미한다.

4. Repository

Spring Data Neo4j repository는 JPA repository와 동일하게 동작한다:

public interface PersonRepository extends Neo4jRepository<Person, Long> {
 
    Optional<Person> findByName(String name);
 
    @Query("MATCH (p:Person)-[:FRIEND_OF]->(f:Person) WHERE p.name = $name RETURN f")
    List<Person> findFriendsOf(String name);
}

메서드 이름 기반 쿼리가 기본으로 동작한다. 복잡한 탐색에는 @Query와 Cypher를 사용한다.

5. 기본 Cypher 쿼리

Cypher는 Neo4j의 쿼리 언어다. 필수 패턴 몇 가지:

노드 생성:

CREATE (p:Person {name: 'Alice', age: 30})

관계 생성:

MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:FRIEND_OF]->(b)

친구의 친구 찾기:

MATCH (p:Person {name: 'Alice'})-[:FRIEND_OF]->()-[:FRIEND_OF]->(fof)
WHERE fof <> p
RETURN DISTINCT fof.name

화살표 문법 ()-[]->() 는 탐색 방향을 나타낸다. 가변 길이 경로는 *를 사용한다: [:FRIEND_OF*2]는 정확히 2홉을 의미한다.

6. Service 계층

@Service
@Transactional
public class PersonService {
 
    private final PersonRepository repository;
 
    public PersonService(PersonRepository repository) {
        this.repository = repository;
    }
 
    public Person create(String name, int age) {
        Person person = new Person(name, age);
        return repository.save(person);
    }
 
    public void addFriend(String personName, String friendName) {
        Person person = repository.findByName(personName)
            .orElseThrow(() -> new RuntimeException("Person not found"));
        Person friend = repository.findByName(friendName)
            .orElseThrow(() -> new RuntimeException("Friend not found"));
 
        person.getFriends().add(friend);
        repository.save(person);
    }
 
    public List<Person> getFriends(String name) {
        return repository.findFriendsOf(name);
    }
}

@Transactional 어노테이션은 관계 수정이 원자적으로 이루어지도록 보장한다.

7. Neo4j를 사용해야 할 때

그래프 데이터베이스가 빛을 발하는 경우:

  • 소셜 네트워크 (친구, 팔로워, 연결)
  • 추천 엔진 (X를 산 사용자가 Y도 구매함)
  • 사기 탐지 (거래에서 의심스러운 패턴 찾기)
  • 지식 그래프와 계층 구조

복잡한 관계 없이 단순 CRUD만 필요하다면 관계형 데이터베이스가 더 간단하다. Neo4j는 여러 단계의 관계를 탐색하는 쿼리가 필요할 때 가치를 발휘한다.

8. 결론

Spring Data Neo4j는 Neo4j에 대한 깔끔한 추상화를 제공한다. @Node로 노드를, @Relationship으로 관계를 정의하고, repository로 기본 작업을 처리한다. 복잡한 그래프 탐색에는 Cypher 쿼리가 완전한 제어권을 제공한다.