Skip to content

lgm1007/job-board

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

43 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

μ±„μš©κ³΅κ³  검색 ν”„λ‘œμ νŠΈ (OpenSearch μ‹€μŠ΅)

ν”„λ‘œμ νŠΈ κ°œμš”

  • μ±„μš©κ³΅κ³  검색 주제의 ν”„λ‘œμ νŠΈ
  • OpenSearch μ‹€μŠ΅

κΈ°μˆ μŠ€νƒ

  • Spring Boot
  • Spring Data JPA
  • PostgreSQL
  • Flyway
  • OpenSearch
  • k6

ν™˜κ²½μ„€μ •

  • 둜컬 PostgreSQL 및 OpenSearch 도컀 컴포즈 μ„€μΉ˜
docker-compose up -d
  • 접속 정보

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ν•˜λ©΄ Flywayκ°€ DB에 μƒ˜ν”Œ 데이터 적재

    • resources/db/migration/V1__init.sql : μŠ€ν‚€λ§ˆ 생성
    • resources/db/migration/V2__alter_sequence.sql : PostgreSQL μ‹œν€€μŠ€ μ„€μ • μˆ˜μ •
    • resources/db/migration/R__seed.sql : μƒ˜ν”Œ 데이터 적재
  • k6 μ„±λŠ₯ν…ŒμŠ€νŠΈ μ‹€ν–‰ ν™˜κ²½ μ„€μ •

    • k6 μ„€μΉ˜ μ‚¬μ΄νŠΈμ—μ„œ μ„€μΉ˜ ν›„ λͺ…λ Ήμ–΄ μˆ˜ν–‰
    • RDB λͺ©λ‘ 쑰회 κΈ°λŠ₯: k6 run .\k6\perf\rdb.js
    • OpenSearch 검색 κΈ°λŠ₯: k6 run .\k6\perf\opensearch.js

OpenSearch μ‹€μŠ΅ 포인트

μ‹€μŠ΅ λͺ©ν‘œ

  • RDB 기반의 μ±„μš©κ³΅κ³  μ‹œμŠ€ν…œμ— OpenSearch 검색 μ „μš© μ—”μ§„μœΌλ‘œ 뢄리 적용
  • Outbox νŒ¨ν„΄μ„ ν™œμš©ν•œ 비동기 인덱싱 ꡬ쑰
  • RDB 쑰회 검색 vs OpenSearch 검색 μ—­ν• Β·μ„±λŠ₯Β·ν’ˆμ§ˆ 차이 비ꡐ

RDB 쑰회의 ν•œκ³„

  • 인덱슀 ν™œμš© μ œν•œμ 
  • 관련도 μ •λ ¬ 어렀움
  • 데이터가 λŠ˜μ–΄λ‚ μˆ˜λ‘ μ„±λŠ₯ κΈ‰κ²©νžˆ μ €ν•˜

OpenSearch 인덱슀 섀계

인덱슀 μ΄ˆκΈ°ν™” (IndexInitializer)

JobPostingIndexInitializer.kt

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘ μ‹œ OpenSearch μΈλ±μŠ€κ°€ μ—†μœΌλ©΄ μžλ™ 생성
  • 둜컬/μ‹€μŠ΅ ν™˜κ²½μ— 맞좘 settings & mappings 적용
  • ν•„ν„°λ§μš© ν•„λ“œλŠ” keyword둜 섀계
job_postings
 β”œβ”€ text   : title, description, companyName, location
 β”œβ”€ keyword: status, employmentType, companyIndustry, skillNames
 β”œβ”€ number : companyId, experienceMin, experienceMax
 └─ date   : updatedAt

인덱싱 μ „λž΅: Outbox νŒ¨ν„΄

Outbox ν™œμš© λ°°κ²½

  • DB νŠΈλžœμž­μ…˜κ³Ό OpenSearch 인덱싱을 동기 처리둜 묢으면,
    • OpenSearch μž₯μ•  μ‹œ β†’ API μž₯μ•  μ „νŒŒ
    • DB 컀밋 성곡, But 검색 반영 μ‹€νŒ¨ β†’ μ •ν•©μ„± 문제

