Skip to main content

Command Palette

Search for a command to run...

[Elasticsearch] Elasticsearch 기본용어와 CRUD 명령어

Published
4 min read

-elastic

▶ 들어가며

이번 글에서는 Elasticsearch를 공부하면서 가장 먼저 익혀야 하는 기본 용어를 정리하고,
직접 코드를 쳐가며 CRUD(Create / Read / Update / Delete) 명령어에 익숙해지는 시간을 가져보려고 한다.

Elasticsearch는 처음 보면 생소한 용어가 많아서 막막할 수 있는데,
사실 구조적으로는 우리가 익숙한 MySQL과 닮은 부분이 굉장히 많다.

둘 다 데이터베이스라는 큰 틀 안에서

  • 데이터를 삽입하고(Create)

  • 조회하고(Read)

  • 수정하고(Update)

  • 삭제(Delete)

하는 흐름은 동일하다.

그래서 이번 글에서는
👉 MySQL과 비교하면서 Elasticsearch를 이해하는 방식으로 정리해보려고 한다!!


▶ Elasticsearch 기본 용어 정리

아래는 가장 기본적인 MySQL 과의 대응 관계이다.

-기본 용어 정리

MySQL:

table을 만들고 → column의 schema를 정의하고 → row(record)를 저장하고 → 데이터를 조회/수정/삭제한다

⭐Elasticsearch:

인덱스를 만들고 → field의 mapping을 정의하며 → document를 저장하고 → 데이터들을 검색/수정/삭제한다

라는 구조로 동작하는 것이다.


▶ CRUD 명령어 정리

이제부터는 Elasticsearch에서 실제로 사용하는 CRUD 명령어를 직접 쳐보면서 익혀보자!!
이번 글에서는 앞으로 계속 사용할 기본 인덱스명을 "users"로 고정해서 진행한다.

- Index 생성하기

MySQL에서 CREATE TABLE을 하듯이, Elasticsearch에서는 데이터를 저장하기 위한 Index를 생성한다.

아래 명령어로 users 인덱스를 생성해 보자.

PUT /users


- Index 조회하기

생성한 인덱스가 존재하는지 확인하는 명령어이다.

GET /users


- Index 삭제하기

이번에는 인덱스를 삭제해보자.

DELETE /users

이 상태에서 다시 인덱스를 조회해보면

"index_not_found_exception" 에러가 발생한다

👉 즉, 인덱스가 삭제되었기 때문에 더 이상 존재하지 않는 상태임을 확인할 수 있다!


- Mapping 정의하기

MySQL에서 테이블을 만들 때 schema를 정의하듯이, Elasticsearch에서도 index 내부에 어떤 타입의 데이터를 저장할지 정의할 수 있다. 이를 Elasticsearch에서는 Mapping이라고 부른다.

아래 명령어로 users 인덱스에 매핑을 정의해보자.

PUT /users/_mapping 
{    
    "properties": 
        { 
            "name": { "type": "keyword" }, 
            "age": { "type": "integer" }, 
            "is_active": { "type": "boolean" } 
        } 
}

여기서 핵심은 다음과 같다.

  • properties 안에서 field들을 정의한다.

  • 각 field는 type을 가진다.

  • keyword는 MySQL에서 VARCHAR(문자열) 같은 느낌이라고 생각하면 된다.

  • integer, boolean도 그대로 이해하면 된다.

👉 즉, Mapping은 MySQL에서 schema를 정의하는 과정과 거의 유사하다.

매핑이 잘 정의되었는지 확인하고 싶다면 조회 명령어로 확인할 수 있다.

- GET /users


- Document 삽입하기

이제 실제 데이터를 넣어보자!

MySQL에서 테이블에 record(row)를 삽입하는 과정과 동일하게, Elasticsearch에서는 index에 document를 삽입한다.

POST /users/_doc 
{
    "name": "Bo", 
    "age": 26, 
    "is_active": true 
}

이렇게 하면 Elasticsearch가 자동으로 랜덤한 _id 값을 생성해서 document를 저장한다.


- Document 조회하기

삽입된 document를 조회하려면 아래 명령어를 사용한다.

GET /users/_search

결과를 확인해보면 hits 안에 document가 들어가 있을 것이고,
각 document마다 Elasticsearch가 자동으로 생성한 랜덤 _id 값이 붙어있는 것도 확인할 수 있다.


- ID를 지정해서 Document 삽입하기

document를 저장할 때 자동 ID가 아니라, 내가 직접 ID를 지정해서 저장하는 것도 가능하다.

POST /users/_create/1
{
    "name": "Boo", 
    "age": 27, 
    "is_active": true 
}

이렇게 하면 _id = 1로 document가 저장된다.

여기서 중요한 포인트는,

👉 _create 방식은 같은 ID가 이미 존재하면 저장이 실패한다는 점이다.
즉, 중복 저장이 불가능하다. 고유 id를 알아서 처리하는..


- 특정 ID로 Document 조회하기

특정 document 하나만 조회하고 싶다면 아래처럼 조회할 수 있다.

GET /users/_doc/2

👉 여기서 마지막 숫자 2는 document의 "id" 값이다.


- 같은 ID여도 덮어씌우기(업데이트) 하고 싶다면?

