Menu
Coddy logo textTech

은행 시스템

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 106번째.

challenge icon

챌린지

쉬움

계좌, 거래 및 금융 운영을 관리하는 은행 시스템을 구축해 봅시다! 데이터 무결성이 중요한 견고한 시스템을 만들게 됩니다. 계좌 잔액은 검증된 방법을 통해서만 변경되어야 하며, 초과 인출이나 유효하지 않은 금액과 같은 오류는 적절하게 처리되어야 합니다.

코드는 다음 다섯 개의 파일로 구성됩니다:

  • account.go: Deposit(amount float64) errorWithdraw(amount float64) error 메서드를 가진 Transactable 인터페이스를 정의합니다. 그런 다음 이 인터페이스를 구현하는 두 가지 계좌 유형을 만듭니다:

    내보내지 않은(unexported) id, holder, balance 필드를 가진 CheckingAccount입니다. 당좌 예금 계좌(Checking accounts)는 잔액이 정확히 0이 되는 인출은 허용하지만, 0 미만으로 내려가는 것은 허용하지 않습니다.

    동일한 내보내지 않은 필드에 minBalance 필드가 추가된 SavingsAccount입니다. 저축 예금 계좌(Savings accounts)는 최소 잔액 100.0을 유지해야 하며, 이 임계값 미만으로 떨어지는 인출은 실패해야 합니다.

    두 계좌 유형 모두 생성자(NewCheckingAccountNewSavingsAccount)와 Balance() float64 게터(getter) 메서드가 필요합니다. 입금의 경우, 음수 또는 0인 금액은 거부하십시오. 인출의 경우, 음수 또는 0인 금액과 가용 자금을 초과하는 금액은 거부하십시오.

  • transaction.go: 계좌 활동을 기록하기 위한 Transaction 구조체를 만듭니다. 각 거래는 Type (문자열: "deposit" 또는 "withdrawal"), Amount (float64), AccountID (문자열)를 가집니다. NewTransaction 생성자와 [Type] $[Amount] on [AccountID] 형식(금액은 소수점 둘째 자리까지 형식화)을 반환하는 String() string 메서드를 포함합니다.
  • bank.go: 여러 계좌를 관리하고 거래를 기록하는 Bank 구조체를 구축합니다. 계좌는 ID를 키로 하는 맵에 저장하고 거래 슬라이스를 유지합니다. 다음을 구현합니다:
    • NewBank() *Bank — 빈 컬렉션을 초기화합니다.
    • AddAccount(id string, account Transactable) — 계좌를 등록합니다.
    • Deposit(accountID string, amount float64) error — 계좌에 입금하고 성공 시 거래를 기록합니다.
    • Withdraw(accountID string, amount float64) error — 계좌에서 인출하고 성공 시 거래를 기록합니다.
    • Transfer(fromID, toID string, amount float64) error — 계좌 간에 돈을 원자적으로 이동시킵니다 (인출은 성공했지만 입금이 실패하면 인출을 취소해야 합니다).
    • GetBalance(accountID string) (float64, error) — 계좌의 잔액을 반환합니다.

    존재하지 않는 계좌에 대해서는 적절한 오류를 반환합니다.

  • errors.go: 은행 운영을 위한 센티넬 오류(sentinel errors)를 정의합니다:
    • ErrAccountNotFound — 계좌 ID가 존재하지 않을 때
    • ErrInsufficientFunds — 인출 금액이 가용 잔액을 초과할 때
    • ErrInvalidAmount — 입금/인출 금액이 0 또는 음수일 때
    • ErrMinBalanceRequired — 저축 예금 인출이 최소 잔액 규정을 위반할 때
  • main.go: 은행을 생성하고 입력에 따라 작업을 처리합니다.

    생성할 계좌 수를 읽습니다. 각 계좌에 대해 계좌 유형(checking 또는 savings), ID, 소유자 이름, 초기 잔액을 읽습니다. 적절한 계좌 유형을 생성하고 은행에 추가합니다.

    그런 다음 작업 수를 읽습니다. 각 작업은 다음 중 하나입니다:

    • deposit [accountID] [amount]
    • withdraw [accountID] [amount]
    • transfer [fromID] [toID] [amount]
    • balance [accountID]

    각 작업에 대해 결과를 출력합니다: 입금/인출/이체 성공 시 OK, 잔액 조회 시 소수점 둘째 자리까지 형식화된 잔액, 또는 센티넬 오류 메시지를 사용한 실패 시 Error: [message]를 출력합니다.

다음과 같은 입력이 제공됩니다:

  • 계좌 수, 그 다음 각 계좌의 유형, ID, 소유자, 초기 잔액 (각 4줄씩)
  • 작업 수, 그 다음 각 작업 (각 1줄씩)

예를 들어, 다음과 같이 주어지면:

2
checking
ACC001
Alice
500.00
savings
ACC002
Bob
1000.00
6
deposit ACC001 200
balance ACC001
withdraw ACC002 950
withdraw ACC001 800
transfer ACC001 ACC002 100
balance ACC002

출력은 다음과 같아야 합니다:

OK
700.00
Error: minimum balance required
Error: insufficient funds
OK
1000.00

그리고 다음과 같이 주어지면:

1
checking
C100
Charlie
100.00
4
withdraw C100 100
balance C100
deposit C100 -50
withdraw C999 50

출력은 다음과 같아야 합니다:

OK
0.00
Error: invalid amount
Error: account not found

Transactable 인터페이스를 통해 은행이 두 계좌 유형을 동일하게 다루는 동시에, 각 계좌 유형이 고유한 규칙을 강제하는 방식에 주목하세요. Transfer 메서드는 원자적 연산을 보여줍니다. 도중에 문제가 발생하더라도 시스템은 일관성을 유지합니다!

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// 계좌 수 읽기
	scanner.Scan()
	numAccounts, _ := strconv.Atoi(scanner.Text())

	// 새 은행 생성
	bank := NewBank()

	// 계좌 읽기 및 생성
	for i := 0; i < numAccounts; i++ {
		scanner.Scan()
		accountType := scanner.Text()
		scanner.Scan()
		id := scanner.Text()
		scanner.Scan()
		holder := scanner.Text()
		scanner.Scan()
		balance, _ := strconv.ParseFloat(scanner.Text(), 64)

		// TODO: accountType에 따라 적절한 계좌 유형을 생성하고
		// 은행에 추가하십시오.
		_ = accountType
		_ = id
		_ = holder
		_ = balance
	}

	// 작업 수 읽기
	scanner.Scan()
	numOps, _ := strconv.Atoi(scanner.Text())

	// 각 작업 처리
	for i := 0; i < numOps; i++ {
		scanner.Scan()
		parts := strings.Fields(scanner.Text())
		operation := parts[0]

		// TODO: 각 작업 유형 처리:
		// - "deposit": 계좌에 입금, "OK" 또는 오류 출력
		// - "withdraw": 계좌에서 출금, "OK" 또는 오류 출력
		// - "transfer": 계좌 간 이체, "OK" 또는 오류 출력
		// - "balance": 잔액을 가져와 소수점 2자리까지 형식화하여 출력
		_ = operation
	}
}

객체 지향 프로그래밍의 모든 레슨