Outbox νŒ¨ν„΄ 흐름

  1. μ±„μš©κ³΅κ³  생성/μˆ˜μ •/μ‚­μ œ
  2. DB νŠΈλžœμž­μ…˜ 컀밋
  3. outbox_event ν…Œμ΄λΈ”μ— 이벀트 적재
  4. Outbox Pollerκ°€ 이벀트λ₯Ό 읽어 OpenSearch 처리
outbox_event
- aggregate_type = JOB_POSTING
- event_type     = UPSERT | DELETE
- payload        = { "jobPostingId": 123 }
- status         = PENDING / PROCESSING / DONE / FAILED

초기 데이터 처리: 리인덱싱 (Backfill)

  • Outbox μΆ”κ°€ 이전에 이미 μ‘΄μž¬ν•˜λ˜ DB 데이터에 λŒ€ν•΄ OpenSearch 인덱싱
  • 둜컬/μ‹€μŠ΅ ν™˜κ²½μ—μ„œ ApplicationRunner 기반 BackfillRunner μΆ”κ°€
  • 싀무 ν™˜κ²½μ΄λΌλ©΄ 별도 배치/관리 μ»€λ§¨λ“œλ‘œ 뢄리

OpenSearch 검색 κ΅¬ν˜„

OpenSearchJobPostingSearchAdapter.kt

1. Bool Query ꡬ쑰

bool
 β”œβ”€ must   : ν‚€μ›Œλ“œ 검색 (score 계산)
 └─ filter : μ •ν™• λ§€μΉ­ ν•„ν„° (score 영ν–₯ μ—†μŒ)

2. multi_match + ν•„λ“œ κ°€μ€‘μΉ˜

title^3
companyName^2
description
  • 제λͺ© (title) κ°€μž₯ μ€‘μš”
  • νšŒμ‚¬λͺ… 2μˆœμœ„
  • λ³Έλ¬Έ 보쑰

3. operator = AND

  • μž…λ ₯ν•œ 단어λ₯Ό ν¬ν•¨ν•œ λ¬Έμ„œ μš°μ„  검색

4. ν‚€μ›Œλ“œ (q) 없을 λ•Œ

  • match_all + filter
  • 검색이 μ•„λ‹Œ ν•„ν„°λœ λͺ©λ‘ μš©λ„

RDB λͺ©λ‘ 쑰회 vs OpenSearch 검색 비ꡐ

ν•­λͺ© RDB OpenSearch
μ •ν™• λ§€μΉ­ 강함 강함
ν‚€μ›Œλ“œ 검색 μ œν•œμ  맀우 강함
관련도 μ •λ ¬ 어렀움 제곡
ν™•μž₯μ„± μ œν•œ λ†’μŒ
검색 속도 빠름 보톡

RDB 쑰회 vs OpenSearch 검색 μ„±λŠ₯ 비ꡐ

  • 1000λͺ…μ˜ μ‚¬μš©μžκ°€ 20μ΄ˆλ™μ•ˆ μš”μ²­ν•˜λŠ” μ‹œλ‚˜λ¦¬μ˜€
    • RDB 쑰회 κΈ°λŠ₯ μ„±λŠ₯ν…ŒμŠ€νŠΈ k6 슀크립트: rdb.js
    • OpenSearch 검색 κΈ°λŠ₯ μ„±λŠ₯ν…ŒμŠ€νŠΈ k6 슀크립트: opensearch.js
RDB OpenSearch
  • p95 κΈ°μ€€ μ•½ 1.76λ°° RDB 쑰회 κΈ°λŠ₯이 더 빠름 (477ms vs 847ms)

RDB 쑰회 vs OpenSearch 검색 ν’ˆμ§ˆ 비ꡐ

  • μš”μ²­ νŒŒλΌλ―Έν„°: ?q=Java&status=OPEN&page=0&size=20
