자바 프로그래밍 학습에서 가장 큰 벽은 문법이 아니라 설계라는 사실을 깨닫는 데 걸리는 시간이다. 수많은 입문자가 if-else와 for문을 능숙하게 다루고도 막상 작은 프로그램 하나를 구조적으로 만들지 못해 좌절한다. 가장 빠른 해결책은 작은 콘솔 프로젝트를 처음부터 완성해보는 것이고, 그중에서도 은행 입출금 관리 프로그램은 객체 설계와 메서드 분리를 연습하기에 더할 나위 없이 좋은 소재다. 비용을 들이지 않고 자바 프로그래밍 학습을 이어가고 싶다면, 지금부터 설명할 방식 그대로 따라 하면 된다.
초보자가 이 프로젝트에서 저지르는 가장 흔한 실수는 모든 로직을 main 메서드 한곳에 우르르 몰아넣는 것이다. 입금, 출금, 잔액 조회, 거래 내역 출력까지 전부 main 안에서 처리하다 보면 코드가 수백 줄로 늘어나고, 변수 하나만 잘못 건드려도 프로그램 전체가 무너진다. 이런 코드는 실행은 되지만 자바 프로그래밍 학습 목적에는 전혀 부합하지 않는다. 객체지향의 핵심인 책임 분리와 재사용성을 경험하지 못한 채, 단순히 문법을 나열하는 수준에 머물고 만다. 이 글에서는 이런 함정을 피하고 실제 업무에서도 통용되는 구조로 프로그램을 만드는 과정을 단계별로 풀어낸다.
프로젝트를 시작하기 전에 개발 환경을 갖추는 일이 선행되어야 한다. 자바 입문자를 위한 개발 환경 설정은 생각보다 단순하다. JDK(Java Development Kit)를 설치하고, 텍스트 편집기만 있어도 콘솔 프로그램을 작성하고 실행하는 데 전혀 문제가 없다. 통합 개발 환경(IDE) 없이 명령 프롬프트에서 javac와 java 명령어로 컴파일하고 실행하는 과정을 먼저 경험해보는 것이 좋다. 이 과정이 익숙해지면 나중에 어떤 도구를 쓰든 자바가 실제로 어떻게 동작하는지 이해할 수 있다. IDE를 처음부터 쓰면 편리하지만, 내부에서 일어나는 일을 보지 못한 채 자동화에 의존하게 되는 단점이 있다. 적어도 첫 프로젝트는 메모장이나 간단한 편집기로 시작하길 권한다.
이제 본격적으로 프로그램을 설계해보자. 은행 입출금 관리 프로그램의 핵심은 세 가지 클래스로 나뉜다. 첫 번째는 계좌 정보와 잔액을 관리하는 Account 클래스이고, 두 번째는 입금과 출금, 잔액 조회 같은 비즈니스 로직을 담당하는 BankService 클래스, 세 번째는 사용자 입력을 받고 결과를 화면에 출력하는 Main 클래스다. 이 구조가 익숙해지면 나중에 웹 애플리케이션이나 모바일 앱을 만들 때도 동일한 패턴을 적용할 수 있다.
Account 클래스부터 살펴보자. 이 클래스는 계좌 번호, 소유자 이름, 잔액, 거래 내역 목록을 필드로 가진다. 여기서 주의할 점은 필드를 private으로 선언하고 getter와 setter만 제공하는 캡슐화 원칙을 지키는 것이다. 초보자들은 필드를 public으로 열어두고 어디서든 직접 접근하는 실수를 자주 한다. 예를 들어 account.balance = account.balance – 1000; 이런 식으로 직접 잔액을 수정하면, 출금 가능 금액 검증 같은 중요한 규칙을 어기기 쉽다. balance 필드는 private으로 감추고 출금 메서드를 통해서만 변경할 수 있게 설계해야 안전하다.
거래 내역은 어떻게 저장할까. 자바에서 자주 쓰는 자료구조 활용법 중에서 가장 기본이 되는 ArrayList를 사용하면 된다. List
BankService 클래스는 입금과 출금의 비즈니스 규칙을 담당한다. deposit 메서드는 입금 금액이 0보다 큰지 확인한 후 Account의 잔액을 증가시키고 거래 내역을 추가한다. withdraw 메서드는 출금 금액이 잔액보다 크지 않은지 확인하고, 조건을 통과하면 잔액을 차감한다. 여기서 핵심은 예외 처리를 함께 구현하는 것이다. 잔액 부족 상황이나 잘못된 금액 입력에 대해 단순히 return으로 처리하면 호출하는 쪽에서 실패 사유를 알 수 없다. 자바 예외 처리와 디버깅 팁을 적용해, IllegalArgumentException이나 InsufficientBalanceException 같은 사용자 정의 예외를 던지는 방식이 훨씬 견고하다. 이렇게 하면 main 메서드나 상위 호출부에서 catch 블록을 통해 실패 이유를 구체적으로 출력할 수 있다.
이제 메서드 분리의 실제 흐름을 보여주는 핵심 부분으로 넘어간다. main 메서드는 단순한 실행 진입점 역할만 해야 한다. 프로그램 실행, 메뉴 표시, 사용자 선택 처리, 각 기능 호출이라는 네 가지 책임만 가진다. 실제 비즈니스 로직은 BankService에 있고, 데이터 저장은 Account에 있으므로 main에서는 이 객체들을 조립하고 흐름을 제어하는 데 집중한다. 예를 들어 사용자가 숫자 1을 입력하면 입금 메뉴로 진입하고, 금액을 입력받아 BankService의 deposit 메서드를 호출한 뒤 결과를 출력한다. 이 구조에서는 각 메서드의 길이가 짧고 역할이 명확해져서, 문제가 발생했을 때 해당 클래스만 살펴보면 원인을 빠르게 찾을 수 있다.
초보자들이 메서드 분리에서 놓치는 또 다른 지점은 입력 검증과 화면 출력의 분리다. Scanner로 입력받은 값을 금액으로 변환할 때, 숫자가 아닌 값이 들어오면 NumberFormatException이 발생한다. 이 예외를 main에서 처리하거나, 더 좋게는 별도의 InputValidator 같은 클래스나 메서드로 분리해 처리하는 것이 바람직하다. 검증 로직과 출력 로직이 뒤섞이면 코드를 읽기가 어려워지고, 나중에 기능을 추가할 때마다 기존 코드를 수정해야 하는 부담이 생긴다. 실행 흐름과 검증, 데이터 처리, 화면 표현이라는 네 가지 관심사를 분리하는 것이 프로젝트의 완성도를 결정한다.
이 프로젝트를 진행하면서 콘솔 화면에 메뉴를 표시할 때는 switch문이나 enum을 사용해 메뉴 항목을 관리한다. 숫자 1에서 5까지의 메뉴 중에서 잘못된 입력이 들어오면 다시 입력을 받도록 while 루프로 감싸는 것도 중요한 포인트다. 또한 무한 루프에 빠지지 않도록 프로그램 종료 메뉴(일반적으로 숫자 0 또는 5)를 반드시 포함해야 한다. 이렇게 작은 디테일을 하나하나 신경 쓰는 과정이 곧 자바 프로그래밍 학습에서 가장 가치 있는 경험이 된다.
이 프로젝트가 끝나고 나면 한 단계 더 나아가 파일 저장 기능을 추가해볼 수 있다. 현재 프로그램은 메모리에서만 동작하므로 프로그램을 종료하면 모든 데이터가 사라진다. FileOutputStream이나 BufferedWriter를 사용해 거래 내역을 텍스트 파일로 저장하고, 프로그램 시작 시 파일에서 읽어와 복원하는 기능을 추가하면 실용성이 크게 높아진다. 이 과정에서 자바의 입출력 스트림과 예외 처리에 대한 이해가 자연스럽게 깊어진다. 파일 경로를 하드코딩하지 않고 설정 변수로 분리하는 습관을 들이면 나중에 데이터베이스 연결로 전환할 때도 같은 구조를 유지할 수 있다.
정리하자면, 은행 입출금 관리 프로그램은 자바 기초 문법과 객체지향 개념을 동시에 익힐 수 있는 최적의 연습 소재다. 클래스의 책임 분리, 캡슐화, 예외 처리, 자료구조 활용, 메서드 분리라는 다섯 가지 핵심 역량을 모두 이 작은 프로젝트 안에서 경험할 수 있다. 처음부터 완벽한 설계를 하려고 부담을 가질 필요 없다. 일단 아무렇게나 동작하는 코드를 만든 다음, 리팩토링을 통해 점진적으로 구조를 개선해가면 된다. 자바 프로그래밍 학습에서 중요한 것은 실행 결과물이 아니라 결과물에 도달하기까지의 설계 과정과 그 과정에서 발생하는 수많은 시행착오다. 이 글에서 제시한 흐름대로 프로젝트를 진행하다 보면, 어느 순간 자연스럽게 객체지향의 사고방식이 몸에 배어 있는 자신을 발견하게 될 것이다. 비용이 들지 않는 것이 이 학습 방법의 가장 큰 장점이니, 오늘 바로 프로젝트 폴더를 만들고 시작해보기를 권한다.