Skip to content

Commit 433b6ee

Browse files
JIWONKIMSclaude
andauthored
Bug/be/141 (#143)
* feat(be): Add dummy guide data initializer for dev environment - DevConfig에 더미 가이드 2명 자동 생성 기능 추가 - 서울 가이드 1명, 부산 사하구 가이드 1명 - dev 프로필에서만 실행되며 중복 방지 로직 포함 - 생성/기존 통계 콘솔 출력 기능 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * feat(be): Add RabbitMQ infrastructure and configuration - Add docker-compose.yml for local RabbitMQ development - Configure RabbitMQ in application.yml and application-prod.yml - Add RabbitMQ container setup in Terraform (infra/main.tf) - Add RabbitMQ environment variables to deploy.yml - Remove docker-compose.yml from .gitignore for team sharing - Connection timeout and heartbeat settings for production stability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 421d087 commit 433b6ee

File tree

10 files changed

+164
-10
lines changed

10 files changed

+164
-10
lines changed

.github/workflows/deploy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ jobs:
234234
-e REDIS_HOST=redis_1 \
235235
-e REDIS_PORT=6379 \
236236
-e REDIS_PASSWORD="${PASSWORD_1}" \
237+
-e RABBITMQ_HOST=rabbitmq_1 \
238+
-e RABBITMQ_PORT=5672 \
239+
-e RABBITMQ_USERNAME=admin \
240+
-e RABBITMQ_PASSWORD="${PASSWORD_1}" \
241+
-e RABBITMQ_STOMP_PORT=61613 \
237242
"${IMAGE}"
238243
239244
# ---------------------------------------------------------

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,4 @@ build/reports/
7575
coverage/
7676

7777
# Test file
78-
index.html
79-
docker-compose.yml
78+
index.html

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
implementation("org.springframework.boot:spring-boot-starter-web")
3535
implementation("org.springframework.boot:spring-boot-starter-webflux")
3636
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
37+
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
3738
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml")
3839
implementation("org.jetbrains.kotlin:kotlin-reflect")
3940

docker-compose.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
version: "3.8"
2+
3+
services:
4+
rabbit:
5+
image: rabbitmq:3-management # 버전 명시 권장 (예: 3.13-management)
6+
container_name: rabbitmq-1
7+
ports:
8+
- "5672:5672" # AMQP (Spring ↔ RabbitMQ)
9+
- "61613:61613" # STOMP (Relay가 여기에 붙음)
10+
- "15672:15672" # Management UI (로컬에서만)
11+
environment:
12+
RABBITMQ_DEFAULT_USER: admin
13+
RABBITMQ_DEFAULT_PASS: admin
14+
volumes: # 영속화가 필요할 때만 유지
15+
- ./dockerProjects/rabbitmq-1/volumes/etc/rabbitmq:/etc/rabbitmq
16+
- ./dockerProjects/rabbitmq-1/volumes/var/lib/rabbitmq:/var/lib/rabbitmq
17+
- ./dockerProjects/rabbitmq-1/volumes/var/log/rabbitmq:/var/log/rabbitmq
18+
command: >
19+
sh -c "
20+
rabbitmq-plugins enable rabbitmq_management &&
21+
rabbitmq-plugins enable rabbitmq_stomp &&
22+
rabbitmq-server
23+
"

infra/main.tf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,34 @@ CREATE DATABASE \"${var.app_1_db_name}\" OWNER team11;
263263
GRANT ALL PRIVILEGES ON DATABASE \"${var.app_1_db_name}\" TO team11;
264264
"
265265
266+
# rabbitmq 설치
267+
docker run -d \
268+
--name rabbitmq_1 \
269+
--restart unless-stopped \
270+
--network common \
271+
-p 5672:5672 \
272+
-p 61613:61613 \
273+
-p 15672:15672 \
274+
-e RABBITMQ_DEFAULT_USER=admin \
275+
-e RABBITMQ_DEFAULT_PASS=${var.password_1} \
276+
-e TZ=Asia/Seoul \
277+
-v /dockerProjects/rabbitmq_1/volumes/data:/var/lib/rabbitmq \
278+
rabbitmq:3-management
279+
280+
# RabbitMQ가 준비될 때까지 대기
281+
echo "RabbitMQ가 기동될 때까지 대기 중..."
282+
until docker exec rabbitmq_1 rabbitmqctl status &> /dev/null; do
283+
echo "RabbitMQ가 아직 준비되지 않음. 5초 후 재시도..."
284+
sleep 5
285+
done
286+
echo "RabbitMQ가 준비됨. STOMP 플러그인 활성화 중..."
287+
288+
# RabbitMQ STOMP 플러그인 활성화
289+
docker exec rabbitmq_1 rabbitmq-plugins enable rabbitmq_stomp
290+
docker exec rabbitmq_1 rabbitmq-plugins enable rabbitmq_management
291+
292+
echo "RabbitMQ 설치 및 설정 완료!"
293+
266294
echo "${var.github_access_token_1}" | docker login ghcr.io -u ${var.github_access_token_1_owner} --password-stdin
267295
268296
END_OF_FILE

src/main/kotlin/com/back/koreaTravelGuide/common/config/DevConfig.kt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.back.koreaTravelGuide.common.config
22

3+
import com.back.koreaTravelGuide.domain.user.entity.User
4+
import com.back.koreaTravelGuide.domain.user.enums.Region
5+
import com.back.koreaTravelGuide.domain.user.enums.UserRole
6+
import com.back.koreaTravelGuide.domain.user.repository.UserRepository
37
import org.springframework.boot.CommandLineRunner
48
import org.springframework.context.annotation.Bean
59
import org.springframework.context.annotation.Configuration
@@ -93,4 +97,67 @@ class DevConfig {
9397
println("=".repeat(80) + "\n")
9498
}
9599
}
100+
101+
/**
102+
* dev 모드에서 더미 가이드 데이터 생성
103+
* 서버 시작시 자동으로 가이드 2명을 데이터베이스에 추가
104+
*/
105+
@Bean
106+
fun dummyGuideDataInitializer(userRepository: UserRepository): CommandLineRunner {
107+
return CommandLineRunner {
108+
// 생성할 더미 가이드 리스트
109+
val dummyGuides =
110+
listOf(
111+
User(
112+
oauthProvider = "dev",
113+
oauthId = "dev-guide-001",
114+
email = "[email protected]",
115+
nickname = "서울 투어 김가이드",
116+
profileImageUrl = "https://i.pravatar.cc/300?img=12",
117+
role = UserRole.GUIDE,
118+
location = Region.SEOUL,
119+
description =
120+
"안녕하세요! 서울에서 10년간 가이드 경험이 있는 김가이드입니다. " +
121+
"서울의 숨은 명소부터 핫플레이스까지 모두 안내해드릴 수 있습니다. " +
122+
"특히 한식 맛집과 전통시장 투어에 자신 있습니다!",
123+
),
124+
User(
125+
oauthProvider = "dev",
126+
oauthId = "dev-guide-002",
127+
email = "[email protected]",
128+
nickname = "부산 사하구 박가이드",
129+
profileImageUrl = "https://i.pravatar.cc/300?img=33",
130+
role = UserRole.GUIDE,
131+
location = Region.BUSAN,
132+
description =
133+
"부산 사하구 토박이 박가이드입니다! 다대포 해수욕장, 을숙도, 감천문화마을 등 " +
134+
"부산의 숨은 보석 같은 명소들을 소개해드립니다. " +
135+
"특히 사하구 맛집과 바다 뷰 카페 투어는 제가 제일 자신 있어요. 부산 사투리로 정감있게 안내해드립니다!",
136+
),
137+
)
138+
139+
println("\n📝 더미 가이드 데이터 초기화 시작...")
140+
var createdCount = 0
141+
var existingCount = 0
142+
143+
dummyGuides.forEach { guide ->
144+
val existing = userRepository.findByEmail(guide.email)
145+
if (existing == null) {
146+
userRepository.save(guide)
147+
createdCount++
148+
println("\n✅ 가이드 생성 완료:")
149+
println(" 📧 Email: ${guide.email}")
150+
println(" 👤 Nickname: ${guide.nickname}")
151+
println(" 📍 Location: ${guide.location?.displayName}")
152+
} else {
153+
existingCount++
154+
println("\n✅ 이미 존재하는 가이드: ${existing.nickname} (ID: ${existing.id})")
155+
}
156+
}
157+
158+
println("\n📊 더미 가이드 데이터 초기화 완료!")
159+
println(" ✨ 새로 생성: ${createdCount}")
160+
println(" ♻️ 기존 유지: ${existingCount}")
161+
}
162+
}
96163
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.back.koreaTravelGuide.common.config
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import com.fasterxml.jackson.databind.SerializationFeature
5+
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
6+
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
7+
import org.springframework.context.annotation.Bean
8+
import org.springframework.context.annotation.Configuration
9+
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
10+
11+
@Configuration
12+
class JacksonConfig {
13+
@Bean
14+
fun objectMapper(): ObjectMapper {
15+
return Jackson2ObjectMapperBuilder()
16+
.modulesToInstall(JavaTimeModule())
17+
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
18+
.build<ObjectMapper>()
19+
.registerKotlinModule()
20+
}
21+
}

