Skip to content

Commit 6b07d0f

Browse files
robinjoonclaude
andauthored
feat: auth BC 구현 (회원가입/로그인 JWT) (#5)
* feat: auth BC 구현 (회원가입/로그인 JWT) DDD + Clean Architecture 기반 auth Bounded Context 구현. 회원가입(register)과 로그인(login) GraphQL Mutation을 통해 BCrypt 비밀번호 해싱 + JWT AccessToken 발급을 제공한다. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: JWT 토큰 검증 및 @authorize ArgumentResolver 구현 - JwtTokenProvider에 validateToken, getMemberIdFromToken 추가 - DGS ArgumentResolver 기반 @authorize 어노테이션으로 DataFetcher 파라미터 단위 인증 - application.properties를 profile별 YAML 설정으로 전환 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: GraphQL 스키마에 description 추가 및 제약 조건 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fbb331c commit 6b07d0f

File tree

42 files changed

+961
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+961
-2
lines changed

build.gradle.kts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,26 @@ extra["springCloudVersion"] = "2025.1.0"
3737
extra["exposedVersion"] = "1.0.0"
3838
extra["kotestVersion"] = "6.1.2"
3939
extra["mockkVersion"] = "1.14.9"
40+
extra["jjwtVersion"] = "0.12.6"
4041

4142
dependencies {
4243
// Spring Boot
4344
implementation("org.springframework.boot:spring-boot-h2console")
4445
implementation("org.springframework.boot:spring-boot-starter-actuator")
4546
implementation("org.springframework.boot:spring-boot-starter-flyway")
47+
implementation("org.springframework.boot:spring-boot-starter-security")
4648
implementation("org.springframework.boot:spring-boot-starter-webmvc")
4749
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-graphql-starter")
4850
implementation("org.flywaydb:flyway-database-postgresql")
4951
implementation("org.jetbrains.kotlin:kotlin-reflect")
5052
implementation("org.springframework.cloud:spring-cloud-starter-openfeign")
5153
implementation("tools.jackson.module:jackson-module-kotlin")
5254

55+
// JWT
56+
implementation("io.jsonwebtoken:jjwt-api:${property("jjwtVersion")}")
57+
runtimeOnly("io.jsonwebtoken:jjwt-impl:${property("jjwtVersion")}")
58+
runtimeOnly("io.jsonwebtoken:jjwt-jackson:${property("jjwtVersion")}")
59+
5360
// Exposed ORM
5461
implementation("org.jetbrains.exposed:exposed-spring-boot4-starter:${property("exposedVersion")}")
5562
implementation("org.jetbrains.exposed:exposed-kotlin-datetime:${property("exposedVersion")}")
@@ -67,6 +74,7 @@ dependencies {
6774
// Test - Spring Boot
6875
testImplementation("org.springframework.boot:spring-boot-starter-actuator-test")
6976
testImplementation("org.springframework.boot:spring-boot-starter-flyway-test")
77+
testImplementation("org.springframework.boot:spring-boot-starter-security-test")
7078
testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test")
7179
testImplementation("com.netflix.graphql.dgs:graphql-dgs-spring-graphql-starter-test")
7280

@@ -101,12 +109,17 @@ kotlin {
101109

102110
tasks.generateJava {
103111
schemaPaths.add("$projectDir/src/main/resources/graphql-client")
112+
schemaPaths.add("$projectDir/src/main/resources/schema")
104113
packageName = "kr.io.team.loop.codegen"
105-
generateClient = true
114+
generateClient = false
106115
}
107116

108117
ktlint {
109118
version = "1.8.0"
119+
filter {
120+
exclude { it.file.absolutePath.contains("/build/") }
121+
exclude { it.file.absolutePath.contains("/learning/") }
122+
}
110123
}
111124

112125
tasks.withType<Test> {

docs/plan/auth/checklist.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# auth BC 검증 체크리스트
2+
3+
## 필수 항목
4+
- [x] 아키텍처 원칙 준수 (docs/architecture.md 기준)
5+
- [x] 레이어 의존성 규칙 위반 없음 (ArchitectureTest 통과)
6+
- [x] 테스트 코드 작성 완료 (Domain, Application 필수)
7+
- [x] 모든 테스트 통과
8+
- [x] 기존 테스트 깨지지 않음
9+
- [x] `./gradlew build` 성공
10+
11+
## 선택 항목 (해당 시)
12+
- [x] Flyway 마이그레이션 작성 (V1__Create_member_table.sql)
13+
- [x] GraphQL register/login mutation 스키마 정의 완료

docs/plan/auth/context.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# auth BC 맥락
2+
3+
## 배경
4+
PRD의 모든 1순위 기능(목표/태스크/회고)은 회원 인증을 전제로 한다. 현재 프로덕션 코드가 전혀 없는 상태이므로, auth BC를 첫 번째 기능으로 구현한다.
5+
6+
## 목표
7+
- 회원가입(register) + 로그인(login) GraphQL Mutation 제공
8+
- JWT AccessToken 발급
9+
- BCrypt 비밀번호 해싱
10+
- DDD + Clean Architecture 준수
11+
12+
## 제약조건
13+
- 아키텍처: DDD + Clean Architecture (docs/architecture.md)
14+
- Spring Security 7 API 사용 (docs/spring-security-7.md)
15+
- Domain/Application 레이어 TDD 필수
16+
- DGS Codegen으로 GraphQL 타입 자동 생성
17+
- Exposed 1.0.0 (v1 패키지) 사용
18+
- RefreshToken 미구현 (MVP 범위 외)
19+
- Password VO는 Domain에 두지 않음 (해싱은 인프라 관심사)
20+
21+
## 관련 문서
22+
- PRD (Google Drive ID: 1Pb_Ma6mfLJZpD3gpUVaqPkLdBsyAfPFuwY6AIy6J19A)
23+
- DB 스키마: docs/schema.sql
24+
- 아키텍처: docs/architecture.md
25+
- 레이어 가이드: docs/layers/*.md
26+
- Spring Security 7: docs/spring-security-7.md

docs/plan/auth/plan.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# auth BC 개발 계획
2+
3+
## 단계
4+
5+
- [x] 0단계: 사전 설정 (빌드/의존성/마이그레이션/스키마/application.properties)
6+
- [x] 1단계: Common 모듈 (MemberId VO)
7+
- [x] 2단계: Domain Layer (TDD — LoginId, Nickname, Member, MemberCommand, MemberRepository)
8+
- [x] 3단계: Application Layer (TDD — AuthTokenDto, AuthService)
9+
- [x] 4단계: Infrastructure Layer (MemberTable, ExposedMemberRepository, SecurityConfig, JwtTokenProvider)
10+
- [x] 5단계: Presentation Layer (AuthDataFetcher)
11+
- [x] 6단계: 검증 (전체 테스트, ArchitectureTest, 빌드)

docs/plan/config-yaml/checklist.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# 설정 파일 YAML 전환 검증 체크리스트
2+
3+
## 필수 항목
4+
- [x] 모든 테스트 통과
5+
- [x] `./gradlew build` 성공

docs/plan/config-yaml/context.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# 설정 파일 YAML 전환 맥락
2+
3+
## 배경
4+
application.properties를 YAML로 전환하고, 로컬(H2)과 테스트 환경 모두에서 Flyway가 동작하도록 설정한다.
5+
6+
## 목표
7+
- application.yml로 전환 완료
8+
- local 프로파일: H2 + Flyway 동작
9+
- test 환경: H2 + Flyway 동작
10+
- prod 프로파일: PostgreSQL + Flyway 동작
11+
12+
## 제약조건
13+
- 설정 파일만 변경 (코드 변경 없음)

docs/plan/config-yaml/plan.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# 설정 파일 YAML 전환 계획
2+
3+
## 단계
4+
5+
- [x] 1단계: application.properties → application.yml 전환 (프로파일 분리)
6+
- [x] 2단계: 테스트 환경 application.yml 생성
7+
- [x] 3단계: 빌드/테스트 검증
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# GraphQL 스키마 description 검증 체크리스트
2+
3+
## 필수 항목
4+
- [x] 모든 테스트 통과
5+
- [x] 기존 테스트 깨지지 않음
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# GraphQL 스키마 description 맥락
2+
3+
## 배경
4+
GraphQL 스키마에 description이 없어 API 문서화가 부족하다.
5+
6+
## 목표
7+
모든 type, input, field, mutation에 한국어 description을 추가한다.
8+
9+
## 제약조건
10+
- 스키마 구조 변경 없음, description만 추가
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# GraphQL 스키마 description 추가 계획
2+
3+
## 단계
4+
5+
- [x] 1단계: auth.graphqls에 description 추가
6+
- [x] 2단계: 빌드 검증
7+
- [ ] 3단계: description 제약 조건을 실제 코드와 일치시키기

0 commit comments

Comments
 (0)