유저 혹은 Frontend Application의 요청을 처리하고, 적절한 응답을 줄 수 있어야 한다.
예외 처리를 할 수 있고, 예외가 발생했을 때 적절한 응답을 줄 수 있어야 한다.
인증과 인가 처리를 할 수 있어야 한다.
비즈니스 로직을 처리할 수 있어야 한다.
트랜잭션(Transaction) 관리 전략이 있어야 한다.
스토리지 및 다른 외부 시스템과 통신할 수 있어야 한다.
스토리지(Storage) :
외부 시스템 : 아마존 AWS 등
// 내부 변수들을 쉽게 얻고(get). 수정(set)하기 위해서 data class 선언
// address : 계좌 주소
// balance : 계좌 잔액
// userID : 유저 아이디, 원래는 유저 클래스가 가지고 있어야하지만 지금은 BankAccount가 가지고 있다고 설정
data class BankAccount(val address: String, var balance: Int, val userID: String) {
}
// 내부 변수들을 쉽게 얻고(get). 수정(set)하기 위해서 data class 선언
// amount : 송금 금액
// fromAddress : 돈을 보내는 계좌 주소
// toAddress : 돈을 받는 계좌 주소
// userID : 송금하려는 유저의 아이디
data class TransferRequest(val amount: Int, val fromAddress : String, val toAddress: String, val userId: String) {
}
// 내부 변수들을 쉽게 얻고(get). 수정(set)하기 위해서 data class 선언
// success : 전송 성공 여부
// message : 전송 메시지
data class TransferResponse(val success: Boolean, val message: String) {
}
class TransferService {
// 은행 계좌 리스트
// 현재는 메모리에 저장되기 때문에 어플이 종료되면 얘들도 사라짐
// 원래는 데이터베이스에 저장되야 됨
private val bankAccounts = listOf<BankAccount>(
BankAccount(address = "abc", balance = 100, userID = "a"),
BankAccount(address = "abcd", balance = 200, userID = "b")
)
//request를 받으면 응답을 줘야 됨
fun transfer(request: TransferRequest): TransferResponse{
// 리퀘스트 보낸 쪽의 은행 계좌
val senderAccount = getBankAccountByAddress(request.fromAddress)
// 돈 받는 쪽 은행 계좌
val receiverAccount = getBankAccountByAddress(request.toAddress)
//실제 계좌 주인인지 확인하고 맞으면 인가
if(!autehnticate(senderAccount, request.userId)){
return TransferResponse(success = false, message = "Unauthorized")
}
// 보내는 금액 확인
if(request.amount < 0){ //송금액이 음수일 경우
return TransferResponse(success = false, message = "Invalid amount")
}
// 보내는 주소, 받는 주소가 실제로 존재하는지 확인
if (!isValidAddress(request.fromAddress) || !isValidAddress(request.toAddress)){
return TransferResponse(success = false, message = "Invalid address")
}
// 돈을 송금하는 계좌에 돈이 충분히 있는지 확인
if(!isSufficientBalance(senderAccount, request.amount)){
return TransferResponse(success = false, message = "No sufficient balance")
}
/*==============동시에 이뤄져야 됨=================*/
senderAccount.balance -= request.amount // 돈을 보내는 쪽 계좌에서 송금 금액만큼 돈이 빠져나감
receiverAccount.balance += request.amount // 송금 금액만큼 돈을 받는 쪽 계좌의 금액을 늘려줌
/*==============동시에 이뤄져야 됨=================*/
return TransferResponse(success = true, message = "Succeed!!")
}
// 실제 계좌 주인인지 인증하는 메소드
private fun autehnticate(bankAccount: BankAccount, userId: String):Boolean{
return bankAccount.userID == userId
}
//실제 계좌가 존재하는지 체크하는 메소드
private fun isValidAddress(address: String): Boolean{
// bankAccounts에 address가 있다면 true 반환
// bankAccounts에 address가 있다면 false 반환
return bankAccounts.any{ it.address == address}
}
//계좌에 송금하는 금액만큼 돈이 존재하는지 확인
private fun isSufficientBalance(bankAccount: BankAccount, amount: Int): Boolean{
return bankAccount.balance >= amount
}
//주소 기반으로 은행계좌 가져옮
private fun getBankAccountByAddress(address: String): BankAccount{
return bankAccounts.first { it.address == address}
}
}