src/main/kotlin/com/back/koreaTravelGuide/common/config/RedisConfig.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import com.back.koreaTravelGuide.domain.ai.tour.dto.TourResponse
55
import com.back.koreaTravelGuide.domain.ai.weather.dto.MidForecastDto
66
import com.back.koreaTravelGuide.domain.ai.weather.dto.TemperatureAndLandForecastDto
77
import com.fasterxml.jackson.databind.ObjectMapper
8-
import com.fasterxml.jackson.module.kotlin.KotlinModule
98
import org.springframework.beans.factory.annotation.Value
109
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
1110
import org.springframework.cache.CacheManager
@@ -45,13 +44,6 @@ class RedisConfig {
4544
return LettuceConnectionFactory(redisConfiguration)
4645
}
4746

48-
@Bean
49-
fun objectMapper(): ObjectMapper =
50-
ObjectMapper().apply {
51-
// Kotlin 모듈 등록 (data class 생성자 인식)
52-
registerModule(KotlinModule.Builder().build())
53-
}
54-
5547
@Bean
5648
fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, String> {
5749
val template = RedisTemplate<String, String>()

src/main/resources/application-prod.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ spring:
3232
password: ${REDIS_PASSWORD:}
3333
database: 0
3434

35+
# RabbitMQ 설정 (WebSocket STOMP Relay용)
36+
rabbitmq:
37+
host: ${RABBITMQ_HOST}
38+
port: ${RABBITMQ_PORT}
39+
username: ${RABBITMQ_USERNAME}
40+
password: ${RABBITMQ_PASSWORD}
41+
stomp-port: ${RABBITMQ_STOMP_PORT}
42+
connection-timeout: 5000
43+
requested-heartbeat: 30
44+
3545
session:
3646
store-type: redis
3747
timeout: 30m

src/main/resources/application.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ spring:
8181
max-idle: 8
8282
min-idle: 0
8383

84+
# RabbitMQ 설정 (WebSocket STOMP Relay용)
85+
rabbitmq:
86+
host: ${RABBITMQ_HOST:localhost}
87+
port: ${RABBITMQ_PORT:5672}
88+
username: ${RABBITMQ_USERNAME:admin}
89+
password: ${RABBITMQ_PASSWORD:admin}
90+
stomp-port: ${RABBITMQ_STOMP_PORT:61613}
91+
8492
# 세션 관리 (개발용: none, 운영용: redis)
8593
session:
8694
store-type: none # Redis 없어도 실행 가능하도록 변경

0 commit comments

Comments
 (0)