diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cdbece7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# OS +.DS_Store +Thumbs.db + +# Python +__pycache__/ +*.py[cod] +*.egg-info/ +*.egg +dist/ +build/ + +# Logs +log/**/*.log + +# Redis data +compose/redis/data/ + +# SSL certificates +compose/ssl/certs/ +compose/ssl/letsencrypt/ + +# Application code (mounted volume) +www/*/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Claude +.claude/ diff --git a/README.md b/README.md index 6b0c8d0..12bfc89 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,7 @@ aio2o의 분산된 인프라 서비스 및 설정을 단일 프로젝트로 통 - **FastAPI 애플리케이션 서버**: Gunicorn + Uvicorn ASGI 워커 기반의 비동기 Python 웹 서버 - **Nginx 리버스 프록시**: SSL/TLS 지원, 정적 파일 서빙, WebSocket 지원 -- **데이터베이스**: PostgreSQL 및 MySQL(Percona) 지원 -- **캐싱 및 메시지 브로커**: Redis 기반 캐싱 및 Celery 태스크 큐 지원 +- **캐싱**: Redis 기반 캐싱 지원 - **SSL 인증서 자동화**: Let's Encrypt + Certbot 자동 갱신 - **로그 관리**: 일별 로그 로테이션 및 30일 보관 @@ -19,9 +18,7 @@ aio2o의 분산된 인프라 서비스 및 설정을 단일 프로젝트로 통 | 프레임워크 | FastAPI | | ASGI 서버 | Gunicorn + Uvicorn | | 웹 서버 | Nginx 1.26 | -| 데이터베이스 | PostgreSQL, MySQL (Percona) | -| 캐시/브로커 | Redis | -| 태스크 큐 | Celery + Celery Beat | +| 캐시 | Redis | | 컨테이너 | Docker, Docker Compose | ## 디렉토리 구조 @@ -31,17 +28,12 @@ o2o-infrakit/ ├── compose/ # Docker Compose 설정 │ ├── docker-compose.yml # 메인 오케스트레이션 파일 │ ├── .env # 환경 변수 -│ ├── mysql/ # MySQL 데이터 볼륨 -│ ├── pgdata/ # PostgreSQL 데이터 볼륨 │ ├── redis/ # Redis 설정 및 데이터 │ └── ssl/ # SSL 인증서 및 Let's Encrypt │ ├── config/ # 서비스별 설정 │ ├── app-server/ # 애플리케이션 서버 설정 │ │ └── gunicorn_uvicorn.conf.py -│ ├── database/ # 데이터베이스 설정 -│ │ ├── mysql/ # MySQL 설정 (my.cnf, init.sql) -│ │ └── postgresql/ # PostgreSQL 설정 │ └── web-server/ # 웹 서버 설정 │ ├── nginx_conf/ # Nginx 메인 설정 │ ├── conf.d/ # 도메인별 Nginx 설정 @@ -57,9 +49,7 @@ o2o-infrakit/ │ └── logrotate/ # 로그 로테이션 설정 │ ├── log/ # 로그 디렉토리 (볼륨) -│ ├── mysql/ # MySQL 로그 │ ├── nginx/ # Nginx 액세스/에러 로그 -│ ├── postgresql/ # PostgreSQL 로그 │ └── uvicorn/ # Uvicorn/FastAPI 로그 │ └── www/ # 애플리케이션 코드 볼륨 @@ -86,10 +76,8 @@ cp .env.example .env 주요 환경 변수: - `PROJECT_DIR`: 애플리케이션 프로젝트 디렉토리명 -- `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`: PostgreSQL 접속 정보 -- `CELERY_BROKER_URL`: Celery 브로커 URL -### 2. 데이터베이스 볼륨 권한 설정 +### 2. Redis 볼륨 권한 설정 ```bash cd compose @@ -99,13 +87,78 @@ chmod +x set_mysql_permission.sh ### 3. SSL 인증서 설정 (선택) +Let's Encrypt를 통해 무료 SSL 인증서를 발급받습니다. 이 스크립트는 **Nginx 컨테이너 내부**에서 실행해야 합니다. + ```bash -cd script +docker exec -it nginx-uvicorn-webserver bash +cd /script chmod +x letsencrypt.sh ./letsencrypt.sh ``` -### 4. 컨테이너 실행 +스크립트 실행 시 아래 3가지 정보를 순서대로 입력해야 합니다: + +| 입력 항목 | 설명 | 예시 | +|-----------|------|------| +| **webroot_folder** | Nginx 웹 루트 디렉토리명 (`/www/` 하위 경로) | `o2o-castad-frontend` | +| **domain** | 인증서를 발급할 도메인 (공백으로 구분하여 여러 개 입력 가능, 메인 도메인을 먼저 입력) | `example.com www.example.com api.example.com` | +| **e-mail** | 인증서 만료 알림을 받을 이메일 주소 | `admin@example.com` | + +스크립트 동작 순서: +1. Certbot 및 필수 패키지 설치 +2. OpenSSL DH 파라미터 생성 (4096bit, 최초 1회) +3. Certbot을 통한 SSL 인증서 발급 (webroot 방식) +4. 자동 갱신 cron 등록 (매주 월요일 오전 5시) + +### 4. Nginx 설정 파일 생성 + +서비스 도메인에 맞는 Nginx conf 파일을 자동 생성하는 스크립트입니다. 템플릿 기반으로 동작하며, HTTP 또는 HTTPS 용도에 따라 스크립트를 선택합니다. + +```bash +cd config/web-server +``` + +#### HTTP 설정 파일 생성 + +```bash +chmod +x nginx_conf.sh +./nginx_conf.sh +``` + +`sample_nginx.conf` 템플릿을 기반으로 HTTP conf 파일을 생성합니다. + +#### HTTPS 설정 파일 생성 + +```bash +chmod +x nginx_https_conf.sh +./nginx_https_conf.sh +``` + +`sample_nginx_https.conf` 템플릿을 기반으로 HTTPS conf 파일을 생성합니다. HTTP → HTTPS 리다이렉트, SSL/TLS 설정, 보안 헤더, WebSocket 지원 등이 포함됩니다. + +#### 입력 항목 + +두 스크립트 모두 동일한 항목을 입력받습니다: + +| 입력 항목 | 필수 | 설명 | 예시 | +|-----------|------|------|------| +| **webroot** | O | 웹 루트 경로 (`/www/` 하위). 하위 경로가 있으면 `\/`로 구분 | `o2o-castad-frontend` | +| **portnumber** | O | Nginx가 수신할 포트 번호 | `80` | +| **domain** | O | 서비스 도메인 | `example.com` | +| **appname** | O | 프록시 대상 컨테이너(서비스)명 | `uvicorn-app` | +| **serviceport** | - | 프록시 대상 포트 (빈 값 입력 시 포트 없이 설정) | `8000` | +| **filename** | O | 생성될 conf 파일의 접두사 | `example` | + +#### 생성 파일 경로 + +| 스크립트 | 생성 경로 | +|----------|-----------| +| `nginx_conf.sh` | `config/web-server/conf.d/{filename}_gunicorn_ng.conf` | +| `nginx_https_conf.sh` | `config/web-server/conf.d/{filename}_gunicorn_https_ng.conf` | + +생성된 conf 파일은 Nginx 컨테이너의 `/etc/nginx/conf.d/` 디렉토리에 볼륨 마운트되어 자동으로 로드됩니다. + +### 5. 컨테이너 실행 ```bash cd compose @@ -120,9 +173,7 @@ docker compose up -d |--------|------|------| | nginx | 리버스 프록시, SSL 종료 | 80, 443 | | uvicorn-app | FastAPI 애플리케이션 | 8000 (내부) | -| redis | 캐시 및 메시지 브로커 | 6379 (내부) | -| postgresql | 데이터베이스 | 5432 (내부) | -| mysql | 데이터베이스 (선택) | 3306 (내부) | +| redis | 캐시 | 6379 (내부) | ### Gunicorn 설정 (config/app-server/gunicorn_uvicorn.conf.py) @@ -132,13 +183,157 @@ docker compose up -d - **최대 요청**: 1000 (메모리 누수 방지) - **바인드**: 0.0.0.0:8000 -### Nginx 설정 (config/web-server/nginx_conf/nginx.conf) +### Nginx 메인 설정 (config/web-server/nginx_conf/nginx.conf) -- **워커 프로세스**: auto (CPU 코어 수에 맞게 자동 조정) -- **워커 연결**: 1024/프로세스 -- **Keep-alive**: 30초 -- **최대 요청 본문**: 50MB -- **프록시 타임아웃**: 300초 +Nginx 전역 동작을 제어하는 메인 설정 파일입니다. 컨테이너 내 `/etc/nginx/nginx.conf`에 마운트되며, 모든 서버 블록에 공통 적용됩니다. + +#### 워커 설정 + +| 항목 | 기본값 | 설명 | +|------|--------|------| +| `worker_processes` | `auto` | 워커 프로세스 수. `auto`는 CPU 코어 수에 맞게 자동 설정 | +| `worker_rlimit_nofile` | `8192` | 워커당 열 수 있는 최대 파일 디스크립터 수 | +| `worker_connections` | `1024` | 워커당 동시 연결 수. 최대 동시 연결 = `worker_processes × worker_connections` | +| `multi_accept` | `off` | `off` 시 워커 간 균등한 연결 분배로 안정적 성능 확보 | +| `use` | `epoll` | 리눅스 환경에서 권장하는 이벤트 처리 방식 | + +#### HTTP 설정 + +| 항목 | 기본값 | 설명 | +|------|--------|------| +| `keepalive_timeout` | `30s` | 클라이언트 연결 유지 시간 | +| `keepalive_requests` | `1000` | 하나의 keep-alive 연결에서 처리할 최대 요청 수 | +| `client_max_body_size` | `50M` | 최대 업로드 크기. 대용량 파일 업로드 시 증가 필요 | +| `client_body_buffer_size` | `128k` | 요청 본문 버퍼 크기 (64KB~256KB 권장) | +| `client_body_timeout` | `15s` | 클라이언트 본문 수신 타임아웃 | +| `client_header_timeout` | `15s` | 클라이언트 헤더 수신 타임아웃 | +| `send_timeout` | `15s` | 클라이언트로 응답 전송 타임아웃 | + +#### 프록시 설정 + +| 항목 | 기본값 | 설명 | +|------|--------|------| +| `proxy_connect_timeout` | `300s` | 백엔드 연결 타임아웃 | +| `proxy_send_timeout` | `300s` | 백엔드로 요청 전송 타임아웃 | +| `proxy_read_timeout` | `300s` | 백엔드 응답 수신 타임아웃 | +| `proxy_request_buffering` | `off` | 대용량 파일 스트리밍 업로드를 위해 비활성화 | + +#### 압축 설정 + +| 항목 | 기본값 | 설명 | +|------|--------|------| +| `gzip` | `off` | 실시간 압축 비활성화 (CPU 부하 감소) | +| `gzip_static` | `on` | 미리 압축된 `.gz` 파일 제공 방식 사용 | +| `gzip_vary` | `on` | `Vary: Accept-Encoding` 헤더 추가 (프록시 캐시 호환성) | + +#### 기타 + +- **`server_tokens off`**: Nginx 버전 정보 노출 차단 +- **`resolver 127.0.0.11`**: Docker 내부 DNS를 사용하여 컨테이너 이름 해석 +- **`map $http_upgrade`**: WebSocket과 일반 HTTP 요청을 동적으로 구분하여 Connection 헤더 설정 + +### 프록시 헤더 설정 (config/web-server/proxy_params/proxy_params) + +모든 서버 블록에서 공통으로 사용하는 프록시 헤더 설정 파일입니다. `nginx.conf`의 `http` 블록에서 `include`되어 전역 적용됩니다. + +| 헤더/설정 | 값 | 설명 | +|-----------|-----|------| +| `Host` | `$http_host` | 클라이언트가 요청한 원본 호스트 정보를 백엔드에 전달 | +| `X-Real-IP` | `$remote_addr` | 클라이언트 실제 IP 주소 전달 | +| `X-Forwarded-For` | `$proxy_add_x_forwarded_for` | 프록시 체인을 거친 클라이언트 IP 목록 | +| `X-Forwarded-Proto` | `$scheme` | 원본 요청 프로토콜 (http/https) 전달 | +| `Upgrade` | `$http_upgrade` | WebSocket 업그레이드 요청 헤더 전달 | +| `Connection` | `$connection_upgrade` | WebSocket 연결 시 `upgrade`, 일반 요청 시 빈 값 | +| `proxy_cache_bypass` | `$http_upgrade` | WebSocket 요청은 캐시를 우회 | +| `proxy_buffering` | `off` | 응답 버퍼링 비활성화 (실시간 스트리밍/SSE 지원) | +| `proxy_redirect` | `off` | 백엔드 리다이렉트 URL 재작성 비활성화 | +| `proxy_buffers` | `32 4k` | 프록시 응답 버퍼 개수 및 크기 | +| `proxy_headers_hash_max_size` | `512` | 프록시 헤더 해시 테이블 크기 | +| `proxy_headers_hash_bucket_size` | `64` | 프록시 헤더 해시 버킷 크기 | + +### 도메인별 서버 설정 (conf.d/) + +`nginx_conf.sh` 또는 `nginx_https_conf.sh`로 생성되는 도메인별 서버 블록 설정입니다. + +#### HTTP conf 설정 가이드 (sample_nginx.conf 기반) + +`nginx_conf.sh`로 생성되는 HTTP 전용 서버 블록의 주요 설정입니다. + +| 설정 | 템플릿 변수 | 설명 | 설정 가이드 | +|------|-------------|------|-------------| +| `listen` | `portnumber` | 수신 포트 | 일반적으로 `80`. 내부 서비스는 다른 포트 사용 가능 | +| `server_name` | `domain` | 서비스 도메인 | `example.com www.example.com` 형식으로 입력 | +| `access_log` | `filename` | 액세스 로그 경로 | `/log/nginx/{filename}.com.gunicorn_access.log` 형식으로 자동 생성 | +| `error_log` | `filename` | 에러 로그 경로 | `/log/nginx/{filename}.com.gunicorn_error.log` 형식으로 자동 생성 | +| `location /media` | `webroot` | 미디어 파일 경로 | `/www/{webroot}/media` — 사용자 업로드 파일 서빙 경로 | +| `location /static` | `webroot` | 정적 파일 경로 | `/www/{webroot}/static` — CSS, JS, 이미지 등 정적 리소스 경로 | +| `proxy_pass` | `appname`, `serviceport` | 백엔드 프록시 | `http://{appname}:{serviceport}` — Docker Compose 서비스명과 포트 | +| `location /.well-known` | `webroot` | ACME 챌린지 | Let's Encrypt 인증서 발급/갱신을 위한 경로. 수정 불필요 | + +**보안 설정** (자동 포함, 수정 불필요): +- 닷 파일 차단 (`.env`, `.git` 등) +- 민감한 파일 확장자 차단 (`.log`, `.sql`, `.key` 등) +- 설정 파일 접근 차단 (`composer.json`, `package.json` 등) + +#### HTTPS conf 설정 가이드 (sample_nginx_https.conf 기반) + +`nginx_https_conf.sh`로 생성되는 HTTPS 서버 블록의 주요 설정입니다. HTTP conf의 모든 설정을 포함하며, 추가로 아래 설정이 적용됩니다. + +**HTTP → HTTPS 리다이렉트 (포트 80)** + +| 설정 | 설명 | 설정 가이드 | +|------|------|-------------| +| `server_name` | 리다이렉트 대상 도메인 | HTTPS 서버 블록과 동일한 도메인 설정 | +| 호스트 검증 정규식 | 허용되지 않은 도메인 차단 | 도메인 확장자가 `.com`, `.kr`, `.net`, `.org` 외라면 정규식에 추가 필요 | +| `return 301` | HTTPS로 영구 리다이렉트 | 수정 불필요 | + +**SSL/TLS 인증서 (포트 443)** + +| 설정 | 설명 | 설정 가이드 | +|------|------|-------------| +| `ssl_certificate` | SSL 인증서 경로 | `/etc/letsencrypt/live/{domain}/fullchain.pem` — `letsencrypt.sh` 실행 시 자동 생성 | +| `ssl_certificate_key` | SSL 개인키 경로 | `/etc/letsencrypt/live/{domain}/privkey.pem` — 자동 생성 | +| `ssl_dhparam` | DH 파라미터 경로 | `/etc/ssl/certs/{domain}/dhparam.pem` — `letsencrypt.sh` 실행 시 자동 생성 | +| `ssl_protocols` | 허용 TLS 버전 | `TLSv1.2 TLSv1.3` — 최신 프로토콜만 사용. TLSv1.0/1.1은 보안 취약 | +| `ssl_session_cache` | SSL 세션 캐시 | `shared:SSL:50m` — 트래픽이 많을수록 크기 증가 권장 | +| `ssl_session_timeout` | SSL 세션 타임아웃 | `10m` — 세션 재사용으로 핸드셰이크 오버헤드 감소 | +| `ssl_session_tickets` | 세션 티켓 | `off` — 보안 강화를 위해 비활성화 | +| `ssl_stapling` | OCSP 스테이플링 | `on` — SSL 핸드셰이크 성능 향상 | +| `ssl_trusted_certificate` | OCSP 신뢰 인증서 | `/etc/letsencrypt/live/{domain}/chain.pem` — 자동 생성 | + +**보안 헤더** + +| 헤더 | 기본값 | 설명 | 설정 가이드 | +|------|--------|------|-------------| +| `Strict-Transport-Security` | `max-age=63072000` | HSTS — 브라우저가 항상 HTTPS 사용 강제 | 최초 적용 시 `max-age`를 짧게 설정하여 테스트 후 증가 권장 | +| `X-Frame-Options` | `DENY` | 클릭재킹 방지. iframe 삽입 차단 | 외부 iframe 허용이 필요하면 `SAMEORIGIN`으로 변경 | +| `X-Content-Type-Options` | `nosniff` | MIME 스니핑 방지 | 수정 불필요 | +| `X-XSS-Protection` | `1; mode=block` | 레거시 XSS 보호 | 수정 불필요 | +| `Referrer-Policy` | `strict-origin-when-cross-origin` | 리퍼러 정보 제어 | 수정 불필요 | +| `Content-Security-Policy` | `default-src 'self'` | XSS 방지를 위한 CSP | **반드시 서비스에 맞게 수정 필요**. `unsafe-inline`은 프로덕션에서 nonce/hash 방식으로 대체 권장 | + +**프록시 및 성능 설정** + +| 설정 | 기본값 | 설명 | 설정 가이드 | +|------|--------|------|-------------| +| `client_max_body_size` | `100M` | 최대 업로드 크기 | 대용량 파일 업로드 서비스는 증가 필요 | +| `proxy_connect_timeout` | `60s` | 백엔드 연결 타임아웃 | 장시간 처리 작업이 있으면 증가 | +| `proxy_send_timeout` | `60s` | 백엔드 요청 전송 타임아웃 | 대용량 업로드 시 증가 | +| `proxy_read_timeout` | `60s` | 백엔드 응답 수신 타임아웃 | AI 추론 등 오래 걸리는 API가 있으면 증가 | +| `proxy_buffering` | `on` | 응답 버퍼링 | WebSocket/SSE 사용 시 `off`로 변경 | +| `proxy_request_buffering` | `on` | 요청 버퍼링 | WebSocket/SSE 사용 시 `off`로 변경 | +| `open_file_cache` | `max=1000 inactive=20s` | 파일 캐시 | 정적 파일이 많으면 `max` 값 증가 | +| `limit_req` | `zone=general burst=20` | 요청 속도 제한 (DDoS 방지) | `burst` 값은 순간 트래픽 허용량. `nginx.conf`의 `limit_req_zone` 정의 필요 | +| `limit_conn` | `addr 10` | IP당 동시 연결 제한 | `nginx.conf`의 `limit_conn_zone` 정의 필요 | +| `limit_except` | `GET POST HEAD OPTIONS` | 허용 HTTP 메서드 | PUT, DELETE 등이 필요하면 허용 목록에 추가 | + +**정적 리소스 캐싱** + +| 설정 | 기본값 | 설명 | +|------|--------|------| +| `/media` 경로 | `expires 30d` | 미디어 파일 30일 캐시 | +| `/static` 경로 | `expires 30d` | 정적 파일 30일 캐시 | +| 이미지/폰트/CSS/JS | `expires 1y` | 정적 리소스 1년 캐시. `Cache-Control: public, immutable` 적용 | ## 운영 기능 @@ -165,7 +360,5 @@ docker compose up -d | 스크립트 | 설명 | |----------|------| | `script/letsencrypt.sh` | Let's Encrypt SSL 인증서 발급 | -| `compose/set_mysql_permission.sh` | 데이터베이스 볼륨 권한 설정 | +| `compose/set_mysql_permission.sh` | Redis 볼륨 권한 설정 | | `script/crontab_gunicorn_set.sh` | 컨테이너 자동 재시작 cron 설정 | - - diff --git a/compose/.env b/compose/.env index eb3fc39..836873d 100644 --- a/compose/.env +++ b/compose/.env @@ -2,10 +2,3 @@ PROJECT_DIR=o2o-castad-backend LOG_DRIVER=json-file LOG_OPT_MAXF=5 LOG_OPT_MAXS=100m -CELERY_BROKER_URL=redis://redis:6379/3 -FLOWER_ID=admin -FLOWER_PWD=admin -POSTGRES_DB=ado3_dev -POSTGRES_USER=ado3_dev_admin -POSTGRES_PASSWORD=ado31324 -MYSQL_PASSWORD=ado31324 \ No newline at end of file diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index ba35659..8a8abe9 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -21,7 +21,6 @@ services: ports: - 80:80 - 443:443 - # - 8000:8000 environment: TZ: "Asia/Seoul" restart: always @@ -70,25 +69,3 @@ services: TZ: "Asia/Seoul" restart: always command: redis-server /usr/local/etc/redis/redis.conf - - # mysql: - # image: percona/percona-server:latest - # logging: - # driver: "${LOG_DRIVER}" - # options: - # max-file: "${LOG_OPT_MAXF}" - # max-size: "${LOG_OPT_MAXS}" - # container_name: mysql - # environment: - # MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD} - # TZ: Asia/Seoul - # ports: - # - "3306:3306" - # volumes: - # - ./mysql:/var/lib/mysql - # - ../config/database/mysql/my.cnf:/etc/my.cnf - # # - ../config/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro - # - ../log/mysql:/var/log/mysql - # restart: always - # profiles: - # - mysql diff --git a/compose/mysql/.gitkeep b/compose/mysql/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/compose/pgdata/.gitkeep b/compose/pgdata/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/compose/redis/data/dump.rdb b/compose/redis/data/dump.rdb deleted file mode 100644 index 7d8d174..0000000 Binary files a/compose/redis/data/dump.rdb and /dev/null differ diff --git a/compose/set_mysql_permission.sh b/compose/set_mysql_permission.sh index aaea530..15d8ad4 100755 --- a/compose/set_mysql_permission.sh +++ b/compose/set_mysql_permission.sh @@ -1,67 +1,15 @@ #!/usr/bin/env bash # ============================================================ -# set_mysql_permission.sh -# MySQL, PostgreSQL, Redis 데이터 디렉터리 권한 설정 스크립트 +# set_permission.sh +# Redis 데이터 디렉터리 권한 설정 스크립트 # ============================================================ # 스크립트 실행 경로 기준 -MYSQL_DIR="./mysql" -PGDATA_DIR="./pgdata" REDIS_DIR="./redis" -# ============================================================ -# MySQL (Percona) 권한 설정 -# ============================================================ -echo "[MySQL] 데이터 디렉터리 권한 설정을 시작합니다..." -echo "[MySQL] 대상 디렉터리: $MYSQL_DIR" - -if [ ! -d "$MYSQL_DIR" ]; then - echo "[MySQL] $MYSQL_DIR 디렉터리가 존재하지 않아 새로 생성합니다." - sudo mkdir -p "$MYSQL_DIR" -fi - -# Percona의 mysql 유저 UID는 보통 1001 -MYSQL_UID=1001 -MYSQL_GID=1001 - -echo "[MySQL] 소유권을 $MYSQL_UID:$MYSQL_GID 로 변경합니다..." -sudo chown -R ${MYSQL_UID}:${MYSQL_GID} "$MYSQL_DIR" - -echo "[MySQL] 권한을 750 (rwxr-x---) 으로 설정합니다..." -sudo chmod -R 750 "$MYSQL_DIR" - -echo "[MySQL] 적용 결과:" -ls -ld "$MYSQL_DIR" - -# ============================================================ -# PostgreSQL 권한 설정 -# ============================================================ -echo "" -echo "[PostgreSQL] 데이터 디렉터리 권한 설정을 시작합니다..." -echo "[PostgreSQL] 대상 디렉터리: $PGDATA_DIR" - -if [ ! -d "$PGDATA_DIR" ]; then - echo "[PostgreSQL] $PGDATA_DIR 디렉터리가 존재하지 않아 새로 생성합니다." - sudo mkdir -p "$PGDATA_DIR" -fi - -# PostgreSQL의 postgres 유저 UID는 보통 999 (공식 Docker 이미지 기준) -POSTGRES_UID=999 -POSTGRES_GID=999 - -echo "[PostgreSQL] 소유권을 $POSTGRES_UID:$POSTGRES_GID 로 변경합니다..." -sudo chown -R ${POSTGRES_UID}:${POSTGRES_GID} "$PGDATA_DIR" - -echo "[PostgreSQL] 권한을 700 (rwx------) 으로 설정합니다..." -sudo chmod -R 700 "$PGDATA_DIR" - -echo "[PostgreSQL] 적용 결과:" -ls -ld "$PGDATA_DIR" - # ============================================================ # Redis 권한 설정 # ============================================================ -echo "" echo "[Redis] 데이터 디렉터리 권한 설정을 시작합니다..." echo "[Redis] 대상 디렉터리: $REDIS_DIR" diff --git a/config/database/mysql/init.sql b/config/database/mysql/init.sql deleted file mode 100644 index 1ccc7dd..0000000 --- a/config/database/mysql/init.sql +++ /dev/null @@ -1,5 +0,0 @@ --- 1. admin 권한 계정 생성 -CREATE USER IF NOT EXISTS 'devadmin'@'%' IDENTIFIED BY 'test!'; --- 2. 전체 권한 부여 -GRANT ALL PRIVILEGES ON *.* TO 'devadmin'@'%' WITH GRANT OPTION; -FLUSH PRIVILEGES; \ No newline at end of file diff --git a/config/database/mysql/my.cnf b/config/database/mysql/my.cnf deleted file mode 100644 index 4f36fcb..0000000 --- a/config/database/mysql/my.cnf +++ /dev/null @@ -1,546 +0,0 @@ -# ======================================================================== -# Percona Server / MySQL 8.0 최적화 설정 -# 하드웨어 사양: 4코어 CPU, 4GB RAM, SSD, 1GB LAN -# ======================================================================== - -[mysqld] - -# ------------------------------------------------------------------------ -# 기본 경로 설정 -# ------------------------------------------------------------------------ -datadir=/var/lib/mysql -socket=/var/lib/mysql/mysql.sock -pid-file=/var/run/mysqld/mysqld.pid - -# ------------------------------------------------------------------------ -# 네트워크 및 연결 설정 -# ------------------------------------------------------------------------ - -# 바인드 주소 -bind-address = 0.0.0.0 -# 기본값: 127.0.0.1 (로컬만) -# 변경값: 0.0.0.0 (모든 IP) -# 목적: 원격 접속 허용 -# 보안: 방화벽 설정 필수 - -# 포트 -port = 3306 -# 기본값: 3306 -# MySQL 표준 포트 - -# 최대 연결 수 -max_connections = 200 -# 기본값: 151 -# 변경값: 200 -# 목적: 4GB RAM 환경에서 충분한 연결 수 제공 -# 계산: 각 연결당 약 4-8MB 메모리 사용 -# 200 연결 = 최대 1.6GB 메모리 (버퍼 포함) -# 참고: 연결 풀링(ProxySQL, MaxScale) 사용 시 더 효율적 - -max_connect_errors = 1000000 -# 기본값: 100 -# 변경값: 1000000 -# 목적: 연결 오류로 인한 호스트 차단 방지 -# 성능: 네트워크 이슈로 인한 불필요한 차단 감소 - -# 대기 시간 설정 -wait_timeout = 600 -# 기본값: 28800 (8시간) -# 변경값: 600 (10분) -# 목적: 유휴 연결 자동 정리 -# 성능: 불필요한 연결 점유 방지 - -interactive_timeout = 600 -# 기본값: 28800 -# 변경값: 600 -# 목적: 대화형 클라이언트 타임아웃 -# 성능: 리소스 효율적 관리 - -connect_timeout = 10 -# 기본값: 10 -# 유지 이유: 연결 시도 타임아웃 - -# 스레드 캐시 -thread_cache_size = 50 -# 기본값: 8 -# 변경값: 50 -# 목적: 스레드 재사용으로 연결 생성 오버헤드 감소 -# 성능: 연결 빈도가 높은 환경에서 효과적 -# 계산: max_connections의 약 25% - -# 백로그 큐 -back_log = 512 -# 기본값: 80 -# 변경값: 512 -# 목적: 대기 중인 연결 요청 큐 크기 -# 성능: 트래픽 버스트 시 연결 손실 방지 - -# ------------------------------------------------------------------------ -# InnoDB 버퍼 풀 설정 (가장 중요!) -# ------------------------------------------------------------------------ - -innodb_buffer_pool_size = 2G -# 기본값: 128MB -# 변경값: 2GB (전체 RAM 4GB의 50%) -# 목적: 데이터와 인덱스를 메모리에 캐싱 -# 성능: 디스크 I/O를 크게 감소시키는 가장 중요한 설정 -# 권장: 전용 서버는 RAM의 70-80%, 혼합 환경은 50-60% -# 계산: 2GB buffer pool + 1GB 연결/쿼리 + 1GB OS/기타 - -innodb_buffer_pool_instances = 4 -# 기본값: 1 (또는 자동) -# 변경값: 4 -# 목적: 버퍼 풀을 여러 인스턴스로 분할하여 동시성 향상 -# 성능: 멀티 코어 환경에서 잠금 경합 감소 -# 권장: CPU 코어 수와 동일하게 설정 -# 참고: buffer_pool_size >= 1GB일 때만 효과적 - -innodb_buffer_pool_chunk_size = 128M -# 기본값: 128MB -# 유지 이유: buffer_pool_size가 instances × chunk_size의 배수여야 함 -# 계산: 2GB = 4 instances × 4 chunks × 128MB - -# ------------------------------------------------------------------------ -# InnoDB 로그 설정 -# ------------------------------------------------------------------------ - -innodb_log_file_size = 512M -# 기본값: 48MB -# 변경값: 512MB -# 목적: Redo 로그 파일 크기 -# 성능: 쓰기 집약적 워크로드에서 체크포인트 빈도 감소 -# 권장: buffer_pool_size의 25% 정도 -# 주의: 너무 크면 크래시 복구 시간 증가 - -innodb_log_buffer_size = 32M -# 기본값: 16MB -# 변경값: 32MB -# 목적: Redo 로그 버퍼 -# 성능: 디스크 쓰기 전 로그를 메모리에 버퍼링 -# 권장: 대용량 트랜잭션이 많으면 증가 - -innodb_flush_log_at_trx_commit = 1 -# 기본값: 1 -# 유지 이유: ACID 보장 (데이터 무결성) -# 옵션: -# 0: 로그를 메모리에만 (속도↑, 안정성↓↓) -# 1: 매 커밋마다 디스크에 flush (속도↓, 안정성↑↑) ← 권장 -# 2: OS 캐시까지만 (속도↑, 안정성↑) -# 주의: 성능을 위해 2로 변경 가능하나 크래시 시 1초 데이터 손실 - -innodb_flush_method = O_DIRECT -# 기본값: fsync (Linux) -# 변경값: O_DIRECT -# 목적: OS 파일 시스템 캐시 우회 -# 성능: 이중 버퍼링 방지, SSD 환경에서 효과적 -# 권장: SSD 사용 시 필수 설정 - -# ------------------------------------------------------------------------ -# InnoDB I/O 설정 (SSD 최적화) -# ------------------------------------------------------------------------ - -innodb_io_capacity = 2000 -# 기본값: 200 (HDD 기준) -# 변경값: 2000 -# 목적: InnoDB가 초당 수행할 수 있는 I/O 작업 수 -# 성능: SSD의 높은 IOPS 활용 -# 권장: SSD는 2000-5000, NVMe는 10000+ -# 측정: fio 벤치마크로 실제 IOPS 측정 후 70% 수준으로 설정 - -innodb_io_capacity_max = 4000 -# 기본값: 2000 -# 변경값: 4000 (io_capacity의 2배) -# 목적: 긴급 상황(체크포인트 등)에서 최대 I/O -# 성능: 버스트 상황에서 더 많은 I/O 허용 - -innodb_read_io_threads = 4 -# 기본값: 4 -# 유지 이유: CPU 코어 수와 일치 -# 목적: 읽기 작업을 위한 I/O 스레드 - -innodb_write_io_threads = 4 -# 기본값: 4 -# 유지 이유: CPU 코어 수와 일치 -# 목적: 쓰기 작업을 위한 I/O 스레드 - -innodb_flush_neighbors = 0 -# 기본값: 1 (HDD 최적화) -# 변경값: 0 -# 목적: 인접 페이지 flush 비활성화 -# 성능: SSD는 랜덤 쓰기가 빠르므로 불필요 -# 권장: SSD 환경에서는 반드시 0으로 설정 - -# ------------------------------------------------------------------------ -# InnoDB 동시성 설정 -# ------------------------------------------------------------------------ - -innodb_thread_concurrency = 0 -# 기본값: 0 (무제한) -# 유지 이유: MySQL이 자동으로 최적화 -# 목적: 동시 실행 스레드 수 제한 -# 참고: 특정 워크로드에서 제한이 필요한 경우 CPU 코어 수 × 2 - -innodb_lock_wait_timeout = 50 -# 기본값: 50 -# 유지 이유: 락 대기 타임아웃 (초) -# 성능: 데드락 상황 빠른 감지 - -# ------------------------------------------------------------------------ -# 테이블 및 파일 설정 -# ------------------------------------------------------------------------ - -innodb_file_per_table = ON -# 기본값: ON (MySQL 5.6.6+) -# 유지 이유: 테이블별로 별도 파일 생성 -# 성능: 테이블 삭제 시 공간 즉시 반환, 관리 용이 - -innodb_open_files = 2000 -# 기본값: 300 -# 변경값: 2000 -# 목적: InnoDB가 동시에 열 수 있는 파일 수 -# 성능: 많은 테이블이 있을 때 파일 열기 오버헤드 감소 - -table_open_cache = 4000 -# 기본값: 2000 -# 변경값: 4000 -# 목적: 열린 테이블 캐시 -# 성능: 테이블 열기/닫기 오버헤드 감소 -# 계산: max_connections × 평균 조인 테이블 수 - -table_open_cache_instances = 16 -# 기본값: 16 -# 유지 이유: 캐시를 여러 인스턴스로 분할 -# 성능: 동시성 향상 - -table_definition_cache = 2000 -# 기본값: 400 -# 변경값: 2000 -# 목적: 테이블 정의 캐시 (.frm 파일) -# 성능: 테이블 메타데이터 접근 속도 향상 - -# ------------------------------------------------------------------------ -# 쿼리 캐시 (MySQL 8.0에서는 제거됨) -# ------------------------------------------------------------------------ - -# MySQL 8.0에서는 쿼리 캐시가 제거되었습니다. -# 대신 애플리케이션 레벨 캐싱(Redis, Memcached) 사용 권장 - -# ------------------------------------------------------------------------ -# 임시 테이블 설정 -# ------------------------------------------------------------------------ - -tmp_table_size = 64M -# 기본값: 16MB -# 변경값: 64MB -# 목적: 메모리 내 임시 테이블 최대 크기 -# 성능: 복잡한 쿼리의 임시 테이블을 메모리에 유지 -# 주의: max_heap_table_size와 함께 설정 - -max_heap_table_size = 64M -# 기본값: 16MB -# 변경값: 64MB -# 목적: MEMORY 테이블 최대 크기 -# 성능: tmp_table_size와 동일하게 설정 - -# ------------------------------------------------------------------------ -# 정렬 및 조인 버퍼 -# ------------------------------------------------------------------------ - -sort_buffer_size = 4M -# 기본값: 256KB -# 변경값: 4MB -# 목적: 정렬 작업에 사용되는 버퍼 -# 성능: ORDER BY, GROUP BY 성능 향상 -# 주의: 세션별로 할당되므로 너무 크면 메모리 부족 -# 계산: 200 연결 × 4MB = 최대 800MB - -read_buffer_size = 2M -# 기본값: 128KB -# 변경값: 2MB -# 목적: 순차 스캔 버퍼 -# 성능: 전체 테이블 스캔 시 성능 향상 - -read_rnd_buffer_size = 4M -# 기본값: 256KB -# 변경값: 4MB -# 목적: 정렬 후 행 읽기 버퍼 -# 성능: ORDER BY 후 행 검색 속도 향상 - -join_buffer_size = 4M -# 기본값: 256KB -# 변경값: 4MB -# 목적: 인덱스를 사용하지 않는 조인 버퍼 -# 성능: 조인 성능 향상 - -# ------------------------------------------------------------------------ -# 바이너리 로그 설정 -# ------------------------------------------------------------------------ - -# 바이너리 로그 활성화 (복제 및 Point-in-Time 복구에 필수) -# log_bin = /var/lib/mysql/mysql-bin -# 목적: 데이터 변경 사항 기록 -# 용도: 복제(Replication), 백업, 복구 -# 참고: 복제를 사용하지 않으면 disable_log_bin 설정 가능 - -server_id = 1 -# 기본값: 1 -# 목적: 복제 환경에서 서버 식별자 -# 참고: 각 서버마다 고유한 값 필요 - -binlog_format = ROW -# 기본값: ROW (MySQL 8.0+) -# 옵션: -# STATEMENT: SQL 문 저장 (크기↓, 안정성↓) -# ROW: 실제 행 변경 저장 (크기↑, 안정성↑) ← 권장 -# MIXED: 자동 선택 -# 권장: ROW (가장 안전하고 일관성 있음) - -binlog_expire_logs_seconds = 604800 -# 기본값: 2592000 (30일) -# 변경값: 604800 (7일) -# 목적: 오래된 바이너리 로그 자동 삭제 -# 성능: 디스크 공간 관리 -# 참고: 백업 주기에 따라 조정 - -max_binlog_size = 100M -# 기본값: 1GB -# 변경값: 100MB -# 목적: 단일 바이너리 로그 파일 최대 크기 -# 성능: 작은 파일로 관리 용이성 향상 - -sync_binlog = 1 -# 기본값: 1 -# 유지 이유: 매 커밋마다 바이너리 로그를 디스크에 동기화 -# 성능: 안정성 최우선 (크래시 시 데이터 손실 방지) -# 참고: 성능이 중요하면 0으로 설정 가능하나 권장하지 않음 - -# ------------------------------------------------------------------------ -# 에러 로그 설정 -# ------------------------------------------------------------------------ - -# log_error = /var/log/mysql/error.log -log_error = /var/log/mysqld.log -# 목적: 에러 로그 파일 위치 -# 참고: 디렉토리가 존재하고 mysql 사용자가 쓰기 권한 필요 - -log_error_verbosity = 2 -# 기본값: 2 -# 옵션: 1 (오류만), 2 (오류+경고), 3 (오류+경고+정보) -# 권장: 2 (운영 환경) - -# ------------------------------------------------------------------------ -# 슬로우 쿼리 로그 -# ------------------------------------------------------------------------ - -# slow_query_log = 1 -# 기본값: 0 (비활성화) -# 변경값: 1 (활성화) -# 목적: 느린 쿼리 기록 -# 성능: 쿼리 최적화에 필수 - -slow_query_log_file = /var/log/mysql/slow-query.log -# 목적: 슬로우 쿼리 로그 파일 위치 - -long_query_time = 2 -# 기본값: 10 -# 변경값: 2 -# 목적: 2초 이상 걸리는 쿼리 기록 -# 권장: 1-2초 (애플리케이션 특성에 따라 조정) - -log_queries_not_using_indexes = 1 -# 기본값: 0 -# 변경값: 1 -# 목적: 인덱스를 사용하지 않는 쿼리도 기록 -# 성능: 인덱스 누락 쿼리 발견 - -# ------------------------------------------------------------------------ -# 일반 쿼리 로그 (개발 환경에서만 사용) -# ------------------------------------------------------------------------ - -# 운영 환경에서는 비활성화 권장 (과도한 로그 생성) -# general_log = 0 -# general_log_file = /var/log/mysql/general.log - -# ------------------------------------------------------------------------ -# 문자셋 및 콜레이션 -# ------------------------------------------------------------------------ - -character_set_server = utf8mb4 -# 기본값: utf8mb4 (MySQL 8.0+) -# 목적: 서버 기본 문자셋 -# 참고: 이모지 등 4바이트 문자 지원 - -collation_server = utf8mb4_unicode_ci -# 기본값: utf8mb4_0900_ai_ci (MySQL 8.0+) -# 변경값: utf8mb4_unicode_ci -# 목적: 다국어 정렬 규칙 -# 참고: 호환성을 위해 unicode_ci 사용 - -# ------------------------------------------------------------------------ -# SQL 모드 -# ------------------------------------------------------------------------ - -sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION -# 기본값: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,... (MySQL 8.0+) -# 목적: SQL 엄격 모드 설정 -# 권장: STRICT_TRANS_TABLES (데이터 무결성) -# 참고: 레거시 애플리케이션은 모드 조정 필요 - -# ------------------------------------------------------------------------ -# 타임존 -# ------------------------------------------------------------------------ - -# default_time_zone = '+09:00' -# 기본값: SYSTEM -# 변경값: '+09:00' (한국 시간) -# 목적: 서버 타임존 설정 -# 참고: 글로벌 서비스는 '+00:00' (UTC) 권장 - -# ------------------------------------------------------------------------ -# 성능 스키마 (Performance Schema) -# ------------------------------------------------------------------------ - -performance_schema = ON -# 기본값: ON -# 유지 이유: 성능 모니터링 및 진단 -# 참고: 약간의 오버헤드 있지만 필수 모니터링 도구 - -# ------------------------------------------------------------------------ -# 보안 설정 -# ------------------------------------------------------------------------ - -# 로컬 파일 로드 비활성화 (보안) -local_infile = 0 -# 기본값: 0 (MySQL 8.0+) -# 목적: LOAD DATA LOCAL INFILE 비활성화 -# 보안: 로컬 파일 접근 방지 - -# 심볼릭 링크 비활성화 -symbolic_links = 0 -# 기본값: 0 -# 목적: 심볼릭 링크 사용 비활성화 -# 보안: 디렉토리 탐색 공격 방지 - -# ------------------------------------------------------------------------ -# 기타 최적화 -# ------------------------------------------------------------------------ - -# 쿼리 결과 캐시 (애플리케이션 레벨 권장) -# MySQL 8.0에서는 쿼리 캐시 제거됨 - -# 오픈 파일 제한 -open_files_limit = 65535 -# 기본값: 5000 -# 변경값: 65535 -# 목적: 동시에 열 수 있는 파일 수 -# 성능: 많은 테이블과 연결을 처리할 때 필요 - -# 최대 허용 패킷 크기 -max_allowed_packet = 64M -# 기본값: 64MB (MySQL 8.0+) -# 유지 이유: 대용량 데이터 처리 -# 참고: 필요시 증가 가능 (최대 1GB) - -# 그룹 커밋 최적화 -binlog_group_commit_sync_delay = 0 -# 기본값: 0 -# 목적: 바이너리 로그 그룹 커밋 지연 (마이크로초) -# 성능: 0보다 크면 처리량 증가, 지연 약간 증가 -# 참고: 초당 수천 개 트랜잭션 환경에서 1000-10000 설정 - -binlog_group_commit_sync_no_delay_count = 0 -# 기본값: 0 -# 목적: 지연 없이 커밋할 트랜잭션 수 - -# ------------------------------------------------------------------------ -# 설정 파일 추가 포함 -# ------------------------------------------------------------------------ -!includedir /etc/my.cnf.d - -# ======================================================================== -# 주요 변경사항 요약 -# ======================================================================== -# -# 1. 메모리 설정 (4GB RAM 기준) -# - innodb_buffer_pool_size: 128MB → 2GB (50% of RAM) -# - tmp_table_size / max_heap_table_size: 16MB → 64MB -# - sort_buffer_size: 256KB → 4MB -# - read_buffer_size: 128KB → 2MB -# - join_buffer_size: 256KB → 4MB -# -# 2. 연결 설정 -# - max_connections: 151 → 200 -# - thread_cache_size: 8 → 50 -# - wait_timeout: 28800 → 600 (10분) -# -# 3. InnoDB 최적화 (SSD 특화) -# - innodb_io_capacity: 200 → 2000 -# - innodb_io_capacity_max: 2000 → 4000 -# - innodb_flush_neighbors: 1 → 0 (SSD 최적화) -# - innodb_flush_method: fsync → O_DIRECT -# -# 4. 로그 설정 -# - innodb_log_file_size: 48MB → 512MB -# - innodb_log_buffer_size: 16MB → 32MB -# - slow_query_log: 활성화 (2초 이상 쿼리) -# -# 5. 버퍼 풀 설정 -# - innodb_buffer_pool_instances: 1 → 4 (CPU 코어 수) -# -# ======================================================================== -# 예상 성능 향상 -# ======================================================================== -# -# - 읽기 성능: 40-60% 향상 (innodb_buffer_pool_size 증가) -# - 쓰기 성능: 30-50% 향상 (SSD 최적화, 로그 버퍼 증가) -# - 복잡한 쿼리: 50-100% 향상 (정렬/조인 버퍼 증가) -# - 동시 연결: 연결 처리 능력 향상 (thread_cache, max_connections) -# - 전체 처리량: 30-50% 향상 -# -# ======================================================================== -# 적용 방법 -# ======================================================================== -# -# 1. 이 파일을 /etc/my.cnf로 저장 (기존 파일 백업) -# sudo cp /etc/my.cnf /etc/my.cnf.backup -# sudo vi /etc/my.cnf -# -# 2. 로그 디렉토리 생성 및 권한 설정 -# sudo mkdir -p /var/log/mysql -# sudo chown mysql:mysql /var/log/mysql -# sudo chmod 755 /var/log/mysql -# -# 3. MySQL 재시작 -# sudo systemctl restart mysql -# 또는 -# sudo service mysql restart -# -# 4. 설정 확인 -# mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" -# mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';" -# -# 5. 슬로우 쿼리 로그 분석 (정기적으로) -# mysqldumpslow /var/log/mysql/slow-query.log -# -# 6. 성능 모니터링 -# mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" -# mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Threads%';" -# -# ======================================================================== -# Docker 환경 주의사항 -# ======================================================================== -# -# Docker 환경에서 사용 시: -# 1. 로그 디렉토리를 볼륨 마운트 -# volumes: -# - ./logs/mysql:/var/log/mysql -# -# 2. 권한 문제 방지 -# - 컨테이너 시작 전 호스트에서 디렉토리 생성 -# mkdir -p ./logs/mysql -# chmod 777 ./logs/mysql # 또는 적절한 권한 -# -# 3. 메모리 제한 확인 -# - Docker 컨테이너에 최소 4GB RAM 할당 -# -# ======================================================================== diff --git a/config/database/postgresql/init.sql b/config/database/postgresql/init.sql deleted file mode 100644 index b38e384..0000000 --- a/config/database/postgresql/init.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE ROLE IF NOT EXISTS devadmin WITH - LOGIN - PASSWORD 'test!' - SUPERUSER; diff --git a/config/database/postgresql/pg_hba.conf b/config/database/postgresql/pg_hba.conf deleted file mode 100644 index b5be892..0000000 --- a/config/database/postgresql/pg_hba.conf +++ /dev/null @@ -1,128 +0,0 @@ -# PostgreSQL Client Authentication Configuration File -# =================================================== -# -# Refer to the "Client Authentication" section in the PostgreSQL -# documentation for a complete description of this file. A short -# synopsis follows. -# -# ---------------------- -# Authentication Records -# ---------------------- -# -# This file controls: which hosts are allowed to connect, how clients -# are authenticated, which PostgreSQL user names they can use, which -# databases they can access. Records take one of these forms: -# -# local DATABASE USER METHOD [OPTIONS] -# host DATABASE USER ADDRESS METHOD [OPTIONS] -# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] -# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] -# hostgssenc DATABASE USER ADDRESS METHOD [OPTIONS] -# hostnogssenc DATABASE USER ADDRESS METHOD [OPTIONS] -# -# (The uppercase items must be replaced by actual values.) -# -# The first field is the connection type: -# - "local" is a Unix-domain socket -# - "host" is a TCP/IP socket (encrypted or not) -# - "hostssl" is a TCP/IP socket that is SSL-encrypted -# - "hostnossl" is a TCP/IP socket that is not SSL-encrypted -# - "hostgssenc" is a TCP/IP socket that is GSSAPI-encrypted -# - "hostnogssenc" is a TCP/IP socket that is not GSSAPI-encrypted -# -# DATABASE can be "all", "sameuser", "samerole", "replication", a -# database name, a regular expression (if it starts with a slash (/)) -# or a comma-separated list thereof. The "all" keyword does not match -# "replication". Access to replication must be enabled in a separate -# record (see example below). -# -# USER can be "all", a user name, a group name prefixed with "+", a -# regular expression (if it starts with a slash (/)) or a comma-separated -# list thereof. In both the DATABASE and USER fields you can also write -# a file name prefixed with "@" to include names from a separate file. -# -# ADDRESS specifies the set of hosts the record matches. It can be a -# host name, or it is made up of an IP address and a CIDR mask that is -# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that -# specifies the number of significant bits in the mask. A host name -# that starts with a dot (.) matches a suffix of the actual host name. -# Alternatively, you can write an IP address and netmask in separate -# columns to specify the set of hosts. Instead of a CIDR-address, you -# can write "samehost" to match any of the server's own IP addresses, -# or "samenet" to match any address in any subnet that the server is -# directly connected to. -# -# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", -# "gss", "sspi", "ident", "peer", "pam", "oauth", "ldap", "radius" or -# "cert". Note that "password" sends passwords in clear text; "md5" or -# "scram-sha-256" are preferred since they send encrypted passwords. -# -# OPTIONS are a set of options for the authentication in the format -# NAME=VALUE. The available options depend on the different -# authentication methods -- refer to the "Client Authentication" -# section in the documentation for a list of which options are -# available for which authentication methods. -# -# Database and user names containing spaces, commas, quotes and other -# special characters must be quoted. Quoting one of the keywords -# "all", "sameuser", "samerole" or "replication" makes the name lose -# its special character, and just match a database or username with -# that name. -# -# --------------- -# Include Records -# --------------- -# -# This file allows the inclusion of external files or directories holding -# more records, using the following keywords: -# -# include FILE -# include_if_exists FILE -# include_dir DIRECTORY -# -# FILE is the file name to include, and DIR is the directory name containing -# the file(s) to include. Any file in a directory will be loaded if suffixed -# with ".conf". The files of a directory are ordered by name. -# include_if_exists ignores missing files. FILE and DIRECTORY can be -# specified as a relative or an absolute path, and can be double-quoted if -# they contain spaces. -# -# ------------- -# Miscellaneous -# ------------- -# -# This file is read on server startup and when the server receives a -# SIGHUP signal. If you edit the file on a running system, you have to -# SIGHUP the server for the changes to take effect, run "pg_ctl reload", -# or execute "SELECT pg_reload_conf()". -# -# ---------------------------------- -# Put your actual configuration here -# ---------------------------------- -# -# If you want to allow non-local connections, you need to add more -# "host" records. In that case you will also need to make PostgreSQL -# listen on a non-local interface via the listen_addresses -# configuration parameter, or via the -i or -h command line switches. - -# CAUTION: Configuring the system for local "trust" authentication -# allows any local user to connect as any PostgreSQL user, including -# the database superuser. If you do not trust all your local users, -# use another authentication method. - - -# TYPE DATABASE USER ADDRESS METHOD - -# "local" is for Unix domain socket connections only -local all all trust -# IPv4 local connections: -host all all 127.0.0.1/32 trust -# IPv6 local connections: -host all all ::1/128 trust -# Allow replication connections from localhost, by a user with the -# replication privilege. -local replication all trust -host replication all 127.0.0.1/32 trust -host replication all ::1/128 trust - -host all all all scram-sha-256 diff --git a/config/database/postgresql/postgresql.conf b/config/database/postgresql/postgresql.conf deleted file mode 100644 index 0ab73ce..0000000 --- a/config/database/postgresql/postgresql.conf +++ /dev/null @@ -1,766 +0,0 @@ -# ----------------------------- -# PostgreSQL 18 최적화 설정 -# 하드웨어 사양: 4코어 CPU, 4GB RAM, SSD, 1GB LAN -# ----------------------------- - -#------------------------------------------------------------------------------ -# FILE LOCATIONS -#------------------------------------------------------------------------------ - -#data_directory = 'ConfigDir' -#hba_file = 'ConfigDir/pg_hba.conf' -#ident_file = 'ConfigDir/pg_ident.conf' -#external_pid_file = '' - -#------------------------------------------------------------------------------ -# CONNECTIONS AND AUTHENTICATION -#------------------------------------------------------------------------------ - -# - Connection Settings - - -listen_addresses = '*' -# 기본값: 'localhost' -# 변경값: '*' (모든 IP에서 접근 허용) -# 목적: 네트워크를 통한 원격 접속 허용 - -#port = 5432 - -max_connections = 100 -# 기본값: 100 -# 유지 이유: 4GB RAM 환경에서 적절한 연결 수 -# 성능: 각 연결은 약 10MB의 메모리를 사용하므로 100개 연결 = 약 1GB -# 참고: 연결 풀링(pgBouncer 등) 사용 시 더 효율적 - -#reserved_connections = 0 -#superuser_reserved_connections = 3 -#unix_socket_directories = '/var/run/postgresql' -#unix_socket_group = '' -#unix_socket_permissions = 0777 -#bonjour = off -#bonjour_name = '' - -# - TCP settings - - -tcp_keepalives_idle = 60 -# 기본값: 0 (시스템 기본값 사용, 보통 7200초) -# 변경값: 60초 -# 목적: 유휴 연결을 60초마다 체크하여 죽은 연결을 빠르게 감지 -# 성능: 네트워크 장애 시 빠른 연결 정리로 리소스 확보 - -tcp_keepalives_interval = 10 -# 기본값: 0 (시스템 기본값 사용, 보통 75초) -# 변경값: 10초 -# 목적: keepalive 재전송 간격 -# 성능: 연결 문제를 빠르게 탐지 - -tcp_keepalives_count = 3 -# 기본값: 0 (시스템 기본값 사용, 보통 9회) -# 변경값: 3회 -# 목적: 연결 실패 판정까지의 재시도 횟수 -# 성능: 60초 + (10초 × 3) = 최대 90초 내에 죽은 연결 정리 - -#tcp_user_timeout = 0 -#client_connection_check_interval = 0 - -# - Authentication - - -#authentication_timeout = 1min -#password_encryption = scram-sha-256 -#scram_iterations = 4096 - -# - SSL - - -#ssl = off -#ssl_ca_file = '' -#ssl_cert_file = 'server.crt' - -#------------------------------------------------------------------------------ -# RESOURCE USAGE (except WAL) -#------------------------------------------------------------------------------ - -# - Memory - - -shared_buffers = 1GB -# 기본값: 128MB -# 변경값: 1GB (전체 RAM 4GB의 25%) -# 목적: 데이터베이스가 디스크에서 읽은 데이터를 캐시하는 메모리 -# 성능: 자주 사용되는 데이터를 메모리에 유지하여 디스크 I/O 크게 감소 -# 참고: PostgreSQL에서 가장 중요한 메모리 설정 중 하나 - -huge_pages = try -# 기본값: try -# 유지 이유: 가능한 경우 huge pages 사용으로 메모리 관리 효율 향상 -# 성능: TLB 미스 감소, 대용량 shared_buffers 사용 시 특히 효과적 - -#huge_page_size = 0 -#temp_buffers = 8MB -#max_prepared_transactions = 0 - -work_mem = 16MB -# 기본값: 4MB -# 변경값: 16MB -# 목적: 정렬, 해시 테이블 등 쿼리 작업에 사용되는 메모리 -# 성능: 복잡한 쿼리의 정렬/조인 성능 향상, 디스크 임시 파일 사용 감소 -# 주의: (max_connections × work_mem)이 너무 크면 OOM 위험 -# 계산: 100 연결 × 16MB = 최대 1.6GB (복잡한 쿼리가 동시 실행될 경우) - -#hash_mem_multiplier = 2.0 - -maintenance_work_mem = 256MB -# 기본값: 64MB -# 변경값: 256MB (RAM의 약 6%) -# 목적: VACUUM, CREATE INDEX, ALTER TABLE 등 유지보수 작업에 사용 -# 성능: 인덱스 생성 및 VACUUM 작업 속도 대폭 향상 -# 참고: 유지보수 작업은 동시에 많이 실행되지 않으므로 크게 설정 가능 - -autovacuum_work_mem = 256MB -# 기본값: -1 (maintenance_work_mem 사용) -# 변경값: 256MB -# 목적: autovacuum 전용 메모리 할당 -# 성능: autovacuum 성능 향상으로 테이블 bloat 감소 - -#logical_decoding_work_mem = 64MB - -max_stack_depth = 2MB -# 기본값: 2MB -# 유지 이유: 기본값이 대부분의 경우에 적절 - -#shared_memory_type = mmap - -dynamic_shared_memory_type = posix -# 기본값: posix (Linux에서) -# 유지 이유: Linux에서 가장 효율적인 방식 - -#min_dynamic_shared_memory = 0MB - -# - Disk - - -#temp_file_limit = -1 -#file_copy_method = copy - -# - Kernel Resources - - -#max_files_per_process = 1000 - -# - Background Writer - - -bgwriter_delay = 200ms -# 기본값: 200ms -# 유지 이유: SSD 환경에서도 기본값이 적절 - -bgwriter_lru_maxpages = 100 -# 기본값: 100 -# 유지 이유: 백그라운드 쓰기 작업의 균형 유지 - -#bgwriter_lru_multiplier = 2.0 - -bgwriter_flush_after = 512kB -# 기본값: 512kB -# 유지 이유: SSD에서 적절한 flush 크기 - -# - I/O - - -#backend_flush_after = 0 - -effective_io_concurrency = 200 -# 기본값: 1 (HDD), 16 (SSD 감지 시) -# 변경값: 200 -# 목적: SSD의 높은 IOPS를 활용한 병렬 I/O 요청 수 -# 성능: bitmap heap scan 등에서 여러 페이지를 동시에 prefetch -# 참고: SSD는 동시 I/O 처리 능력이 뛰어나므로 높게 설정 - -maintenance_io_concurrency = 200 -# 기본값: 10 -# 변경값: 200 -# 목적: VACUUM, CREATE INDEX 등 유지보수 작업의 병렬 I/O -# 성능: 유지보수 작업 속도 향상 - -#io_max_combine_limit = 128kB -#io_combine_limit = 128kB -#io_method = worker -#io_max_concurrency = -1 -#io_workers = 3 - -# - Worker Processes - - -max_worker_processes = 8 -# 기본값: 8 -# 유지 이유: 4코어 환경에서 적절 (코어 수 × 2) -# 성능: 병렬 쿼리, autovacuum 등 다양한 백그라운드 작업 처리 - -max_parallel_workers_per_gather = 2 -# 기본값: 2 -# 변경값: 2 (4코어 환경에서 적절) -# 목적: 단일 쿼리가 사용할 수 있는 최대 병렬 worker 수 -# 성능: 대용량 테이블 스캔 시 쿼리 속도 향상 -# 참고: 너무 높으면 다른 쿼리의 리소스 부족 발생 가능 - -max_parallel_maintenance_workers = 2 -# 기본값: 2 -# 유지 이유: CREATE INDEX 등 유지보수 작업의 병렬화 -# 성능: 인덱스 생성 속도 향상 - -max_parallel_workers = 4 -# 기본값: 8 -# 변경값: 4 (CPU 코어 수) -# 목적: 시스템 전체에서 동시 실행 가능한 병렬 worker 총 수 -# 성능: CPU 코어 수에 맞춰 과도한 컨텍스트 스위칭 방지 - -#parallel_leader_participation = on - -#------------------------------------------------------------------------------ -# WRITE-AHEAD LOG -#------------------------------------------------------------------------------ - -# - Settings - - -#wal_level = replica -#fsync = on -#synchronous_commit = on -#wal_sync_method = fsync -#full_page_writes = on -#wal_log_hints = off - -wal_compression = lz4 -# 기본값: off -# 변경값: lz4 -# 목적: WAL 파일 압축으로 I/O 및 스토리지 사용량 감소 -# 성능: 네트워크를 통한 복제 시 대역폭 절약, 아카이빙 효율 향상 -# 참고: CPU 사용량은 약간 증가하지만 4코어 환경에서 무리 없음 - -#wal_init_zero = on -#wal_recycle = on - -wal_buffers = 16MB -# 기본값: -1 (shared_buffers의 3%, 최소 64kB, 최대 약 16MB) -# 변경값: 16MB -# 목적: WAL 데이터를 디스크에 쓰기 전 버퍼링 -# 성능: 쓰기 집약적 워크로드에서 WAL 쓰기 성능 향상 - -#wal_writer_delay = 200ms - -wal_writer_flush_after = 1MB -# 기본값: 1MB -# 유지 이유: SSD에서 적절한 flush 크기 - -#wal_skip_threshold = 2MB -#commit_delay = 0 -#commit_siblings = 5 - -# - Checkpoints - - -checkpoint_timeout = 15min -# 기본값: 5min -# 변경값: 15min -# 목적: 체크포인트 발생 간격 조정 -# 성능: 체크포인트 빈도 감소로 I/O spike 완화, 전체 성능 향상 -# 참고: 크래시 복구 시간은 약간 증가하지만 일반적으로 허용 가능 - -checkpoint_completion_target = 0.9 -# 기본값: 0.9 -# 유지 이유: 체크포인트를 시간에 걸쳐 분산하여 I/O spike 방지 -# 성능: 90%의 시간에 걸쳐 checkpoint 완료하여 부하 분산 - -#checkpoint_flush_after = 256kB -#checkpoint_warning = 30s - -max_wal_size = 2GB -# 기본값: 1GB -# 변경값: 2GB -# 목적: 체크포인트 간 생성 가능한 최대 WAL 크기 -# 성능: 쓰기 집약적 워크로드에서 체크포인트 빈도 감소 -# 참고: SSD 환경에서 더 큰 WAL 크기는 성능에 유리 - -min_wal_size = 1GB -# 기본값: 80MB -# 변경값: 1GB -# 목적: 항상 유지할 최소 WAL 크기 -# 성능: WAL 파일 재사용으로 파일 생성/삭제 오버헤드 감소 - -# - Prefetching during recovery - - -#recovery_prefetch = try -#wal_decode_buffer_size = 512kB - -# - Archiving - - -#archive_mode = off -#archive_library = '' -#archive_command = '' -#archive_timeout = 0 - -#------------------------------------------------------------------------------ -# REPLICATION -#------------------------------------------------------------------------------ - -# - Sending Servers - - -#max_wal_senders = 10 -#max_replication_slots = 10 -#wal_keep_size = 0 -#max_slot_wal_keep_size = -1 -#idle_replication_slot_timeout = 0 -#wal_sender_timeout = 60s -#track_commit_timestamp = off - -# - Primary Server - - -#synchronous_standby_names = '' -#synchronized_standby_slots = '' - -# - Standby Servers - - -#primary_conninfo = '' -#primary_slot_name = '' -#hot_standby = on -#max_standby_archive_delay = 30s -#max_standby_streaming_delay = 30s -#wal_receiver_create_temp_slot = off -#wal_receiver_status_interval = 10s -#hot_standby_feedback = off -#wal_receiver_timeout = 60s -#wal_retrieve_retry_interval = 5s -#recovery_min_apply_delay = 0 -#sync_replication_slots = off - -# - Subscribers - - -#max_active_replication_origins = 10 -#max_logical_replication_workers = 4 -#max_sync_workers_per_subscription = 2 -#max_parallel_apply_workers_per_subscription = 2 - -#------------------------------------------------------------------------------ -# QUERY TUNING -#------------------------------------------------------------------------------ - -# - Planner Method Configuration - - -#enable_async_append = on -#enable_bitmapscan = on -#enable_gathermerge = on -#enable_hashagg = on -#enable_hashjoin = on -#enable_incremental_sort = on -#enable_indexscan = on -#enable_indexonlyscan = on -#enable_material = on -#enable_memoize = on -#enable_mergejoin = on -#enable_nestloop = on -#enable_parallel_append = on -#enable_parallel_hash = on -#enable_partition_pruning = on -#enable_partitionwise_join = off -#enable_partitionwise_aggregate = off -#enable_presorted_aggregate = on -#enable_seqscan = on -#enable_sort = on -#enable_tidscan = on - -# - Planner Cost Constants - - -#seq_page_cost = 1.0 - -random_page_cost = 1.1 -# 기본값: 4.0 (HDD), 1.1 (SSD 자동 감지 시) -# 변경값: 1.1 -# 목적: SSD의 랜덤 액세스 특성을 반영 -# 성능: 인덱스 스캔 선호도 증가, 쿼리 플래너의 더 나은 결정 -# 참고: HDD는 4.0, SSD는 1.1-1.5가 적절 - -#cpu_tuple_cost = 0.01 -#cpu_index_tuple_cost = 0.005 -#cpu_operator_cost = 0.0025 -#parallel_setup_cost = 1000.0 -#parallel_tuple_cost = 0.1 -#min_parallel_table_scan_size = 8MB -#min_parallel_index_scan_size = 512kB - -effective_cache_size = 3GB -# 기본값: 4GB (시스템에 따라 다름) -# 변경값: 3GB (전체 RAM 4GB의 75%) -# 목적: OS와 PostgreSQL이 파일 캐싱에 사용 가능한 메모리 추정 -# 성능: 쿼리 플래너가 인덱스 스캔 비용을 더 정확히 계산 -# 참고: shared_buffers + OS 파일 캐시 = 약 3GB - -#jit_above_cost = 100000 -#jit_inline_above_cost = 500000 -#jit_optimize_above_cost = 500000 - -# - Genetic Query Optimizer - - -#geqo = on -#geqo_threshold = 12 - -# - Other Planner Options - - -default_statistics_target = 100 -# 기본값: 100 -# 유지 이유: 통계 정확도와 ANALYZE 시간의 균형 -# 성능: 쿼리 플래너의 정확한 비용 추정 -# 참고: 특정 컬럼에 대해 개별적으로 높일 수 있음 - -#constraint_exclusion = partition -#cursor_tuple_fraction = 0.1 -#from_collapse_limit = 8 -#jit = on -#join_collapse_limit = 8 -#plan_cache_mode = auto -#recursive_worktable_factor = 10.0 - -#------------------------------------------------------------------------------ -# REPORTING AND LOGGING -#------------------------------------------------------------------------------ - -# 로깅 설정은 기본값 유지 (사용자 요청사항) - -#log_destination = 'stderr' -#logging_collector = off -#log_directory = 'log' -#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' -#log_file_mode = 0600 -#log_rotation_age = 1d -#log_rotation_size = 10MB -#log_truncate_on_rotation = off -#syslog_facility = 'LOCAL0' -#syslog_ident = 'postgres' -#syslog_sequence_numbers = on -#syslog_split_messages = on -#event_source = 'PostgreSQL' -#log_min_messages = warning -#log_min_error_statement = error -#log_min_duration_statement = -1 -#log_min_duration_sample = -1 -#log_statement_sample_rate = 1.0 -#log_transaction_sample_rate = 0.0 -#log_startup_progress_interval = 10s -#debug_print_parse = off -#debug_print_rewritten = off -#debug_print_plan = off -#debug_pretty_print = on -#log_autovacuum_min_duration = 10min -#log_checkpoints = on -#log_connections = '' -#log_disconnections = off -#log_duration = off -#log_error_verbosity = default -#log_hostname = off -#log_line_prefix = '%m [%p] ' -#log_lock_waits = off -#log_lock_failures = off -#log_recovery_conflict_waits = off -#log_parameter_max_length = -1 -#log_parameter_max_length_on_error = 0 -#log_statement = 'none' -#log_replication_commands = off -#log_temp_files = -1 -log_timezone = 'Etc/UTC' -#cluster_name = '' -#update_process_title = on - -#------------------------------------------------------------------------------ -# STATISTICS -#------------------------------------------------------------------------------ - -#track_activities = on -#track_activity_query_size = 1024 -#track_counts = on -#track_cost_delay_timing = off - -track_io_timing = on -# 기본값: off -# 변경값: on -# 목적: I/O 작업의 시간 추적으로 성능 병목 지점 파악 -# 성능: EXPLAIN ANALYZE 등으로 I/O 병목 진단 가능 -# 참고: 약간의 오버헤드 있지만 성능 튜닝에 매우 유용 - -#track_wal_io_timing = off -#track_functions = none -#stats_fetch_consistency = cache - -# - Monitoring - - -#compute_query_id = auto -#log_statement_stats = off -#log_parser_stats = off -#log_planner_stats = off -#log_executor_stats = off - -#------------------------------------------------------------------------------ -# VACUUMING -#------------------------------------------------------------------------------ - -# - Automatic Vacuuming - - -#autovacuum = on - -autovacuum_worker_slots = 8 -# 기본값: 16 (PostgreSQL 18 신규 파라미터) -# 변경값: 8 -# 목적: autovacuum worker 슬롯 수 (동시 실행 가능한 worker 총량) -# 성능: 4코어 환경에서 적절한 슬롯 수로 CPU 리소스 균형 -# 참고: max_workers와 별개로 동적으로 worker 생성 가능 - -autovacuum_max_workers = 3 -# 기본값: 3 -# 변경값: 3 -# 목적: 동시에 실행 가능한 autovacuum worker 프로세스 수 -# 성능: 여러 테이블을 동시에 vacuum 처리 -# 참고: 4코어 환경에서 적절한 수준 - -autovacuum_naptime = 30s -# 기본값: 1min -# 변경값: 30s -# 목적: autovacuum이 데이터베이스를 체크하는 주기 -# 성능: 더 빈번한 체크로 테이블 bloat 감소, 성능 유지 -# 참고: 쓰기가 많은 환경에서 효과적 - -#autovacuum_vacuum_threshold = 50 -#autovacuum_vacuum_insert_threshold = 1000 -#autovacuum_analyze_threshold = 50 - -autovacuum_vacuum_scale_factor = 0.1 -# 기본값: 0.2 (테이블의 20%) -# 변경값: 0.1 (테이블의 10%) -# 목적: vacuum 실행 trigger 조건 (dead tuple 비율) -# 성능: 더 자주 vacuum 실행으로 테이블 bloat 최소화 -# 참고: 대형 테이블에서 특히 효과적 - -#autovacuum_vacuum_insert_scale_factor = 0.2 - -autovacuum_analyze_scale_factor = 0.05 -# 기본값: 0.1 (테이블의 10%) -# 변경값: 0.05 (테이블의 5%) -# 목적: analyze 실행 trigger 조건 -# 성능: 더 빈번한 통계 업데이트로 쿼리 플래너의 정확도 향상 - -#autovacuum_vacuum_max_threshold = 100000000 -#autovacuum_freeze_max_age = 200000000 -#autovacuum_multixact_freeze_max_age = 400000000 -#autovacuum_vacuum_cost_delay = 2ms -#autovacuum_vacuum_cost_limit = -1 - -# - Cost-Based Vacuum Delay - - -#vacuum_cost_delay = 0 -#vacuum_cost_page_hit = 1 -#vacuum_cost_page_miss = 2 -#vacuum_cost_page_dirty = 20 -#vacuum_cost_limit = 200 - -# - Default Behavior - - -#vacuum_truncate = on - -# - Freezing - - -#vacuum_freeze_table_age = 150000000 -#vacuum_freeze_min_age = 50000000 -#vacuum_failsafe_age = 1600000000 -#vacuum_multixact_freeze_table_age = 150000000 -#vacuum_multixact_freeze_min_age = 5000000 -#vacuum_multixact_failsafe_age = 1600000000 -#vacuum_max_eager_freeze_failure_rate = 0.03 - -#------------------------------------------------------------------------------ -# CLIENT CONNECTION DEFAULTS -#------------------------------------------------------------------------------ - -# - Statement Behavior - - -#client_min_messages = notice -#search_path = '"$user", public' -#row_security = on -#default_table_access_method = 'heap' -#default_tablespace = '' -#default_toast_compression = 'pglz' -#temp_tablespaces = '' -#check_function_bodies = on -#default_transaction_isolation = 'read committed' -#default_transaction_read_only = off -#default_transaction_deferrable = off -#session_replication_role = 'origin' - -statement_timeout = 30000 -# 기본값: 0 (무제한) -# 변경값: 30000ms (30초) -# 목적: 장시간 실행되는 쿼리 자동 종료 -# 성능: 문제있는 쿼리로 인한 리소스 점유 방지 -# 참고: 애플리케이션 특성에 따라 조정 필요, 0으로 비활성화 가능 - -#transaction_timeout = 0 - -lock_timeout = 5000 -# 기본값: 0 (무제한) -# 변경값: 5000ms (5초) -# 목적: 락 대기 시간 제한 -# 성능: 데드락 상황 빠른 감지, 애플리케이션 응답성 향상 - -#idle_in_transaction_session_timeout = 0 - -idle_session_timeout = 300000 -# 기본값: 0 (무제한) -# 변경값: 300000ms (5분) -# 목적: 유휴 세션 자동 종료 -# 성능: 불필요한 연결로 인한 리소스 낭비 방지 -# 참고: 연결 풀 사용 시 조정 필요 - -#bytea_output = 'hex' -#xmlbinary = 'base64' -#xmloption = 'content' -#gin_pending_list_limit = 4MB -#createrole_self_grant = '' -#event_triggers = on - -# - Locale and Formatting - - -datestyle = 'iso, mdy' -#intervalstyle = 'postgres' -timezone = 'Etc/UTC' -#timezone_abbreviations = 'Default' -#extra_float_digits = 1 -#client_encoding = sql_ascii - -lc_messages = 'en_US.utf8' -lc_monetary = 'en_US.utf8' -lc_numeric = 'en_US.utf8' -lc_time = 'en_US.utf8' -#icu_validation_level = warning - -default_text_search_config = 'pg_catalog.english' - -# - Shared Library Preloading - - -#local_preload_libraries = '' -#session_preload_libraries = '' -#shared_preload_libraries = '' -#jit_provider = 'llvmjit' - -# - Other Defaults - - -#dynamic_library_path = '$libdir' -#extension_control_path = '$system' -#gin_fuzzy_search_limit = 0 - -#------------------------------------------------------------------------------ -# LOCK MANAGEMENT -#------------------------------------------------------------------------------ - -deadlock_timeout = 1s -# 기본값: 1s -# 유지 이유: 데드락 감지를 위한 적절한 대기 시간 - -#max_locks_per_transaction = 64 -#max_pred_locks_per_transaction = 64 -#max_pred_locks_per_relation = -2 -#max_pred_locks_per_page = 2 - -#------------------------------------------------------------------------------ -# VERSION AND PLATFORM COMPATIBILITY -#------------------------------------------------------------------------------ - -#array_nulls = on -#backslash_quote = safe_encoding -#escape_string_warning = on -#lo_compat_privileges = off -#quote_all_identifiers = off -#standard_conforming_strings = on -#synchronize_seqscans = on -#transform_null_equals = off -#allow_alter_system = on - -#------------------------------------------------------------------------------ -# ERROR HANDLING -#------------------------------------------------------------------------------ - -#exit_on_error = off -#restart_after_crash = on -#data_sync_retry = off -#recovery_init_sync_method = fsync - -#------------------------------------------------------------------------------ -# CONFIG FILE INCLUDES -#------------------------------------------------------------------------------ - -#include_dir = '...' -#include_if_exists = '...' -#include = '...' - -#------------------------------------------------------------------------------ -# CUSTOMIZED OPTIONS -#------------------------------------------------------------------------------ - -# ============================================================================= -# 주요 변경사항 요약 -# ============================================================================= -# -# 1. 메모리 설정 (4GB RAM 기준) -# - shared_buffers: 128MB → 1GB (25% of RAM) -# - effective_cache_size: 4GB → 3GB (75% of RAM) -# - work_mem: 4MB → 16MB (쿼리 성능 향상) -# - maintenance_work_mem: 64MB → 256MB (유지보수 작업 가속) -# -# 2. 연결 관리 -# - tcp_keepalives 설정: 죽은 연결 빠른 감지 (90초 이내) -# - statement_timeout: 30초 (장시간 쿼리 방지) -# - lock_timeout: 5초 (락 대기 제한) -# - idle_session_timeout: 5분 (유휴 세션 정리) -# -# 3. 병렬 처리 (4코어 최적화) -# - max_parallel_workers: 4 (CPU 코어 수) -# - max_parallel_workers_per_gather: 2 -# - max_worker_processes: 8 -# -# 4. I/O 최적화 (SSD 특화) -# - random_page_cost: 4.0 → 1.1 -# - effective_io_concurrency: 1 → 200 -# - maintenance_io_concurrency: 10 → 200 -# -# 5. WAL 및 체크포인트 -# - wal_compression: off → lz4 (I/O 감소) -# - wal_buffers: 자동 → 16MB -# - checkpoint_timeout: 5min → 15min -# - max_wal_size: 1GB → 2GB -# - min_wal_size: 80MB → 1GB -# -# 6. Autovacuum 튜닝 -# - autovacuum_worker_slots: 16 → 8 -# - autovacuum_naptime: 1min → 30s (더 빈번한 체크) -# - autovacuum_vacuum_scale_factor: 0.2 → 0.1 (더 자주 실행) -# - autovacuum_analyze_scale_factor: 0.1 → 0.05 -# -# 7. 모니터링 -# - track_io_timing: off → on (I/O 성능 진단) -# -# ============================================================================= -# 예상 성능 향상 -# ============================================================================= -# -# - 읽기 성능: 30-50% 향상 (shared_buffers, effective_cache_size) -# - 쓰기 성능: 20-40% 향상 (WAL 설정, checkpoint 최적화) -# - 복잡한 쿼리: 40-100% 향상 (work_mem, 병렬 처리) -# - 유지보수 작업: 100-300% 향상 (maintenance_work_mem, I/O 동시성) -# - 전체 처리량: 25-50% 향상 (모든 최적화의 시너지) -# -# ============================================================================= -# 적용 방법 -# ============================================================================= -# -# 1. 이 파일을 postgresql.conf로 저장 (또는 기존 파일 백업 후 교체) -# 2. PostgreSQL 재시작: -# sudo systemctl restart postgresql -# 또는 -# sudo pg_ctl restart -D /var/lib/postgresql/data -# -# 3. 설정 확인: -# SHOW shared_buffers; -# SHOW effective_cache_size; -# SHOW work_mem; -# -# 4. 모니터링 (첫 며칠간): -# - 메모리 사용량: free -h, htop -# - 체크포인트 빈도: 로그 확인 -# - 쿼리 성능: pg_stat_statements 활용 -# -# ============================================================================= \ No newline at end of file diff --git a/config/web-server/conf.d/backup/backend.conf b/config/web-server/conf.d/backend.conf similarity index 98% rename from config/web-server/conf.d/backup/backend.conf rename to config/web-server/conf.d/backend.conf index d50bdb8..14f10ec 100644 --- a/config/web-server/conf.d/backup/backend.conf +++ b/config/web-server/conf.d/backend.conf @@ -1,6 +1,6 @@ server { listen 80; - server_name demo.castad.net; + server_name localhost; if ($bad_bot) { return 403; diff --git a/config/web-server/conf.d/castad_gunicorn_https_ng.conf b/config/web-server/conf.d/castad_gunicorn_https_ng.conf deleted file mode 100644 index a17a439..0000000 --- a/config/web-server/conf.d/castad_gunicorn_https_ng.conf +++ /dev/null @@ -1,245 +0,0 @@ -# =============================================== -# Production Level Nginx Configuration (Sample Template) -# 서버 사양: 쿼드코어 CPU, 4GB RAM, ~50 req/s -# 백엔드: FastAPI REST API Server -# =============================================== - -# HTTP 서버 블록 (포트 80) - HTTPS로 리다이렉트 -server { - listen 80; - server_name demo.castad.net www.demo.castad.net; - - # 보안을 위한 호스트 검증 - 허용되지 않은 도메인 차단 - # 도메인 확장자가 다르다면 추가해줘야함 - # if ($host !~* ^(www\.)?demo.castad.net\.(com|kr|net|org)$) { - # return 444; - # } - - # Let's Encrypt 도메인 검증 프로그램 허용 (리다이렉트 전에 처리) - # SSL 인증서 갱신을 위해 필수 - location ^~ /.well-known/acme-challenge/ { - allow all; - root /www/certbot; - try_files $uri =404; # 디렉토리 순회 공격 방지 - } - - # HTTP를 HTTPS로 리다이렉트 (acme-challenge 제외) - # return 301은 rewrite보다 효율적이며 $server_name이 $host보다 안전함 - location / { - return 301 https://$server_name$request_uri; - } -} - -# HTTPS 서버 블록 (포트 443) - 메인 애플리케이션 -server { - listen 443 ssl; - http2 on; - - server_name demo.castad.net www.demo.castad.net; - - # 악성 봇 차단 (nginx.conf의 http 블록에서 $bad_bot 맵 정의 필요) - if ($bad_bot) { - return 403; - } - - # SSL/TLS 인증서 설정 - ssl_certificate /etc/letsencrypt/live/demo.castad.net/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/demo.castad.net/privkey.pem; - ssl_dhparam /etc/ssl/certs/demo.castad.net/dhparam.pem; # openssl dhparam -out /etc/ssl/certs/demo.castad.net/dhparam.pem 2048 - - # 최신 SSL/TLS 설정 - SSL Labs A+ 등급 달성 가능 - ssl_session_cache shared:SSL:50m; # SSL 세션 캐시 크기 증가 (트래픽 많을 시 유용) - ssl_session_timeout 10m; # SSL 세션 타임아웃 - ssl_session_tickets off; # 보안 향상을 위해 세션 티켓 비활성화 (nginx >= 1.5.9) - ssl_protocols TLSv1.2 TLSv1.3; # 최신 TLS 프로토콜만 사용 - ssl_prefer_server_ciphers off; # TLSv1.3에서는 클라이언트 선호 암호화 사용 (모범 사례) - # 최신 암호화 스위트 - CHACHA20-POLY1305 포함 (모바일 최적화) - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; - ssl_ecdh_curve secp384r1; # ECDH 곡선 설정 (nginx >= 1.1.0) - - # OCSP 스테이플링 - SSL 핸드셰이크 성능 향상 - # 인증서에 OCSP URL이 없으면 자동으로 비활성화됨 (경고는 정상) - #ssl_stapling on; - #ssl_stapling_verify on; - ssl_trusted_certificate /etc/letsencrypt/live/demo.castad.net/chain.pem; - resolver 1.1.1.1 8.8.8.8 valid=300s; # Cloudflare와 Google DNS 사용 - resolver_timeout 5s; - - # 보안 헤더 - 다양한 공격으로부터 보호 - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; # HSTS - 다운그레이드 공격 방지 - add_header X-Frame-Options "DENY" always; # 클릭재킹 방지 - add_header X-Content-Type-Options "nosniff" always; # MIME 스니핑 방지 - add_header X-XSS-Protection "1; mode=block" always; # 레거시 XSS 보호 - add_header Referrer-Policy "strict-origin-when-cross-origin" always; # 리퍼러 정보 제어 - #add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' ''; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: ws:;" always; - #add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com https://www.youtube.com https://s.ytimg.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.tailwindcss.com; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: https: https://i.ytimg.com https://img.youtube.com; connect-src 'self' wss: ws: https://cdn.tailwindcss.com; frame-src 'self' https://www.youtube.com https://www.youtube-nocookie.com; media-src 'self' https://www.youtube.com;" always; - add_header Content-Security-Policy "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;" always; - - # XSS 방지를 위한 CSP - # 'unsafe-inline'은 범용 설정이 아니며, 보안상 위험한 설정입니다. CSP의 핵심 보호 기능을 무력화시키므로, 개발 환경이나 레거시 코드 마이그레이션 과정에서만 임시로 사용하고, 프로덕션 환경에서는 nonce, hash, 또는 외부 파일 분리 방식으로 대체해야 합니다. - - # 클라이언트가 업로드할 수 있는 전체 요청 본문(body) 의 최대 허용 크기 - # 요청 바디(파일, 폼 데이터 등)가 이 값을 초과하면 Nginx는 즉시 413 Request Entity Too Large 에러를 반환 - # 업로드 제한선. - client_max_body_size 100M; # 최대 업로드 크기 제한 (애플리케이션에 맞게 조정) - - # 파일 캐시 - I/O 성능 향상 - open_file_cache max=1000 inactive=20s; # 최대 1000개 파일 캐시, 20초 비활성 시 제거 - open_file_cache_valid 30s; # 캐시 유효성 검사 주기 - open_file_cache_min_uses 2; # 최소 2회 사용 시 캐시 - open_file_cache_errors on; # 파일 오류도 캐시 - - # 로깅 설정 - 버퍼링으로 I/O 감소 - access_log /log/nginx/demo.castad.net.com.gunicorn_access.log main buffer=32k flush=5s; - error_log /log/nginx/demo.castad.net.com.gunicorn_error.log warn; - - # frontend에 오류 페이지 정의가 되어 있는 경우 사용 가능 - # # 커스텀 오류 페이지 - 더 나은 사용자 경험 및 정보 노출 방지 - # error_page 404 /404.html; - # error_page 500 502 503 504 /50x.html; - - # location = /404.html { - # internal; # 내부 리다이렉트만 허용 - # root /www/error_pages; - # } - - # location = /50x.html { - # internal; # 내부 리다이렉트만 허용 - # root /www/error_pages; - # } - - # 프론트엔드 정적 파일 루트 - root /www/o2o-castad-frontend/dist; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - # Fastapi 미디어 파일 - 사용자 업로드 파일 - location /media { - autoindex off; # 디렉토리 목록 비활성화 - # gzip_static on; # 사전 압축된 .gz 파일 사용 - expires 30d; # 브라우저 캐시 30일 후 브라우저가 다시 요청할 때 재검증 - alias /www/o2o-castad-backend/media; # Fastapi 프로젝트의 미디어 파일 경로 - - # 정적 파일 캐싱 - 브라우저 캐시 최적화 - add_header Cache-Control "public, immutable"; - access_log off; # 액세스 로그 비활성화로 성능 향상 - } - - # Fastapi 정적 파일 - CSS, JS, 이미지 등 - location /static { - autoindex off; # 디렉토리 목록 비활성화 - # gzip_static on; # 사전 압축된 .gz 파일 사용 압축된 파일이 없다면 설정 무의미 - expires 30d; # 브라우저 캐시 30일 후 브라우저가 다시 요청할 때 재검증 - alias /www/o2o-castad-backend/static; # Fastapi 프로젝트의 정적 파일 경로 - - # 정적 파일 캐싱 - 브라우저 캐시 최적화 - add_header Cache-Control "public, immutable"; - access_log off; # 액세스 로그 비활성화로 성능 향상 - } - - # 메인 애플리케이션 - 백엔드로 프록시 - location /api/ { - autoindex off; # 디렉토리 목록 비활성화 - - # 속도 제한 - DDoS 및 무차별 대입 공격 방지 - # (nginx.conf의 http 블록에서 limit_req_zone과 limit_conn_zone 정의 필요) - #limit_req zone=general burst=20 nodelay; # 초당 요청 제한 - #limit_conn addr 10; # IP당 동시 연결 제한 - - # HTTP 메서드 제한 - HTTP 동사 변조 공격 방지 - limit_except GET POST HEAD OPTIONS DELETE { - deny all; - } - - # 백엔드 애플리케이션으로 프록시 - proxy_pass http://uvicorn-app:8000/; - - # WebSocket 지원 - 실시간 통신 애플리케이션에 필수 - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; # nginx.conf에서 $connection_upgrade 맵 정의 필요 - - # 프록시 헤더 - 클라이언트 정보 전달 - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Port $server_port; - - # 타임아웃 설정 - 애플리케이션에 맞게 조정 - proxy_connect_timeout 300s; - proxy_send_timeout 300s; - proxy_read_timeout 300s; - - # 버퍼 설정 - 대화형 애플리케이션에 최적화 - Websocket 사용시 설정 - # proxy_buffering off; # 즉시 응답 전달 - # proxy_request_buffering off; # 즉시 요청 전달 - - # 버퍼링 활성화 (기본값) - 기본 fastapi 사용시 설정 - proxy_buffering on; - proxy_request_buffering on; - - # 버퍼 크기 설정 - 기본 fastapi 사용시 설정 - proxy_buffer_size 4k; - proxy_buffers 8 4k; - proxy_busy_buffers_size 8k; - - proxy_set_header Accept-Encoding gzip; - } - - # Let's Encrypt 도메인 검증 프로그램 허용 (HTTPS에서도 필요시) - location ^~ /.well-known/acme-challenge/ { - allow all; - root /www/certbot; - try_files $uri =404; # 디렉토리 순회 공격 방지 - } - - # 정적 리소스 캐싱 - 이미지, 폰트, CSS, JS 등 - # 브라우저 캐시로 로드 시간 단축 및 서버 부하 감소 - location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ { - expires 1y; # 1년 캐시 - add_header Cache-Control "public, immutable"; - access_log off; # 액세스 로그 비활성화로 성능 향상 - } - - # 닷 파일 차단 - .htaccess, .htpasswd, .svn, .git, .env 등 - # 민감한 설정 파일 노출 방지 - location ~ /\. { - deny all; - access_log off; # 차단된 시도 로그 비활성화 - log_not_found off; - } - - # 민감한 파일 확장자 차단 - 로그, 인증서, 스크립트, SQL 등 - # 보안을 위해 직접 접근 차단 - location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ { - deny all; - access_log off; # 차단된 시도 로그 비활성화 - log_not_found off; - } - - # 민감한 설정 파일 차단 - composer, package.json, phpunit 등 - # 프로젝트 메타데이터 및 설정 파일 노출 방지 - location ~* (composer\.json|composer\.lock|composer\.phar|contributing\.md|license\.txt|readme\.rst|readme\.md|readme\.txt|copyright|artisan|gulpfile\.js|package\.json|phpunit\.xml|access_log|error_log|gruntfile\.js)$ { - deny all; - access_log off; # 차단된 시도 로그 비활성화 - log_not_found off; - } - - # 파비콘 - 로그 노이즈 제거 - location = /favicon.ico { - log_not_found off; - access_log off; - } - - # robots.txt - 검색 엔진 크롤러 제어 - location = /robots.txt { - log_not_found off; - access_log off; - allow all; - } -} diff --git a/docker/gunicorn/Dockerfile b/docker/gunicorn/Dockerfile index b92c9e5..5efcbb3 100644 --- a/docker/gunicorn/Dockerfile +++ b/docker/gunicorn/Dockerfile @@ -15,7 +15,7 @@ RUN apt-get update && \ curl wget git tar gnupg2 lsb-release lz4 zstd vim \ build-essential zlib1g-dev libncurses5-dev libgdbm-dev \ libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev \ - python3-dev libmysqlclient-dev pkg-config ca-certificates + python3-dev pkg-config ca-certificates # ======================================== # 2. Python 3.13 build & install @@ -47,28 +47,11 @@ RUN rm -f /usr/bin/python /usr/bin/python3 && \ RUN pip install --upgrade pip && \ pip install wheel && \ pip install sqlalchemy alembic pydantic && \ - pip install psycopg2-binary asyncpg && \ - pip install mysqlclient asyncmy && \ pip install gunicorn uvicorn[standard] && \ pip install fastapi uv poetry # ======================================== -# 5. Percona XtraBackup (mysql backup) -# ======================================== -RUN curl -O https://repo.percona.com/apt/percona-release_latest.generic_all.deb && \ - apt-get install -y ./percona-release_latest.generic_all.deb && \ - rm -f percona-release_latest.generic_all.deb && \ - apt-get update && \ - percona-release enable pxb-84-lts && \ - apt-get install -y percona-xtrabackup-84 - -# ======================================== -# 6. PostgreSQL backup (pgbackrest) -# ======================================== -RUN apt-get install -y pgbackrest - -# ======================================== -# 7. Cleanup +# 5. Cleanup # ======================================== RUN apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ diff --git a/log/mysql/.gitkeep b/log/mysql/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/log/postgresql/.gitkeep b/log/postgresql/.gitkeep deleted file mode 100644 index e69de29..0000000