목차

1. Elasticsearch, ElasticsearchClient 의존성 추가

dependencies {
		// Elasticsearch Java 클라이언트
		implementation 'co.elastic.clients:elasticsearch-java:8.15.2'
		implementation 'org.elasticsearch.client:elasticsearch-rest-client:8.15.2'
}

2. Elastic Cloud 연결 설정

application.yml 설정

spirng:
	  elasticsearch:
	    uris: ${ELASTICCLOUD_ENDPOINT}
	    username: elastic
	    password: ${ELASTICCLOUD_PASSWORD}
	    
elasticsearch:
  uris: ${ELASTICCLOUD_ENDPOINT}
  username: elastic
  password: ${ELASTICCLOUD_PASSWORD}

3. ElasticsearchConfig 설정

/batch/infrastructure/config/ElasticsearchConfig.java 구현

@Configuration
@RequiredArgsConstructor
public class ElasticsearchConfig{

    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConfig.class);

    // application.yml에서 설정된 값들을 가져오기
    @Value("${elasticsearch.uris}")
    private String elasticsearchUri;

    @Value("${elasticsearch.username}")
    private String elasticsearchUsername;

    @Value("${elasticsearch.password}")
    private String elasticsearchPassword;

    /**
     * ElasticsearchClient 빈을 생성하여 Spring 컨텍스트에 등록
     * @return ElasticsearchClient
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        // 기본 자격 증명 공급자 설정 (사용자 이름, 비밀번호)
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(elasticsearchUsername, elasticsearchPassword));

        // Elasticsearch 연결을 위한 RestClientBuilder 설정
        RestClientBuilder builder = RestClient.builder(HttpHost.create(elasticsearchUri))
                .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));

        // RestClient 및 Transport 생성
        RestClient restClient = builder.build();
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        // ElasticsearchClient 생성
        return new ElasticsearchClient(transport);
    }
}

4. Elasticsearch 초기화

/batch/infrastructure/config/ElasticsearchInitializer.java 공시자료 인덱스 생성

@Service
@RequiredArgsConstructor
public class ElasticsearchInitializer {

    private final ElasticsearchClient elasticsearchClient;

    @PostConstruct
    public void configureElasticsearchIndex() throws IOException {
        boolean indexExists = elasticsearchClient.indices().exists(e -> e.index("disclosures")).value();

        if (!indexExists) {
            createDisclosureIndex(elasticsearchClient);
        }
    }

    private void createDisclosureIndex(ElasticsearchClient client) throws IOException {
        String indexSettings = """
            {
              "settings": {
                "analysis": {
                  "analyzer": {
                    "nori_analyzer": {
                      "type": "custom",
                      "tokenizer": "nori_tokenizer",
                      "filter": ["lowercase"]
                    }
                  }
                }
              },
              "mappings": {
                "properties": {
                  "corpName": {
                    "type": "text",
                    "analyzer": "nori_analyzer"
                  },
                  "reportNm": {
                    "type": "text",
                    "analyzer": "nori_analyzer"
                  },
                  "rceptDt": {
                    "type": "date",
                    "format": "yyyyMMdd"
                  }
                }
              }
            }
            """;

        client.indices().create(c -> c
                .index("disclosures")
                .withJson(new StringReader(indexSettings))
        );

        LoggerFactory.getLogger(ElasticsearchInitializer.class).info("Successfully created 'disclosures' index with Nori analyzer.");
    }
}

5. Document Entity 작성

package com.tradingtrends.batch.domain.model.Entity;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;

import java.time.LocalDateTime;

@Getter
@Setter
@NoArgsConstructor
@ToString
@Document(indexName = "disclosures")
@Setting(settingPath = "elastic/document-setting.json")
@Mapping(mappingPath = "elastic/document-mapping.json")
public class DisclosureDocument {

    @Id
    private String rceptNo;

    @Field(type = FieldType.Text)
    private String corpName;

    @Field(type = FieldType.Text)
    private String corpCode;

    @Field(type = FieldType.Text)
    private String reportNm;

    @Field(type = FieldType.Text)
    private String rceptDt;

    @Field(type = FieldType.Date, format = DateFormat.date_time)
    private LocalDateTime loadDt;

    @Field(type = FieldType.Text)
    private String rawXmlData;  // XML 원본 데이터를 저장
}
 

6. Elasticsearch에 데이터 인덱싱

Elasticsearch 관련 Service 파일에 다음과 같은 메서드를 작성하여 데이터 인덱싱 요청