Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0de70fa
feat ( #20 ) : InternalAdminResponse
coehgns Aug 1, 2025
cd3e381
feat ( #20 ) : AdminGrpcClient
coehgns Aug 1, 2025
e852472
feat ( #20 ) : admin.proto
coehgns Aug 1, 2025
31dbbfa
chore ( #20 ) : ๋ˆ„๋ฝ๋œ ์ปค๋ฐ‹
coehgns Aug 1, 2025
92bcf33
build ( #20 ) : gRPC Dependencies ์ถ”๊ฐ€
coehgns Aug 1, 2025
8d42d7f
build ( #20 ) : gRPC DependenciesVersion ์ถ”๊ฐ€
coehgns Aug 1, 2025
2a2567c
build ( #20 ) : kotlin version ์ˆ˜์ •
coehgns Aug 1, 2025
c1d20e2
build ( #20 ) : detekt.yml ์ˆ˜์ •
coehgns Aug 1, 2025
c8474fc
build ( #20 ) : ๋ˆ„๋ฝ๋œ ์ปค๋ฐ‹
coehgns Aug 1, 2025
e6775e7
feat ( #20 ) : admin.proto ํŒจํ‚ค์ง€ ๋„ค์ด๋ฐ ์ˆ˜์ •
coehgns Aug 2, 2025
e869946
build ( #20 ) : Dependencies์— ์˜์กด์„ฑ ์˜คํƒ€ ์ˆ˜์ •
coehgns Aug 2, 2025
3dd4807
build ( #20 ) : DependencyVersion์— ์˜์กด์„ฑ ์˜คํƒ€ ์ˆ˜์ •
coehgns Aug 2, 2025
fc0d926
build ( #20 ) : Dependencies์— ์ฝ”๋ฃจํ‹ด ์ถ”๊ฐ€
coehgns Aug 2, 2025
160a967
build ( #20 ) : DependencyVersion์— ์ฝ”๋ฃจํ‹ด ์ถ”๊ฐ€
coehgns Aug 2, 2025
0c6f6bd
build ( #20 ) : ์ฝ”๋ฃจํ‹ด ์˜์กด์„ฑ ์ถ”๊ฐ€
coehgns Aug 2, 2025
f2bac81
refactor ( #20 ) : Stub์„ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ๋งž๊ฒŒ ๋กœ์ง ์ˆ˜์ •
coehgns Aug 2, 2025
983b933
chore ( #20 ) : Dependencies์— ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ ์‚ญ์ œ
coehgns Aug 2, 2025
2907e9b
chore ( #20 ) : DependencyVersion์— ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ ์‚ญ์ œ
coehgns Aug 2, 2025
b175734
refactor ( #20 ) : AdminGrpcClient.kt
coehgns Aug 11, 2025
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
4 changes: 4 additions & 0 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ object Dependencies {
const val GRPC_KOTLIN_STUB = "io.grpc:grpc-kotlin-stub:${DependencyVersion.GRPC_KOTLIN}"
const val PROTOBUF_KOTLIN = "com.google.protobuf:protobuf-kotlin:${DependencyVersion.PROTOBUF}"
const val GRPC_TESTING = "io.grpc:grpc-testing:${DependencyVersion.GRPC}"
const val GRPC_CLIENT = "net.devh:grpc-client-spring-boot-starter:${DependencyVersion.GRPC_CLIENT}"
const val GOOGLE_PROTOBUF = "com.google.protobuf:protobuf-java:${DependencyVersion.GOOGLE_PROTOBUF}"

// coroutines
const val COROUTINES = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${DependencyVersion.COROUTINES}"

// swagger
const val SWAGGER = "org.springdoc:springdoc-openapi-starter-webmvc-ui:${DependencyVersion.SWAGGER_VERSION}"
Expand Down
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/DependencyVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ object DependencyVersion {
const val SPRING_DEPENDENCY_MANAGEMENT = "1.1.7"
const val DETEKT = "1.23.6"
const val KTLINT = "12.1.1"
const val COROUTINES = "1.8.0"

const val JWT = "0.11.5"
const val ORG_JSON = "20230227"
Expand All @@ -12,6 +13,8 @@ object DependencyVersion {
const val GRPC = "1.61.1"
const val GRPC_KOTLIN = "1.4.1"
const val PROTOBUF = "3.25.3"
const val GRPC_CLIENT = "2.15.0.RELEASE"
const val GOOGLE_PROTOBUF = "3.25.3"

const val SWAGGER_VERSION = "2.5.0"
const val AWS = "1.12.281"
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/PluginVersion.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
object PluginVersion {
const val KOTLIN_VERSION = "1.9.25"
const val KOTLIN_VERSION = "1.9.23"
const val SPRING_BOOT_VERSION = "3.4.4"
const val SPRING_DEPENDENCY_MANAGEMENT_VERSION = "1.1.7"
const val DETEKT_VERSION = "1.23.6"
const val KTLINT_VERSION = "12.1.1"
const val PROTOBUF_VERSION = "0.9.4"
}
}
128 changes: 128 additions & 0 deletions casper-feed/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
plugins {
id(Plugin.KOTLIN_JVM) version PluginVersion.KOTLIN_VERSION
id(Plugin.KOTLIN_SPRING) version PluginVersion.KOTLIN_VERSION
id(Plugin.KOTLIN_KAPT)
id(Plugin.SPRING_BOOT) version PluginVersion.SPRING_BOOT_VERSION
id(Plugin.SPRING_DEPENDENCY_MANAGEMENT) version PluginVersion.SPRING_DEPENDENCY_MANAGEMENT_VERSION
id(Plugin.CASPER_DOCUMENTATION)
id(Plugin.PROTOBUF) version PluginVersion.PROTOBUF_VERSION
}

group = "hs.kr.entrydsm"
version = "0.0.1-SNAPSHOT"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

repositories {
mavenCentral()
}

dependencies {
// ์Šคํ”„๋ง ๋ถ€ํŠธ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ
implementation(Dependencies.SPRING_BOOT_STARTER)

// ์ฝ”ํ‹€๋ฆฐ ๋ฆฌํ”Œ๋ ‰์…˜
implementation(Dependencies.KOTLIN_REFLECT)

// ์Šคํ”„๋ง ๋ถ€ํŠธ ํ…Œ์ŠคํŠธ ๋„๊ตฌ
testImplementation(Dependencies.SPRING_BOOT_STARTER_TEST)

// ์ฝ”ํ‹€๋ฆฐ + JUnit5 ํ…Œ์ŠคํŠธ
testImplementation(Dependencies.KOTLIN_TEST_JUNIT5)

// JUnit5 ์‹คํ–‰ ๋Ÿฐ์ฒ˜
testRuntimeOnly(Dependencies.JUNIT_PLATFORM_LAUNCHER)

// ์›น ๊ด€๋ จ
implementation(Dependencies.SPRING_BOOT_STARTER_WEB)

// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
implementation(Dependencies.SPRING_BOOT_STARTER_DATA_JPA)
implementation(Dependencies.SPRING_BOOT_STARTER_DATA_REDIS)
runtimeOnly(Dependencies.MYSQL_CONNECTOR)

// ๋ณด์•ˆ
implementation(Dependencies.SPRING_BOOT_STARTER_SECURITY)

// ๊ฒ€์ฆ
implementation(Dependencies.SPRING_BOOT_STARTER_VALIDATION)

// JSON ์ฒ˜๋ฆฌ
implementation(Dependencies.JACKSON_MODULE_KOTLIN)
implementation(Dependencies.ORG_JSON)

// JWT
implementation(Dependencies.JWT_API)
implementation(Dependencies.JWT_IMPL)
runtimeOnly(Dependencies.JWT_JACKSON)

implementation(Dependencies.MAPSTRUCT)
kapt(Dependencies.MAPSTRUCT_PROCESSOR)

// grpc
implementation(Dependencies.GRPC_NETTY_SHADED)
implementation(Dependencies.GRPC_PROTOBUF)
implementation(Dependencies.GRPC_STUB)
implementation(Dependencies.GRPC_KOTLIN_STUB)
implementation(Dependencies.PROTOBUF_KOTLIN)
testImplementation(Dependencies.GRPC_TESTING)
implementation(Dependencies.GRPC_CLIENT)
implementation(Dependencies.GOOGLE_PROTOBUF)

// ์ฝ”๋ฃจํ‹ด
implementation(Dependencies.COROUTINES)

// swagger
implementation(Dependencies.SWAGGER)

// aws
implementation(Dependencies.AWS)

// feign
implementation(Dependencies.OPEN_FEIGN)

// Kafka
implementation(Dependencies.KAFKA)
implementation("org.springframework.kafka:spring-kafka:3.1.2")

// Cloud Config
// implementation(Dependencies.CLOUD_CONFIG)
}

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${DependencyVersion.PROTOBUF}"
}
plugins {
create("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${DependencyVersion.GRPC}"
}
create("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:${DependencyVersion.GRPC_KOTLIN}:jdk8@jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
create("grpc")
create("grpckt")
}
}

}

}

kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package hs.kr.entrydsm.feed.infrastructure.grpc.client

import hs.kr.entrydsm.casper.admin.proto.AdminServiceGrpc
import hs.kr.entrydsm.casper.admin.proto.AdminServiceProto
import hs.kr.entrydsm.feed.infrastructure.grpc.client.dto.response.InternalAdminResponse
import io.grpc.Channel
import io.grpc.stub.StreamObserver
import kotlinx.coroutines.suspendCancellableCoroutine
import net.devh.boot.grpc.client.inject.GrpcClient
import org.springframework.stereotype.Component
import java.util.UUID
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

/**
* ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค์™€์˜ gRPC ํ†ต์‹ ์„ ๋‹ด๋‹นํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
*
* @property channel gRPC ํ†ต์‹ ์„ ์œ„ํ•œ ์ฑ„๋„ (user-service๋กœ ์ž๋™ ์ฃผ์ž…๋จ)
*/
@Component
class AdminGrpcClient {

@GrpcClient("user-service")
lateinit var channel: Channel

/**
* ๊ด€๋ฆฌ์ž ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ด€๋ฆฌ์ž ์ •๋ณด๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
* gRPC ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค๋กœ๋ถ€ํ„ฐ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
*
* @param adminId ์กฐํšŒํ•  ๊ด€๋ฆฌ์ž์˜ ๊ณ ์œ  ์‹๋ณ„์ž(UUID)
* @return ์กฐํšŒ๋œ ๊ด€๋ฆฌ์ž ์ •๋ณด๋ฅผ ๋‹ด์€ [InternalAdminResponse] ๊ฐ์ฒด
* @throws io.grpc.StatusRuntimeException gRPC ์„œ๋ฒ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ
* @throws java.util.concurrent.CancellationException ์ฝ”๋ฃจํ‹ด์ด ์ทจ์†Œ๋œ ๊ฒฝ์šฐ
*/
suspend fun getAdminInfoByAdminId(adminId: UUID): InternalAdminResponse {
val adminStub = AdminServiceGrpc.newStub(channel)

val request = AdminServiceProto.GetAdminIdRequest.newBuilder()
.setAdminId(adminId.toString())
.build()

val response = suspendCancellableCoroutine { continuation ->
adminStub.getAdminByUUID(request, object : StreamObserver<AdminServiceProto.GetAdminIdResponse> {
override fun onNext(value: AdminServiceProto.GetAdminIdResponse) {
continuation.resume(value)
}
override fun onError(t: Throwable) {
continuation.resumeWithException(t)
}
override fun onCompleted() {}
})
}

return InternalAdminResponse(id = UUID.fromString(response.adminId))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hs.kr.entrydsm.feed.infrastructure.grpc.client.dto.response

import java.util.UUID

/**
* ๊ด€๋ฆฌ์ž ์ •๋ณด๋ฅผ ๋‹ด๋Š” ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
*
* @property id ๊ด€๋ฆฌ์ž์˜ ๊ณ ์œ  ์‹๋ณ„์ž(UUID)
*/
data class InternalAdminResponse(
val id: UUID
)
18 changes: 18 additions & 0 deletions casper-feed/src/main/proto/admin.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

package casper.feed;

option java_package = "hs.kr.entrydsm.casper.admin.proto";
option java_outer_classname = "AdminServiceProto";

service AdminService {
rpc GetAdminByUUID(GetAdminIdRequest) returns (GetAdminIdResponse);
}

message GetAdminIdRequest {
string admin_id =1;
}

message GetAdminIdResponse{
string admin_id = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hs.kr.entrydsm.feed

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest

/**
* Casper Feed ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
*
* ์ด ํด๋ž˜์Šค๋Š” Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ชจ๋“  ํ•„์š”ํ•œ ๋นˆ๊ณผ ์„ค์ •๊ณผ ํ•จ๊ป˜
* ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œ๋˜๋Š”์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
*/
@SpringBootTest(classes = [CasperFeedApplication::class])
class CasperFeedApplicationTests {

/**
* ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.
*
* ์ด ํ…Œ์ŠคํŠธ๋Š” Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ชจ๋“  ํ•„์š”ํ•œ ์„ค์ •๊ณผ ๋นˆ์ด ์ œ๋Œ€๋กœ
* ์ดˆ๊ธฐํ™”๋œ ์ƒํƒœ๋กœ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
* ์ปจํ…์ŠคํŠธ ๋กœ๋”ฉ์— ์‹คํŒจํ•  ๊ฒฝ์šฐ ์ด ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
*/
@Test
fun contextLoads() {
// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œ๋˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค.
}
}
4 changes: 2 additions & 2 deletions detekt.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
complexity:
active: true
LongParameterList:
active: true
active: false
functionThreshold: 6
constructorThreshold: 7

Expand All @@ -11,7 +11,7 @@ style:
active: true
maxLineLength: 120
MagicNumber:
active: true
active: false
ignoreNumbers:
- '-1'
- '0'
Expand Down