Repository of JobDri BackEnd
๋ก์ปฌ ์คํ:
cp .env.example .env
docker compose up --buildํฌํจ ์๋น์ค:
- Spring Boot API:
http://localhost:8080 - FastAPI worker health:
http://localhost:8000/health - RabbitMQ:
amqp://localhost:5672 - RabbitMQ management:
http://localhost:15672
๋ฐฐํฌ ์๋ฒ ์คํ:
cp .env.production.example .env
docker compose -f docker-compose.prod.yml up -dprod ํ๋กํ์ /actuator/health๋ฅผ ๋
ธ์ถํฉ๋๋ค.
ํ์ฌ ๋น๋๊ธฐ ๊ตฌ์กฐ๋ ์๋์ฒ๋ผ ๋ถ๋ฆฌ๋ฉ๋๋ค.
- API ์๋ฒ: task row ์์ฑ, ์ํ ์กฐํ API ์ ๊ณต, RabbitMQ publish, ์ต์ข DB ์ ์ฅ
- RabbitMQ:
job posting ingest์์ ๋ฒํผ๋ง๊ณผ ์ฌ์ ๋ฌ - FastAPI worker: MQ consume, OpenAI ๊ธฐ๋ฐ ์ถ์ถ/๋ถ๋ฅ/์์ฑ ์ํ, ๋ด๋ถ API callback
๋ก์ปฌ์ ํ์ํ ์ถ๊ฐ env:
RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_VHOST=/
APP_WORKER_INTERNAL_API_KEY=change-me-internal-worker-key
APP_WORKER_JOB_POSTING_EXCHANGE=jobdri.worker.exchange
APP_WORKER_JOB_POSTING_QUEUE=jobdri.job-posting.ingest
APP_WORKER_JOB_POSTING_ROUTING_KEY=job-posting.ingest
APP_WORKER_JOB_POSTING_DLQ=jobdri.job-posting.ingest.dlq
WORKER_MAX_RETRY_COUNT=3์ค๋ชจํฌ ํ ์คํธ:
docker compose up --build- ๋ก๊ทธ์ธ ํ ํฐ์ ์ค๋นํฉ๋๋ค.
POST /api/job-postings/ingest๋กrawText๋๋imageObjectKey๋ฅผ ์ ์กํฉ๋๋ค.- ์๋ต์
taskId๋กGET /api/job-postings/ingest/async/{taskId}๋ฅผ ์กฐํํฉ๋๋ค. - worker๊ฐ ์ฑ๊ณตํ๋ฉด
SUCCEEDED, ์คํจํ๋ฉดFAILED์ ์๋ฌ ๋ฉ์์ง๊ฐ ๋ฐํ๋ฉ๋๋ค.
worker ๋จ๋ ์คํ:
python3 -m venv .venv
source .venv/bin/activate
pip install -r worker/requirements.txt
uvicorn worker.app.main:app --host 0.0.0.0 --port 8000๋์ฉ๋ corpus ์์ ์ ์ฌ๋ ๊ด๋ฆฌ์ API ๋์ Python ์คํฌ๋ฆฝํธ๋ก ์ง์ ์คํํ ์ ์์ต๋๋ค.
์ค์น:
python3 -m venv .venv
source .venv/bin/activate
pip install -r scripts/requirements-corpus-import.txt์คํ:
cp .env.example .env
python scripts/import_corpus.py /absolute/path/to/file.xlsx.env์DB_URL,DB_USERNAME,DB_PASSWORD๋ฅผ ์ฌ์ฉํฉ๋๋ค.- ๊ธฐ๋ณธ env ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ฐ๊พธ๋ ค๋ฉด
--env-file /path/to/.env์ต์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. - ์์
์ํธ๋ช
์
jd_embed_corpus,question_embed_corpus๋ฅผ ์ฌ์ฉํฉ๋๋ค. source_analysis_id,source_question_id๊ธฐ์ค์ผ๋กINSERT ... ON CONFLICT DO UPDATE๋ฐฉ์์ผ๋ก ์ ์ฌํฉ๋๋ค.
๊ด๋ฆฌ์ API ๋์ Python ์คํฌ๋ฆฝํธ๋ก corpus ์๋ฒ ๋ฉ์ ์ผ๊ด ๋๊ธฐํํ ์ ์์ต๋๋ค.
์คํ:
source .venv/bin/activate
pip install -r scripts/requirements-corpus-import.txt
python scripts/sync_corpus_embeddings.py --env-file .env์ต์ ์์:
python scripts/sync_corpus_embeddings.py --env-file .env --limit 100
python scripts/sync_corpus_embeddings.py --env-file .env --job-only
python scripts/sync_corpus_embeddings.py --env-file .env --question-only --batch-size 16.env์DB_URL,DB_USERNAME,DB_PASSWORD,COHERE_API_KEY๋ฅผ ์ฌ์ฉํฉ๋๋ค.- ๊ธฐ๋ณธ ๋ชจ๋ธ์
embed-v4.0, ๊ธฐ๋ณธ ๋ฐฐ์น ํฌ๊ธฐ๋32์ ๋๋ค. mock_job_posting_embeddings,mock_question_embeddingsํ ์ด๋ธ์INSERT ... ON CONFLICT DO UPDATE๋ฐฉ์์ผ๋ก ์ ์ฌํฉ๋๋ค.
CI:main,develop๋ธ๋์น push ๋ฐ PR์์ ํ ์คํธ์ Docker ์ด๋ฏธ์ง ๋น๋๋ฅผ ์คํํฉ๋๋ค.Deploy:main๋ธ๋์น push ๋๋ ์๋ ์คํ ์ GHCR์ ์ด๋ฏธ์ง๋ฅผ ํธ์ํ๊ณ , ๋ฐฐํฌ ์๋ฒ secret์ด ์์ผ๋ฉด SSH๋กdocker-compose.prod.yml์ ๊ฐฑ์ ํฉ๋๋ค.
GitHub Actions ๋ฐฐํฌ secret:
DEPLOY_HOSTDEPLOY_USERDEPLOY_PORToptional, default22DEPLOY_SSH_KEYDEPLOY_PATHGHCR_USERNAMEGHCR_TOKEN
๋ฐฑ์๋ API๋ Docker ์ด๋ฏธ์ง๋ก ๋น๋๋์ด GHCR์ ์ ๋ก๋๋๊ณ , GitHub Actions๋ฅผ ํตํด EC2 ์๋ฒ์ ๋ฐฐํฌ๋ฉ๋๋ค.
- ์๋ฒ: AWS EC2
t3.small - OS: Amazon Linux 2023
- DB: AWS RDS PostgreSQL
db.t3.micro - Redis: Upstash Redis
- ์น ์๋ฒ: Nginx
- ์ปจํ ์ด๋ ๋ฐํ์: Docker, Docker Compose
main๋ธ๋์น์ ๋ณ๊ฒฝ์ฌํญ์ด ๋ฐ์๋ฉ๋๋ค.- GitHub Actions๊ฐ Docker ์ด๋ฏธ์ง๋ฅผ ๋น๋ํฉ๋๋ค.
- ์ด๋ฏธ์ง๋ฅผ GHCR์ ํธ์ํฉ๋๋ค.
- GitHub Actions๊ฐ EC2์ SSH๋ก ์ ์ํฉ๋๋ค.
- EC2์์
docker-compose.prod.yml์ ์ฌ์ฉํด ์ต์ ์ด๋ฏธ์ง๋ฅผ pullํ๊ณ API ์ปจํ ์ด๋๋ฅผ ์ฌ๊ธฐ๋ํฉ๋๋ค.
/opt/jobdri-api์๋ฒ์๋ ์๋ ํ์ผ์ด ํ์ํฉ๋๋ค.
docker-compose.prod.yml
.env
์ด์ API๋ Nginx reverse proxy์ Let's Encrypt ์ธ์ฆ์๋ฅผ ํตํด HTTPS๋ก ์ ๊ณต๋ฉ๋๋ค.
https://api.jobdri.site
- Nginx๋ 80/443 ์์ฒญ์ Spring Boot API ์ปจํ ์ด๋์ 8080 ํฌํธ๋ก ํ๋ก์ํฉ๋๋ค.
- SSL ์ธ์ฆ์๋ Certbot์ผ๋ก ๋ฐ๊ธํ์ผ๋ฉฐ ์๋ ๊ฐฑ์ ์ด ์ค์ ๋์ด ์์ต๋๋ค.
- ์ํ ํ์ธ:
https://api.jobdri.site/actuator/health
์ ์ ์๋ต:
{"status":"UP","groups":["liveness","readiness"]}