DB&JDBC(07-1) - 미니프로젝트 - 수업 29,30일차
이전 복습 키워드
stack | heap | start() | run() | Thread | Synchronized | DBMS | SQL | Middleware | jdbc | DML | CRUD | DDL | DCL | Transaction | con.setAutoCommit() | rollback() | throw |
첫 날 오후 수업에 설계부터 시작해서 총 삼일에 걸쳐 미니 프로그램을 진행했습니다.
DB와 JDBC를 배우며 크게 복잡하지 않은 기능들을 구현했지만, 수업을 처음 시작했을 때를 생각해보면 감회가 새로운 것 같습니다.
동료 수강생분들 중에는 전공자분들도 계시고, 코딩을 완전히 처음 접해보신 분들도 계십니다. 물론 코딩이 이미 익숙한 분들에게는 지금의 프로그램에 별다른 감흥이 없으실 수도 있겠지만, 저로서는 수업을 시작한 지 한달이 조금 넘은 이 시점에 이런 프로그램을 만들었다는 것에 기쁨과 성취감을 느끼며, 새로운 자극이 되는 것 같습니다.
목차
미니 프로젝트(은행 계좌 프로젝트)
프로그램을 만들기 전에 먼저 요구사항을 분석, 설계한 뒤 프로그램을 구현하도록 하겠습니다.
요구사항분석
저희가 만들 프로그램의 명칭은 계좌관리 프로그램입니다.
요구 사항을 살펴보면 아래와 같습니다.
- 사용자는 계좌 개설이 가능하다.
- 계좌 개설 시 계좌번호, 계좌주명, 비밀번호, 잔액정보가 저장되어야 한다.
- 최초 계좌 개설 시 초기 납입액이 1000원 이상이 되어야한다
- 계좌번호는 유일해야하고 시스템에서 자동 발급하다
- 잔액조회는 계좌번호가 존재해야하고 계좌번호에 맞는 비밀번호가 일치해야 한다
- 입금액, 출금액, 계좌이체액은 모두 0원을 초과해야한다
- 입금 시 계좌번호, 비밀번호가 일치해야 한다
- 출금 시 계좌번호, 비밀번호가 일치해야하며 잔액 확인 절차가 필요하다(잔액이 부족하면 안되에)
- 계좌이체 시 송금자 및 수금자의 계좌가 존재해야하고 이체액은 0원을 초과해야하며
송금자의 비밀번호 또한 일치해야하고 송금자의 잔액 확인 절차가 필요하다
- 송금 및 입금 처리가 정상적으로 수행될 경우에만 이체 처리가 되도록 한다
- 계좌 잔액이 가장 높은 계좌주명과 잔액을 조회할 수 있다
얼핏 보기에 복잡해 보이는 조건들도 있고, 보자마자 어떤 키워드가 생각나는 조건들도 있으실 겁니다. 저희가 만들어야할 기능들을 추려보자면 아래와 같습니다.
- 주요 업무:
- 계좌 개설
- 잔액 조회
- 입금
- 출금
- 계좌 이체
- 보유잔액 가장 높은 계좌 정보 조회(서브쿼리 연습)
설계
수업 중에는 제공된 요구사항을 토대로 조별 토의를 진행하였으며 주요 기능을 간략하게 도출해내고, 이를 토대로 starUML 프로그램을 사용해서 Class Diagram으로 설계했습니다.
한 번에 완성시키지 않고, 단계별로 진행 상황에 맞게 수정하면서 진행했습니다.
첫 번째 단계입니다.
DB에 입력할 데이터(테이블)는 bank-project.sql
파일에 작성할텐데 현재 다이어그램 상에는 나타나지 않습니다.
테이블에서 사용되는 컬럼값에 매칭되는 변수들을 AccountVO
클래스에 작성했습니다.
accountNo
가 계좌번호이자 SQL에서는 pk값이며 계좌주명은 name
, 비밀번호는 password
, 잔액은 balance
로 이름지었습니다.
AccountDAO
가 기능을 담는 클래스인데, 현재 시점에서는 계좌개설, 잔액조회 기능과 입금 기능은 메서드명만 구성해 놓았습니다. 추후 프로그램을 만들면서 차근차근 설계를 완성할 예정입니다.
그리고 단위테스트를 진행하기 위해 TestUnit1
, TestUnit2
파일이 있는데, 이 역시 기능마다 단위테스트를 진행해야하기 때문에 추가 작성이 필요한 부분이고 아래 세 개의 Exception은 현재 시점에 떠올릴 수 있는 예외 상황 처리를 위한 Exception 클래스들을 미리 설정했습니다.
기능구현
본격적으로 기능을 구현해보도록 하겠습니다.
바로 자바 프로그램을 작성하기 전에 먼저 SQL 파일을 생성해서 테이블을 작성하고 시퀀스를 만들어줘야 자바에서도 DB와 연결해서 사용할 수 있겠죠?
1
2
3
4
5
6
7
create table account(
account_no number primary key,
name varchar2(100) not null,
password varchar2(100) not null,
balance number not null
)
create sequence account_seq;
계좌 번호를 pk로 설정해주고 시퀀스를 바로 만들어주면 기본 생성은 마쳤습니다.
자바 프로그램 작성에 앞서 단위테스트 또한 진행해야 하니 계좌 생성 부분만 확인해보고 넘어가도록 하겠습니다.
1
insert into account(account_no,name,password,balance) values(account_seq.nextval,'아이유','1234',1000);
시퀀스 부분에 유의해서 작성합니다.
1. 계좌 개설
이제 자바로 넘어오겠습니다.
메서드 작성 전에 우선 기본적으로 생성해야할 파일들을 만들도록 하겠습니다.
class diagram에서 보셨다시피 메인 클래스 파일은 test파일에서 단위테스트를 진행하고, AccountVO
와 AccountDAO
를 만들어야 합니다.
그리고 DB와의 연결을 위한 정보를 인터페이스로 만들어서 DbInfo
에 저장하도록 하겠습니다.
첫번째로 TestUnit1
에서 계좌 개설 기능을 테스트하겠습니다.
계좌를 개설할 때 고려해야 할 사항은 세 가지입니다.
- 계좌번호, 계좌주명, 비밀번호, 잔액정보가 저장되어야 합니다.
- 최초 계좌 개설 시 초기 납입액이 1000원 이상이어야 합니다.
- 계좌번호는 유일해야하고 시스템에서 자동 발급합니다.
위 사항들을 모두 만족할 수 있도록 입력값을 다르게 하여 TestUnit1
에서 테스트를 진행합니다.
우선 AccountVO
에서는 기존에 해왔던 것처럼 인스턴스 변수를 만들고 생성자와 게터, 세터, toString()을 생성합니다.
추가적으로 생성자를 만들 때 필요에 맞게 기본생성자와 accountNo
를 제외한 세 개의 매개변수를 갖는 생성자를 만들어두면 나중에 다양한 메서드에서 필요에 맞게 호출할 수 있습니다.
(종종 기본 생성자도 생성하곤 하는데 빈 객체를 생성함으로써 get, set을 이용해 자유롭게 값을 할당해주기 위함입니다. 주로 1개의 값을 필요로 할 때 많이 사용합니다.)
AccountVO 전체 코드
AccountDAO
에서 기능을 구현해보겠습니다.
전에 예제를 진행했던 것처럼 우선 Driver loading
을 한 뒤 closeAll()
메서드를 여러 번 사용하기에 미리 만들어줍니다.
그리고나서 저희가 목표로 하는 기능을 구현하도록 합니다.
sql문을 먼저 작성해서 테스트한 뒤 메서드를 작성하게 되는데, 계좌 개설에 예외 상황이 있기 때문에 우선 처리해주도록 합니다.
왜냐하면 계좌 개설 시 초기 납입금이 1000원이 안될 경우 더 이상의 진행이 필요가 없기 때문에 먼저 처리를 해주도록 합니다.
그래서 저희가 직접 Exception
을 extends
하는 Exception class를 만들어서 저희가 지정하는 메세지를 반환하도록 만들어줍니다.
이를 활용해서 계좌정보에서 balance
가 1000보다 작을 경우 Exception
을 throw
하게 해줍니다.
예외 상황이 처리가 되었다면 그 뒤로는 먼저 테스트해본 sql문에 맞게 코드를 작성해주시면 됩니다.
계좌 개설은 반환값이 필요치 않기에 ResultSet
을 사용하지 않고, sql문의 치환문자의 순서에 유의하여 진행해주시면 됩니다.
2. 잔액 조회
두번째 기능인 계좌 조회 메서드를 만들어보겠습니다.
이번에도 조건을 다시 한 번 살펴보겠습니다.
- 계좌번호가 존재해야 합니다
- 계좌번호에 해당하는 비밀번호가 정확해야 합니다
위 두 가지 예외 상황을 확인하기 위해 테스트 클래스에서 아래와 같이 진행합니다.
- 존재하지 않는 계좌번호 입력
- 잘못된 비번입력
이렇게 잘못된 입력 시 예외가 올바르게 처리되어야 저희가 목표로 하는 기능을 온전히 구현할 수 있습니다.
이제 SQL문 테스트를 해보고 기능 구현에 들어갈텐데, 저는 처음에 위 조건을 보고 balance
(잔액)를 조회하되 계좌번호와 비밀번호가 특정한 조건을 생각하고 풀이를 진행해서 어려움을 겪었던 것 같습니다.
SELECT balance FROM account WHERE accountNo=? AND password=?;
이렇게 생각을 했습니다.
if(rs.next)
구문에서 계좌번호나 비밀번호가 불일치하다면 exception을 발생시킬 생각이었는데, 제대로 적용이 되지 않았고, 그 다음으로는 list에 값들을 집어넣어서 내용 일치를 확인할 생각이었는데 이 역시 상당히 번거롭고 iterator를 사용해서 contains 기능을 활용하려 했지만 컴파일 에러가 발생했습니다.
어디서 잘못되었을까 고민을 하던 찰나에 강사님께서 힌트를 제공해주셨는데(사실상 정답을 알려주신 것과 다름 없던 것 같습니다) SQL문에서 password와 balance를 조회하고 계좌번호를 조건문으로 사용하면 된다고 하셔서 아차 싶은 생각에 작성해보니 정상적으로 작동을 하는 것을 확인했습니다.
8번 라인을 보시면 sql문을 확인하실 수 있는데 balance
만을 조회하는 것이 아니라 저희가 할당한 account_no
와 일치하는 password
와 balance
를 같이 조회하는 것이 관건이었습니다.
이렇게 함으로써 12번 라인~ 20번 라인까지의 코드를 구성할 수 있게 됩니다.
해당 결과가 반환된다면 계좌번호가 존재한다는 의미이고, 여기서 다시 password
의 일치 여부를 판단해서 일치하지 않을 경우 exception
을 throw
해주고 일치한다면 balance
를 반환하도록 합니다.
계좌번호가 존재하지 않는다면 그에 맞게 exception
을 throw
해주면 됩니다.
이번 글에서는 두번째 기능까지만 구현해보도록 하고 다음 글에서 남은 기능들을 구현해보고 class diagram도 업데이트 해보도록 하겠습니다.
댓글남기기