[Spring boot] Bank App - 계좌 목록 조회
- -
👨💻 지난 포스팅에서 계좌생성을 구현했습니다. 이어 이번 포스팅에서는 계좌 목록 조회 과정을 다뤄보겠습니다. 🚀
Spring Boot를 활용한 계좌 목록 조회 기능 구현 🚀
이번 글에서는 계좌 목록을 조회하는 기능을 단계별로 구현하겠습니다.
📌 학습 목표
- AccountRepository 및 account.xml을 수정하여 계좌 목록 조회 기능 추가
- AccountService 및 AccountController에서 계좌 목록 조회 기능 구현
- account/list.jsp를 생성하여 계좌 목록 화면 구성
1. AccountRepository 및 account.xml 코드 수정
✔ 기존 문제점 확인
<select id="findAllByUserId" resultType="com.tenco.bank.repository.model.Account">
select * from account_tb
</select>
위와 같은 쿼리는 모든 계좌를 조회하는 문제가 있습니다.
따라서 특정 사용자(userId)의 계좌만 조회하도록 수정해야 합니다.
✔ 수정된 account.xml 코드
<select id="findAllByUserId" resultType="com.tenco.bank.repository.model.Account">
select * from account_tb where user_id = #{userId}
</select>
✔ AccountRepository.java 코드 수정
package com.tenco.bank.repository.interfaces;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.tenco.bank.repository.model.Account;
@Mapper
public interface AccountRepository {
// 코드 확인 (계좌 생성)
public int insert(Account account);
public int updateById(Account account);
public int deleteById(Integer id);
// 계좌 조회 - 1 유저 , N 계좌
public List<Account> findAllByUserId();
public Account findByNumber(Integer id);
}
위 코드의 findAllByUserId()는 특정 사용자의 계좌만 조회하는 것이 아니라
모든 계좌를 조회하는 문제가 발생할 수 있습니다.
✔ 수정된 코드 (사용자 ID 기반 조회)
@Mapper
public interface AccountRepository {
// 계좌 조회 - 특정 사용자의 모든 계좌 조회
// @Param 어노테이션을 사용하여 XML과 변수명을 맞춰줌
public List<Account> findAllByUserId(@Param("userId") Integer principalId);
}
📌 변경 사항
- 특정 사용자(principalId)의 계좌만 조회하도록 SQL 쿼리 변경
- MyBatis의 @Param 어노테이션을 사용하여 XML과 일관된 변수명을 유지
- 여러 개의 파라미터가 필요할 경우 @Param을 반드시 사용해야 함
📌 데이터베이스의 N:M(다대다) 관계 해결 방법
우리 서비스에서는 모임 통장 개념을 사용하지 않으며,
한 명의 사용자는 여러 개의 계좌를 가질 수 있는 1:N(일대다) 관계로 모델링합니다.
하지만 만약 N:M(다대다) 관계가 필요한 경우에는 중간 테이블을 활용하여 두 개의 1:N 관계로 변환하는 것이 일반적입니다.
✔ N:M 관계의 예제
한 학생(Student)이 여러 개의 강좌(Course)를 수강할 수 있고,
한 강좌도 여러 명의 학생이 수강할 수 있다고 가정하겠습니다.
📌 잘못된 모델링 (N:M 관계)
CREATE TABLE 학생 (
학생ID INT PRIMARY KEY,
이름 VARCHAR(100)
);
CREATE TABLE 강좌 (
강좌ID INT PRIMARY KEY,
강좌명 VARCHAR(100)
);
이렇게 구성하면 어떤 학생이 어떤 강좌를 듣는지 직접적으로 표현할 수 없습니다.
✔ 해결 방법: 중간 테이블(연결 테이블) 활용
중간 테이블을 생성하여 두 개의 1:N 관계로 변환합니다.
이를 통해 다대다(N:M) 관계를 1:N + N:1 관계로 분리할 수 있습니다.
CREATE TABLE 학생 (
학생ID INT PRIMARY KEY,
이름 VARCHAR(100)
);
CREATE TABLE 강좌 (
강좌ID INT PRIMARY KEY,
강좌명 VARCHAR(100)
);
-- 학생과 강좌를 연결하는 중간 테이블 (수강 테이블)
CREATE TABLE 수강 (
학생ID INT,
강좌ID INT,
PRIMARY KEY (학생ID, 강좌ID),
FOREIGN KEY (학생ID) REFERENCES 학생(학생ID),
FOREIGN KEY (강좌ID) REFERENCES 강좌(강좌ID)
);
✔ 중간 테이블을 활용하는 이유
- 중복된 데이터를 방지할 수 있음
- 추가적인 속성(수강 날짜, 성적 등)을 저장할 수 있음
- 데이터베이스 정규화를 통해 관리가 용이함
2. 계좌 목록 기능 만들기
✔ 계좌 목록 조회 서비스 구현
/**
* 복잡한 Select 쿼리문일 경우 트랜잭션 처리를 해주 것이 좋습니다.
* 여기서는 단순한 Select 구문이라 바로 진행 합니다.
* @param principalId
* @return
*/
public List<Account> readAccountListByUserId(Integer principalId) {
List<Account> accountListEntity = null;
try {
accountListEntity = accountRepository.findAllByUserId(principalId);
} catch (DataAccessException e) {
throw new DataDeliveryException("잘못된 처리 입니다", HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
// 예외 처리 - 에러 페이지로 이동
throw new RedirectException("알 수 없는 오류", HttpStatus.SERVICE_UNAVAILABLE);
}
return accountListEntity;
}
✔ 핵심 포인트
- 특정 사용자의 계좌 목록을 데이터베이스에서 조회
- 트랜잭션 처리 불필요 (단순 SELECT 쿼리)
- 예외 처리 적용
- DataAccessException → 데이터베이스 관련 오류 발생 시 처리
- RedirectException → 알 수 없는 오류 발생 시 에러 페이지로 리디렉트
📌AccountController 코드 추가 (계좌 목록 페이지 요청 처리)
/**
* 계좌 목록 페이지
*
* @param model - accountList
* @return list.jsp
*/
@GetMapping({ "/list", "/" })
public String listPage(Model model) {
// 1.인증 검사가 필요(account 전체 필요)
User principal = (User) session.getAttribute("principal");
if (principal == null) {
throw new UnAuthorizedException("인증된 사용자가 아닙니다", HttpStatus.UNAUTHORIZED);
}
// 경우의 수 -> 유, 무
List<Account> accountList = accountService.readAccountListByUserId(principal.getId());
if (accountList.isEmpty()) {
model.addAttribute("accountList", null);
} else {
model.addAttribute("accountList", accountList);
}
return "account/list";
}
✔ 핵심 포인트
- 로그인한 사용자만 계좌 목록을 조회할 수 있도록 인증 검사 적용
- 계좌 목록 조회 후 Model 객체에 저장하여 JSP로 전달
- 사용자가 계좌를 가지고 있지 않을 경우 null로 설정하여 예외 방지
- 뷰 페이지(account/list.jsp)로 이동하여 결과를 출력
3. account/list.jsp 파일 생성 (계좌 목록 페이지 구성)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- header.jsp -->
<%@ include file="/WEB-INF/view/layout/header.jsp"%>
<!-- start of content.jsp(메인 영역) -->
<div class="col-sm-8">
<h2>계좌 목록(인증)</h2>
<h5>Bank App 오신 걸 환영합니다.</h5>
<c:choose>
<c:when test="${accountList != null }">
<table class="table">
<thead>
<tr>
<th>계좌 번호</th>
<th>잔액</th>
</tr>
</thead>
<tbody>
<c:forEach var="account" items="${accountList}">
<tr>
<td>${account.number}</td>
<td>${account.balance}</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:when>
<c:otherwise>
<div class="jumbotron display-4">
<h5><small>아직 생성된 계좌가 없습니다</small></h5>
</div>
</c:otherwise>
</c:choose>
</div>
</div>
</div>
<!-- end of content.jsp(메인 영역) -->
<!-- footer.jsp -->
<%@ include file="/WEB-INF/view/layout/footer.jsp"%>
✔ 핵심 포인트
- c:choose를 활용하여 계좌 목록이 있을 경우 테이블로 출력
- 계좌 목록이 없을 경우 "아직 생성된 계좌가 없습니다" 메시지 출력
- c:forEach를 활용하여 계좌 데이터를 반복 출력
📌 결과 화면
📌 계좌가 없을 경우 화면
📌 전체 요약
✅ 특정 사용자의 계좌 목록을 조회하도록 AccountRepository 수정
✅ AccountService에서 예외 처리를 포함한 계좌 목록 조회 로직 구현
✅ AccountController에서 로그인한 사용자만 계좌 목록을 볼 수 있도록 인증 적용
✅ JSP(account/list.jsp)에서 계좌 목록을 테이블로 출력 (없을 경우 안내 메시지 출력)
🎯 마무리
이제 /account/list 페이지에서 로그인한 사용자의 계좌 목록을 확인할 수 있습니다!
이러한 흐름을 이해하면 계좌 상세 조회, 계좌 이체, 출금 기능도 쉽게 확장할 수 있습니다.
🚀 다음 포스팅에서는 출금 기능에 대해서 적어볼게요! 🚀
계좌 생성이 궁금하다면??
[Spring boot] Bank App - 계좌 생성
👨💻 지난 포스팅에서 로그인, 로그아웃을 구현하였습니다. 이번 포스팅에서는 계좌 생성 과정을 다뤄보겠습니다. 🚀Spring Boot로 계좌 생성 기능 구현하기웹 애플리케이션에서 계좌 생성
seohong.tistory.com
'Spring' 카테고리의 다른 글
[Spring boot] 💸Bank App - 입금 기능 (1) | 2025.02.19 |
---|---|
[Spring boot] Bank App - 출금 (0) | 2025.02.18 |
[Spring boot] Bank App - 계좌 생성 (0) | 2025.02.17 |
[Spring boot] Bank App - 로그인 처리 (0) | 2025.02.17 |
Spring[Spring boot] Bank App - 회원가입(화면구현) (2) | 2025.02.15 |