ElasticSearch란, 강력한 오픈소스 검색 및 분석 엔진
클러스터링이란, 여러대의 서버를 하나의 논리적인 시스템(클러스터)으로 묶어서 사용하는 것
때문에 필요에 따라 서버를 추가하며 클러스터의 규모를 늘릴 수 있다.
Kibana란, Elasticsearch와 함께 사용되는 데이터 분석 및 시각화 도구
Elasticsearch에 저장된 데이터를 분석해서 한눈에 보기 쉽게 시각화해줌
이러한 장점들 때문에 Elasticsearch를 사용한다.
진행 과정의 예시를 보고 이해해보자
우선 Elasticsearch는 SpringBoot에서 제공하는 서버와 다른 서버를 사용한다. 때문에 도커를 사용해서 서버를 빌려와야하고 이 서버에 접근할 수 있는 Entity,Controller, Service, Repository를 구현해야한다.
// elasticsearch 의존성 시작
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
//elasticsearch 의존성 끝
@Getter
@Setter
@Document(indexName = "team")
@Setting(replicas = 0)
public class TeamDocument {
@Id
private String id;
@Field(type = FieldType.Integer, index = false, docValues = false)
private int teamId;
@Field(type = FieldType.Text, analyzer = "nori")
private String name;
@Field(type = FieldType.Text, index = false, docValues = false)
private String comment;
}
@Tag(name = "검색 API", description = "검색 API Swagger")
@RestController
@RequestMapping("/api/team/search")
public class SearchController {
private final TeamSearchService teamSearchService;
public SearchController(TeamSearchService teamSearchService) {
this.teamSearchService = teamSearchService;
}
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공"),
@ApiResponse(responseCode = "401", description = "인증 실패"),
@ApiResponse(responseCode = "404", description = "사용자 없음"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@Operation(summary = "팀 검색", description = "<strong>팀 이름</strong>를 통해 팀 검색을 한다.")
@GetMapping(value = "/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getTeamByName(@PathVariable("name") String name) {
return ResponseEntity.status(200).body(teamSearchService.searchTeamByName(name));
}
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공"),
@ApiResponse(responseCode = "401", description = "인증 실패"),
@ApiResponse(responseCode = "404", description = "사용자 없음"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@Operation(summary = "팀 가입(elasticsearch)", description = "<strong>팀 이름</strong>를 통해 팀 가입(elasticsearch)을 한다.")
@PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> create(@RequestBody TeamDocument document) {
teamSearchService.createTeam(document);
return ResponseEntity.status(200).body(BaseResponseBody.of("팀이 생성되었습니다(elasticsearch)", 200));
}
}
public interface TeamSearchService {
TeamDocument createTeam(TeamDocument teamDocument);
List<TeamDocument> searchTeamByName(String name);
}
@Service
@RequiredArgsConstructor
public class TeamSearchServiceImpl implements TeamSearchService {
private final TeamSearchRepository teamSearchRepository;
@Override
public TeamDocument createTeam(TeamDocument teamDocument) {
return teamSearchRepository.save(teamDocument);
}
@Override
public List<TeamDocument> searchTeamByName(String name) {
return teamSearchRepository.findByName(name);
}
}
public interface TeamSearchRepository extends ElasticsearchRepository<TeamDocument, Integer> {
List<TeamDocument> findByName(String name);
}
이제 관련 Elasticsearch 관련 객체들은 구현했으니 설정클래스를 작성한다.
@Configuration
public class ElasticsearchConfig extends ElasticsearchConfiguration {
// @Value("${spring.elasticsearch.username}")
// private String username;
//
// @Value("${spring.elasticsearch.password}")
// private String password;
@Value("${spring.elasticsearch.uris}")
private String[] esHost;
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo(esHost)
// .withBasicAuth(username, password)
.build();
}
}
주의할점은 태그(버전)을 꼭 명시해서 Pull 한다.
이때 cmd를 사용해서 실행시키던가 DockerDesktop을 사용해서 실행시키는 방법이 있는데 cmd를 사용한다면 elasticsearch를 컨테이너화 시키기위한 설정을 명령어로 모두 작성해야한다.
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:8.7.0
저자는 DockerDesktop을 사용해서 실행했기때문에 이미지를 실행시킬때 나오는 추가 설정에서
해당 환경변수를 지정해주고 Run 시켰다
마지막으로 application.properties 설정에서
spring.jpa.hibernate.ddl-auto=create
이 설정을 update로 해놓으면 에러가 발생하더라 이것도 시간많이 잡아먹었다.