Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth 인증 정보로 회원 조회 로직 개발 #28

Merged
merged 19 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id("org.springframework.boot") version "3.4.2"
id("io.spring.dependency-management") version "1.1.7"
id("org.jetbrains.kotlin.plugin.jpa") version "1.9.25"
kotlin("kapt") version "1.9.25"
}

group = "com.ssak3"
Expand All @@ -30,11 +31,18 @@ dependencies {

implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.2.0")


// QueryDSL 추가
val querydslVersion = "5.0.0"
implementation("com.querydsl:querydsl-jpa:$querydslVersion:jakarta")
kapt("com.querydsl:querydsl-apt:$querydslVersion:jakarta")

implementation("io.jsonwebtoken:jjwt-api:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")

runtimeOnly("com.mysql:mysql-connector-j")
runtimeOnly("com.h2database:h2")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ssak3.timeattack.common.config

import com.querydsl.jpa.impl.JPAQueryFactory
import jakarta.persistence.EntityManager
import jakarta.persistence.PersistenceContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class QueryDslConfig {

@PersistenceContext
lateinit var entityManager: EntityManager

@Bean
fun jpaQueryFactory(): JPAQueryFactory {
return JPAQueryFactory(entityManager)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ssak3.timeattack.member.infrastructure

import com.ssak3.timeattack.member.domain.Member
import com.ssak3.timeattack.member.domain.OAuthProvider

interface MemberCustomRepository {
fun findByProviderAndSubject(oauthProvider: OAuthProvider, subject: String): Member?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.ssak3.timeattack.member.infrastructure

import com.querydsl.jpa.impl.JPAQueryFactory
import com.ssak3.timeattack.member.domain.Member
import com.ssak3.timeattack.member.domain.OAuthProvider
import com.ssak3.timeattack.member.domain.QMember
import org.springframework.stereotype.Repository

@Repository
class MemberCustomRepositoryImpl(
private val queryFactory: JPAQueryFactory,
) : MemberCustomRepository {

override fun findByProviderAndSubject(oauthProvider: OAuthProvider, subject: String): Member? {
val qMember = QMember.member
return queryFactory
.select(qMember)
.from(qMember)
.where(
qMember.oAuthProviderInfo.oauthProvider.eq(oauthProvider),
qMember.oAuthProviderInfo.subject.eq(subject)
)
.fetchOne()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.ssak3.timeattack.member.infrastructure

import com.ssak3.timeattack.member.domain.Member
import org.springframework.data.jpa.repository.JpaRepository

interface MemberRepository : JpaRepository<Member, Long>, MemberCustomRepository
21 changes: 21 additions & 0 deletions src/main/resources/application-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
spring:
datasource:
driver-class-name: org.h2.Driver
url: 'jdbc:h2:mem:timeattack'
username: 'user'
password: ''
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show_sql: true
h2:
console:
enabled: true
path: '/h2-console'

data:
redis:
port: 6379
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.ssak3.timeattack.member.infrastructure

import com.ssak3.timeattack.member.domain.Member
import com.ssak3.timeattack.member.domain.OAuthProvider
import com.ssak3.timeattack.member.domain.OAuthProviderInfo
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles

@SpringBootTest
@ActiveProfiles("test")
class MemberRepositoryTest @Autowired constructor(
private val memberRepository: MemberRepository
) {
private lateinit var member: Member

@BeforeEach
fun setMember() {
// given
val provider = OAuthProvider.KAKAO
val subject = "1234567890"
val nickname = "testUser"
member = Member(
nickname = nickname,
email = "test@test.com",
profileImageUrl = "https://test.com",
oAuthProviderInfo = OAuthProviderInfo(oauthProvider = provider, subject = subject),
)
}

@Test
@DisplayName("주어진 subject, provider와 일치하는 유저가 존재하면 해당 유저 반환")
fun test_findByProviderAndSubject_ShouldReturnExpectedMember() {
// given
// saveAndFlush() << 즉시 DB에 반영 -> 조회 시 영속성 컨텍스트 캐시가 아닌 실제 DB 상태를 보장하기 위해서
memberRepository.saveAndFlush(member)

// when
val findMember = memberRepository.findByProviderAndSubject(
member.oAuthProviderInfo.oauthProvider,
member.oAuthProviderInfo.subject
)

// then
assertThat(findMember).isNotNull
assertThat(findMember?.nickname).isEqualTo(member.nickname)
}

@Test
@DisplayName("주어진 subject, provider와 일치하는 유저가 없으면 null 반환")
fun test_findByProviderAndSubject_ShouldReturnNull() {
// given
memberRepository.saveAndFlush(member)

// when
val findMember = memberRepository.findByProviderAndSubject(
member.oAuthProviderInfo.oauthProvider,
"different subject"
)

// then
assertThat(findMember).isNull()
}
}
Loading