### 스프링 부트에서 엘라스틱서치(Elasticsearch)를 사용하는 방법 엘라스틱서치(Elasticsearch)는 분산 검색 엔진으로, 대규모 데이터의 검색, 분석, 저장을 효율적으로 처리할 수 있는 도구입니다. 스프링 부트에서 엘라스틱서치를 사용하면 `Spring Data Elasticsearch`를 통해 쉽게 통합할 수 있으며, REST API나 Java 클라이언트를 활용해 데이터를 조작할 수 있습니다. 아래에서는 설정부터 사용 방법까지 단계별로 설명하겠습니다. --- #### 1. 의존성 추가 스프링 부트 프로젝트에서 엘라스틱서치를 사용하려면 `pom.xml`에 `spring-boot-starter-data-elasticsearch` 의존성을 추가합니다. ```xml org.springframework.boot spring-boot-starter-data-elasticsearch ``` - **참고**: 스프링 부트 버전에 따라 엘라스틱서치 클라이언트 버전이 달라질 수 있으니, 사용하는 엘라스틱서치 서버 버전과 호환되도록 확인하세요 (예: 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 { List findByName(String name); // 이름으로 검색 List 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 findUserById(String id) { return userRepository.findById(id); } public List 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 getUser(@PathVariable String id) { return userService.findUserById(id) .map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); } @GetMapping("/search") public List searchUsersByName(@RequestParam String name) { return userService.findUsersByName(name); } @DeleteMapping("/{id}") public ResponseEntity 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 searchByName(String name) { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("name", name)) .build(); SearchHits 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`을 활용할 수 있습니다. 이를 통해 검색 성능을 극대화하고 대규모 데이터를 효율적으로 관리할 수 있습니다. 추가 질문이 있다면 언제든 물어보세요!