[Spring Boot] Bank App (2) 모델링, DB 설계
모델링
모델링이란?
모델링은 현실 세계의 개념을 컴퓨터 시스템에서 표현하는 과정이에요.
중요한 정보를 정리하고, 관계를 정의하면서 데이터 구조와 알고리즘을 설계하는 작업이에요.
특히, 데이터베이스 모델링은 정보 시스템의 데이터 구조를 설계하는 데 초점이 맞춰져 있어요.
그런데 DB의 데이터 타입과 자바의 데이터 타입은 완전히 같지 않아요.
그래서 DB의 개념을 자바에서 활용할 수 있도록 변환하는 과정이 필요합니다.
ORM (Object-Relational Mapping)
ORM은 객체와 관계형 데이터베이스를 매핑하는 기술이에요.
쉽게 말하면, SQL을 직접 작성하지 않고도 객체의 속성과 메서드를 활용해 데이터를 조작할 수 있는 방법이에요.
ORM을 사용하면 좋은 점
✔ SQL을 직접 작성하지 않아도 돼서 코드가 간결해져요.
✔ 비즈니스 로직에 집중할 수 있어요.
✔ 데이터베이스 변경 시 유지보수가 쉬워요.
대표적인 ORM 기술
- Java → Hibernate, MyBatis
- Python → SQLAlchemy
- Ruby → ActiveRecord
TRM (Table-Relational Mapping)
TRM은 테이블 간의 관계를 매핑하는 과정이에요.
우리가 흔히 말하는 1:1, 1:N, N:M 같은 관계를 설계하는 것을 의미해요.
테이블 간 관계 예시
- 1:N 관계 → 한 명의 유저는 여러 개의 계좌를 가질 수 있음
- N:M 관계 → 한 계좌를 여러 명이 공유할 수도 있음
테이블 간의 관계를 잘 정리해야, 나중에 데이터를 다룰 때 훨씬 수월해져요.
데이터베이스 테이블 설계
-- 데이터베이스 생성
CREATE DATABASE mybank;
USE mybank;
-- 유저 테이블
CREATE TABLE user_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
fullname VARCHAR(50) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- 계좌 테이블
CREATE TABLE account_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
number VARCHAR(30) NOT NULL UNIQUE,
password VARCHAR(30) NOT NULL,
balance BIGINT NOT NULL COMMENT '계좌잔액',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
user_id INT
);
-- 거래 내역 테이블
CREATE TABLE history_tb (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '거래내역 ID',
amount BIGINT NOT NULL COMMENT '거래금액',
w_account_id INT COMMENT '출금 계좌 ID',
d_account_id INT COMMENT '입금 계좌 ID',
w_balance BIGINT COMMENT '출금 후 잔액',
d_balance BIGINT COMMENT '입금 후 잔액',
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
테이블을 자바 객체(Entity)로 변환
User.java (유저 모델)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String fullname;
private Timestamp createdAt;
}
Account.java (계좌 모델)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Account {
private Integer id;
private String number;
private String password;
private Long balance;
private Integer userId;
private Timestamp createdAt;
// 출금 기능
public void withdraw(Long amount) {
this.balance -= amount;
}
// 입금 기능
public void deposit(Long amount) {
this.balance += amount;
}
}
History.java (거래 내역 모델)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class History {
private Integer id;
private Long amount;
private Long wBalance;
private Long dBalance;
private Integer wAccountId;
private Integer dAccountId;
private Timestamp createdAt;
}
📌 DTO vs Entity 차이점
구분 | DTO (Data Transfer Object) | Entity (데이터 모델) |
목적 | 데이터를 주고받기 위한 용도 | DB 테이블과 직접 매핑 |
사용 위치 | 컨트롤러-서비스 간 데이터 전달 | DB와 직접 연결 |
로직 포함 여부 | ❌ 로직 없음 | ✅ 비즈니스 로직 포함 가능 |
변경 가능 여부 | 불변 (Immutable) | 상태 변경 가능 |
예시 | UserDto, AccountDto | User, Account |
✔ DTO → 데이터를 주고받을 때 사용 (ex. API 응답)
✔ Entity → DB 테이블과 연결되는 객체 (ex. Hibernate, MyBatis에서 사용)
웹 요청이 처리되는 흐름
1️⃣ 정적 파일 요청 흐름 (CSS, JS, 이미지 파일 요청)
[웹 브라우저] → [Spring Boot 내장 웹서버] → [정적 파일 응답]
브라우저가 index.html이나 style.css 요청하면, Spring Boot가 바로 파일을 찾아서 반환해요.
2️⃣ 동적 요청 흐름 (JSP, JSON, DB 요청 등)
[웹 브라우저] → [웹 서버] → [WAS] → [Spring 컨트롤러] → [서비스 로직] → [DB] → [응답]
요청 흐름 예시
- 사용자가 /account 요청
- 컨트롤러가 요청을 받음
- 서비스 계층에서 로직 실행
- DB에서 데이터 가져와 응답
- 요청이 들어오면, 컨트롤러 → 서비스 → 리포지토리 → DB 순으로 처리됨
📌 서블릿 컨테이너
서블릿 컨테이너는 개발자가 웹 서버와 통신하기 위해 소켓을 생성하고, 특정 포트에 리스닝하고, 스트림을 생성하는 등의 복잡한 작업을 하지 않아도 되도록 해주는 역할을 함.
서블릿 컨테이너의 역할
✔ 서블릿의 생성부터 소멸까지의 생명주기(life-cycle)를 관리
✔ 요청이 들어올 때마다 새로운 스레드를 생성하여 개별 요청을 처리
✔ JSP & 서블릿 실행 환경 제공
→ 서블릿 컨테이너는 클라이언트의 HTTP 요청을 받아들이고, 서블릿 및 JSP를 실행하는 환경을 제공하는 소프트웨어임.
✔ 모델링이란? 데이터를 체계적으로 정리하는 과정
✔ ORM vs TRM → ORM은 객체-테이블 매핑, TRM은 테이블 간 관계 매핑
✔ DB 테이블 설계 & 자바 모델 변환
✔ DTO와 Entity 차이점 정리
✔ 웹 요청 흐름 정리
✔ 서블릿 컨테이너의 역할