포스트

2023-03-10-TIL

2023-03-10-TIL

Today I Learned

Elasticsearch

Elasticsearch는 Apache Lucene 기반의 분산 검색, 분석 엔진이다. 김종민의 『Elastic 가이드북』은 특징을 이렇게 정리한다.

  • 전문(full text) 검색: Lucene처럼 색인된 데이터를 역파일 색인(inverted index) 구조로 저장한다. 단어에서 문서를 찾아가는 구조라서 관계형 DB의 LIKE '%검색어%'로는 어려운 전문 검색과 점수 기반 정렬이 가능하다.
  • 실시간에 가까운 처리: 데이터를 넣으면 거의 실시간(near real-time)으로 검색, 집계할 수 있다.
  • JSON 문서 기반: 사용자는 JSON 문서로 데이터를 넣고 받는다.
  • REST API: 조회, 입력, 삭제를 모두 HTTP 기반 REST API로 처리한다.
  • 멀티테넌시: 데이터는 인덱스라는 논리적 단위로 나뉘어 분산 저장되고, 여러 인덱스를 한 질의로 검색할 수 있다.

Logstash(수집, 가공), Kibana(시각화)와 묶어 Elastic Stack(ELK)으로 많이 쓴다. 관계형 DB를 대체하기보다는 원본 데이터는 DB에 두고, 검색과 로그 분석용 사본을 Elasticsearch에 색인하는 구성이 일반적이다. 공식 문서의 시작 가이드는 Elastic Cloud 배포를 만들고 데이터를 넣어 검색, 시각화하는 흐름을 안내한다.

  • https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-general-purpose.html
  • https://www.elastic.co/guide/index.html
  • https://github.com/elastic
  • https://www.elastic.co/kr/
  • https://www.elastic.co/guide/index.html
  • https://www.elastic.co/kr/training/?ultron=B-Stack-Trials-APJ-BMM&gambit=Stack-training&blade=adwords-s&hulk=paid&Device=c&thor=elasticsearch%20training&gclid=Cj0KCQiAgaGgBhC8ARIsAAAyLfGkLDIWBlLAFsoEw6bTAeVQTp3tlVTjt6lPLy8R_phgy8QuZRsvpNMaAk9uEALw_wcB
  • https://medium.com/javarevisited/5-best-elastic-search-courses-for-beginners-to-learn-kibna-logstash-and-elk-stack-in-2022-eb3e1e0015c4
  • https://esbook.kimjmin.net/01-overview/1.1-elastic-stack/1.1.1-elasticsearch
  • https://songha0.tistory.com/107
  • https://brunch.co.kr/@springboot/182
  • https://medium.com/@andrewrymaruk/elasticsearch-quick-guide-e2302a921cbc
  • https://sematext.com/guides/elasticsearch/
  • https://www.tutorialspoint.com/elasticsearch/index.htm
  • https://logz.io/blog/elasticsearch-tutorial/
  • https://www.udemy.com/course/elasticsearch-complete-guide/?utm_source=adwords&utm_medium=udemyads&utm_campaign=DSA_Catchall_la.EN_cc.ROW&utm_content=deal4584&utm_term=._ag_88010211481.ad_535397282061.kw__._de_c.dm__._pl__._ti_dsa-406594358574.li_1009871.pd__.&matchtype=&gclid=Cj0KCQiAgaGgBhC8ARIsAAAyLfEqVGs_Mc3Y3WB1D0SeTKl_nO1kSHm-jQcUWK9e0i9Fh0YOfcSRRAQaAvw9EALw_wcB

UUID

UUID도 여러가지 종류가 있는데, 여기에서 “-“를 제거하면 특정 seed값을 기반으로 생성한 경우 seed에서 첨가한 정보를 역으로 추출해낼 수 없게 된다. 따라서 UUID의 원본 형식을 그대로 따르는 것이 좋다.

RFC 4122는 UUID를 128비트 값으로 정의하고 버전을 다섯 가지로 나눈다. 버전 1은 시각과 노드(MAC 주소) 기반, 버전 2는 DCE 보안용, 버전 3과 5는 이름(네임스페이스와 문자열)을 각각 MD5, SHA-1로 해시한 값 기반, 버전 4는 난수 기반이다. 문자열 표현은 각 필드를 16진수로 출력해 하이픈으로 이은 8-4-4-4-12 형식이다. 하이픈은 표기 형식일 뿐이라 제거해도 128비트 값과 버전 정보는 그대로지만, UUID.fromString() 같은 표준 파서와 다른 시스템이 이 형식을 기대하므로 표준 형식을 유지하는 편이 호환성 면에서 안전하다.

기본 키로 쓸 때는 다른 문제가 있다. Vlad Mihalcea의 글은 무작위 UUID를 기본 키로 쓰면 레코드마다 16바이트를 차지하고 외래 키까지 커지며, 값이 무작위라 B+Tree 인덱스에 순서 없이 끼어들어 페이지 분할과 낮은 채움률을 만든다고 지적한다. 그래서 앞부분이 시간순으로 증가하는 식별자(TSID 등)를 대안으로 권한다.

  • https://vladmihalcea.com/uuid-database-primary-key/
  • https://www.baeldung.com/java-uuid
  • https://stackoverflow.com/questions/42087787/how-to-generate-uuid-using-spring-annotations
  • https://medium.com/javarevisited/how-to-make-unique-id-generator-microservice-using-spring-boot-7e38b8c736c8
  • https://thorben-janssen.com/generate-uuids-primary-keys-hibernate/
  • https://docs.spring.io/spring-xd/docs/1.0.0.M1/api/org/springframework/xd/dirt/container/UUIDGenerator.html

Primary Key in URL is Good or Bad?

/posts/457처럼 자동 증가 기본 키를 URL에 그대로 노출하면 열거 공격(enumeration attack)에 취약하다. sqlfordevs.com의 설명대로 공격자가 ID를 하나씩 늘려 가며 요청하면 공개된 리소스를 전부 긁어 갈 수 있고, ID 값으로 전체 데이터 규모나 증가 속도도 짐작할 수 있다. 권한 검사가 빠진 곳이 있다면 남의 데이터까지 노출된다.

대응은 두 갈래다. 내부 키는 정수로 유지하고 외부에 보여 줄 별도 컬럼(UUID 등)을 두어 URL에는 그 값을 쓰거나, Hashids처럼 정수 ID를 되돌릴 수 있는 짧은 문자열로 인코딩해 노출한다. 다만 ID를 숨기는 것은 보조 수단이고, 리소스마다 접근 권한을 검사하는 것이 근본적인 방어다.

  • https://romansorin.com/blog/hiding-primary-keys-and-database-ids-using-hashids
  • https://sqlfordevs.com/uuid-prevent-enumeration-attack
  • https://softwareengineering.stackexchange.com/questions/218306/why-not-expose-a-primary-key

Package by Components

ttulka의 DDD 예제 저장소는 판매(sales) 컴포넌트의 주문(order) 패키지처럼 컴포넌트 단위로 패키지를 나누고, 외부에 공개할 API만 public으로 둔다. 컴포넌트 내부 구현은 패키지 접근 제어로 숨겨서, 다른 컴포넌트가 내부 클래스에 직접 의존하지 못하게 한다.

  • https://github.com/ttulka/ddd-example-ecommerce-microservices/tree/main/sales/order
  • https://learning-notes.mistermicheels.com/architecture-design/reference-architectures/package-by-feature-or-component/
  • https://docs.oracle.com/cd/E19683-01/806-7008/6jftmsc10/index.html
참고한 자료외부 출처 4

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다