From 5b7fbafefa5fae4b4f8283decf51c8a0abaddfc7 Mon Sep 17 00:00:00 2001 From: HaramJo Date: Fri, 23 Jan 2026 20:48:10 +0900 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=EC=A0=84=20?= =?UTF-8?q?=EB=A1=9C=EC=BB=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=ED=99=98=EA=B2=BD=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 10 +++++++--- services/api/build.gradle | 3 +++ .../src/main/resources/application-prod.properties | 13 ++++++++++++- .../api/src/main/resources/application.properties | 7 +++++-- services/gateway/nginx/nginx.conf | 4 ++-- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f8676fb..81b192a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,7 @@ services: - mysql - redis environment: - SPRING_PROFILES_ACTIVE: docker + SPRING_PROFILES_ACTIVE: prod env_file: - .env networks: @@ -85,14 +85,18 @@ services: networks: - app-network - kafka: + kafka-1: image: confluentinc/cp-kafka:7.4.0 ports: - "9092:9092" #도커 내부 포트 9092를 내 컴퓨터 포트 9092에 매핑 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 # 도커 외부에서 도는 API 서버가 카프카를 찾아갈 수 있음 + # ✅ 리스너 이름을 서비스 이름인 kafka-1로 설정 + KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,CONTROLLER://0.0.0.0:9092 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-1:29092,CONTROLLER://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 depends_on: - zookeeper diff --git a/services/api/build.gradle b/services/api/build.gradle index 65a8ec6..859a29b 100644 --- a/services/api/build.gradle +++ b/services/api/build.gradle @@ -70,6 +70,9 @@ dependencies { // 테스트를 위한 설정 (선택 사항) testImplementation 'org.springframework.kafka:spring-kafka-test' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + + } tasks.named('test') { diff --git a/services/api/src/main/resources/application-prod.properties b/services/api/src/main/resources/application-prod.properties index 842729f..87776b7 100644 --- a/services/api/src/main/resources/application-prod.properties +++ b/services/api/src/main/resources/application-prod.properties @@ -1,4 +1,4 @@ -# ----- API는 local, MySQL는 Docker ----- +# ----- API\uB294 local, MySQL\uB294 Docker ----- spring.datasource.url=jdbc:mysql://mysql:3306/appdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=app @@ -11,3 +11,14 @@ spring.jpa.properties.hibernate.format_sql=true # schema.sql/data.sql ???? ????? ??? ? ???(??? always?) spring.sql.init.mode=never + +# Redis \uC8FC\uC18C\uB3C4 \uB3C4\uCEE4 \uC11C\uBE44\uC2A4 \uC774\uB984\uC73C\uB85C \uBCC0\uACBD +spring.data.redis.host=my-redis + +# Kafka \uC8FC\uC18C\uB3C4 \uB3C4\uCEE4 \uC11C\uBE44\uC2A4 \uC774\uB984\uC73C\uB85C \uBCC0\uACBD +spring.kafka.bootstrap-servers=kafka-1:29092 + +# Actuator \uD5EC\uC2A4 \uC5D4\uB4DC\uD3EC\uC778\uD2B8 \uC5F4\uAE30 +management.endpoints.web.exposure.include=health +management.endpoint.health.show-details=always + diff --git a/services/api/src/main/resources/application.properties b/services/api/src/main/resources/application.properties index af03c58..b767d8c 100644 --- a/services/api/src/main/resources/application.properties +++ b/services/api/src/main/resources/application.properties @@ -1,8 +1,11 @@ spring.application.name=api -spring.profiles.active=local +spring.profiles.active=prod # JWT \uC124\uC815 jwt.secret=${JWT_SECRET} # TMDB API \uD1A0\uD070 (\uACF5\uD1B5) -custom.tmdb.access-token=${TMDB_ACCESS_TOKEN} \ No newline at end of file +custom.tmdb.access-token=${TMDB_ACCESS_TOKEN} + +# Actuator endpoint \uBAA8\uB450 \uB178\uCD9C +management.endpoints.web.exposure.include=* diff --git a/services/gateway/nginx/nginx.conf b/services/gateway/nginx/nginx.conf index 1e1cffe..c095668 100644 --- a/services/gateway/nginx/nginx.conf +++ b/services/gateway/nginx/nginx.conf @@ -21,14 +21,14 @@ worker_processes auto; # 일반 API 요청 (로컬 API 서버 연결) location /api/ { - proxy_pass http://host.docker.internal:8080; + proxy_pass http://api:8080; # ✅ 요기 수정 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # SSE 전용 설정 (실시간 알림용) location /api/sse { - proxy_pass http://host.docker.internal:8080; + proxy_pass http://api:8080; # ✅ 여기도 수정 proxy_set_header Connection ""; proxy_http_version 1.1; proxy_buffering off; # 새로고침 안해도 알람 전송해주는 설정 From 98b61df1d889f90cae89ec3b4f730bd858637be8 Mon Sep 17 00:00:00 2001 From: HaramJo Date: Fri, 23 Jan 2026 21:08:53 +0900 Subject: [PATCH 2/4] =?UTF-8?q?chore:=20AWS=20=EB=B0=B0=ED=8F=AC=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20api=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EC=84=A4=EC=A0=95=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sprint/api/config/SecurityConfig.java | 21 +++++-------- .../resources/application-prod.properties | 31 +++++++++---------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/services/api/src/main/java/com/sprint/api/config/SecurityConfig.java b/services/api/src/main/java/com/sprint/api/config/SecurityConfig.java index 5b052c0..1a1b8d4 100644 --- a/services/api/src/main/java/com/sprint/api/config/SecurityConfig.java +++ b/services/api/src/main/java/com/sprint/api/config/SecurityConfig.java @@ -44,12 +44,16 @@ public PasswordEncoder passwordEncoder() { public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - // 프론트엔드 포트 허용 - configuration.setAllowedOrigins(List.of("http://localhost:5173")); + // [핵심 수정] 환경 변수에서 프론트엔드 주소를 가져오고, 없으면 로컬 주소를 기본값으로 사용 + String frontendUrl = System.getenv("FRONTEND_URL"); + if (frontendUrl == null) frontendUrl = "http://localhost:5173"; + + // 로컬과 실제 배포 주소를 모두 허용 목록에 넣습니다. + configuration.setAllowedOrigins(List.of(frontendUrl, "http://localhost:5173")); + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); - // 쿠키 전송을 위해 필수 설정 - configuration.setAllowCredentials(true); + configuration.setAllowCredentials(true); // 쿠키/인증정보 전송 허용 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); @@ -110,12 +114,3 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http.build(); } } - - /* 테스트 코드 - .csrf(csrf -> csrf.disable()) // 테스트 위해 임시허용 - // 모든 경로에 대해 접근 허용 - .authorizeHttpRequests(auth -> auth - .anyRequest().permitAll() - ); - http.addFilterBefore(customLoginFilter(), UsernamePasswordAuthenticationFilter.class); - */ diff --git a/services/api/src/main/resources/application-prod.properties b/services/api/src/main/resources/application-prod.properties index 87776b7..92b296d 100644 --- a/services/api/src/main/resources/application-prod.properties +++ b/services/api/src/main/resources/application-prod.properties @@ -1,24 +1,23 @@ -# ----- API\uB294 local, MySQL\uB294 Docker ----- -spring.datasource.url=jdbc:mysql://mysql:3306/appdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul +# 1. Database (RDS \uC5F0\uACB0\uC6A9) +# \uD658\uACBD \uBCC0\uC218\uAC00 \uC788\uC73C\uBA74 \uADF8 \uAC12\uC744 \uC4F0\uACE0, \uC5C6\uC73C\uBA74 \uAE30\uBCF8\uAC12(mysql:3306)\uC744 \uC0AC\uC6A9\uD558\uB3C4\uB85D \uC124\uC815\uD568 +spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME:mysql}:${RDS_PORT:3306}/${RDS_DB_NAME:appdb}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul +spring.datasource.username=${RDS_USERNAME:app} +spring.datasource.password=${RDS_PASSWORD:app} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.username=app -spring.datasource.password=app -# JPA +# 2. JPA (\uC6B4\uC601 \uD658\uACBD \uC8FC\uC758!) +# \uBC30\uD3EC \uC2DC\uC5D0\uB294 'update'\uBCF4\uB2E4 'none'\uC774\uB098 'validate'\uAC00 \uC548\uC804\uD558\uC9C0\uB9CC, \uCD08\uAE30 \uAD6C\uCD95 \uC2DC\uC5D0\uB294 update\uB97C \uC720\uC9C0\uD574\uB3C4 \uB428 spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.properties.hibernate.format_sql=true -# schema.sql/data.sql ???? ????? ??? ? ???(??? always?) -spring.sql.init.mode=never +# 3. Redis (ElastiCache \uC5F0\uACB0\uC6A9) +spring.data.redis.host=${REDIS_HOST:my-redis} +spring.data.redis.port=${REDIS_PORT:6379} -# Redis \uC8FC\uC18C\uB3C4 \uB3C4\uCEE4 \uC11C\uBE44\uC2A4 \uC774\uB984\uC73C\uB85C \uBCC0\uACBD -spring.data.redis.host=my-redis +# 4. Kafka (MSK \uB610\uB294 Cloud Kafka \uC5F0\uACB0\uC6A9) +spring.kafka.bootstrap-servers=${KAFKA_BROKERS:kafka-1:29092} -# Kafka \uC8FC\uC18C\uB3C4 \uB3C4\uCEE4 \uC11C\uBE44\uC2A4 \uC774\uB984\uC73C\uB85C \uBCC0\uACBD -spring.kafka.bootstrap-servers=kafka-1:29092 - -# Actuator \uD5EC\uC2A4 \uC5D4\uB4DC\uD3EC\uC778\uD2B8 \uC5F4\uAE30 +# 5. Actuator (\uBCF4\uC548\uC744 \uC704\uD574 health\uB9CC \uB178\uCD9C) management.endpoints.web.exposure.include=health -management.endpoint.health.show-details=always - +management.endpoint.health.show-details=always \ No newline at end of file From 2114dced4abf6b7448bd3118fb23ac0ac65b004c Mon Sep 17 00:00:00 2001 From: HaramJo Date: Fri, 23 Jan 2026 21:23:58 +0900 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20AWS=20=EB=B0=B0=ED=8F=AC=EB=A5=BC?= =?UTF-8?q?=20=EC=9C=84=ED=95=9C=20api,batch,gateway=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=20=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/application-docker.properties | 6 +- services/gateway/nginx/nginx.conf | 81 ++++++++++--------- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/services/batch/src/main/resources/application-docker.properties b/services/batch/src/main/resources/application-docker.properties index 25ba884..27ff751 100644 --- a/services/batch/src/main/resources/application-docker.properties +++ b/services/batch/src/main/resources/application-docker.properties @@ -1,8 +1,8 @@ server.port=8081 -spring.datasource.url=jdbc:mysql://mysql:3306/appdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul -spring.datasource.username=app -spring.datasource.password=app +spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME:mysql}:${RDS_PORT:3306}/${RDS_DB_NAME:appdb}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul +spring.datasource.username=${RDS_USERNAME:app} +spring.datasource.password=${RDS_PASSWORD:app} spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=false diff --git a/services/gateway/nginx/nginx.conf b/services/gateway/nginx/nginx.conf index c095668..048093a 100644 --- a/services/gateway/nginx/nginx.conf +++ b/services/gateway/nginx/nginx.conf @@ -1,39 +1,48 @@ # Nginx 전체 설정 파일 worker_processes auto; - events { - worker_connections 1024; - } - - http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - sendfile on; - keepalive_timeout 65; - - # 1. 기존 include는 주석 처리하거나 그대로 둡니다. - # include /etc/nginx/conf.d/*.conf; - - # 2. 서버 설정 - server { - listen 80; - - # 일반 API 요청 (로컬 API 서버 연결) - location /api/ { - proxy_pass http://api:8080; # ✅ 요기 수정 - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } - - # SSE 전용 설정 (실시간 알림용) - location /api/sse { - proxy_pass http://api:8080; # ✅ 여기도 수정 - proxy_set_header Connection ""; - proxy_http_version 1.1; - proxy_buffering off; # 새로고침 안해도 알람 전송해주는 설정 - proxy_cache off; - proxy_read_timeout 3600s; - } - } - } \ No newline at end of file +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + + # [필수] AWS 내부 DNS 서버 주소 (Service Discovery를 찾기 위해 꼭 필요함) + resolver 10.0.0.2 valid=30s; + + # [필수] 변수 정의: API 서버의 내부 도메인 주소 + set $api_url http://api.mopl.local:8080; + + # 1. 일반 API 요청 + location /api/ { + proxy_pass $api_url; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # 2. SSE 전용 설정 (실시간 알림용) + location /api/sse { + proxy_pass $api_url; + proxy_set_header Connection ""; + proxy_http_version 1.1; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 3600s; + } + + # [추가] ALB 건강 체크용 (배포 시 필수) + location /health { + access_log off; + return 200 'OK'; + } + } +} \ No newline at end of file From 8dcb6636374fb4c52c305125cdd5ef39147915a9 Mon Sep 17 00:00:00 2001 From: HaramJo Date: Mon, 26 Jan 2026 10:09:28 +0900 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..e69de29