2025-04-08T19:56:24
This commit is contained in:
231
docs/elasticsearch.md
Normal file
231
docs/elasticsearch.md
Normal file
@@ -0,0 +1,231 @@
|
||||
### 스프링 부트에서 엘라스틱서치(Elasticsearch)를 사용하는 방법
|
||||
|
||||
엘라스틱서치(Elasticsearch)는 분산 검색 엔진으로, 대규모 데이터의 검색, 분석, 저장을 효율적으로 처리할 수 있는 도구입니다. 스프링 부트에서 엘라스틱서치를 사용하면 `Spring Data Elasticsearch`를 통해 쉽게 통합할 수 있으며, REST API나 Java 클라이언트를 활용해 데이터를 조작할 수 있습니다. 아래에서는 설정부터 사용 방법까지 단계별로 설명하겠습니다.
|
||||
|
||||
---
|
||||
|
||||
#### 1. 의존성 추가
|
||||
스프링 부트 프로젝트에서 엘라스틱서치를 사용하려면 `pom.xml`에 `spring-boot-starter-data-elasticsearch` 의존성을 추가합니다.
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
- **참고**: 스프링 부트 버전에 따라 엘라스틱서치 클라이언트 버전이 달라질 수 있으니, 사용하는 엘라스틱서치 서버 버전과 호환되도록 확인하세요 (예: Elasticsearch 8.x 사용 시 최신 클라이언트 필요).
|
||||
|
||||
---
|
||||
|
||||
#### 2. `application.yaml` 설정
|
||||
엘라스틱서치 서버와의 연결을 설정합니다.
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
elasticsearch:
|
||||
uris: http://localhost:9200 # 엘라스틱서치 서버 URL
|
||||
username: elastic # 기본 사용자 이름 (선택)
|
||||
password: yourpassword # 비밀번호 (선택, 기본 인증 사용 시)
|
||||
```
|
||||
|
||||
- **옵션**:
|
||||
- `uris`: 단일 또는 다중 노드 URL (예: `http://node1:9200,http://node2:9200`).
|
||||
- `username`/`password`: 엘라스틱서치 보안 설정(X-Pack) 활성화 시 필요.
|
||||
|
||||
---
|
||||
|
||||
#### 3. 엔티티 클래스 정의
|
||||
엘라스틱서치에 저장할 데이터를 표현하는 엔티티 클래스를 정의합니다. `@Document` 어노테이션을 사용해 인덱스를 지정합니다.
|
||||
|
||||
```java
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
|
||||
@Document(indexName = "users") // 인덱스 이름 지정
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Field(type = FieldType.Text)
|
||||
private String name;
|
||||
|
||||
@Field(type = FieldType.Integer)
|
||||
private int age;
|
||||
|
||||
// Getter, Setter, Constructor
|
||||
public User() {}
|
||||
|
||||
public User(String id, String name, int age) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
// ... getters and setters ...
|
||||
}
|
||||
```
|
||||
|
||||
- **`@Document`**: 인덱스 이름과 설정(샤드 수, 복제본 수 등)을 정의.
|
||||
- **`@Id`**: 문서의 고유 식별자.
|
||||
- **`@Field`**: 필드 타입과 매핑 설정.
|
||||
|
||||
---
|
||||
|
||||
#### 4. 리포지토리 인터페이스 생성
|
||||
`Spring Data Elasticsearch`는 JPA와 유사하게 리포지토리 인터페이스를 제공합니다.
|
||||
|
||||
```java
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
|
||||
public interface UserRepository extends ElasticsearchRepository<User, String> {
|
||||
List<User> findByName(String name); // 이름으로 검색
|
||||
List<User> findByAgeGreaterThan(int age); // 나이 기준 검색
|
||||
}
|
||||
```
|
||||
|
||||
- **기능**: 기본 CRUD 메서드(`save`, `findById`, `delete` 등)와 쿼리 메서드 자동 생성.
|
||||
|
||||
---
|
||||
|
||||
#### 5. 서비스 및 컨트롤러 구현
|
||||
리포지토리를 사용해 데이터를 조작하는 서비스와 컨트롤러를 작성합니다.
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public UserService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public User saveUser(User user) {
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
public Optional<User> findUserById(String id) {
|
||||
return userRepository.findById(id);
|
||||
}
|
||||
|
||||
public List<User> findUsersByName(String name) {
|
||||
return userRepository.findByName(name);
|
||||
}
|
||||
|
||||
public void deleteUser(String id) {
|
||||
userRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public User createUser(@RequestBody User user) {
|
||||
return userService.saveUser(user);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<User> getUser(@PathVariable String id) {
|
||||
return userService.findUserById(id)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElseGet(() -> ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@GetMapping("/search")
|
||||
public List<User> searchUsersByName(@RequestParam String name) {
|
||||
return userService.findUsersByName(name);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> deleteUser(@PathVariable String id) {
|
||||
userService.deleteUser(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 6. 커스텀 쿼리 사용 (옵션)
|
||||
복잡한 검색 쿼리가 필요할 경우 `ElasticsearchRestTemplate`을 사용합니다.
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class ElasticsearchConfig {
|
||||
|
||||
@Bean
|
||||
public ElasticsearchRestTemplate elasticsearchTemplate(RestHighLevelClient client) {
|
||||
return new ElasticsearchRestTemplate(client);
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
public class CustomUserService {
|
||||
|
||||
private final ElasticsearchRestTemplate template;
|
||||
|
||||
public CustomUserService(ElasticsearchRestTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
public List<User> searchByName(String name) {
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||
.withQuery(QueryBuilders.matchQuery("name", name))
|
||||
.build();
|
||||
SearchHits<User> searchHits = template.search(searchQuery, User.class);
|
||||
return searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **`ElasticsearchRestTemplate`**: 저수준 API로 복잡한 쿼리 실행.
|
||||
- **`QueryBuilders`**: 쿼리 빌더를 사용해 검색 조건 정의.
|
||||
|
||||
---
|
||||
|
||||
#### 7. 테스트
|
||||
엘라스틱서치가 실행 중인지 확인하고, 애플리케이션을 실행합니다. 예를 들어:
|
||||
- **데이터 추가**: `POST /api/users`에 `{ "id": "1", "name": "John", "age": 30 }` 요청.
|
||||
- **검색**: `GET /api/users/search?name=John`으로 이름 검색.
|
||||
|
||||
---
|
||||
|
||||
### 추가 팁
|
||||
1. **의존성 버전 확인**:
|
||||
- 엘라스틱서치 서버 버전과 클라이언트 버전이 일치해야 합니다. 스프링 부트 3.x는 기본적으로 Elasticsearch 8.x를 지원합니다.
|
||||
- 필요 시 `spring.elasticsearch.restclient.version` 속성으로 버전 조정.
|
||||
|
||||
2. **인덱스 관리**:
|
||||
- 인덱스는 자동 생성되지만, 매핑을 미리 정의하려면 `@Mapping` 어노테이션이나 엘라스틱서치 API 사용.
|
||||
|
||||
3. **운영 환경 설정**:
|
||||
```yaml
|
||||
spring:
|
||||
elasticsearch:
|
||||
uris: http://prod-es:9200
|
||||
username: elastic
|
||||
password: securepassword
|
||||
```
|
||||
|
||||
4. **로컬 테스트**:
|
||||
- Docker로 엘라스틱서치를 실행:
|
||||
```bash
|
||||
docker run -d -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.12.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 결론
|
||||
스프링 부트에서 엘라스틱서치를 사용하려면 `spring-boot-starter-data-elasticsearch` 의존성을 추가하고, `application.yaml`으로 연결 설정을 정의한 후, 엔티티와 리포지토리를 작성하면 됩니다. 간단한 CRUD는 `ElasticsearchRepository`로 처리하고, 복잡한 쿼리는 `ElasticsearchRestTemplate`을 활용할 수 있습니다. 이를 통해 검색 성능을 극대화하고 대규모 데이터를 효율적으로 관리할 수 있습니다. 추가 질문이 있다면 언제든 물어보세요!
|
||||
Reference in New Issue
Block a user