기본 흐름
1. 검색 UI 생성 → 사용자가 검색어 입력
2. 서버에서 DB 검색 → 검색어가 포함된 게시물 조회
3. 결과를 EJS로 전송 → 검색 결과 페이지 표시
HTML 구조
<!-- list.ejs -->
<input class="search">
<button class="search-send">검색</button>
CSS 스타일링
.search {
margin-left: 20px;
padding: 5px;
}
.search-send {
padding: 6px 10px;
background: lightgray;
border: none;
border-radius: 5px;
vertical-align: middle;
}
JavaScript로 검색 요청
<!-- list.ejs 하단 -->
<script>
document.querySelector('.search-send').addEventListener('click', function(){
let 입력한거 = document.querySelector('.search').value
location.href = '/search?val=' + 입력한거
})
</script>
기본 검색 (정확히 일치하는 제목)
app.get('/search', async (요청, 응답) => {
let result = await db.collection('post').find({title: 요청.query.val}).toArray()
응답.render('search.ejs', { 글목록: result })
})
정규식을 활용한 부분 검색
app.get('/search', async (요청, 응답) => {
let result = await db.collection('post').find({
title: { $regex: 요청.query.val }
}).toArray()
응답.render('search.ejs', { 글목록: result })
})
일반적인 검색 방식의 문제점
Index의 필요성
MongoDB에서 Index 생성
1. Collection → Indexes → Create Index
2. 필드명과 데이터 타입 설정
"title": "text""title": 1Text Index 활용한 검색
db.collection().find({
$text: { $search: '안녕' }
}).toArray()
성능 확인
// 성능 비교
db.collection().find({title: '안녕'}).explain('executionStats')
db.collection().find({$text: {$search: '안녕'}}).explain('executionStats')
Index의 단점
1. 용량 증가: 컬렉션을 복사하여 저장하므로 용량 2배
2. 수정 시 부담: 문서 추가/수정/삭제 시 Index도 함께 수정
3. 정확한 단어만 검색: 한국어 조사나 어미 변화 검색 불가
동작 원리
1. 전처리: 불용어, 조사 제거 (은/는/이/가/을/를 등)
2. 단어 추출 및 정렬: 의미있는 단어들만 정렬하여 저장
3. 문서 위치 기록: 각 단어가 어떤 문서에 있는지 매핑
4. 점수 계산: 검색 정확도에 따른 Score 부여
Search Index 생성
1. Collection → Search Indexes → Create Index
2. Analyzer: lucene.korean 선택 (한국어 불용어 제거)
3. Dynamic Mapping: 끄기 (수동으로 필드 선택)
4. Field Mapping: 검색할 필드 지정 (예: title)
서버에서 Search Index 활용
app.get('/search', async (요청, 응답) => {
let 검색조건 = [
{
$search: {
index: '사용할 인덱스 이름',
text: {
query: 요청.query.val,
path: 'title'
}
}
}
]
let result = await db.collection('post').aggregate(검색조건).toArray()
응답.render('search.ejs', { 글목록: result })
})
다양한 검색 조건 조합
let 검색조건 = [
{
$search: {
index: '사용할 인덱스 이름',
text: { query: '검색어', path: '검색할 필드이름' }
}
},
{ $sort: { _id: 1 } }, // 정렬 (기본값: score 순)
{ $limit: 10 }, // 결과 개수 제한
{ $skip: 5 }, // 앞의 5개 건너뛰기
{ $project: { 제목: 1, _id: 0 } } // 특정 필드만 반환
]
주요 연산자 설명
검색 결과 페이지네이션 예시
// 첫 번째 페이지: 3개씩, skip 0
{ $skip: 0 }, { $limit: 3 }
// 두 번째 페이지: 3개씩, skip 3
{ $skip: 3 }, { $limit: 3 }
// 세 번째 페이지: 3개씩, skip 6
{ $skip: 6 }, { $limit: 3 }
Search Index의 장점