Compare commits

..

9 Commits

Author SHA1 Message Date
doyeon 060921e756 백엔드 컨테이너 실행 가이드 문서 추가
- deployment/container/run-container-guide-back.md 파일 생성
- VM 접속 및 ACR 로그인 방법
- 컨테이너 실행 및 관리 방법
- 문제 해결 가이드
- 헬스체크 및 모니터링 방법
- 자동화 스크립트 예시
- 서비스별 실행 예시 포함

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:17:23 +09:00
doyeon b198c46d06 Analytics 서비스 및 보안 기능 업데이트
- Analytics 서비스 구현 추가 (API, 소스 코드)
- Event 서비스 소스 코드 추가
- 보안 관련 공통 컴포넌트 업데이트 (JWT, UserPrincipal, ErrorCode)
- API 컨벤션 및 명세서 업데이트
- 데이터베이스 SQL 스크립트 추가
- 백엔드 개발 문서 및 테스트 가이드 추가
- Kafka 메시지 체크 도구 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:11:00 +09:00
doyeon 003b3843cc Merge branch 'develop' into docker/participation
- 충돌 해결 완료
- settings.local.json 및 make-run-profile.md 병합

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:10:47 +09:00
hyeda2020 8323b795df Merge pull request #8 from ktds-dg0501/feature/user
UserPricipal 충돌 부분 조치
2025-10-27 15:28:05 +09:00
hyeda2020 ce3e01008a Merge branch 'develop' into feature/user 2025-10-27 15:27:57 +09:00
wonho ea807cf33e UserPricipal 충돌 부분 조치 2025-10-27 15:19:35 +09:00
Hyowon Yang 394c7a0029 Merge pull request #7 from ktds-dg0501/feature/analytics
Feature/analytics
2025-10-27 15:10:51 +09:00
doyeon e70f121db5 배포 가이드 및 명령어 추가
- 배포 관련 slash 명령어 추가 (컨테이너 이미지 빌드, 실행, K8s 배포, CI/CD)
- 백엔드/프론트엔드 각각에 대한 배포 가이드 문서 추가
- 프롬프트 파일 추가 (think, design, develop)
- deployment 디렉토리 생성
- 기존 명령어 파일 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:03:36 +09:00
doyeon 6465719b2c SecurityConfig와 application.yml 설정 업데이트
- SecurityConfig: CORS 설정 및 보안 필터 체인 구성
- application.yml: 환경 변수 플레이스홀더 방식으로 변경

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 14:06:02 +09:00
48 changed files with 1402 additions and 1003 deletions
@@ -1,3 +1,7 @@
---
command: "/deploy-actions-cicd-guide-back"
---
@cicd
'백엔드GitHubActions파이프라인작성가이드'에 따라 GitHub Actions를 이용한 CI/CD 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,3 +1,7 @@
---
command: "/deploy-actions-cicd-guide-front"
---
@cicd
'프론트엔드GitHubActions파이프라인작성가이드'에 따라 GitHub Actions를 이용한 CI/CD 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,2 +1,6 @@
---
command: "/deploy-build-image-back"
---
@cicd
'백엔드컨테이너이미지작성가이드'에 따라 컨테이너 이미지를 작성해 주세요.
@@ -1,2 +1,6 @@
---
command: "/deploy-build-image-front"
---
@cicd
'프론트엔드컨테이너이미지작성가이드'에 따라 컨테이너 이미지를 작성해 주세요.
+49 -23
View File
@@ -1,55 +1,81 @@
배포 작업 순서
---
command: "/deploy-help"
---
# 배포 작업 순서
## 1단계: 컨테이너 이미지 작성
### 백엔드
```
/deploy-build-image-back
- 백엔드컨테이너이미지작성가이드에 따라 컨테이너 이미지를 작성합니다
```
- 백엔드컨테이너이미지작성가이드를 참고하여 컨테이너 이미지를 빌드합니다
### 프론트엔드
```
/deploy-build-image-front
- 프론트엔드컨테이너이미지작성가이드에 따라 컨테이너 이미지를 작성합니다
```
- 프론트엔드컨테이너이미지작성가이드를 참고하여 컨테이너 이미지를 빌드합니다
## 2단계: 컨테이너 실행 가이드 작성
### 백엔드
```
/deploy-run-container-guide-back
- 백엔드컨테이너실행방법가이드에 따라 실행 가이드를 작성합니다
- [실행정보] 섹션에 ACR명, VM 정보를 제공해야 합니다
```
- 백엔드컨테이너실행방법가이드를 참고하여 컨테이너 실행 방법을 작성합니다
- 실행정보(ACR명, VM정보)가 필요합니다
### 프론트엔드
```
/deploy-run-container-guide-front
- 프론트엔드컨테이너실행방법가이드에 따라 실행 가이드를 작성합니다
- [실행정보] 섹션에 시스템명, ACR명, VM 정보를 제공해야 합니다
```
- 프론트엔드컨테이너실행방법가이드를 참고하여 컨테이너 실행 방법을 작성합니다
- 실행정보(시스템명, ACR명, VM정보)가 필요합니다
## 3단계: 쿠버네티스 배포 가이드 작성
## 3단계: Kubernetes 배포 가이드 작성
### 백엔드
```
/deploy-k8s-guide-back
- 백엔드배포가이드에 따라 K8s 배포 가이드를 작성합니다
- [실행정보] 섹션에 ACR명, k8s명, 네임스페이스, 리소스 정보를 제공해야 합니다
```
- 백엔드배포가이드를 참고하여 쿠버네티스 배포 방법을 작성합니다
- 실행정보(ACR명, k8s명, 네임스페이스, 리소스 설정)가 필요합니다
### 프론트엔드
```
/deploy-k8s-guide-front
- 프론트엔드배포가이드에 따라 K8s 배포 가이드를 작성합니다
- [실행정보] 섹션에 시스템명, ACR명, k8s명, 네임스페이스, 리소스, Gateway Host 정보를 제공해야 합니다
```
- 프론트엔드배포가이드를 참고하여 쿠버네티스 배포 방법을 작성합니다
- 실행정보(시스템명, ACR명, k8s명, 네임스페이스, Gateway Host, 리소스 설정)가 필요합니다
## 4단계: CI/CD 파이프라인
### Jenkins CI/CD
## 4단계: CI/CD 파이프라인
### Jenkins 사용 시
#### 백엔드
```
/deploy-jenkins-cicd-guide-back
- 백엔드Jenkins파이프라인작성가이드에 따라 작성합니다
- [실행정보] 섹션에 ACR_NAME, RESOURCE_GROUP, AKS_CLUSTER, NAMESPACE 정보를 제공해야 합니다
```
- 백엔드Jenkins파이프라인작성가이드를 참고하여 Jenkins CI/CD 파이프라인을 구성합니다
#### 프론트엔드
```
/deploy-jenkins-cicd-guide-front
- 프론트엔드Jenkins파이프라인작성가이드에 따라 작성합니다
- [실행정보] 섹션에 SYSTEM_NAME, ACR_NAME, RESOURCE_GROUP, AKS_CLUSTER, NAMESPACE 정보를 제공해야 합니다
```
- 프론트엔드Jenkins파이프라인작성가이드를 참고하여 Jenkins CI/CD 파이프라인을 구성합니다
### GitHub Actions CI/CD
### GitHub Actions 사용 시
#### 백엔드
```
/deploy-actions-cicd-guide-back
- 백엔드GitHubActions파이프라인작성가이드에 따라 작성합니다
- [실행정보] 섹션에 ACR_NAME, RESOURCE_GROUP, AKS_CLUSTER, NAMESPACE 정보를 제공해야 합니다
```
- 백엔드GitHubActions파이프라인작성가이드를 참고하여 GitHub Actions CI/CD 파이프라인을 구성합니다
#### 프론트엔드
```
/deploy-actions-cicd-guide-front
- 프론트엔드GitHubActions파이프라인작성가이드에 따라 작성합니다
- [실행정보] 섹션에 SYSTEM_NAME, ACR_NAME, RESOURCE_GROUP, AKS_CLUSTER, NAMESPACE 정보를 제공해야 합니다
```
- 프론트엔드GitHubActions파이프라인작성가이드를 참고하여 GitHub Actions CI/CD 파이프라인을 구성합니다
## 참고사항
- 각 명령 실행 전 필요한 실행정보를 프롬프트에 포함해야 합니다
- 실행정보가 없으면 안내 메시지가 표시되며 작업이 중단됩니다
- CI/CD 도구는 Jenkins 또는 GitHub Actions 중 선택하여 사용합니다
@@ -1,3 +1,7 @@
---
command: "/deploy-jenkins-cicd-guide-back"
---
@cicd
'백엔드Jenkins파이프라인작성가이드'에 따라 Jenkins를 이용한 CI/CD 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,3 +1,7 @@
---
command: "/deploy-jenkins-cicd-guide-front"
---
@cicd
'프론트엔드Jenkins파이프라인작성가이드'에 따라 Jenkins를 이용한 CI/CD 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,3 +1,7 @@
---
command: "/deploy-k8s-guide-back"
---
@cicd
'백엔드배포가이드'에 따라 백엔드 서비스 배포 방법을 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,3 +1,7 @@
---
command: "/deploy-k8s-guide-front"
---
@cicd
'프론트엔드배포가이드'에 따라 프론트엔드 서비스 배포 방법을 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -1,3 +1,7 @@
---
command: "/deploy-run-container-guide-back"
---
@cicd
'백엔드컨테이너실행방법가이드'에 따라 컨테이너 실행 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
@@ -6,6 +10,6 @@
[실행정보]
- ACR명: acrdigitalgarage01
- VM
- KEY파일: ~/home/bastion-dg0502
- KEY파일: ~/home/bastion-dg0500
- USERID: azureuser
- IP: 4.218.10.89
- IP: 4.230.5.6
@@ -1,3 +1,7 @@
---
command: "/deploy-run-container-guide-front"
---
@cicd
'프론트엔드컨테이너실행방법가이드'에 따라 컨테이너 실행 가이드를 작성해 주세요.
프롬프트에 '[실행정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-api"
---
@architecture
API를 설계해 주세요:
- '공통설계원칙'과 'API설계가이드'를 준용하여 설계
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-class"
---
@architecture
'공통설계원칙'과 '클래스설계가이드'를 준용하여 클래스를 설계해 주세요.
프롬프트에 '[클래스설계 정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-data"
---
@architecture
데이터 설계를 해주세요:
- '공통설계원칙'과 '데이터설계가이드'를 준용하여 설계
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-fix-prototype"
---
@fix as @front
'[오류내용]'섹션에 제공된 오류를 해결해 주세요.
프롬프트에 '[오류내용]'섹션이 없으면 수행 중단하고 안내 메시지 표시
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-front"
---
@plan as @front
'프론트엔드설계가이드'를 준용하여 **프론트엔드설계서**를 작성해 주세요.
프롬프트에 '[백엔드시스템]'항목이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-high-level"
---
@architecture
'HighLevel아키텍처정의가이드'를 준용하여 High Level 아키텍처 정의서를 작성해 주세요.
'CLOUD' 정보가 없으면 수행을 중단하고 안내메시지를 표시하세요.
@@ -1,3 +1,6 @@
---
command: "/design-improve-prototype"
---
@improve as @front
'[개선내용]'섹션에 있는 내용을 개선해 주세요.
프롬프트에 '[개선내용]'항목이 없으면 수행을 중단하고 안내 메시지 표시
@@ -1,2 +1,5 @@
---
command: "/design-improve-userstory"
---
@analyze as @front 프로토타입을 웹브라우저에서 분석한 후,
@document as @scribe 수정된 프로토타입에 따라 유저스토리를 업데이트 해주십시오.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-logical"
---
@architecture
논리 아키텍처를 설계해 주세요:
- '공통설계원칙'과 '논리아키텍처 설계 가이드'를 준용하여 설계
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-pattern"
---
@design-pattern
클라우드 아키텍처 패턴 적용 방안을 작성해 주세요:
- '클라우드아키텍처패턴선정가이드'를 준용하여 작성
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-physical"
---
@architecture
'물리아키텍처설계가이드'를 준용하여 물리아키텍처를 설계해 주세요.
'CLOUD' 정보가 없으면 수행을 중단하고 안내메시지를 표시하세요.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-prototype"
---
@prototype
프로토타입을 작성해 주세요:
- '프로토타입작성가이드'를 준용하여 작성
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-seq-inner"
---
@architecture
내부 시퀀스 설계를 해 주세요:
- '공통설계원칙'과 '내부시퀀스설계 가이드'를 준용하여 설계
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-seq-outer"
---
@architecture
외부 시퀀스 설계를 해 주세요:
- '공통설계원칙'과 '외부시퀀스설계가이드'를 준용하여 설계
@@ -1,2 +1,5 @@
---
command: "/design-test-prototype"
---
@test-front
프로토타입을 테스트 해 주세요.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/design-uiux"
---
@uiux
UI/UX 설계를 해주세요:
- 'UI/UX설계가이드'를 준용하여 작성
+3
View File
@@ -1,2 +1,5 @@
---
command: "/design-update-uiux"
---
@document @front
현재 프로토타입과 유저스토리를 기준으로 UI/UX설계서와 스타일가이드를 수정해 주세요.
+3
View File
@@ -1,3 +1,6 @@
---
command: "/think-help"
---
기획 작업 순서
1단계: 서비스 기획
+3
View File
@@ -1,3 +1,6 @@
---
command: "/think-planning"
---
아래 내용을 터미널에 표시만 하고 수행을 하지는 않습니다.
```
아래 가이드를 참고하여 서비스 기획을 수행합니다.
+6
View File
@@ -1,3 +1,7 @@
---
command: "/think-userstory"
---
```
@document
유저스토리를 작성하세요.
프롬프트에 '[요구사항]'섹션이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
@@ -16,3 +20,5 @@ Case 2) 다른 방법으로 이벤트스토밍을 한 경우는 요구사항을
2. 유저스토리 작성
- '유저스토리작성방법'과 '유저스토리예제'를 참고하여 유저스토리를 작성
- 결과파일은 'design/userstory.md'에 생성
```
-27
View File
@@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="EventServiceApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" folderName="Event Service">
<option name="ACTIVE_PROFILES" />
<option name="ENABLE_LAUNCH_OPTIMIZATION" value="true" />
<envs>
<env name="DB_HOST" value="20.249.177.232" />
<env name="DB_PORT" value="5432" />
<env name="DB_NAME" value="eventdb" />
<env name="DB_USERNAME" value="eventuser" />
<env name="DB_PASSWORD" value="Hi5Jessica!" />
<env name="REDIS_HOST" value="localhost" />
<env name="REDIS_PORT" value="6379" />
<env name="REDIS_PASSWORD" value="" />
<env name="KAFKA_BOOTSTRAP_SERVERS" value="localhost:9092" />
<env name="SERVER_PORT" value="8081" />
<env name="DDL_AUTO" value="update" />
<env name="LOG_LEVEL" value="DEBUG" />
<env name="SQL_LOG_LEVEL" value="DEBUG" />
<env name="DISTRIBUTION_SERVICE_URL" value="http://localhost:8084" />
</envs>
<module name="kt-event-marketing.event-service.main" />
<option name="SPRING_BOOT_MAIN_CLASS" value="com.kt.event.eventservice.EventServiceApplication" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
-89
View File
@@ -1,89 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="analytics-service" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<!-- Database Settings -->
<entry key="DB_KIND" value="postgresql" />
<entry key="DB_HOST" value="4.230.49.9" />
<entry key="DB_PORT" value="5432" />
<entry key="DB_NAME" value="analyticdb" />
<entry key="DB_USERNAME" value="eventuser" />
<entry key="DB_PASSWORD" value="Hi5Jessica!" />
<!-- Redis Settings -->
<entry key="REDIS_HOST" value="20.214.210.71" />
<entry key="REDIS_PORT" value="6379" />
<entry key="REDIS_PASSWORD" value="Hi5Jessica!" />
<entry key="REDIS_DATABASE" value="5" />
<!-- Kafka Settings -->
<entry key="KAFKA_ENABLED" value="true" />
<entry key="KAFKA_BOOTSTRAP_SERVERS" value="4.230.50.63:9092" />
<entry key="KAFKA_CONSUMER_GROUP_ID" value="analytics-service" />
<!-- Sample Data Settings (MVP Only) -->
<!-- ⚠️ 실제 운영 환경에서는 false로 설정 (다른 서비스들이 이벤트 발행) -->
<entry key="SAMPLE_DATA_ENABLED" value="true" />
<!-- JPA Settings -->
<entry key="SHOW_SQL" value="true" />
<entry key="DDL_AUTO" value="update" />
<!-- Server Settings -->
<entry key="SERVER_PORT" value="8086" />
<!-- JWT Settings -->
<entry key="JWT_SECRET" value="dev-jwt-secret-key-for-development-only-analytics-service-2024" />
<entry key="JWT_ACCESS_TOKEN_VALIDITY" value="1800" />
<entry key="JWT_REFRESH_TOKEN_VALIDITY" value="86400" />
<!-- CORS Settings -->
<entry key="CORS_ALLOWED_ORIGINS" value="http://localhost:*" />
<!-- Logging Settings -->
<entry key="LOG_LEVEL_APP" value="DEBUG" />
<entry key="LOG_LEVEL_WEB" value="INFO" />
<entry key="LOG_LEVEL_SQL" value="DEBUG" />
<entry key="LOG_LEVEL_SQL_TYPE" value="TRACE" />
<entry key="LOG_FILE" value="logs/analytics-service.log" />
<!-- Batch Settings -->
<entry key="BATCH_ENABLED" value="true" />
<entry key="BATCH_REFRESH_INTERVAL" value="300000" />
<entry key="BATCH_INITIAL_DELAY" value="30000" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="analytics-service:bootRun" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<EXTENSION ID="com.intellij.execution.ExternalSystemRunConfigurationJavaExtension">
<extension name="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
<ENTRIES>
<ENTRY IS_ENABLED="true" PARSER="runconfig" IS_EXECUTABLE="false" />
</ENTRIES>
</extension>
</EXTENSION>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+82
View File
@@ -0,0 +1,82 @@
# 백엔드 컨테이너이미지 작성가이드
[요청사항]
- 백엔드 각 서비스를의 컨테이너 이미지 생성
- 실제 빌드 수행 및 검증까지 완료
- '[결과파일]'에 수행한 명령어를 포함하여 컨테이너 이미지 작성 과정 생성
[작업순서]
- 서비스명 확인
서비스명은 settings.gradle에서 확인
예시) include 'common'하위의 4개가 서비스명임.
```
rootProject.name = 'tripgen'
include 'common'
include 'user-service'
include 'location-service'
include 'ai-service'
include 'trip-service'
```
- 실행Jar 파일 설정
실행Jar 파일명을 서비스명과 일치하도록 build.gradle에 설정 합니다.
```
bootJar {
archiveFileName = '{서비스명}.jar'
}
```
- Dockerfile 생성
아래 내용으로 deployment/container/Dockerfile-backend 생성
```
# Build stage
FROM openjdk:23-oraclelinux8 AS builder
ARG BUILD_LIB_DIR
ARG ARTIFACTORY_FILE
COPY ${BUILD_LIB_DIR}/${ARTIFACTORY_FILE} app.jar
# Run stage
FROM openjdk:23-slim
ENV USERNAME=k8s
ENV ARTIFACTORY_HOME=/home/${USERNAME}
ENV JAVA_OPTS=""
# Add a non-root user
RUN adduser --system --group ${USERNAME} && \
mkdir -p ${ARTIFACTORY_HOME} && \
chown ${USERNAME}:${USERNAME} ${ARTIFACTORY_HOME}
WORKDIR ${ARTIFACTORY_HOME}
COPY --from=builder app.jar app.jar
RUN chown ${USERNAME}:${USERNAME} app.jar
USER ${USERNAME}
ENTRYPOINT [ "sh", "-c" ]
CMD ["java ${JAVA_OPTS} -jar app.jar"]
```
- 컨테이너 이미지 생성
아래 명령으로 각 서비스 빌드. shell 파일을 생성하지 말고 command로 수행.
서브에이젼트를 생성하여 병렬로 수행.
```
DOCKER_FILE=deployment/container/Dockerfile-backend
service={서비스명}
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="${서비스명}/build/libs" \
--build-arg ARTIFACTORY_FILE="${서비스명}.jar" \
-f ${DOCKER_FILE} \
-t ${서비스명}:latest .
```
- 생성된 이미지 확인
아래 명령으로 모든 서비스의 이미지가 빌드되었는지 확인
```
docker images | grep {서비스명}
```
[결과파일]
deployment/container/build-image.md
+220
View File
@@ -0,0 +1,220 @@
# 설계 프롬프트
아래 순서대로 설계합니다.
## UI/UX 설계
command: "/design-uiux"
prompt:
```
@uiux
UI/UX 설계를 해주세요:
- 'UI/UX설계가이드'를 준용하여 작성
```
---
# 프로토타입 작성
command: "/design-prototype"
prompt:
**1.작성**
```
@prototype
프로토타입을 작성해 주세요:
- '프로토타입작성가이드'를 준용하여 작성
```
---
**2.검증**
command: "/design-test-prototype"
prompt:
```
@test-front
프로토타입을 테스트 해 주세요.
```
---
**3.오류수정**
command: "/design-fix-prototype"
prompt:
```
@fix as @front
'[오류내용]'섹션에 제공된 오류를 해결해 주세요.
프롬프트에 '[오류내용]'섹션이 없으면 수행 중단하고 안내 메시지 표시
{안내메시지}
'[오류내용]'섹션 하위에 오류 내용을 제공
```
---
**4.개선**
command: "/design-improve-prototype"
prompt:
```
@improve as @front
'[개선내용]'섹션에 있는 내용을 개선해 주세요.
프롬프트에 '[개선내용]'항목이 없으면 수행을 중단하고 안내 메시지 표시
{안내메시지}
'[개선내용]'섹션 하위에 개선할 내용을 제공
```
---
**5.유저스토리 품질 높이기**
command: "/design-improve-userstory"
prompt:
```
@analyze as @front 프로토타입을 웹브라우저에서 분석한 후,
@document as @scribe 수정된 프로토타입에 따라 유저스토리를 업데이트 해주십시오.
```
---
**6.설계서 다시 업데이트**
command: "/design-update-uiux"
prompt:
```
@document @front
현재 프로토타입과 유저스토리를 기준으로 UI/UX설계서와 스타일가이드를 수정해 주세요.
```
---
## 클라우드 아키텍처 패턴 선정
command: "/design-pattern"
prompt:
```
@design-pattern
클라우드 아키텍처 패턴 적용 방안을 작성해 주세요:
- '클라우드아키텍처패턴선정가이드'를 준용하여 작성
```
---
## 논리아키텍처 설계
command: "/design-logical"
prompt:
```
@architecture
논리 아키텍처를 설계해 주세요:
- '공통설계원칙'과 '논리아키텍처 설계 가이드'를 준용하여 설계
```
---
## 외부 시퀀스 설계
command: "/design-seq-outer"
prompt:
```
@architecture
외부 시퀀스 설계를 해 주세요:
- '공통설계원칙'과 '외부시퀀스설계가이드'를 준용하여 설계
```
---
## 내부 시퀀스 설계
command: "/design-seq-inner"
prompt:
```
@architecture
내부 시퀀스 설계를 해 주세요:
- '공통설계원칙'과 '내부시퀀스설계 가이드'를 준용하여 설계
```
---
## API 설계
command: "/design-api"
prompt:
```
@architecture
API를 설계해 주세요:
- '공통설계원칙'과 'API설계가이드'를 준용하여 설계
```
---
## 클래스 설계
command: "/design-class"
prompt:
```
@architecture
'공통설계원칙'과 '클래스설계가이드'를 준용하여 클래스를 설계해 주세요.
프롬프트에 '[클래스설계 정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
{안내메시지}
'[클래스설계 정보]' 섹션에 아래 예와 같은 정보를 제공해 주십시오.
[클래스설계 정보]
- 패키지 그룹: com.unicorn.tripgen
- 설계 아키텍처 패턴
- User: Layered
- Trip: Clean
- Location: Layered
- AI: Layered
```
---
## 데이터 설계
command: "/design-data"
prompt:
```
@architecture
데이터 설계를 해주세요:
- '공통설계원칙'과 '데이터설계가이드'를 준용하여 설계
```
---
## High Level 아키텍처 정의서 작성
command: "/design-high-level"
prompt:
```
@architecture
'HighLevel아키텍처정의가이드'를 준용하여 High Level 아키텍처 정의서를 작성해 주세요.
'CLOUD' 정보가 없으면 수행을 중단하고 안내메시지를 표시하세요.
{안내메시지}
아래 예와 같이 CLOUD 제공자를 Azure, AWS, Google과 같이 제공하세요.
- CLOUD: Azure
```
---
## 물리 아키텍처 설계
command: "/design-physical"
prompt:
```
@architecture
'물리아키텍처설계가이드'를 준용하여 물리아키텍처를 설계해 주세요.
'CLOUD' 정보가 없으면 수행을 중단하고 안내메시지를 표시하세요.
{안내메시지}
아래 예와 같이 CLOUD 제공자를 Azure, AWS, Google과 같이 제공하세요.
- CLOUD: Azure
```
## 프론트엔드 설계
command: "/design-front"
prompt:
```
@plan as @front
'프론트엔드설계가이드'를 준용하여 **프론트엔드설계서**를 작성해 주세요.
프롬프트에 '[백엔드시스템]'항목이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
{안내메시지}
'[백엔드시스템]' 섹션에 아래 예와 같은 정보를 제공해 주십시오.
[백엔드시스템]
- 시스템: tripgen
- 마이크로서비스: user-service, location-service, trip-service, ai-service
- API문서
- user service: http://localhost:8081/v3/api-docs
- location service: http://localhost:8082/v3/api-docs
- trip service: http://localhost:8083/v3/api-docs
- ai service: http://localhost:8084/v3/api-docs
[요구사항]
- 각 화면에 Back 아이콘 버튼과 화면 타이틀 표시
- 하단 네비게이션 바 아이콘화: 홈, 새여행, 주변장소검색, 여행보기
```
+180
View File
@@ -0,0 +1,180 @@
# 개발 프롬프트
## 데이터베이스 설치계획서 작성 요청
command: "/develop-db-guide"
prompt:
```
@backing-service
"데이터베이스설치계획서가이드"에 따라 데이터베이스 설치계획서를 작성해 주십시오.
```
---
## 데이터베이스 설치 수행 요청
command: "/develop-db-install"
prompt:
```
@backing-service
[요구사항]
'데이터베이스설치가이드'에 따라 설치해 주세요.
'[설치정보]'섹션이 없으면 수행을 중단하고 안내 메시지를 표시하세요.
{안내메시지}
'[설치정보]'섹션 하위에 아래 예와 같이 설치에 필요한 정보를 추가해 주세요.
- 설치대상환경: 개발환경
- AKS Resource Group: rg-digitalgarage-01
- AKS Name: aks-digitalgarage-01
- Namespace: tripgen-dev
```
---
## 데이터베이스 설치 제거 요청 (필요시)
command: "/develop-db-remove"
prompt:
```
@backing-service
[요구사항]
- "데이터베이스설치결과서"를 보고 관련된 모든 리소스를 삭제
- "캐시설치결과서"를 보고 관련된 모든 리소스를 삭제
- 현재 OS에 맞게 수행
- 서브 에이젼트를 병렬로 수행하여 삭제
- 결과파일은 생성할 필요 없고 화면에만 결과 표시
[참고자료]
- 데이터베이스설치결과서
- 캐시설치결과서
```
---
## Message Queue 설치 계획서 작성 요청
command: "/develop-mq-guide"
prompt:
```
@backing-service
"MQ설치게획서가이드"에 따라 Message Queue 설치계획서를 작성해 주세요.
```
---
## Message Queue 설치 수행 요청(필요시)
command: "/develop-mq-install"
prompt:
```
@backing-service
[요구사항]
'MQ설치가이드'에 따라 설치해 주세요.
'[설치정보]'섹션이 없으면 수행을 중단하고 안내 메시지를 표시하세요.
{안내메시지}
'[설치정보]'섹션 하위에 아래 예와 같이 설치에 필요한 정보를 추가해 주세요.
- 설치대상환경: 개발환경
- Resource Group: rg-digitalgarage-01
- Namespace: tripgen-dev
```
---
## Message Queue 설치 제거 요청
command: "/develop-mq-remove"
prompt:
```
@backing-service
[요구사항]
- "MQ설치결과서"를 보고 관련된 모든 리소스를 삭제
- 현재 OS에 맞게 수행
- 서브 에이젼트를 병렬로 수행하여 삭제
- 결과파일은 생성할 필요 없고 화면에만 결과 표시
[참고자료]
- MQ설치결과서
```
---
## 백엔드 개발 요청
command: "/develop-dev-backend"
prompt:
```
@dev-backend
"백엔드개발가이드"에 따라 개발해 주세요.
프롬프트에 '[개발정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
{안내메시지}
[개발정보]
- 개발 아키텍처패턴
- auth: Layered
- bill-inquiry: Clean
- product-change: Layered
- kos-mock: Layered
```
---
## 백엔드 오류 해결 요청
command: "/develop-fix-backend"
prompt:
```
@fix as @back
개발된 각 서비스와 common 모듈을 컴파일하고 에러를 해결해 주세요.
- common 모듈 우선 수행
- 각 서비스별로 서브 에이젠트를 병렬로 수행
- 컴파일이 모두 성공할때까지 계속 수행
```
---
## 서비스 실행파일 작성 요청
command: "/develop-make-run-profile"
prompt:
```
@test-backend
'서비스실행파일작성가이드'에 따라 테스트를 해 주세요.
프롬프트에 '[작성정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
DB나 Redis의 접근 정보는 지정할 필요 없습니다. 특별히 없으면 '[작성정보]'섹션에 '없음'이라고 하세요.
{안내메시지}
[작성정보]
- API Key
- Claude: sk-ant-ap...
- OpenAI: sk-proj-An4Q...
- Open Weather Map: 1aa5b...
- Kakao API Key: 5cdc24....
```
---
## 백엔드 테스트 요청
command: "/develop-test-backend"
prompt:
```
@test-backend
'백엔드테스트가이드'에 따라 테스트를 해 주세요.
프롬프트에 '[테스트정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
테스트 대상 서비스를 지정안하면 모든 서비스를 테스트 합니다.
{안내메시지}
'[테스트정보]'섹션 하위에 아래 예와 같이 테스트에 필요한 정보를 제시해 주세요.
테스트 대상 서비스를 콤마로 구분하여 입력할 수 있으며 전체를 테스트 할 때는 '전체'라고 입력하세요.
- 서비스: user-service
- API Key
- Claude: sk-ant-ap...
- OpenAI: sk-proj-An4Q...
- Open Weather Map: 1aa5b...
- Kakao API Key: 5cdc24....
```
---
## 프론트엔드 개발 요청
command: "/develop-dev-front"
prompt:
```
@dev-front
"프론트엔드개발가이드"에 따라 개발해 주세요.
프롬프트에 '[개발정보]'항목이 없으면 수행을 중단하고 안내 메시지를 표시해 주세요.
{안내메시지}
'[개발정보]'섹션 하위에 아래 예와 같이 개발에 필요한 정보를 제시해 주세요.
[개발정보]
- 개발프레임워크: Typescript + React 18
- UI프레임워크: MUI v5
- 상태관리: Redux Toolkit
- 라우팅: React Router v6
- API통신: Axios
- 스타일링: MUI + styled-components
- 빌드도구: Vite
```
+41
View File
@@ -0,0 +1,41 @@
# 서비스 기획 프롬프트
## 서비스 기획
command: "/think-planning"
prompt:
아래 내용을 터미널에 표시만 하고 수행을 하지는 않습니다.
```
아래 가이드를 참고하여 서비스 기획을 수행합니다.
https://github.com/cna-bootcamp/aiguide/blob/main/AI%ED%99%9C%EC%9A%A9%20%EC%84%9C%EB%B9%84%EC%8A%A4%20%EA%B8%B0%ED%9A%8D%20%EA%B0%80%EC%9D%B4%EB%93%9C.md
```
---
## 유저스토리 작성
command: "/think-userstory"
prompt:
```
@document
유저스토리를 작성하세요.
프롬프트에 '[요구사항]'섹션이 없으면 수행을 중단하고 안내 메시지를 표시합니다.
{안내메시지}
'[요구사항]' 섹션에 아래 예와 같은 정보를 제공해 주십시오.
[요구사항]
Case 1) 이벤트스토밍을 피그마로 수행한 경우는 피그마 채널ID를 제공
예) 피그마 채널ID 'abcde'에 접속하여 분석
Case 2) 다른 방법으로 이벤트스토밍을 한 경우는 요구사항을 정리한 파일 경로를 제공
예) 요구사항문서 'design/requirement.md'를 읽어 분석
프롬프트에 '[요구사항]'섹션이 있으면 아래와 같이 수행합니다.
1. 요구사항 분석
- 피그마 채널ID가 제공된 경우 figma MCP를 이용하여 해당 채널에 접속하여 분석
- 요구사항문서 경로가 제공된 경우 해당 문서를 읽어 요구사항을 분석
2. 유저스토리 작성
- '유저스토리작성방법'과 '유저스토리예제'를 참고하여 유저스토리를 작성
- 결과파일은 'design/userstory.md'에 생성
```
@@ -56,13 +56,14 @@ public class JwtTokenProvider {
* @param roles 역할 목록
* @return Access Token
*/
public String createAccessToken(UUID userId, UUID storeId, String email, String name, List<String> roles) {
public String createAccessToken(Long userId, Long storeId, String email, String name, List<String> roles) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + accessTokenValidityMs);
return Jwts.builder()
.subject(userId.toString())
.claim("storeId", storeId.toString())
.claim("storeId", storeId != null ? storeId.toString() : null)
.claim("email", email)
.claim("name", name)
.claim("roles", roles)
@@ -112,8 +113,9 @@ public class JwtTokenProvider {
public UserPrincipal getUserPrincipalFromToken(String token) {
Claims claims = parseToken(token);
UUID userId = UUID.fromString(claims.getSubject());
UUID storeId = UUID.fromString(claims.get("storeId", String.class));
Long userId = Long.parseLong(claims.getSubject());
String storeIdStr = claims.get("storeId", String.class);
Long storeId = storeIdStr != null ? Long.parseLong(storeIdStr) : null;
String email = claims.get("email", String.class);
String name = claims.get("name", String.class);
@SuppressWarnings("unchecked")
@@ -31,6 +31,11 @@ public class UserPrincipal implements UserDetails {
*/
private final UUID storeId;
/**
* 매장 ID
*/
private final Long storeId;
/**
* 사용자 이메일
*/
+146 -295
View File
@@ -1,118 +1,40 @@
# 백엔드 컨테이너 이미지 작성 결과
# 백엔드 컨테이너 이미지 빌드 결과
작성일: 2025-10-27
작성자: DevOps Engineer
## 프로젝트 정보
- **프로젝트명**: kt-event-marketing
- **빌드 일시**: 2025-10-27
- **빌드 대상**: 3개 마이크로서비스 (content-service, participation-service, user-service)
## 1. 개요
## 1. 사전 준비
KT 이벤트 마케팅 플랫폼의 백엔드 마이크로서비스들을 컨테이너 이미지로 빌드하는 과정을 문서화합니다.
## 2. 서비스 현황
### 2.1 전체 서비스 목록 (settings.gradle 기준)
```
rootProject.name = 'kt-event-marketing'
// Common module
include 'common'
// Microservices
include 'user-service'
include 'event-service'
include 'ai-service'
include 'content-service'
include 'distribution-service'
include 'participation-service'
include 'analytics-service'
```
### 2.2 구현 상태
| 서비스명 | 구현 상태 | JAR 빌드 | 컨테이너 이미지 | 비고 |
|---------|----------|---------|---------------|------|
| common | ✅ | N/A | N/A | 공통 라이브러리 |
| user-service | ⚠️ | ❌ | ⏸️ | 컴파일 에러 (타입 불일치) |
| event-service | ✅ | ✅ | ⏸️ | Docker Desktop 필요 |
| ai-service | ❌ | ❌ | ❌ | 미구현 |
| content-service | ✅ | ✅ | ⏸️ | Docker Desktop 필요 |
| distribution-service | ❌ | ❌ | ❌ | 미구현 |
| participation-service | ✅ | ✅ | ⏸️ | Docker Desktop 필요 |
| analytics-service | ✅ | ✅ | ⏸️ | Docker Desktop 필요 |
**빌드 가능 서비스**: 4개 (event-service, content-service, participation-service, analytics-service)
## 3. JAR 파일 빌드
### 3.1 bootJar 설정 확인
root `build.gradle`에 이미 설정되어 있음:
### 1.1 서비스 확인
settings.gradle에서 확인된 구현 완료 서비스:
- ✅ content-service
- ✅ participation-service
- ✅ user-service
- ⏳ ai-service (미구현)
- ⏳ analytics-service (미구현)
- ⏳ distribution-service (미구현)
- ⏳ event-service (미구현)
### 1.2 bootJar 설정 확인
build.gradle에 이미 설정되어 있음 (line 101-103):
```gradle
// Configure bootJar task for each service
bootJar {
archiveFileName = "${project.name}.jar"
}
```
### 3.2 JAR 빌드 실행
#### gradlew 실행 권한 설정 (최초 1회)
VM 환경에서 실행 시 권한 오류가 발생할 수 있으므로 먼저 실행 권한을 부여합니다:
## 2. Dockerfile 생성
### 2.1 디렉토리 생성
```bash
chmod +x gradlew
mkdir -p deployment/container
```
#### 빌드 명령어 실행
### 2.2 Dockerfile-backend 작성
파일 위치: `deployment/container/Dockerfile-backend`
**명령어**:
```bash
./gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar :user-service:bootJar --no-daemon
```
**권한 오류 발생 시 대체 방법**:
```bash
# gradlew에 실행 권한이 없는 경우
bash gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar :user-service:bootJar --no-daemon
```
**빌드 결과**:
**성공한 서비스 (4개)**:
- `analytics-service/build/libs/analytics-service.jar`
- `content-service/build/libs/content-service.jar`
- `event-service/build/libs/event-service.jar`
- `participation-service/build/libs/participation-service.jar`
**실패한 서비스 (1개)**:
- `user-service`: 컴파일 에러 발생
**user-service 컴파일 에러 상세**:
```
UserController.java:93: error: incompatible types: UUID cannot be converted to Long
Long userId = principal.getUserId();
^
UserController.java:109: error: incompatible types: UUID cannot be converted to Long
Long userId = principal.getUserId();
^
UserController.java:126: error: incompatible types: UUID cannot be converted to Long
Long userId = principal.getUserId();
^
AuthenticationServiceImpl.java:72: error: method createAccessToken in class JwtTokenProvider cannot be applied to given types;
required: UUID,UUID,String,String,List<String>
found: Long,String,String,List<String>
reason: actual and formal argument lists differ in length
```
**조치 필요**: user-service의 User ID 타입을 Long에서 UUID로 변경 필요
## 4. Dockerfile 작성
**파일 위치**: `deployment/container/Dockerfile-backend`
**내용**:
```dockerfile
# Build stage
FROM openjdk:23-oraclelinux8 AS builder
@@ -141,241 +63,170 @@ ENTRYPOINT [ "sh", "-c" ]
CMD ["java ${JAVA_OPTS} -jar app.jar"]
```
**특징**:
- Multi-stage build (빌드 단계와 실행 단계 분리)
- OpenJDK 23 사용
- 비root 사용자(k8s)로 실행하여 보안 강화
- JAVA_OPTS 환경변수로 JVM 옵션 커스터마이징 가능
- linux/amd64 플랫폼 지원
**주요 특징**:
- Multi-stage build로 이미지 크기 최적화
- Non-root user(k8s) 생성으로 보안 강화
- JAVA_OPTS 환경 변수로 JVM 옵션 설정 가능
## 5. 컨테이너 이미지 빌드
## 3. JAR 파일 빌드
### 5.1 사전 조건
⚠️ **Docker Desktop 실행 필요**
이미지 빌드 전에 Docker Desktop이 실행되어 있어야 합니다:
1. Windows에서 Docker Desktop 실행
2. 시스템 트레이에서 "Docker Desktop is running" 확인
3. 확인 명령어: `docker ps`
### 5.2 빌드 명령어
#### analytics-service
### 3.1 빌드 명령어
```bash
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="analytics-service/build/libs" \
--build-arg ARTIFACTORY_FILE="analytics-service.jar" \
-f deployment/container/Dockerfile-backend \
-t analytics-service:latest .
./gradlew :content-service:bootJar :participation-service:bootJar :user-service:bootJar
```
#### content-service
```bash
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="content-service/build/libs" \
--build-arg ARTIFACTORY_FILE="content-service.jar" \
-f deployment/container/Dockerfile-backend \
-t content-service:latest .
### 3.2 빌드 결과
```
BUILD SUCCESSFUL in 15s
18 actionable tasks: 5 executed, 13 up-to-date
```
#### event-service
### 3.3 생성된 JAR 파일
```bash
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="event-service/build/libs" \
--build-arg ARTIFACTORY_FILE="event-service.jar" \
-f deployment/container/Dockerfile-backend \
-t event-service:latest .
$ ls -lh */build/libs/*.jar
-rw-r--r-- 1 KTDS 197121 78M content-service/build/libs/content-service.jar
-rw-r--r-- 1 KTDS 197121 85M participation-service/build/libs/participation-service.jar
-rw-r--r-- 1 KTDS 197121 96M user-service/build/libs/user-service.jar
```
#### participation-service
## 4. Docker 이미지 빌드
### 4.1 content-service 이미지 빌드
```bash
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="participation-service/build/libs" \
--build-arg ARTIFACTORY_FILE="participation-service.jar" \
-f deployment/container/Dockerfile-backend \
-t participation-service:latest .
```
DOCKER_FILE=deployment/container/Dockerfile-backend
service=content-service
### 5.3 일괄 빌드 스크립트
모든 서비스를 한 번에 빌드하려면 다음 스크립트를 사용하세요:
**Windows (PowerShell)**:
```powershell
# 빌드 가능한 서비스 목록
$services = @(
"analytics-service",
"content-service",
"event-service",
"participation-service"
)
# 각 서비스 빌드
foreach ($service in $services) {
Write-Host "Building $service..." -ForegroundColor Green
docker build `
--platform linux/amd64 `
--build-arg BUILD_LIB_DIR="$service/build/libs" `
--build-arg ARTIFACTORY_FILE="$service.jar" `
-f deployment/container/Dockerfile-backend `
-t ${service}:latest .
if ($LASTEXITCODE -eq 0) {
Write-Host "$service build completed" -ForegroundColor Green
} else {
Write-Host "$service build failed" -ForegroundColor Red
}
}
```
**Linux/Mac (Bash)**:
```bash
#!/bin/bash
# 빌드 가능한 서비스 목록
services=(
"analytics-service"
"content-service"
"event-service"
"participation-service"
)
# 각 서비스 빌드
for service in "${services[@]}"; do
echo "Building $service..."
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="${service}/build/libs" \
--build-arg ARTIFACTORY_FILE="${service}.jar" \
-f deployment/container/Dockerfile-backend \
-f ${DOCKER_FILE} \
-t ${service}:latest .
if [ $? -eq 0 ]; then
echo "$service build completed"
else
echo "$service build failed"
fi
done
```
## 6. 이미지 확인
### 6.1 빌드된 이미지 목록 확인
**빌드 결과**:
- Image ID: 06af046cbebe
- Size: 1.01GB
- Platform: linux/amd64
- Status: ✅ SUCCESS
### 4.2 participation-service 이미지 빌드
```bash
docker images | grep -E "analytics-service|content-service|event-service|participation-service"
DOCKER_FILE=deployment/container/Dockerfile-backend
service=participation-service
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="${service}/build/libs" \
--build-arg ARTIFACTORY_FILE="${service}.jar" \
-f ${DOCKER_FILE} \
-t ${service}:latest .
```
**예상 출력**:
```
analytics-service latest <IMAGE_ID> <TIME> <SIZE>
content-service latest <IMAGE_ID> <TIME> <SIZE>
event-service latest <IMAGE_ID> <TIME> <SIZE>
participation-service latest <IMAGE_ID> <TIME> <SIZE>
```
### 6.2 개별 서비스 이미지 확인
**빌드 결과**:
- Image ID: 486f2c00811e
- Size: 1.04GB
- Platform: linux/amd64
- Status: ✅ SUCCESS
### 4.3 user-service 이미지 빌드
```bash
# analytics-service
docker images analytics-service:latest
DOCKER_FILE=deployment/container/Dockerfile-backend
service=user-service
# content-service
docker images content-service:latest
# event-service
docker images event-service:latest
# participation-service
docker images participation-service:latest
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="${service}/build/libs" \
--build-arg ARTIFACTORY_FILE="${service}.jar" \
-f ${DOCKER_FILE} \
-t ${service}:latest .
```
### 6.3 이미지 상세 정보 확인
**빌드 결과**:
- Image ID: 7ef657c343dd
- Size: 1.09GB
- Platform: linux/amd64
- Status: ✅ SUCCESS
## 5. 빌드 결과 확인
### 5.1 이미지 목록 조회
```bash
# 이미지 레이어 확인
docker history <service-name>:latest
$ docker images | grep -E "(content-service|participation-service|user-service)"
# 이미지 메타데이터 확인
docker inspect <service-name>:latest
participation-service latest 486f2c00811e 48 seconds ago 1.04GB
user-service latest 7ef657c343dd 48 seconds ago 1.09GB
content-service latest 06af046cbebe 48 seconds ago 1.01GB
```
## 7. 테스트 실행
### 5.2 빌드 요약
| 서비스명 | Image ID | 크기 | 상태 |
|---------|----------|------|------|
| content-service | 06af046cbebe | 1.01GB | ✅ |
| participation-service | 486f2c00811e | 1.04GB | ✅ |
| user-service | 7ef657c343dd | 1.09GB | ✅ |
### 7.1 로컬에서 컨테이너 실행 테스트
## 6. 다음 단계
### 6.1 컨테이너 실행 테스트
각 서비스의 Docker 이미지를 컨테이너로 실행하여 동작 확인:
```bash
# analytics-service 실행 예시
docker run -d \
--name analytics-service-test \
-p 8080:8080 \
-e JAVA_OPTS="-Xms256m -Xmx512m" \
-e SPRING_PROFILES_ACTIVE=dev \
analytics-service:latest
# 로그 확인
docker logs -f analytics-service-test
# 헬스체크
curl http://localhost:8080/actuator/health
# 컨테이너 정리
docker stop analytics-service-test
docker rm analytics-service-test
docker run -d -p 8080:8080 --name content-service content-service:latest
docker run -d -p 8081:8081 --name participation-service participation-service:latest
docker run -d -p 8082:8082 --name user-service user-service:latest
```
### 6.2 컨테이너 레지스트리 푸시
이미지를 Docker Hub 또는 프라이빗 레지스트리에 푸시:
```bash
# 이미지 태깅
docker tag content-service:latest [registry]/content-service:1.0.0
docker tag participation-service:latest [registry]/participation-service:1.0.0
docker tag user-service:latest [registry]/user-service:1.0.0
# 레지스트리 푸시
docker push [registry]/content-service:1.0.0
docker push [registry]/participation-service:1.0.0
docker push [registry]/user-service:1.0.0
```
### 6.3 Kubernetes 배포
Kubernetes 클러스터에 배포하기 위한 매니페스트 작성 및 적용
## 7. 참고 사항
### 7.1 보안 고려사항
- ✅ Non-root user(k8s) 사용으로 보안 강화
- ✅ Multi-stage build로 빌드 도구 제외
- ⚠️ 프로덕션 환경에서는 이미지 스캔 권장
### 7.2 이미지 최적화
- 현재 이미지 크기: ~1GB
- JVM 튜닝 옵션 활용 가능: `JAVA_OPTS` 환경 변수
- 추후 경량화 검토: Alpine 기반 이미지, jlink 활용
### 7.3 빌드 자동화
향후 CI/CD 파이프라인에서 자동 빌드 통합 가능:
- GitHub Actions
- Jenkins
- GitLab CI/CD
- ArgoCD
## 8. 문제 해결
### 8.1 user-service 컴파일 에러
### 8.1 빌드 실패 시
- Gradle clean 실행 후 재빌드
- Docker daemon 상태 확인
- 디스크 공간 확인
**문제**: UUID와 Long 타입 불일치
### 8.2 이미지 크기 문제
- Multi-stage build 활용 (현재 적용됨)
- .dockerignore 파일 활용
- 불필요한 의존성 제거
**해결 방법**:
1. `UserController.java`에서 `Long userId``UUID userId` 변경
2. `AuthenticationServiceImpl.java``UserServiceImpl.java`에서 `createAccessToken` 메서드 호출 시 첫 번째 파라미터로 `sessionId` 추가
3. 변경 후 재빌드:
```bash
./gradlew :user-service:bootJar --no-daemon
```
---
### 8.2 ai-service 및 distribution-service
**문제**: 소스 코드 미구현
**조치**: 해당 서비스의 구현이 완료된 후 컨테이너 이미지 빌드 진행
### 8.3 Docker Desktop 연결 실패
**에러 메시지**:
```
error during connect: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.
```
**해결 방법**:
1. Docker Desktop 실행
2. 완전히 시작될 때까지 대기 (트레이 아이콘 확인)
3. `docker ps` 명령으로 정상 동작 확인
4. 빌드 명령 재실행
## 9. 다음 단계
1. ✅ **완료**: Dockerfile 작성 및 JAR 빌드
2. ⏸️ **대기 중**: Docker Desktop 실행 후 이미지 빌드
3. 📋 **예정**:
- user-service 컴파일 에러 수정
- ai-service 및 distribution-service 구현 완료 후 빌드
- 이미지 레지스트리에 푸시 (ACR 등)
- Kubernetes 배포 매니페스트 작성
## 10. 참고 자료
- Dockerfile: `deployment/container/Dockerfile-backend`
- JAR 위치: `<service-name>/build/libs/<service-name>.jar`
- 빌드 스크립트: 본 문서의 5.3 섹션 참조
- OpenJDK 23 Documentation: https://openjdk.org/projects/jdk/23/
**작성자**: DevOps Engineer (송근정)
**작성일**: 2025-10-27
**버전**: 1.0.0
@@ -0,0 +1,502 @@
# 백엔드 컨테이너 실행 가이드
백엔드 서비스를 Azure VM에서 Docker 컨테이너로 실행하는 가이드를 제공합니다.
## 📋 목차
1. [사전 준비](#사전-준비)
2. [컨테이너 이미지 확인](#컨테이너-이미지-확인)
3. [컨테이너 실행](#컨테이너-실행)
4. [컨테이너 관리](#컨테이너-관리)
5. [문제 해결](#문제-해결)
---
## 사전 준비
### 1. VM 접속 정보
```yaml
ACR: acrdigitalgarage01
VM:
KEY파일: ~/home/bastion-dg0505
사용자: azureuser
IP: 20.196.65.160
```
### 2. VM 접속
```bash
# SSH 접속
ssh -i ~/home/bastion-dg0505 azureuser@20.196.65.160
```
### 3. Docker 및 ACR 로그인 확인
```bash
# Docker 실행 확인
docker --version
# ACR 로그인 (필요시)
az acr login --name acrdigitalgarage01
```
---
## 컨테이너 이미지 확인
### 1. ACR에서 이미지 목록 조회
```bash
# 이미지 목록 확인
az acr repository list --name acrdigitalgarage01 --output table
# 특정 이미지의 태그 확인
az acr repository show-tags --name acrdigitalgarage01 \
--repository {service-name} --output table
```
### 2. 실행할 이미지 Pull
```bash
# 이미지 다운로드
docker pull acrdigitalgarage01.azurecr.io/{service-name}:{tag}
# 예: participation-service
docker pull acrdigitalgarage01.azurecr.io/participation-service:latest
```
---
## 컨테이너 실행
### 1. 환경 변수 준비
각 서비스별 환경 변수를 확인하고 준비합니다.
```bash
# .env 파일 생성 (예시)
cat > ~/event-marketing.env << EOF
# Database
DB_HOST=your-db-host
DB_PORT=5432
DB_NAME=event_marketing
DB_USERNAME=your-username
DB_PASSWORD=your-password
# Redis
REDIS_HOST=your-redis-host
REDIS_PORT=6379
# Kafka
KAFKA_BOOTSTRAP_SERVERS=your-kafka:9092
# Application
SERVER_PORT=8080
SPRING_PROFILES_ACTIVE=prod
EOF
```
### 2. 네트워크 생성 (선택사항)
여러 컨테이너를 함께 실행할 경우 네트워크를 생성합니다.
```bash
# Docker 네트워크 생성
docker network create event-marketing-network
```
### 3. 컨테이너 실행
#### 기본 실행
```bash
docker run -d \
--name {service-name} \
--env-file ~/event-marketing.env \
-p 8080:8080 \
acrdigitalgarage01.azurecr.io/{service-name}:latest
```
#### 네트워크 포함 실행
```bash
docker run -d \
--name {service-name} \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-p 8080:8080 \
acrdigitalgarage01.azurecr.io/{service-name}:latest
```
#### 볼륨 마운트 포함 실행
```bash
docker run -d \
--name {service-name} \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-p 8080:8080 \
-v ~/logs/{service-name}:/app/logs \
acrdigitalgarage01.azurecr.io/{service-name}:latest
```
### 4. 여러 서비스 실행 (docker-compose 사용)
`docker-compose.yml` 파일 생성:
```yaml
version: '3.8'
services:
participation-service:
image: acrdigitalgarage01.azurecr.io/participation-service:latest
container_name: participation-service
env_file:
- ./event-marketing.env
ports:
- "8080:8080"
networks:
- event-marketing-network
volumes:
- ./logs/participation:/app/logs
restart: unless-stopped
# 다른 서비스 추가...
networks:
event-marketing-network:
driver: bridge
volumes:
logs:
```
실행:
```bash
# docker-compose로 모든 서비스 시작
docker-compose up -d
# 특정 서비스만 시작
docker-compose up -d participation-service
```
---
## 컨테이너 관리
### 1. 컨테이너 상태 확인
```bash
# 실행 중인 컨테이너 확인
docker ps
# 모든 컨테이너 확인 (중지된 것 포함)
docker ps -a
# 특정 컨테이너 상세 정보
docker inspect {container-name}
```
### 2. 로그 확인
```bash
# 실시간 로그 확인
docker logs -f {container-name}
# 최근 100줄 로그 확인
docker logs --tail 100 {container-name}
# 타임스탬프 포함 로그 확인
docker logs -t {container-name}
```
### 3. 컨테이너 중지/시작/재시작
```bash
# 중지
docker stop {container-name}
# 시작
docker start {container-name}
# 재시작
docker restart {container-name}
# 강제 중지
docker kill {container-name}
```
### 4. 컨테이너 삭제
```bash
# 중지된 컨테이너 삭제
docker rm {container-name}
# 실행 중인 컨테이너 강제 삭제
docker rm -f {container-name}
# 중지된 모든 컨테이너 삭제
docker container prune
```
### 5. 컨테이너 내부 접속
```bash
# bash 쉘로 접속
docker exec -it {container-name} bash
# 특정 명령 실행
docker exec {container-name} ls -la /app
```
### 6. 리소스 사용량 확인
```bash
# 실시간 리소스 사용량
docker stats
# 특정 컨테이너의 리소스 사용량
docker stats {container-name}
```
---
## 문제 해결
### 1. 컨테이너가 시작되지 않는 경우
```bash
# 로그 확인
docker logs {container-name}
# 컨테이너 상태 확인
docker inspect {container-name}
# 환경 변수 확인
docker exec {container-name} env
```
### 2. 포트 충돌
```bash
# 포트 사용 확인
netstat -tuln | grep {port}
# 다른 포트로 매핑
docker run -d -p 8081:8080 ...
```
### 3. 네트워크 연결 문제
```bash
# 네트워크 목록 확인
docker network ls
# 네트워크 상세 정보
docker network inspect {network-name}
# 컨테이너를 네트워크에 연결
docker network connect {network-name} {container-name}
```
### 4. 이미지 Pull 실패
```bash
# ACR 로그인 재시도
az acr login --name acrdigitalgarage01
# 수동으로 Pull
docker pull acrdigitalgarage01.azurecr.io/{service-name}:{tag}
```
### 5. 디스크 공간 부족
```bash
# 사용하지 않는 이미지 삭제
docker image prune -a
# 사용하지 않는 볼륨 삭제
docker volume prune
# 전체 정리 (주의!)
docker system prune -a
```
---
## 헬스체크 및 모니터링
### 1. 헬스체크 엔드포인트 확인
```bash
# Spring Boot Actuator health endpoint
curl http://localhost:8080/actuator/health
# 상세 헬스 정보
curl http://localhost:8080/actuator/health/readiness
curl http://localhost:8080/actuator/health/liveness
```
### 2. 메트릭 확인
```bash
# 메트릭 엔드포인트
curl http://localhost:8080/actuator/metrics
# 특정 메트릭 확인
curl http://localhost:8080/actuator/metrics/jvm.memory.used
```
### 3. 로그 모니터링 스크립트
```bash
#!/bin/bash
# monitor-logs.sh
SERVICE_NAME=$1
if [ -z "$SERVICE_NAME" ]; then
echo "Usage: ./monitor-logs.sh {service-name}"
exit 1
fi
# 에러 로그 모니터링
docker logs -f $SERVICE_NAME 2>&1 | grep -i error
```
---
## 자동화 스크립트
### 1. 서비스 재배포 스크립트
```bash
#!/bin/bash
# redeploy.sh
SERVICE_NAME=$1
IMAGE_TAG=${2:-latest}
if [ -z "$SERVICE_NAME" ]; then
echo "Usage: ./redeploy.sh {service-name} [tag]"
exit 1
fi
echo "📦 Pulling latest image..."
docker pull acrdigitalgarage01.azurecr.io/$SERVICE_NAME:$IMAGE_TAG
echo "🛑 Stopping old container..."
docker stop $SERVICE_NAME
docker rm $SERVICE_NAME
echo "🚀 Starting new container..."
docker run -d \
--name $SERVICE_NAME \
--env-file ~/event-marketing.env \
-p 8080:8080 \
acrdigitalgarage01.azurecr.io/$SERVICE_NAME:$IMAGE_TAG
echo "✅ Deployment complete!"
docker logs -f $SERVICE_NAME
```
### 2. 헬스체크 스크립트
```bash
#!/bin/bash
# healthcheck.sh
SERVICE_NAME=$1
MAX_RETRIES=30
RETRY_INTERVAL=2
if [ -z "$SERVICE_NAME" ]; then
echo "Usage: ./healthcheck.sh {service-name}"
exit 1
fi
echo "⏳ Waiting for $SERVICE_NAME to be healthy..."
for i in $(seq 1 $MAX_RETRIES); do
if curl -f http://localhost:8080/actuator/health > /dev/null 2>&1; then
echo "$SERVICE_NAME is healthy!"
exit 0
fi
echo "Attempt $i/$MAX_RETRIES failed. Retrying in ${RETRY_INTERVAL}s..."
sleep $RETRY_INTERVAL
done
echo "$SERVICE_NAME failed to become healthy"
exit 1
```
---
## 보안 고려사항
### 1. 환경 변수 보호
```bash
# .env 파일 권한 설정
chmod 600 ~/event-marketing.env
# 민감 정보는 Azure Key Vault 사용 권장
```
### 2. 컨테이너 보안
```bash
# 읽기 전용 파일시스템으로 실행
docker run -d --read-only ...
# 리소스 제한
docker run -d \
--memory="512m" \
--cpus="0.5" \
...
```
### 3. 네트워크 보안
```bash
# 필요한 포트만 노출
# 내부 통신은 Docker 네트워크 사용
```
---
## 서비스별 실행 예시
### Participation Service
```bash
docker run -d \
--name participation-service \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-e SERVER_PORT=8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-p 8080:8080 \
-v ~/logs/participation:/app/logs \
acrdigitalgarage01.azurecr.io/participation-service:latest
```
### Event Service
```bash
docker run -d \
--name event-service \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-e SERVER_PORT=8081 \
-e SPRING_PROFILES_ACTIVE=prod \
-p 8081:8081 \
-v ~/logs/event:/app/logs \
acrdigitalgarage01.azurecr.io/event-service:latest
```
### User Service
```bash
docker run -d \
--name user-service \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-e SERVER_PORT=8082 \
-e SPRING_PROFILES_ACTIVE=prod \
-p 8082:8082 \
-v ~/logs/user:/app/logs \
acrdigitalgarage01.azurecr.io/user-service:latest
```
### Analytics Service
```bash
docker run -d \
--name analytics-service \
--network event-marketing-network \
--env-file ~/event-marketing.env \
-e SERVER_PORT=8083 \
-e SPRING_PROFILES_ACTIVE=prod \
-p 8083:8083 \
-v ~/logs/analytics:/app/logs \
acrdigitalgarage01.azurecr.io/analytics-service:latest
```
---
이 가이드를 통해 백엔드 서비스를 안전하고 효율적으로 컨테이너로 실행할 수 있습니다. 추가 질문이나 문제가 있으면 언제든지 문의해 주세요! 🚀
-526
View File
@@ -1,526 +0,0 @@
# 백엔드 컨테이너 실행 가이드
작성일: 2025-10-27
작성자: DevOps Engineer
## 1. 개요
KT 이벤트 마케팅 플랫폼의 백엔드 마이크로서비스들을 Docker 컨테이너로 실행하는 방법을 안내합니다.
## 2. 실행 환경 정보
| 항목 | 값 |
|------|-----|
| **Azure Container Registry** | acrdigitalgarage01 |
| **VM IP** | 4.218.10.89 |
| **VM User ID** | azureuser |
| **SSH Private Key** | ~/home/bastion-dg0502 |
| **시스템명** | kt-event-marketing |
## 3. 빌드 가능한 서비스 목록
| 서비스명 | 포트 | 상태 | 비고 |
|---------|------|------|------|
| analytics-service | 8086 | ✅ 빌드 완료 | 컨테이너 이미지 생성됨 |
| participation-service | 8084 | ⏸️ JAR 빌드 완료 | 컨테이너 이미지 생성 필요 |
| event-service | 8080 | ⏸️ JAR 빌드 완료 | 컨테이너 이미지 생성 필요 |
| content-service | 8083 | ⏸️ JAR 빌드 완료 | 컨테이너 이미지 생성 필요 |
## 4. VM 접속 방법
### 4.1 터미널 실행
- **Linux/Mac**: 기본 터미널 실행
- **Windows**: Windows Terminal 실행
### 4.2 SSH Private Key 권한 설정 (최초 1회)
```bash
chmod 400 ~/home/bastion-dg0502
```
### 4.3 VM 접속
```bash
ssh -i ~/home/bastion-dg0502 azureuser@4.218.10.89
```
## 5. 작업 환경 준비
### 5.1 Workspace 디렉토리 생성
```bash
mkdir -p ~/home/workspace
cd ~/home/workspace
```
### 5.2 Git Repository 클론
```bash
git clone https://github.com/ktds-dg0501/kt-event-marketing.git
```
**참고**: 실제 Git Repository 주소로 변경해 주세요.
### 5.3 프로젝트 디렉토리 이동
```bash
cd kt-event-marketing
```
## 6. 애플리케이션 빌드 및 컨테이너 이미지 생성
### 6.1 gradlew 실행 권한 설정 (최초 1회)
VM 환경에서는 gradlew 파일에 실행 권한이 없을 수 있습니다:
```bash
chmod +x gradlew
```
### 6.2 JAR 파일 빌드
```bash
./gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar --no-daemon
```
**권한 오류 발생 시**:
```bash
bash gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar --no-daemon
```
### 6.3 Docker 이미지 생성
상세한 가이드는 `deployment/container/build-image.md` 파일을 참조하세요.
## 7. Azure Container Registry (ACR) 작업
### 7.1 ACR 인증 정보 확인
```bash
az acr credential show --name acrdigitalgarage01
```
**출력 예시**:
```json
{
"passwords": [
{
"name": "password",
"value": "<PASSWORD>"
},
{
"name": "password2",
"value": "<PASSWORD2>"
}
],
"username": "acrdigitalgarage01"
}
```
### 7.2 ACR 로그인
위에서 확인한 `username``passwords[0].value`를 사용하여 로그인합니다:
```bash
docker login acrdigitalgarage01.azurecr.io -u acrdigitalgarage01 -p <PASSWORD>
```
## 8. 컨테이너 이미지 푸시
### 8.1 analytics-service
```bash
# 이미지 태그
docker tag analytics-service:latest acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
# ACR로 푸시
docker push acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
```
### 8.2 participation-service
```bash
# 이미지 태그
docker tag participation-service:latest acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
# ACR로 푸시
docker push acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
```
### 8.3 event-service
```bash
# 이미지 태그
docker tag event-service:latest acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
# ACR로 푸시
docker push acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
```
### 8.4 content-service
```bash
# 이미지 태그
docker tag content-service:latest acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest
# ACR로 푸시
docker push acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest
```
## 9. 컨테이너 실행
### 9.1 analytics-service
```bash
SERVER_PORT=8086
docker run -d --name analytics-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e DB_KIND=postgresql \
-e DB_HOST=4.230.49.9 \
-e DB_PORT=5432 \
-e DB_NAME=analyticdb \
-e DB_USERNAME=eventuser \
-e DB_PASSWORD=Hi5Jessica! \
-e DDL_AUTO=update \
-e SHOW_SQL=true \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e REDIS_DATABASE=5 \
-e KAFKA_ENABLED=true \
-e KAFKA_BOOTSTRAP_SERVERS=20.249.182.13:9095,4.217.131.59:9095 \
-e KAFKA_CONSUMER_GROUP_ID=analytics-service-consumers \
-e SAMPLE_DATA_ENABLED=true \
-e SERVER_PORT=8086 \
-e JWT_SECRET=dev-jwt-secret-key-for-development-only-kt-event-marketing \
-e JWT_ACCESS_TOKEN_VALIDITY=1800 \
-e JWT_REFRESH_TOKEN_VALIDITY=86400 \
-e CORS_ALLOWED_ORIGINS="http://localhost:*,http://4.218.10.89:3000" \
-e LOG_FILE=logs/analytics-service.log \
-e LOG_LEVEL_APP=DEBUG \
-e LOG_LEVEL_WEB=INFO \
-e LOG_LEVEL_SQL=DEBUG \
-e LOG_LEVEL_SQL_TYPE=TRACE \
acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
```
### 9.2 participation-service
```bash
SERVER_PORT=8084
docker run -d --name participation-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e DB_HOST=4.230.72.147 \
-e DB_NAME=participationdb \
-e DB_PASSWORD=Hi5Jessica! \
-e DB_PORT=5432 \
-e DB_USERNAME=eventuser \
-e DDL_AUTO=validate \
-e JWT_EXPIRATION=86400000 \
-e JWT_SECRET=kt-event-marketing-secret-key-for-development-only-change-in-production \
-e KAFKA_BOOTSTRAP_SERVERS=20.249.182.13:9095,4.217.131.59:9095 \
-e LOG_FILE=logs/participation-service.log \
-e LOG_LEVEL=INFO \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e REDIS_PORT=6379 \
-e SERVER_PORT=8084 \
-e SHOW_SQL=true \
acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
```
### 9.3 event-service
**참고**: event-service는 `.run.xml` 파일이 없어 환경변수 설정이 필요합니다.
아래는 `application.yml`을 기반으로 추정한 환경변수입니다.
```bash
SERVER_PORT=8080
docker run -d --name event-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e DB_HOST=<DB_HOST> \
-e DB_PORT=5432 \
-e DB_NAME=eventdb \
-e DB_USERNAME=eventuser \
-e DB_PASSWORD=<DB_PASSWORD> \
-e DDL_AUTO=update \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e KAFKA_BOOTSTRAP_SERVERS=20.249.182.13:9095,4.217.131.59:9095 \
-e SERVER_PORT=8080 \
-e LOG_LEVEL=DEBUG \
-e SQL_LOG_LEVEL=DEBUG \
acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
```
⚠️ **필수**: `<DB_HOST>``<DB_PASSWORD>`를 실제 값으로 변경해 주세요.
### 9.4 content-service
**참고**: content-service는 `.run.xml` 파일이 없어 환경변수 설정이 필요합니다.
아래는 `application.yml`을 기반으로 추정한 환경변수입니다.
```bash
SERVER_PORT=8083
docker run -d --name content-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e SERVER_PORT=8083 \
-e JWT_SECRET=dev-jwt-secret-key \
-e JWT_ACCESS_TOKEN_VALIDITY=3600000 \
-e JWT_REFRESH_TOKEN_VALIDITY=604800000 \
-e AZURE_STORAGE_CONNECTION_STRING=<AZURE_STORAGE_CONNECTION_STRING> \
-e AZURE_CONTAINER_NAME=event-images \
-e LOG_LEVEL_APP=DEBUG \
-e LOG_LEVEL_ROOT=INFO \
-e LOG_FILE=logs/content-service.log \
acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest
```
⚠️ **필수**: `<AZURE_STORAGE_CONNECTION_STRING>`을 실제 값으로 변경해 주세요.
## 10. 실행 확인
### 10.1 컨테이너 실행 상태 확인
```bash
# 전체 컨테이너 확인
docker ps
# 특정 서비스 확인
docker ps | grep analytics-service
docker ps | grep participation-service
docker ps | grep event-service
docker ps | grep content-service
```
### 10.2 컨테이너 로그 확인
```bash
# 실시간 로그 확인
docker logs -f analytics-service
docker logs -f participation-service
docker logs -f event-service
docker logs -f content-service
# 최근 100줄 로그 확인
docker logs --tail 100 analytics-service
```
### 10.3 헬스체크
```bash
# analytics-service
curl http://4.218.10.89:8086/actuator/health
# participation-service
curl http://4.218.10.89:8084/actuator/health
# event-service
curl http://4.218.10.89:8080/actuator/health
# content-service
curl http://4.218.10.89:8083/actuator/health
```
## 11. 재배포 방법
### 11.1 로컬에서 수정된 소스 푸시
로컬 개발 환경에서 코드 수정 후:
```bash
git add .
git commit -m "변경 사항"
git push
```
### 11.2 VM 접속
```bash
ssh -i ~/home/bastion-dg0502 azureuser@4.218.10.89
```
### 11.3 디렉토리 이동 및 소스 내려받기
```bash
cd ~/home/workspace/kt-event-marketing
git pull
```
### 11.4 컨테이너 이미지 재생성
**JAR 파일 빌드**:
```bash
./gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar --no-daemon
```
**Docker 이미지 빌드** (예: analytics-service):
```bash
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="analytics-service/build/libs" \
--build-arg ARTIFACTORY_FILE="analytics-service.jar" \
-f deployment/container/Dockerfile-backend \
-t analytics-service:latest .
```
상세한 가이드는 `deployment/container/build-image.md` 파일을 참조하세요.
### 11.5 컨테이너 이미지 푸시
**analytics-service 예시**:
```bash
docker tag analytics-service:latest acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
docker push acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
```
### 11.6 컨테이너 중지
```bash
docker stop analytics-service
docker stop participation-service
docker stop event-service
docker stop content-service
```
### 11.7 컨테이너 이미지 삭제 (선택사항)
```bash
docker rmi acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
docker rmi acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
docker rmi acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
docker rmi acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest
```
### 11.8 컨테이너 재실행
위의 [9. 컨테이너 실행](#9-컨테이너-실행) 섹션의 명령어를 다시 실행합니다.
## 12. 일괄 실행 스크립트
### 12.1 전체 서비스 중지
```bash
docker stop analytics-service participation-service event-service content-service
```
### 12.2 전체 서비스 시작 (Bash 스크립트)
**실행 전 주의사항**:
- event-service와 content-service의 환경변수 값을 실제 값으로 변경해야 합니다.
```bash
#!/bin/bash
# analytics-service 실행
SERVER_PORT=8086
docker run -d --name analytics-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e DB_KIND=postgresql \
-e DB_HOST=4.230.49.9 \
-e DB_PORT=5432 \
-e DB_NAME=analyticdb \
-e DB_USERNAME=eventuser \
-e DB_PASSWORD=Hi5Jessica! \
-e DDL_AUTO=update \
-e SHOW_SQL=true \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e REDIS_DATABASE=5 \
-e KAFKA_ENABLED=true \
-e KAFKA_BOOTSTRAP_SERVERS=20.249.182.13:9095,4.217.131.59:9095 \
-e KAFKA_CONSUMER_GROUP_ID=analytics-service-consumers \
-e SAMPLE_DATA_ENABLED=true \
-e SERVER_PORT=8086 \
-e JWT_SECRET=dev-jwt-secret-key-for-development-only-kt-event-marketing \
-e JWT_ACCESS_TOKEN_VALIDITY=1800 \
-e JWT_REFRESH_TOKEN_VALIDITY=86400 \
-e CORS_ALLOWED_ORIGINS="http://localhost:*,http://4.218.10.89:3000" \
-e LOG_FILE=logs/analytics-service.log \
-e LOG_LEVEL_APP=DEBUG \
-e LOG_LEVEL_WEB=INFO \
-e LOG_LEVEL_SQL=DEBUG \
-e LOG_LEVEL_SQL_TYPE=TRACE \
acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
echo "✅ analytics-service started on port 8086"
# participation-service 실행
SERVER_PORT=8084
docker run -d --name participation-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
-e DB_HOST=4.230.72.147 \
-e DB_NAME=participationdb \
-e DB_PASSWORD=Hi5Jessica! \
-e DB_PORT=5432 \
-e DB_USERNAME=eventuser \
-e DDL_AUTO=validate \
-e JWT_EXPIRATION=86400000 \
-e JWT_SECRET=kt-event-marketing-secret-key-for-development-only-change-in-production \
-e KAFKA_BOOTSTRAP_SERVERS=20.249.182.13:9095,4.217.131.59:9095 \
-e LOG_FILE=logs/participation-service.log \
-e LOG_LEVEL=INFO \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e REDIS_PORT=6379 \
-e SERVER_PORT=8084 \
-e SHOW_SQL=true \
acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
echo "✅ participation-service started on port 8084"
# 실행 확인
echo ""
echo "🔍 Running containers:"
docker ps | grep -E "analytics-service|participation-service"
```
## 13. 문제 해결
### 13.1 컨테이너가 즉시 종료되는 경우
**로그 확인**:
```bash
docker logs <container-name>
```
**일반적인 원인**:
- 환경변수 누락 또는 잘못된 값
- 데이터베이스/Redis/Kafka 연결 실패
- 포트 충돌
### 13.2 ACR 로그인 실패
**인증 정보 재확인**:
```bash
az acr credential show --name acrdigitalgarage01
```
**다시 로그인**:
```bash
docker logout acrdigitalgarage01.azurecr.io
docker login acrdigitalgarage01.azurecr.io -u <username> -p <password>
```
### 13.3 포트 충돌
**포트 사용 확인**:
```bash
netstat -tuln | grep <PORT>
```
**다른 포트로 변경**:
```bash
SERVER_PORT=<NEW_PORT>
docker run -d -p ${SERVER_PORT}:${SERVER_PORT} ...
```
## 14. 참고 자료
- 컨테이너 이미지 빌드 가이드: `deployment/container/build-image.md`
- Docker 공식 문서: https://docs.docker.com/
- Azure Container Registry 문서: https://docs.microsoft.com/azure/container-registry/
@@ -14,7 +14,7 @@ import lombok.*;
@Entity
@Table(name = "draw_logs",
indexes = {
@Index(name = "idx_event_id", columnList = "event_id")
@Index(name = "idx_draw_log_event_id", columnList = "event_id")
}
)
@Getter
@@ -13,7 +13,7 @@ import lombok.*;
@Entity
@Table(name = "participants",
indexes = {
@Index(name = "idx_event_id", columnList = "event_id"),
@Index(name = "idx_participant_event_id", columnList = "event_id"),
@Index(name = "idx_event_phone", columnList = "event_id, phone_number")
},
uniqueConstraints = {
@@ -24,6 +24,8 @@ public class SecurityConfig {
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
// Actuator endpoints
.requestMatchers("/actuator/**").permitAll()
.anyRequest().permitAll()
);
@@ -73,3 +73,19 @@ logging:
max-file-size: 10MB
max-history: 7
total-size-cap: 100MB
# Actuator
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
base-path: /actuator
endpoint:
health:
show-details: always
show-components: always
health:
livenessState:
enabled: true
readinessState:
enabled: true
@@ -5,8 +5,10 @@ import com.kt.event.common.security.JwtTokenProvider;
import com.kt.event.user.dto.request.LoginRequest;
import com.kt.event.user.dto.response.LoginResponse;
import com.kt.event.user.dto.response.LogoutResponse;
import com.kt.event.user.entity.Store;
import com.kt.event.user.entity.User;
import com.kt.event.user.exception.UserErrorCode;
import com.kt.event.user.repository.StoreRepository;
import com.kt.event.user.repository.UserRepository;
import com.kt.event.user.service.AuthenticationService;
import com.kt.event.user.service.UserService;
@@ -34,6 +36,7 @@ import java.util.concurrent.TimeUnit;
public class AuthenticationServiceImpl implements AuthenticationService {
private final UserRepository userRepository;
private final StoreRepository storeRepository;
private final PasswordEncoder passwordEncoder;
private final JwtTokenProvider jwtTokenProvider;
private final UserService userService;
@@ -42,10 +45,12 @@ public class AuthenticationServiceImpl implements AuthenticationService {
private RedisTemplate<String, Object> redisTemplate;
public AuthenticationServiceImpl(UserRepository userRepository,
StoreRepository storeRepository,
PasswordEncoder passwordEncoder,
JwtTokenProvider jwtTokenProvider,
UserService userService) {
this.userRepository = userRepository;
this.storeRepository = storeRepository;
this.passwordEncoder = passwordEncoder;
this.jwtTokenProvider = jwtTokenProvider;
this.userService = userService;
@@ -68,21 +73,26 @@ public class AuthenticationServiceImpl implements AuthenticationService {
throw new BusinessException(UserErrorCode.AUTH_FAILED.getErrorCode());
}
// 3. JWT 토큰 생성
// 3. 매장 정보 조회
Store store = storeRepository.findByUserId(user.getId()).orElse(null);
Long storeId = store != null ? store.getId() : null;
// 4. JWT 토큰 생성
String token = jwtTokenProvider.createAccessToken(
user.getId(),
storeId,
user.getEmail(),
user.getName(),
List.of(user.getRole().name())
);
// 4. Redis 세션 저장 (TTL 7일)
// 5. Redis 세션 저장 (TTL 7일)
saveSession(token, user.getId(), user.getRole().name());
// 5. 최종 로그인 시각 업데이트 (비동기)
// 6. 최종 로그인 시각 업데이트 (비동기)
userService.updateLastLoginAt(user.getId());
// 6. 응답 반환
// 7. 응답 반환
return LoginResponse.builder()
.token(token)
.userId(user.getId())
@@ -103,6 +103,7 @@ public class UserServiceImpl implements UserService {
// 6. JWT 토큰 생성
String token = jwtTokenProvider.createAccessToken(
savedUser.getId(),
savedStore.getId(),
savedUser.getEmail(),
savedUser.getName(),
List.of(savedUser.getRole().name())