RDB
{
    "items": [
        {
            "id": 20,
            "title": "[μ•„μ •λ‹Ή] ν”Œλž«νΌ λ°±μ—”λ“œ 개발자 (3λ…„ 이상~5λ…„ μ΄ν•˜)",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 20,
                "name": "μ•„μ •λ„€νŠΈμ›μŠ€"
            },
            "skills": [
                "Kotlin",
                "Java",
                "Spring Boot",
                "AWS"
            ]
        },
        {
            "id": 22,
            "title": "λ°±μ—”λ“œ μ—”μ§€λ‹ˆμ–΄",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 22,
                "name": "μ„Έμ»¨μ‹ λ“œλ‘¬"
            },
            "skills": [
                "Kotlin",
                "Java",
                "Spring Boot",
                "MySQL",
                "PostgreSQL",
                "AWS"
            ]
        },
        {
            "id": 23,
            "title": "μ„œλ²„ 개발 λ‹΄λ‹Ήμž",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 23,
                "name": "ν•˜μž…μ•€μ»΄νΌλ‹ˆ"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "AWS"
            ]
        },
        {
            "id": 25,
            "title": "[μ•„μ΄λ””μ–΄μŠ€] λ°±μ—”λ“œ 개발자 (Java/PHP)",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 25,
                "name": "백패컀"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "AWS"
            ]
        },
        {
            "id": 26,
            "title": "컀머슀 λ°±μ—”λ“œ 개발 (5λ…„ 이상)",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 26,
                "name": "ν”ΌλΉ„μ§€"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "Node.js",
                "Python",
                "FastAPI",
                "Django",
                "MySQL",
                "PostgreSQL",
                "AWS"
            ]
        }
      // μƒλž΅ ...
    ]
}
OpenSearch
{
    "items": [
        {
            "id": 25,
            "title": "[μ•„μ΄λ””μ–΄μŠ€] λ°±μ—”λ“œ 개발자 (Java/PHP)",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 25,
                "name": "백패컀"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "AWS"
            ]
        },
        {
            "id": 37,
            "title": "[Tech] Java Backend Developer - μ •μ‚°μ‹œμŠ€ν…œ 운영/개발",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 37,
                "name": "μœ„λŒ€ν•œμƒμƒ"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "MySQL",
                "MongoDB",
                "Kafka",
                "AWS"
            ]
        },
        {
            "id": 23,
            "title": "μ„œλ²„ 개발 λ‹΄λ‹Ήμž",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 23,
                "name": "ν•˜μž…μ•€μ»΄νΌλ‹ˆ"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "AWS"
            ]
        },
        {
            "id": 29,
            "title": "μ›Ή μ„œλΉ„μŠ€ 개발자",
            "location": "Gwacheon",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 29,
                "name": "μ›μŠ€ν† μ–΄"
            },
            "skills": [
                "Kotlin",
                "Java",
                "Javascript",
                "React"
            ]
        },
        {
            "id": 26,
            "title": "컀머슀 λ°±μ—”λ“œ 개발 (5λ…„ 이상)",
            "location": "Seoul",
            "status": "μ±„μš© 쀑",
            "createdAt": "2026-01-21T03:54:57.145811Z",
            "company": {
                "id": 26,
                "name": "ν”ΌλΉ„μ§€"
            },
            "skills": [
                "Java",
                "Spring Boot",
                "Node.js",
                "Python",
                "FastAPI",
                "Django",
                "MySQL",
                "PostgreSQL",
                "AWS"
            ]
        }
      // μƒλž΅ ...
    ]
}
  • OpenSearch의 경우 ν‚€μ›Œλ“œ 검색 μ‹œ ν•„λ“œ κ°€μ€‘μΉ˜μ— 따라 관련도 검색
  • RDB λͺ©λ‘ 쑰회의 경우 ν‚€μ›Œλ“œκ°€ ν¬ν•¨λ˜μ–΄ μžˆλŠ” λ¬Έμ„œ 전체 쑰회
  • 데이터 규λͺ¨κ°€ μ»€μ§€κ±°λ‚˜ ν‚€μ›Œλ“œ λ³΅μž‘λ„κ°€ μ¦κ°€ν•˜λ©΄ ν• μˆ˜λ‘ OpenSearch 검색 ν’ˆμ§ˆ 높아짐

About

πŸ”Ž OpenSearch μ‹€μŠ΅ μ±„μš©κ³΅κ³  검색 ν”„λ‘œμ νŠΈ

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors