글 작성자: 개발섭

ElasticSearch를 활용한 개발을 하게 되었다.

최근 Spring Boot와 함께 엘라스틱서치를 활용한 인턴 온보딩 프로젝트 개발을 시작하게 되었다. 종종 가끔씩 이제 Elastic과 관련된 글을 쓰지 않을까 싶다. 엘라스틱이 헛갈리는 개념도 많고 여러가지 이슈사항들이 많이 발생하게 되어서 아마 많은 글들을 남기지 않을까 싶다! 다시 본론으로 돌아가자면,

요구사항중 엘라스틱의 저장되있는 모든 index들의 상태를 파악해야했었다. 이러한 요구 사항은 실제로 ES에서는 API로 제공되어서 그 API를 사용하면 됬다.

GET /_cat/indices

이와 같은 API를 사용하면, ElasticSearch에서 전체에서 저장한 ES 내부의 index를 확인해볼 수 있었다. 요구사항에 대해서 처리하는 것이 어렵지 않은 일이기도 했다.

위의 API를 사용하게 된다면 다음 아래와 같은 값을 툭 내뱉기 때문에, 그걸 잘 받아서 처리만 하면 됬었다.

health status index            uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   my-index-000001  u8FNjxh8Rfy_awN11oDKYQ   1   1       1200            0     88.1kb         88.1kb
green  open   my-index-000002  nYFWZEO7TUiOjLQXBaYJpA   1   0          0            0       260b           260b

문제의 발생...

근데 이게 문제가 있었는데 무엇이 문제었냐하면, Spring Boot를 통해서 개발을 진행하다보니까 아무래도 좀 한 문제가 있었다.

ES Java Client를 가지고는 위의 API를 메소드로 불러 올 수 없었다는 문제가 생긴다. 물론 불러올 수는 있었지만, 메소드 단위로 불러오는 high client가 아닌 low client 를 사용해야지만, 이 API와 통신을 할 수 있는 상황...

low와 high의 API 갯수차이는 어마어마하게 났음..

차라리 이럴거면 걍 FE Client에서 처리해주는게 훨씬 더 좋지 않나? 라고 생각한 나는 생각 그대로를 실현 시키기 위해서 바로 API를 FE에서 처리할 수 있도록 했다.

 

fetch 함수를 통해서 API를 전달 받아서 JSON형태로 변환만 시켜 주면 훨씬 쉽게 만들 수 있을거라고 생각해서 값을 전달 받으면 body에서 잘꺼내다가 쓰면 좋겠다고 생각했다.

실제로 아래 형식을 통해서 전달받기만 한다면, JSON 형식으로 받을 수 있었다. 웹 브라우저에서는...

GET /_cat/indices?format=json

문제는 존재했었다. 그녀석을 만나기 전까지 말이다.

또 문제 있어~

응 또 문제 있는뒈~~ 붸뷉

나는 당연히 awaitthen을 통해서 비동기 처리하면 될거라고 생각했으나... 예상외의 난관을 만났었는데, 이 API가 이상한 타입으로 값을 받는 타입이 가장 큰 문제였다.

이 API만 그런것인지 아니면 다른 상황에서도 그런건지는 모르겠으나, 이 전달 받는 response의 body의 값 타입이 ReadableStream 타입으로 전달을 받게 되었다.

Body에 ReadableStream으로 전달된다. 

Json으로 backend에서 전달해본적은 있지 Json 타입을 받기위해서 ReadableStream 이라는 처음 보는 타입으로 전달 받아본적은 또 이번이 처음이라 도대체 뭔가 했었는데,

이런 각종 삽질들을 반복하기도 했었고... 자바스크립트를 잘은 모르다보니까 벌어졌었던 삽질들

await 문에다가 then쓰고 앉아있었다. (어쩌자는거지...)

결국 해결하기 위해서는 다음과 같은 전략을 사용해야했었다.

//let타입을 할 수 밖에 없었다. const 타입으로 했을시 값을 한번 읽고 땡처리 되었었기 때문...
let example4 = fetch("http://localhost:9200/_cat/indices?format=json");
example4.then(r => r.json()) //Json 타입으로 변환
                .then(d=>console.log(d)) //그후 값 받아서 처리했었다. 

다음과 같이 값이 잘 튀어놔왔다. (보기좋게 형식을 약간 수정했다.)

[
    {
    docs.count: "5",
    docs.deleted: "0",
    health: "yellow",
    index: "article",
    pri: "1",
    pri.store.size: "31.8kb",
    rep: "1",
    status: "open",
    store.size: "31.8kb",
    uuid: "RLCbq6QrQHqZx0HPzUstjQ"
  }
]

JavaScript의 fetch를 통한 ES API 불러올 경우에는 다음과 같은 방법으로 readable타입을 처리하면 될 것 같다.

약간의 궁금증해소과 아쉬운 점

이후에 궁금한 점이 조금 생겨서 실험들을 조금 해보았는데 ReadableStream 타입으로 전달된 값은 한번 불러오고 나면 그 이후 내가 then을 통해서 어떤 행위를 하고 난 뒤에는 다시 사용할 수 없는 상태였다.

Promise {<rejected>: TypeError: Failed to execute 'json' on 'Response': body stream already read at <anonymous>:1:22}

즉, Stream을 통해서 값의 변형을 불러올때만 가능하게 만들어놓은 상태로 만들기 위해서 엘라스틱 서치에서 이런 형식으로 값 전달을 만들어 놓은 것 같았다. 스트림형식으로 값이 남아있게 하는 것이아니라 한번 사용하고 나면 바로 없어지는 방식을 통해서 Elastic에서 값을 전달할때 이런 형식으로 전달했다.

만약 이렇게 stream을 다시 사용하기 위해서는 let타입을 통해서 fetch를 다시 불러와서 사용하는 방법을 이용해야한다.

then형식으로 처리는 쉽게 되었는데, 문제는 await방식을 통해서 처리를 해보려 했으나, 예상처럼 잘 되지는 않았다. 혹시나 await 방식을 통해서 코드 개선이 가능하다면, 댓글로 남겨주시면 좋을 것 같습니다! 😎

 

출처: 

https://stackoverflow.com/questions/40385133/retrieve-data-from-a-readablestream-object

 

Retrieve data from a ReadableStream object?

How may I get information from a ReadableStream object? I am using the Fetch API and I don't see this to be clear from the documentation. The body is being returned as a ReadableStream and I wo...

stackoverflow.com

 

'FrontEnd' 카테고리의 다른 글

⌜모던 자바스크립트 핵심 가이드⌟ 서평  (0) 2021.06.22