본문으로 건너뛰기

Neo4j와 Spring Boot 시작하기

Getting Started with Neo4j and Spring Boot

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

Neo4j is a graph database specialized in handling connected data. Spring Data Neo4j integrates naturally with Spring Boot, allowing you to work with graph data using familiar Spring patterns.

1. 의존성

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

1. Dependencies

Add the Spring Data Neo4j starter to your pom.xml:

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

Gradle의 경우:

For Gradle:

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

2. 설정

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

2. Configuration

Configure the connection in application.yml:

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

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

For local development, you can run Neo4j with Docker:

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

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

Port 7474 is for the browser interface, and 7687 is for Bolt protocol connections.

3. 노드 정의

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

3. Defining Nodes

Create entity classes with @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은 다른 사람들이 이 사람을 친구로 여긴다는 것을 의미한다.

The @Relationship annotation defines edges in the graph. Direction matters: OUTGOING means this person has friends, while INCOMING means other people consider this person as their friend.

4. Repository

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

4. Repository

Spring Data Neo4j repositories work identically to JPA repositories:

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를 사용한다.

Method name-based queries work by default. For complex traversals, use @Query with Cypher.

5. 기본 Cypher 쿼리

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

5. Basic Cypher Queries

Cypher is Neo4j's query language. Here are some essential patterns:

노드 생성:

Creating nodes:

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

관계 생성:

Creating relationships:

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

친구의 친구 찾기:

Finding friends of friends:

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

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

The arrow syntax ()-[]->() indicates traversal direction. For variable-length paths, use *: [:FRIEND_OF*2] means exactly 2 hops.

6. Service 계층

6. Service Layer

@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 어노테이션은 관계 수정이 원자적으로 이루어지도록 보장한다.

The @Transactional annotation ensures that relationship modifications are performed atomically.

7. Neo4j를 사용해야 할 때

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

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

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

7. When to Use Neo4j

Cases where graph databases shine:

  • Social networks (friends, followers, connections)
  • Recommendation engines (users who bought X also purchased Y)
  • Fraud detection (finding suspicious patterns in transactions)
  • Knowledge graphs and hierarchies

If you only need simple CRUD without complex relationships, relational databases are simpler. Neo4j proves its value when you need queries that traverse multiple levels of relationships.

8. 결론

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

8. Conclusion

Spring Data Neo4j provides a clean abstraction over Neo4j. Define nodes with @Node, relationships with @Relationship, and handle basic operations with repositories. For complex graph traversals, Cypher queries give you full control.