From de4eeee5b7c46a27f4b137ba32abdd78e7efdafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 28 Jul 2025 15:49:17 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat=20(=20#20=20)=20:=20dto=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grpc/server/dto/InternalUserResponse.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/dto/InternalUserResponse.kt diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/dto/InternalUserResponse.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/dto/InternalUserResponse.kt new file mode 100644 index 0000000..e83a341 --- /dev/null +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/dto/InternalUserResponse.kt @@ -0,0 +1,24 @@ +package hs.kr.entrydsm.user.infrastructure.grpc.server.dto + +import hs.kr.entrydsm.user.domain.user.adapter.out.domain.UserRole +import java.util.UUID + +/** + * 내부 gRPC 통신용 사용자 응답 DTO 클래스입니다. + * 다른 마이크로서비스와의 통신에서 사용자 정보를 전달하는 데 사용됩니다. + * + * @property id 사용자 고유 식별자 + * @property phoneNumber 사용자 전화번호 + * @property name 사용자 이름 + * @property isParent 학부모 여부 + * @property receiptCode 지원서 접수번호 + * @property role 사용자 역할 + */ +data class InternalUserResponse( + val id: UUID, + val phoneNumber: String, + val name: String, + val isParent: Boolean, + val receiptCode: Long?, + val role: UserRole, +) From f4c0a4ca848b4536b6b5c6954ae3bc8e6f2001b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 28 Jul 2025 15:49:29 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat=20(=20#20=20)=20:=20gRPC=20service=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grpc/server/UserGrpcService.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt new file mode 100644 index 0000000..7abb0a1 --- /dev/null +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt @@ -0,0 +1,45 @@ +package hs.kr.entrydsm.user.infrastructure.grpc.server + +import hs.kr.entrydsm.casper.user.proto.UserServiceGrpcKt +import hs.kr.entrydsm.casper.user.proto.UserServiceProto +import hs.kr.entrydsm.user.domain.user.application.port.`in`.QueryUserByUUIDUseCase +import hs.kr.entrydsm.user.infrastructure.grpc.server.mapper.UserGrpcMapper +import io.grpc.Status +import io.grpc.StatusException +import net.devh.boot.grpc.server.service.GrpcService +import java.util.UUID + +/** + * 사용자 관련 gRPC 서비스 구현 클래스입니다. + * 다른 마이크로서비스와의 gRPC 통신을 통해 사용자 정보를 제공합니다. + * + * @property queryUserByUUIDUseCase UUID로 사용자 조회 유스케이스 + * @property userGrpcMapper gRPC 메시지 변환 매퍼 + */ +@GrpcService +class UserGrpcService( + private val queryUserByUUIDUseCase: QueryUserByUUIDUseCase, + private val userGrpcMapper: UserGrpcMapper, +) : UserServiceGrpcKt.UserServiceCoroutineImplBase() { + + /** + * 사용자 ID로 사용자 정보를 조회합니다. + * + * @param request 사용자 ID가 포함된 gRPC 요청 + * @return 사용자 정보 gRPC 응답 + * @throws StatusException UUID 형식이 잘못되었거나 서버 오류가 발생한 경우 + */ + override suspend fun getUserInfoByUserId(request: UserServiceProto.GetUserInfoRequest): UserServiceProto.GetUserInfoResponse { + + return try { + val userId = UUID.fromString(request.userId) + val userInfo = queryUserByUUIDUseCase.getUserById(userId) + userGrpcMapper.toGetUserInfoResponse(userInfo) + } catch (e: IllegalArgumentException) { + throw StatusException(Status.INVALID_ARGUMENT.withDescription("Invalid UUID format")) + } catch (e: Exception) { + throw StatusException(Status.INTERNAL.withDescription("서버 오류")) + } + } + +} From 27009f58c6c43f58afb6fd015c6c2e35f5d1d36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 28 Jul 2025 15:49:38 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat=20(=20#20=20)=20:=20mapper=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grpc/server/mapper/UserGrpcMapper.kt | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/mapper/UserGrpcMapper.kt diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/mapper/UserGrpcMapper.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/mapper/UserGrpcMapper.kt new file mode 100644 index 0000000..fbb0bce --- /dev/null +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/mapper/UserGrpcMapper.kt @@ -0,0 +1,44 @@ +package hs.kr.entrydsm.user.infrastructure.grpc.server.mapper + +import hs.kr.entrydsm.casper.user.proto.UserServiceProto +import hs.kr.entrydsm.user.infrastructure.grpc.server.dto.InternalUserResponse +import hs.kr.entrydsm.user.domain.user.adapter.out.domain.UserRole +import org.springframework.stereotype.Component + +/** + * 사용자 정보를 gRPC 프로토콜 버퍼와 매핑하는 매퍼 클래스입니다. + * 내부 DTO와 gRPC 메시지 간의 변환을 담당합니다. + */ +@Component +class UserGrpcMapper { + + /** + * InternalUserResponse 객체를 gRPC 사용자 정보 응답으로 변환합니다. + * + * @param userResponse 변환할 사용자 응답 DTO + * @return gRPC 사용자 정보 응답 + */ + fun toGetUserInfoResponse(userResponse: InternalUserResponse): UserServiceProto.GetUserInfoResponse { + return UserServiceProto.GetUserInfoResponse.newBuilder() + .setId(userResponse.id.toString()) + .setPhoneNumber(userResponse.phoneNumber) + .setName(userResponse.name) + .setIsParent(userResponse.isParent) + .setRole(toProtoUserRole(userResponse.role)) + .build() + } + + /** + * 도메인 사용자 역할을 gRPC 프로토콜 사용자 역할로 변환합니다. + * + * @param userRole 변환할 도메인 사용자 역할 + * @return gRPC 프로토콜 사용자 역할 + */ + private fun toProtoUserRole(userRole: UserRole): UserServiceProto.UserRole{ + return when(userRole){ + UserRole.ROOT -> UserServiceProto.UserRole.ROOT + UserRole.USER -> UserServiceProto.UserRole.USER + UserRole.ADMIN -> UserServiceProto.UserRole.ADMIN + } + } +} From 045cf40b7e8dcbe8d983dcc3088e3e66205717b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 28 Jul 2025 15:49:53 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat=20(=20#20=20)=20:=20=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=20kafka=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kafka/producer/DeleteAllTableProducer.kt | 13 +++++++++++++ .../kafka/producer/DeleteUserProducer.kt | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteAllTableProducer.kt create mode 100644 casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteUserProducer.kt diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteAllTableProducer.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteAllTableProducer.kt new file mode 100644 index 0000000..079540f --- /dev/null +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteAllTableProducer.kt @@ -0,0 +1,13 @@ +package hs.kr.entrydsm.user.infrastructure.kafka.producer + +/** + * 모든 테이블 삭제 이벤트를 Kafka로 발행하는 Producer 인터페이스입니다. + * 관리자가 전체 데이터를 초기화할 때 다른 마이크로서비스에 알림을 전송하는 역할을 합니다. + */ +interface DeleteAllTableProducer { + /** + * 모든 테이블 삭제 이벤트를 전송합니다. + * 전체 데이터 초기화 이벤트를 Kafka 토픽으로 발행합니다. + */ + fun send() +} diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteUserProducer.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteUserProducer.kt new file mode 100644 index 0000000..4920463 --- /dev/null +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/kafka/producer/DeleteUserProducer.kt @@ -0,0 +1,15 @@ +package hs.kr.entrydsm.user.infrastructure.kafka.producer + +/** + * 사용자 삭제 이벤트를 Kafka로 발행하는 Producer 인터페이스입니다. + * 사용자 탈퇴 시 다른 마이크로서비스에 알림을 전송하는 역할을 합니다. + */ +interface DeleteUserProducer { + /** + * 사용자 삭제 이벤트를 전송합니다. + * 사용자의 접수번호를 포함한 삭제 이벤트를 Kafka 토픽으로 발행합니다. + * + * @param receiptCode 삭제된 사용자의 접수번호 + */ + fun send(receiptCode: Long) +} From 6d54dd727f9df841d4f024df47b01462ffdedc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Tue, 29 Jul 2025 17:42:05 +0900 Subject: [PATCH 5/5] =?UTF-8?q?refactor=20(=20#20=20)=20:=20=EB=B9=84?= =?UTF-8?q?=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20=EB=90=98?= =?UTF-8?q?=EC=96=B4=20=EC=9E=88=EA=B8=B0=20=EB=95=8C=EB=AC=B8=EC=97=90=20?= =?UTF-8?q?try-catch=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/grpc/server/UserGrpcService.kt | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt index 7abb0a1..4689c58 100644 --- a/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt +++ b/casper-user/src/main/kotlin/hs/kr/entrydsm/user/infrastructure/grpc/server/UserGrpcService.kt @@ -30,16 +30,8 @@ class UserGrpcService( * @throws StatusException UUID 형식이 잘못되었거나 서버 오류가 발생한 경우 */ override suspend fun getUserInfoByUserId(request: UserServiceProto.GetUserInfoRequest): UserServiceProto.GetUserInfoResponse { - - return try { - val userId = UUID.fromString(request.userId) - val userInfo = queryUserByUUIDUseCase.getUserById(userId) - userGrpcMapper.toGetUserInfoResponse(userInfo) - } catch (e: IllegalArgumentException) { - throw StatusException(Status.INVALID_ARGUMENT.withDescription("Invalid UUID format")) - } catch (e: Exception) { - throw StatusException(Status.INTERNAL.withDescription("서버 오류")) - } + val userId = UUID.fromString(request.userId) + val userInfo = queryUserByUUIDUseCase.getUserById(userId) + return userGrpcMapper.toGetUserInfoResponse(userInfo) } - }