Blog

[Spring][258] ✅ 예상 질의 응답 목록 - 프로젝트에 대하여 발표흐름에 따른 분류

Category
Author
Tags
PinOnMain
1 more property
질문이 나올만한 부분은 본격적으로 아키텍처 기술도입배경부터 시작된다.
전체적인 요청의 흐름? 전체적으로 클라이언트의 HTTP 요청이 어떻게 처리되는지 알려주세요.
기본 흐름
클라이언트→AJAX요청→로드밸런서→시큐리티필터체인→디스패처서블릿→(컨트롤러→서비스→리포지토리)→데이터베이스
로드밸런서에서는 HTTP는 HTTPS로 리디렉션함
ROUTE53
ACM에서 SSL 인증서
그 흐름에서 카프카는 어떤 역할을 하나요?
기본적으로 저희는 메인서버와, 이벤트만을 위한 독립적인 서버가 별도로 존재합니다.
서버가 나뉘어졌고 그 중개 역할로 카프카가 데이터를 전달하는 역할입니다.(메시지큐)
아래는 연결되는 질문또는 답변입니다.
두개를 나눈이유?
메인서버에서 부하가 많이 생겼을때, 서버를 확장해야 할때 기존의 모놀로식 구조에서는 모든 서비스가 확장되어야하지만,
이 구조를 통해서 이벤트 서버만 독립적으로 확장 할 수 있습니다.
그 흐름에서 레디스는 어떤 역할을 하나요?
레디스는 레디스 분산락을 위해서 구성되어있습니다.
선택한 이유는 분산 DB의 확장을 위해서 선택했습니다.
왜 인메모리 데이터베이스가 필요했는지?
주키퍼와 비교했는데, 저희는 실시간 처리가 필요했기 때문에 인메모리방식인 레디스가 가장 적합했습니다.
동시성 제어가 필요한 이유는 무엇인가요?
트랜잭션, 갱신실패, 데드락
검색 성능을 개선 시킬수 있는 다른방안? 알고리즘과 자료구조랑 관련있는것? 한번 해본것 , 안해본것
1.
Trie (Prefix Tree):
Trie는 문자열 검색을 위한 트리 자료 구조로, 검색어를 트리에 저장하여 빠르게 검색할 수 있습니다. 특히 정적인 데이터나 미리 정의된 검색어에 유용합니다.
2.
Bloom Filters:
Bloom 필터는 어떤 요소가 집합에 속하는지 여부를 빠르게 확인하는 데 사용되며, 문자열 검색에서도 적용될 수 있습니다.
3.
Levenshtein Distance (Edit Distance):
레벤슈타인 거리는 두 문자열 간의 편집 거리를 측정하여 문자열의 유사성을 평가하는데 사용됩니다. 오타가 있는 검색어나 유사한 단어를 찾는데 유용합니다.
사용해보긴했었다. 이건 정렬관련 정확도관련 개선이고, 우리는 속도 개선을 우선했기 때문에 인덱싱을 해보려 넘어갔다.
4.
Inverted Indexing:
역 인덱스는 어떤 단어가 어느 문서에 나타나는지를 기록한 인덱스로, 전체 텍스트 검색 엔진에서 활용됩니다.
스테밍(Stemming)과 레마타이제이션(Lemmatization):
단어의 원형을 추출하여 인덱싱하는 방식으로, 단어의 다양한 형태로부터 검색이 가능하게 합니다.
N-Gram Indexing:
N-Gram은 연속된 N개의 문자를 나타내는 방법으로, 검색어를 N-Gram으로 분리하여 색인을 만들고 검색할 때 활용합니다. 일부 데이터베이스 시스템은 N-Gram 인덱싱을 지원하여 효율적인 문자열 검색을 제공합니다.
구분자기법
텍스트를 특정 구분자를 기준으로 나누어 인덱싱하는 방식입니다. 예를 들어, 쉼표(,)로 구분된 텍스트를 각각의 단어로 분리하여 인덱스를 생성합니다.
불용어(Stop Words) 제거:
흔히 나타나는 불용어(예: and, or, the 등)를 제거하여 인덱스의 용량을 줄이고 검색 성능을 향상시킵니다.
최초 MVP의 검색성능은 왜이리 나쁠까요? 그 이유가 무엇일까요? Like절의 알고리즘은 무엇인가요?
Like 절에서 사용되는 알고리즘은 패턴 매칭(Pattern Matching)이라고 할 수 있습니다. Like 절은 주로 SQL에서 문자열을 검색할 때 사용되며, 특정 패턴에 매칭되는 문자열을 찾습니다. 패턴은 와일드카드(% 또는 _)를 사용하여 지정됩니다. 와일드카드를 포함한 패턴은 인덱스의 특정 부분만을 검색하기 어려워서 전체 테이블을 스캔해야 하는 경우가 발생할 수 있습니다.
이는 일반적으로 인덱스를 사용할 수 없어 성능이 좋지 않을 수 있습니다.
위 요청 흐름에서 엘라스틱 서치는 구체적으로 어떤 역할을 하나요?
MySQL로부터 가져온 도서 데이터를 Elasticsearch에 적재하면, 특히 텍스트 기반의 검색과 분석이 필요한 경우에 강력한 선택지가 되기 때문에 도입하게 되었습니다.
Elasticsearch는 분산 구조로 설계되어 있어, 대용량 데이터셋에 대한 높은 성능을 제공합니다.
MySQL을 사용 할 수 있었는데 궂이 엘라스틱 서치를 사용한 이유가 있을까요? 그리고 두개를 함께 사용하는 이유는 무엇인가요?
우선 MySQL과의 기술적 차이점도 있지만 프로젝트의 상황적 차이도 있습니다.
Elasticsearch는 비정형 데이터, 특히 대량의 텍스트 데이터를 신속하게 검색하고 분석하는 데 특화돼 있는 기술입니다. 특히 검색 엔진으로서의 역할에서 강점을 보여주고 있습니다. Elasticsearch는 대용량 로그, 문서 검색, 실시간 분석 등의 시나리오에서 뛰어난 성능을 보일 수 있는 기술입니다.
초기 MVP에서는 단순한 트랜잭션 처리나 정형 데이터베이스가 목적이었기 때문에 MySQL과 같은 관계형 데이터베이스를 사용하는 것이 적합했습니다. 하지만 700만건의 데이터를 적재하는 순간 성능적 문제가 발생 했었고 문제를 해결하는 선택지 중에 하나였기 때문에 두가지를 비교하게 되었습니다.
결론적으로 텍스트 기반의 검색이란 문제를 해결하기 위해 MySQL 풀텍스트 인덱싱의 복잡도와 Elasticsearch의 구축의 난이도를 나누어 도전하게 되었고 선택을 하게 되었습니다.
결과 검색과 관련된 부분은 엘라스틱 서치를, 그 외 기본적인 데이터베이스는 MySQL을 사용하며 두 시스템은 서로 보완적으로 사용하고 있습니다.
엘라스틱 서치는 어떤 이유에서 텍스트 검색에서 높은 성능을 보여주나요?
그 이유는 엘라스틱 서치는 Lucene이라는 인덱싱 및 검색 라이브러리를 기반으로 하기 때문입니다.
Elasticsearch가 내부적으로 안정적이며 빠른 이유는 여러 가지가 있습니다.
1.
Lucene은 검색 엔진에 사용되는 강력한 오픈 소스 라이브러리로, 텍스트 인덱싱과 검색에 특화돼 있습니다.
2.
Elasticsearch는 대량의 데이터를 효율적으로 처리하기 위해 여러 가지 알고리즘과 자료구조를 사용합니다. 그 중 하나는 역색인화라는 개념입니다. 역색인화는는 단어가 어느 문서에 나타나는지를 기록해 두어 검색 속도를 향상시키는 데 도움이 됩니다.
3.
Elasticsearch는 분산 시스템으로 설계돼 있어서 여러 노드에 데이터를 분산 저장하고 병렬 처리를 가능하게 합니다. 이렇게 함으로써 데이터 검색 및 분석 작업을 효율적으로 처리할 수 있습니다.
4.
Elasticsearch는 실시간 검색을 지원하고 있어서 데이터가 업데이트되더라도 거의 실시간으로 검색 결과를 반영할 수 있습니다. 이는 대규모의 데이터셋에서도 높은 성능을 제공하는 데 기여하고 있습니다.
테스트의 시나리오 설정은 왜 그렇게 되었는지?
검색성능 테스트 환경 설정
1명이 특정 키워드를 포함한 검색요청을 100번 하는것을 테스트
횟수는 신뢰도 높은 데이터를 만들기 위해서 횟수를 늘리게 된 것입니다.
처음엔 10개의 스레드가 10번의 요청을 보내는 것을 했지만,여러 스레드가 요청을 보내게 되면 검색의 성능외에 응답 시간에 영향을 줄 것 같았습니다.
검색 성능에 집중된 테스트를 위해서는 동시에 실행되는 스레드를 없에고 1개의 스레드에서 여러 횟수의 요청을 보냈습니다.
동시성 테스트 환경 설정
100명이 동일한 도서를 0.1초만에 나눔 신청을 요청하는 접근하는 것을 테스트
검색과 반대로 동시성에 집중된 테스트기 스레드의 갯수가 동시에 접속하는 유저를 뜻하고, 그 처리 상태, 속도가 중요
아쉬운점과 앞으로 어떤 것을 딥다이브 하고 싶은지
기본적으로 MySQL의 Full Text Index에 대한 깊은 이해도가 필요하다고 느껴졌습니다.
MySQL의 풀텍인덱스에 대해서 알고리즘이나 자료구조까지 확장해보고 더해서 디폴트 엔진인 InnoDB에 대해서까지 그 차이를 발생시키는것이 무엇인지 알아보기까지 깊은 스터디가 필요하다고 느꼈습니다.
또한 엘라스틱 서치 자체에서도 더 기본적인 구현 방법들을 익히고 싶습니다.
이 부분들을 더 공부하여, 프로젝트의 목표에 맞게 성능을 개선해 나가고 최적화하는 것을 진행해볼 예정입니다.
엘라스틱 서치의 Logstash가 MySQL로부터 데이터를 가져와 전달하고 있습니다. 여기서 실시간 동기화를 해보고 싶습니다.
이를 위해서는 Kafka를 활용해야 할 것으로 보여져 이 부분을 해결 해보고 싶습니다.
캐싱과 관련된 부분을 충분히 도전하지 못한 부분이 아쉽습니다.
검색과 관련해서는 특정 키워드, 빈도수가 높은 태그, 카테고리 등 여러 캐싱이 가능할 것 같은 부분들에 캐싱을 적용하여 성능을 올리는 것을 도전하고 싶습니다.
또한 로그인과 관련된 리프레시토큰 이 부분들을 추가적으로 공부하고자 합니다.
시간이 부족하여 한정된 성능 테스트 밖에 하지 못하였습니다. 이후에는 대규모 트래픽을 가하는 테스트와 동시성 제어 방법에 따른 성능 테스트 등 여러가지 시나리오를 만들어서 성능 테스트를 다각도로 진행할 예정입니다.
추가로 테스트를 진행하며 CPU나 Memory 같은 자원역시 모니터링하고 싶습니다.
마지막으로 아키텍처와 관련되서는 도커에 대한 이해도를 높이고 적용하여 배포해보고 싶습니다.
불용어 제거에 대한 추가내용
불용제거on
구분자
this is an apple
this(X)
is(X)
an(X)
apple
2gram →
this is an apple
th
hi
is(X)
is (X)
an(X)
ap
pp
pl
le
영어는 불용제거 켜놔도 가능한데(인덱싱할 범위가 줄어듬)
한글은 불용어로 등록될것이 조사(는, 이다 등등) 그런데 명사로 쓰이는 단어도 있기도 하고, 기본적으로 whitespace로 구분자가 정확하게 구분되지 않는다. 사람”은” 살아간다에서 “은”는 조서로 불용어처리를 해버리면, “은” silver라는 의미의 명사를 포함한 제목들은 인덱싱이안되서 애매해짐. 이러한 문제를 해결하기 위해서는
1.
커스텀 불용어 목록 작성:
기본 불용어 목록에 추가할 특정 단어들을 선별하여 커스텀 불용어 목록을 작성합니다. 이 목록에서는 중요한 명사 등을 제외하고 조사 등을 포함할 수 있습니다.
2.
형태소 분석 활용:
형태소 분석을 통해 명사 등을 추출하고, 이를 불용어 목록에 추가하지 않거나 별도의 인덱스로 처리할 수 있습니다. 형태소 분석기를 활용하여 의미 있는 어절만을 선택할 수 있습니다.
3.
불용어의 영향 감소:
불용어 처리를 완전히 제거하지 말고, 일부 불용어가 검색 쿼리에 영향을 미치지 않도록 유연하게 처리합니다. 예를 들어, 불용어를 제거하지 않고 검색 쿼리에서는 무시하도록 하는 방법을 고려할 수 있습니다.
4.
동의어 및 유사어 고려:
유의어 사전을 활용하여 동의어나 유사어를 고려하여 검색 결과의 다양성을 확보할 수 있습니다. 이를 통해 불용어 처리로 인한 검색 결과의 손실을 최소화할 수 있습니다.