1. CB사 모듈 개발 연동
CssApplication
이것도 웹 서버가 떠서, 요청 오는 다양한 API를 처리해 줄 수 있어야 한다.
package happyprogfrog.css
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class CssApplication
fun main(args: Array<String>) {
runApplication<CssApplication>(*args)
}
build.gradle.kts
plugins {}
version = "0.0.1"
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
}
포트 변경
api, consumer랑 겹치치 않도록 지정 한다.
server:
port: 8081
LoanRequestDto
대출 심사에 필요한 정보를 담는 Dto
package happyprogfrog.css.dto
class LoanRequestDto {
data class RequestInputDto(
val userKey: String,
val userName: String,
val userIncomeAmount: Long,
var userRegistrationNumber: String
)
}
LoanResultDto
대출 심사 결과를 담는 Dto
package happyprogfrog.css.dto
class LoanResultDto {
data class ResponseDto(
val userKey: String,
val interest: Double,
val limitAmount: Long
)
}
LoanReviewService
대출 심사 로직이 들어간 Service
package happyprogfrog.css.service
import happyprogfrog.css.dto.LoanRequestDto
import happyprogfrog.css.dto.LoanResultDto
import org.springframework.stereotype.Service
@Service
class LoanReviewService {
fun loanReview(loanRequestDto: LoanRequestDto.RequestInputDto): LoanResultDto.ResponseDto {
// 리턴값을 주기 위한 예시이며, 실제로 CB 사의 로직은 이렇게 단순하지 않음
if (loanRequestDto.userIncomeAmount < 0) throw RuntimeException("Invalid userIncomeAmount Param")
if (loanRequestDto.userIncomeAmount < 10000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,0.0, 100000000)
if (loanRequestDto.userIncomeAmount < 20000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,10.0, 200000000)
if (loanRequestDto.userIncomeAmount < 30000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,9.0, 300000000)
if (loanRequestDto.userIncomeAmount < 40000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,8.0, 400000000)
if (loanRequestDto.userIncomeAmount < 50000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,7.0, 500000000)
if (loanRequestDto.userIncomeAmount >= 50000000) return LoanResultDto.ResponseDto(loanRequestDto.userKey,6.0, 600000000)
throw RuntimeException("Invalid userIncomeAmount Param")
}
}
LoanRequestController
- consumer로 부터 오는 요청을 받는 Controller
- 요청을 service로 보내 응답을 받아 리턴
package happyprogfrog.css.controller
import happyprogfrog.css.dto.LoanRequestDto
import happyprogfrog.css.dto.LoanResultDto
import happyprogfrog.css.service.LoanReviewService
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/css/api/v1")
class LoanRequestController(
private val loanReviewService: LoanReviewService
) {
@PostMapping("/request")
fun loanReview(@RequestBody requestInputDto: LoanRequestDto.RequestInputDto
): LoanResultDto.ResponseDto =
loanReviewService.loanReview(requestInputDto)
}
2. Consumer 모듈에서 CB사 모듈 호출하고 결과를 DB에 저장하기
ReviewResponseDto
- CB사의 응답을 담은 Dto
- LoanReview 엔티티로 변환해서 DB에 저장하는 데 사용함
package happyprogfrog.consumer.dto
import happyprogfrog.domain.domain.LoanReview
data class ReviewResponseDto(
val userKey: String,
val interest: Double,
val limitAmount: Long
) {
fun toLoanReviewEntity(): LoanReview =
LoanReview(
userKey = userKey,
loanInterest = interest,
loanLimitedAmount = limitAmount
)
}
LoanRequestService
- CB사로 요청 보내고 응답 저장하는 로직 수행
package happyprogfrog.consumer.service
import happyprogfrog.consumer.dto.ReviewResponseDto
import happyprogfrog.domain.domain.LoanReview
import happyprogfrog.domain.repository.LoanReviewRepository
import happyprogfrog.kafka.dto.LoanRequestDto
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import java.time.Duration
@Service
class LoanRequestService(
private val loanReviewRepository: LoanReviewRepository
) {
companion object {
const val CSS_URL = "http://localhost:8081/css/api/v1/request"
}
fun loanRequest(loanRequestDto: LoanRequestDto) {
// CB 사에 요청 보내기
val reviewResult = loanRequestToCb(loanRequestDto)
// 응답값을 DB에 저장하기
saveLoanReviewData(reviewResult.toLoanReviewEntity())
}
private fun loanRequestToCb(loanRequestDto: LoanRequestDto): ReviewResponseDto {
// WebClient 를 사용하는 방법도 있음
val restTemplate = RestTemplateBuilder()
.setConnectTimeout(Duration.ofMillis(1000))
.setReadTimeout(Duration.ofMillis(1000))
.build()
return restTemplate.postForEntity(CSS_URL, loanRequestDto, ReviewResponseDto::class.java).body!!
}
private fun saveLoanReviewData(loanReview: LoanReview) = loanReviewRepository.save(loanReview)
}
LoanRequestConsumer
- 특정 토픽을 Listen하고 있다가, 메시지가 발행되면 이를 consume해서 service 로직을 태움
package happyprogfrog.consumer.kafka
import com.fasterxml.jackson.databind.ObjectMapper
import happyprogfrog.consumer.service.LoanRequestService
import happyprogfrog.kafka.dto.LoanRequestDto
import org.springframework.kafka.annotation.KafkaListener
import org.springframework.stereotype.Service
@Service
class LoanRequestConsumer(
private val objectMapper: ObjectMapper,
private val loanRequestService: LoanRequestService
) {
@KafkaListener(topics = ["loan_request"], groupId = "fintech")
fun loanRequestTopicConsumer(message: String) {
val loanRequestKafkaDto = objectMapper.readValue(message, LoanRequestDto::class.java)
loanRequestService.loanRequest(loanRequestKafkaDto)
}
}
3. 실행
- api, consumer, css 웹 서버를 띄우고 대출 심사 요청 API 호출
- 대출 심사 결과가 DB에 잘 저장되는지
- 대출 심사 결과 확인 API 호출 시 응답이 잘 오는지 확인
반응형