Skip to content

Commit 58f731b

Browse files
committed
[Fix] initdata ãdebug
1 parent ec4cf13 commit 58f731b

File tree

6 files changed

+182
-9
lines changed

6 files changed

+182
-9
lines changed

back/src/main/java/com/back/global/initdata/InitData.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.back.domain.comment.entity.Comment;
44
import com.back.domain.comment.repository.CommentRepository;
55
import com.back.domain.node.dto.PivotListDto;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.context.annotation.Profile;
68
import com.back.domain.node.dto.base.BaseLineBulkCreateRequest;
79
import com.back.domain.node.dto.base.BaseLineBulkCreateResponse;
810
import com.back.domain.node.dto.decision.DecNodeDto;
@@ -42,8 +44,13 @@
4244
* [요약] 기동 시 admin·user1 생성 → user1에 베이스라인(총7: 헤더+피벗5+테일) 1개와 결정라인 2개(첫 번째 6노드, 두 번째 2노드) 시드 주입.
4345
* 게시글 30개(일반20 + 투표10)과 댓글 14개(마지막 2개 글에 각 7개) 생성.
4446
* 시나리오 3개(베이스 1개 + 완성 1개 + 처리중 1개)와 지표 10개(완성된 시나리오 2개에 각 5개씩) 생성.
47+
*
48+
* [주의] 프로덕션 환경에서는 실행되지 않습니다. (@Profile 설정)
49+
* 프로덕션 필수 데이터는 Flyway 마이그레이션(db/migration)을 통해 관리됩니다.
4550
*/
51+
@Slf4j
4652
@Component
53+
@Profile("!prod") // prod 프로파일에서는 실행 안 함
4754
@RequiredArgsConstructor
4855
public class InitData implements CommandLineRunner {
4956

@@ -62,6 +69,14 @@ public class InitData implements CommandLineRunner {
6269
// user1을 만들고 베이스라인(7)과 결정라인(5)을 시드로 주입한다
6370
@Override
6471
public void run(String... args) {
72+
// 전체 InitData 실행 여부 체크 (user1 존재 여부로 판단)
73+
if (userRepository.findByEmail("[email protected]").isPresent()) {
74+
log.info("[InitData] 이미 초기화 데이터가 존재합니다. 스킵합니다.");
75+
return;
76+
}
77+
78+
log.info("[InitData] 초기화 데이터 생성을 시작합니다...");
79+
6580
if (userRepository.findByEmail("[email protected]").isEmpty()) {
6681
var admin = User.builder()
6782
@@ -221,10 +236,6 @@ public void run(String... args) {
221236
)
222237
);
223238

224-
if (postRepository.count() > 0) {
225-
return;
226-
}
227-
228239
// 잠담 게시글 20개 생성
229240
List<Post> posts = new ArrayList<>();
230241
for (int i = 1; i <= 20; i++) {
@@ -287,11 +298,6 @@ public void run(String... args) {
287298

288299
// ========== Scenario InitData 생성 ==========
289300

290-
// 시나리오 데이터가 이미 있으면 스킵
291-
if (scenarioRepository.count() > 0) {
292-
return;
293-
}
294-
295301
// BaseLine 조회 (위에서 생성한 baseLineId 사용)
296302
BaseLine baseLine = baseLineRepository.findById(baseLineId)
297303
.orElseThrow(() -> new IllegalStateException("BaseLine not found"));
@@ -370,6 +376,12 @@ public void run(String... args) {
370376
.status(ScenarioStatus.PROCESSING)
371377
.build();
372378
scenarioRepository.save(processingScenario);
379+
380+
log.info("[InitData] 초기화 데이터 생성 완료!");
381+
log.info("[InitData] - 사용자: admin, user1");
382+
log.info("[InitData] - 게시글: {} 개", postRepository.count());
383+
log.info("[InitData] - 댓글: {} 개", commentRepository.count());
384+
log.info("[InitData] - 시나리오: {} 개", scenarioRepository.count());
373385
}
374386

375387
/**
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Flyway 마이그레이션 가이드
2+
3+
## 개요
4+
이 디렉토리는 Flyway 데이터베이스 마이그레이션 파일을 관리합니다.
5+
6+
## 파일 구조
7+
```
8+
db/migration/
9+
├── V1__init_schema.sql # 초기 스키마 생성
10+
├── V2__init_prod_essential.sql # 프로덕션 필수 데이터 (admin 계정)
11+
└── README.md # 이 파일
12+
```
13+
14+
## 마이그레이션 파일 명명 규칙
15+
- **형식**: `V{버전}__{설명}.sql`
16+
- **예시**: `V1__init_schema.sql`, `V2__add_user_table.sql`
17+
- **주의**: 언더스코어 2개 (`__`) 사용 필수
18+
19+
## V2__init_prod_essential.sql 사용 전 필수 작업
20+
21+
### 1. BCrypt 패스워드 생성
22+
```bash
23+
# 테스트 실행
24+
./gradlew test --tests "com.back.util.PasswordEncoderTest"
25+
26+
# 콘솔에서 출력된 BCrypt 해시 복사
27+
# 예: $2a$10$N9qo8uLOickgx2ZMRZoMye...
28+
```
29+
30+
### 2. SQL 파일 수정
31+
`V2__init_prod_essential.sql` 파일의 33번째 줄을 실제 BCrypt 해시로 교체:
32+
```sql
33+
-- 수정 전
34+
'$2a$10$YourActualBCryptHashHere', -- TODO: 실제 BCrypt 해시로 교체
35+
36+
-- 수정 후 (실제 값으로)
37+
'$2a$10$N9qo8uLOickgx2ZMRZoMye...', -- PasswordEncoderTest 실행 결과
38+
```
39+
40+
## 프로파일별 동작
41+
42+
### dev / test 프로파일
43+
- Flyway: **비활성화** (`enabled: false`)
44+
- InitData.java: **활성화** (풍부한 테스트 데이터 자동 생성)
45+
46+
### prod 프로파일
47+
- Flyway: **활성화** (`enabled: true`)
48+
- InitData.java: **비활성화** (`@Profile("!prod")`)
49+
50+
## 멱등성 보장
51+
모든 마이그레이션 파일은 `ON CONFLICT DO NOTHING` 구문을 사용하여:
52+
- Blue-Green 배포 시 중복 실행 방지
53+
- 재배포 시 안전성 보장
54+
- 429 API 에러 방지
55+
56+
## 실행 이력 확인
57+
```sql
58+
SELECT * FROM flyway_schema_history ORDER BY installed_rank;
59+
```
60+
61+
## 주의사항
62+
1. **마이그레이션 파일은 절대 수정 금지** (체크섬 검증 실패)
63+
2. **새로운 변경사항은 새 파일로 추가** (V3, V4...)
64+
3. **프로덕션 배포 전 반드시 로컬에서 테스트**
65+
66+
## 문제 해결
67+
68+
### 체크섬 오류 발생 시
69+
```sql
70+
-- 마이그레이션 이력 초기화 (주의: 개발 환경에서만!)
71+
DELETE FROM flyway_schema_history WHERE version = '2';
72+
```
73+
74+
### 마이그레이션 실패 시
75+
```bash
76+
# Flyway repair 명령 (Spring Boot Actuator 필요)
77+
./gradlew flywayRepair
78+
```
79+
80+
## 참고 문서
81+
- [Flyway Documentation](https://documentation.red-gate.com/fd)
82+
- [프로젝트 CLAUDE.md](../../../CLAUDE.md)

back/src/main/resources/db/migration/V1__init_schema.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
--liquibase formatted sql
2+
--dialect postgresql
3+
14
-- ========================================
25
-- 사용자 테이블
36
-- ========================================
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--liquibase formatted sql
2+
--dialect postgresql
3+
4+
-- ============================================
5+
-- V2__init_prod_essential.sql
6+
-- 프로덕션 환경 필수 초기 데이터
7+
-- ============================================
8+
-- 설명:
9+
-- - Blue-Green 배포 시에도 멱등성을 보장합니다
10+
-- - ON CONFLICT DO NOTHING 구문으로 중복 실행 방지
11+
-- - admin 계정만 생성 (테스트 데이터는 제외)
12+
-- ============================================
13+
14+
-- Admin 사용자 생성 (멱등하게)
15+
INSERT INTO users (
16+
email,
17+
password,
18+
role,
19+
username,
20+
nickname,
21+
birthday_at,
22+
gender,
23+
mbti,
24+
beliefs,
25+
created_date,
26+
updated_date
27+
)
28+
VALUES (
29+
30+
-- 주의: 실제 프로덕션에서는 PasswordEncoderTest 실행 결과로 교체하세요
31+
-- 현재 값은 'admin1234!' 인코딩 결과 (매번 다를 수 있음)
32+
'$2a$10$3d.SEWYbRSu6Wett4Txv9OxIL2AccoJP76Hcja5b/T.e4nB9nluIS',
33+
'ADMIN',
34+
'관리자',
35+
'관리자',
36+
'1990-01-01 00:00:00',
37+
'M',
38+
'INTJ',
39+
'합리주의',
40+
CURRENT_TIMESTAMP,
41+
CURRENT_TIMESTAMP
42+
)
43+
ON CONFLICT (email) DO NOTHING;
44+
45+
-- 초기화 완료 로그
46+
-- Flyway는 실행 성공 시 flyway_schema_history 테이블에 자동 기록됩니다.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.back.util;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
5+
import org.springframework.security.crypto.password.PasswordEncoder;
6+
7+
/**
8+
* 프로덕션 Flyway 마이그레이션용 패스워드 인코딩 값을 생성합니다.
9+
* 테스트 실행 후 출력된 값을 V2__init_prod_essential.sql에 사용하세요.
10+
*/
11+
public class PasswordEncoderTest {
12+
13+
private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
14+
15+
@Test
16+
public void generateEncodedPasswords() {
17+
String adminPassword = "admin1234!";
18+
String encodedAdmin = passwordEncoder.encode(adminPassword);
19+
20+
System.out.println("=================================================");
21+
System.out.println("Flyway 마이그레이션용 인코딩된 패스워드");
22+
System.out.println("=================================================");
23+
System.out.println("Admin Password (admin1234!):");
24+
System.out.println(encodedAdmin);
25+
System.out.println("=================================================");
26+
27+
// 검증
28+
System.out.println("\n검증: " + passwordEncoder.matches(adminPassword, encodedAdmin));
29+
}
30+
}

image.png

72.9 KB
Loading

0 commit comments

Comments
 (0)