위에서 확인한 것처럼 이미 존재하는 id값을 POST 하는 경우 ERROR가 발생했지만, MySQL에서 upsert처럼 동작하게 하려면 아래처럼 PUT을 사용하면 된다. 이미 존재하는 id=1 document에 새로운 값을 가지는 데이터를 PUT 하는 경우

PUT /users/_doc/1 
{ 
    "name": "Boo", 
    "age": 28, 
    "is_active": true 
}

데이터 삽입이 성공하는 모습을 확인할 수 있고, 이후 다시 조회해보면 기존 document가 덮어씌워진 것을 확인할 수 있다.


- Document 수정하기 (Update)

사실 위에서 사용했던 PUT /users/_doc/1 자체가
👉 특정 ID document를 수정하는 방식이라고 생각해도된다. 같은 의미지 사실상.

즉, Elasticsearch에서는 PUT 요청이

  • 없으면 생성

  • 있으면 덮어쓰기(update)

방식으로 동작한다.


- 특정 필드만 수정하기

특정 인물의 나이만 변경해야 하는 경우라면? 모든 필드가 아니라, 특정 필드만 수정하고 싶을 수도 있다.

이 경우에는 _update를 사용한다.

POST /users/_update/1 
{ 
    "doc": { "age": 29 } 
}

👉 doc 안에 수정할 필드만 넣어주면 된다.

이 방식은 MySQL의 UPDATE users SET age=29 WHERE id=1 같은 느낌이다.


- Document 삭제하기 (Delete)

마지막으로 특정 ID document를 삭제해보자.

DELETE /users/_doc/1

이후 index에서 해당 id의 document를 조회해보면 document가 삭제된 것을 확인할 수 있다.


▶ 마무리

이번 글에서는 Elasticsearch에서 가장 기본이 되는 용어와 CRUD 명령어를 정리해 봤다. 정리해보면 Elasticsearch는 처음엔 생소했지만, 동작 방식 자체는 MySQL과 굉장히 유사하다는 것을 알 수 있었다. 자주 사용하는 코드들을 자주 쳐보면서 채화시키는 것이 중요할 것 같다.

  • 인덱스를 만들고

  • document를 삽입하고

  • 검색하고

  • 수정하고

  • 삭제한다

이 흐름만 익히면 막막했던 Elasticsearch와 조금 친해지는 느낌이 든다. 👍👍👍

More from this blog

Jpa N+1 문제, 우리는 이렇게 잡았다 — 1:1 문의 Api 실전 최적화기

코드 리뷰 한 줄에서 시작된 쿼리 최적화 여정 1. 시작 — "일단 돌아가게 만들자" Finders 프로젝트에서 1:1 문의(Inquiry) API를 맡았다. 현상소에 문의를 남기고, 답변을 받고, 목록을 조회하는 — 평범한 CRUD다. "JPA 쓰면 쿼리 안 짜도 되는 거 아니야?" 솔직히 처음엔 그렇게 생각했다. JpaRepository에 findAll, findById 쓰면 끝이니까. // 첫 번째 버전의 목록 조회 (QueryDS...

Feb 11, 20268 min read

[모니터링] Sentry 도입부터 Discord 에러 알림까지 — 서버 감시 시스템 구축기

"서버 죽었는데 아무도 몰랐다"에서 "에러나면 1분 안에 안다"까지 1. 모니터링을 시작한 계기 프론트엔드: "API 안 되는데요?"백엔드: "엥? 언제부터요?"프론트엔드: "...2시간 전부터요?"백엔드: 😱 어느 날 서버가 죽어있었는데 아무도 몰랐다. 그날 이후, 모니터링 시스템 구축을 결심했다. (Issue #102) 2. 모니터링 도구 비교: 뭘 쓸까? 처음에는 여러 도구를 비교했다. 도구무료 티어장점단점 Sent...

Feb 11, 20268 min read

[CI/CD] 수동 태그에서 자동 릴리즈까지 — Git Flow와 Auto Release

🚀 우리 auto-release.yml 바로 보러가기 → 이 글에서 설명하는 워크플로우의 전체 코드를 바로 확인할 수 있다! main에 머지만 하면 버전 태그부터 릴리즈 노트까지 알아서 생긴다 1. 우리의 Git 전략: Git Flow (경량 버전) Finders 프로젝트는 Git Flow 전략을 사용하고 있다. 다만 hotfix나 release 브랜치 없이, 조금 가볍게 운영한다. main ← 운영 서버 (prod) 배포 브...

Feb 11, 20265 min read

[ci/cd] 대학생 팀의 배포 파이프라인 진화기

PR 하나면 끝나는 무중단 배포까지, 삽질의 기록 1. 시작은 단순했다 "서버에 올려야 하는데... 어떻게 하지?" Finders 프로젝트를 시작했을 때, 배포라는 걸 해본 적이 없었다. 그래서 처음에는 이렇게 했다. 1. SSH로 서버 접속 2. git pull 3. ./gradlew build 4. java -jar app.jar 당연히 문제가 생겼다. 빌드하는 동안 서버가 꺼져있음 (프론트: "API 왜 안 돼요?" 🔥) 빌...

Feb 11, 20267 min read
F

Finders Tech Blog

16 posts