[ICC-304] Google AI Studio → Vertex AI + GCS 전환 및 Cloudflare DDoS 방어 도입#166
[ICC-304] Google AI Studio → Vertex AI + GCS 전환 및 Cloudflare DDoS 방어 도입#166
Conversation
- Nginx: Cloudflare IP 복원(set_real_ip_from) 추가, Origin CA 인증서 경로 변경, ACME challenge 블록 제거 - docker-compose: Let's Encrypt 볼륨을 Origin CA 볼륨으로 교체 - init-ssl.sh: Let's Encrypt 초기화 스크립트 삭제 (Origin CA로 전환)
- Gemini File API → GCS 업로드로 교체 (GeminiFileServiceImpl) - API Key 인증 → Vertex AI 모드 (project-id + location + ADC) - GCS SDK 의존성 추가 (google-cloud-storage + libraries-bom) - GeminiFileRestClientConfig 삭제 (REST 클라이언트 불필요) - Context Cache URI: files/xxx → gs://bucket/path - 설정값 Jasypt 암호화 (project-id, location, bucket-name)
- GCS 버킷 (q-asker-ai-files, 1일 수명주기) - AI 서비스 계정 + IAM (Storage Object Admin, Vertex AI User) - Vertex AI / Cloud Storage API 활성화 - .gitignore에 tfstate 제외, lock.hcl은 커밋 대상
- 설정 파일 이름 변경: ai.yml→ai-setting, security→spring-security 등 - q-asker.yml → app-common.yml (앱 공통 설정) - server.yml에서 DB 설정 분리 → database-config.yml - resilience4j.yml + rate-limit → resilience.yml 통합 - 파일 검증 설정을 OCI 프로퍼티에서 분리 → FileValidationProperties - 배포 스크립트 .github/resources/ → infra/blue-green/ 이동 - docker-compose에 GCP ADC 볼륨 마운트 추가
- 기술 스택: Google Gemini via Vertex AI, Google Cloud Storage 추가 - 환경 변수: GCP project-id, location, GCS_BUCKET_NAME 추가 - 아키텍처: infra/terraform/gcp 디렉토리 추가
- config: ai.yml, monitoring.yml, oci.yml, security.yml, springdoc.yml - deploy: .github/resources/ → infra/blue-green/ 이동 완료 후 원본 제거
- spring.security.oauth2, spring.security.jwt가 q-asker.security 하위에 있어 Client id of registration 'google' must not be empty 에러 발생 - spring: 블록으로 올바르게 이동
- 멀티 도큐먼트 YAML에서 프로필 섹션이 common 섹션의 registration 맵을 덮어써 client-id가 사라지는 문제 해결 - client-id, client-secret을 local/prod 각 프로필에 직접 포함
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- 프로필별 분리 방식이 멀티 도큐먼트 YAML 병합에서 문제 발생 - client-id/secret을 공통 섹션에 두고 프로필에서는 redirect-uri만 오버라이드
- Nginx SSL 인증서 경로를 Cloudflare Origin CA → Let's Encrypt로 변경 - docker-compose에 /etc/letsencrypt 볼륨 마운트 추가 - Cloudflare Origin CA 설정은 주석으로 보존
- AwsCloudFrontProperties → CdnProperties (prefix: cdn) - aws.cloudfront.base-url → cdn.base-url - checkCloudFrontUrlWithThrowing → checkCdnUrlWithThrowing - 변수명 s3Future/cloudFrontUrl → ociFuture/cdnUrl - 미사용 AWS SDK BOM 의존성 제거 - 주석/DisplayName CloudFront/S3 참조 CDN/OCI로 변경 - CLAUDE.md 기술 스택 갱신 (AWS CloudFront → Cloudflare CDN)
| return Client.builder() | ||
| .apiKey(properties.getApiKey()) | ||
| .project(properties.getProjectId()) | ||
| .location(properties.getLocation()) |
There was a problem hiding this comment.
Google AI Studio(API 키) → Vertex AI(IAM) 전환 핵심. vertexAI(true)로 엔드포인트가 generativelanguage.googleapis.com에서 Vertex AI로 변경되며, project/location 기반 인증을 사용한다.
| this.fileRequestRepeat = | ||
| Counter.builder("gemini.file.request") | ||
| Counter.builder("gcs.file.request") | ||
| .tag("type", "repeat") |
There was a problem hiding this comment.
기존 Gemini Files API의 3단계(initiateUpload → uploadBytes → waitForProcessing 폴링)를 GCS storage.create() 한 줄로 대체. GCS는 업로드 즉시 사용 가능하므로 폴링 루프가 불필요해졌다.
| @@ -81,6 +82,8 @@ private void processAsyncGeneration( | |||
| String sessionId, Long problemSetId, GenerationRequest request) { | |||
|
|
|||
| AtomicInteger atomicGeneratedCount = new AtomicInteger(0); | |||
There was a problem hiding this comment.
퀴즈 번호 경쟁상태 수정: ReentrantLock으로 번호 할당 → DB 저장 → SSE 전송을 직렬화하여 번호 역전 방지. synchronized 대신 ReentrantLock을 쓴 이유는 Virtual Thread 환경에서 캐리어 스레드 pinning 문제를 회피하기 위함.
- Nginx: Origin CA 인증서 경로 활성화, Let's Encrypt 주석 제거 - docker-compose: Let's Encrypt 볼륨 제거
Cloudflare IP 대역에서 API 서버(80/443), MON 서버(3000) 인바운드를 허용하는 NSG 규칙을 Terraform으로 관리하도록 IaC 구성
📢 설명
변경 요약
변경 1: Google AI Studio → Vertex AI + GCS 전환
Google AI Studio API는 GCP 프리 크레딧을 사용할 수 없어서 Vertex AI로 전환했다. Gemini 전용 PDF Context Caching은 Google만 제공하므로 Google 생태계를 유지해야 하고, 기존 Gemini 프롬프트의 콘텐츠 품질을 다른 AI로 옮기면 품질 저하를 예측할 수 없어 Vertex AI가 최선의 선택이었다.
기존 Gemini Files API의 resumable upload + 폴링 루프(
initiateUpload → uploadBytes → waitForProcessing)가 GCSstorage.create()한 줄로 대체되어GeminiFileRestClientConfig전체를 삭제할 수 있었다.💡 의사 선택과정 (trade-off)
얻은 것
잃은 것
대안 검토
변경 2: Cloudflare DDoS 방어 인프라
예방 차원에서 Cloudflare Free 플랜을 도입했다.
api.q-asker.com에 프록시를 활성화하여 DDoS 방어, SSL 터미네이션, CDN 캐싱을 무료로 확보했다.Nginx에 Cloudflare IP 대역
set_real_ip_from과CF-Connecting-IP헤더 설정을 추가하여 Rate Limiting이 실제 클라이언트 IP 기준으로 동작하도록 했다. 배포 파일도.github/resources/→infra/blue-green/으로 이동하여 인프라 관심사를 분리했다.💡 의사 선택과정 (trade-off)
얻은 것
잃은 것
대안 검토
변경 3: 설정 파일 리팩토링 및 프로퍼티 분리
Vertex AI 전환과 함께 설정 파일을 역할 기반 네이밍으로 정리했다.
OciObjectStorageProperties에서 파일 검증 필드를FileValidationProperties로 분리하여, 스토리지와 무관한 비즈니스 검증 규칙을 독립시켰다.server.ymldatabase-config.ymlai.ymlai-setting.ymlsecurity.ymlspring-security.ymloci.ymloci-bucket-config.ymlq-asker.ymlapp-common.yml+resilience.ymlmonitoring.ymlactuator.ymlspringdoc.ymlspring-doc.yml변경 4: 퀴즈 번호 경쟁상태 수정
기존에는 AI 오케스트레이션 레이어에서
AtomicInteger로 번호를 할당한 뒤 소비자에게 전달했는데, 번호 할당 시점과 SSE 전송 시점 사이에 다른 청크가 끼어들어 번호 역전이 발생할 수 있었다. 예: 1번 청크가 번호 15를 받았지만, 2번 청크(번호 610)가 먼저 전송되는 상황.번호 할당을 소비자 측(
GenerationCommandServiceImpl)으로 이동하고,ReentrantLock으로번호 할당 → DB 저장 → SSE 전송을 하나의 임계 구역으로 묶어 순서를 보장했다. Virtual Thread 환경에서synchronized는 캐리어 스레드 pinning 문제가 있어ReentrantLock을 선택했다.💡 의사 선택과정 (trade-off)
얻은 것
잃은 것
수용 이유: lock 구간 내 작업이 DB 저장 + SSE 전송뿐이라 체류 시간이 짧고, 실제 병목인 AI 생성은 lock 밖에서 병렬로 돌아가므로 영향 미미
변경 5: AWS/CloudFront → CDN 네이밍 통일
Cloudflare 도입에 맞춰
AwsCloudFrontProperties→CdnProperties,checkCloudFrontUrlWithThrowing→checkCdnUrlWithThrowing등 벤더 특정 네이밍을 중립적인 CDN으로 변경했다.변경 6: GCP 인프라 Terraform 구성
Vertex AI 전환에 필요한 GCP 리소스(GCS 버킷, 서비스 계정, API 활성화)를 Terraform으로 관리한다. 추후 계정 변경 시에도 동일 인프라를 재현할 수 있다. GCS 버킷은 1일 lifecycle 정책으로 임시 PDF를 자동 삭제한다.
변경 7: 문서 및 기타 정리
CLAUDE.md추가 (프로젝트 개요, 기술 스택, 아키텍처 문서).gitignore에 Terraform state 파일 추가,CLAUDE.md추적 해제 제거frontendDevUrl,AIProblem.number, AWS S3 BOM코드 설명: 인라인 코멘트
✅ 체크리스트
기본