Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- JPA
- JDBC
- 사면초가
- index
- 공통규약
- 클린아키텍처
- AOP
- 냄새라도
- DDD
- TDD
- Transaction
- MVC
- 설정세팅
- 로그백
- SEQUENCE
- springsecurity
- 전전긍긍
- MVC요청플로우
- OOP
- 이벤트핸들러등록
- 이벤트핸들러this
- 단위테스트
- string
- 커뮤니티서버
- 문제선택근거
- model
- SpringLegacy
- Ajax
- 공통기술
- 디스크i/o
Archives
- Today
- Total
개발이군고구마
DB connection 변화의 역사 본문
728x90
1. 이유와 목적
- 고민없이 SQL을 작성하고, 의례 요청이 오면 그에 맞는 비즈니스 로직을 거쳐 DB 서버에 접속해 내용을 반환하겠거니 생각하며 코드를 작성하고 있다.
- 한 요청 별로 다양한 SQL 문이 실행될텐데
-> 예를 들면 로그인을 한다고 가정하면, 회원 테이블에 정보를 입력되고
-> 인증 테이블에도 정보가 입력이 되고
-> 이력 테이블에 내용이 입력되거나 업데이트 되는 등
- 이렇게나 많은 요청이 어떻게 DB 서버와 연결되는 것이며
- (계속해서 연결하면 자원이 심하게 쓰일텐데, 속도는?)
- 만약 비즈니스 상황에 어떤 오류가 생길 때는 요청에 어느 부분까지가 데이터에 완전 반영되는 것이며,
- (중간에 취소가 되면 어떤 정보는 반영이 안되어서, 정보의 불일치가 나타날 수도 있지 않을까?)
- 만약 이를 방지하기 위해서 어느 부분에 방지 코드를 넣어주어야 하는지에 대한 궁금함을 해결해보고 싶었다.
- (ORM 부분에서 처리해주는 것이 있을까? 이것도 코드의 중복을 야기시키지 않을까? 간단하게 처리하는 방법은?)
2. DB connection의 발전 양상
[간단한 요약]
라이브러리 읽음 > DB manager - url, password> DB driver > DB 서버 > 비즈니스 로직
비즈니스 로직> get connection - repository 주입> DB driver > DB 서버 > 비즈니스 로직 > repository
=> 여전히 비즈니스가 datasource와 연결
비즈니스 로직> (datasource 인터페이스) - repository 주입> Hikaripool > DB driver > DB 서버 > repository
트랜잭션 추상화
호출 > “트랜잭션 동기화 매니저 -커넥션 보관” > (transactionmanager 인터페이스) > (datasource 인터페이스) - repository 주입 **> Hikaripool > DB driver > DB 서버 > 비즈니스 로직 > repository
호출 > 프록시 (“트랜잭션 동기화 매니저 -커넥션 보관” > (transactionmanager 인터페이스) > (datasource 인터페이스) - repository 주입 **> Hikaripool > DB driver > DB 서버) > 비즈니스 로직 > repository
1) JDBC
- 자바에서 데이터베이스에 접속할 수 있도록 도와주는 자바 API
- 종류가 다른 서버의 드라이브들이 상속받아 사용함 => 변경할 부분이 줄어듦
SQL Mapper(SQL전달) / JPA Hibernate(객체전달) 를 통해서 JDBC와 연결하는 방식으로 쓰이고 있음- DB서버 커넥션을 얻는 방법
- 라이브러리에 DB서버를 등록함
- DriverManager (JDBC 제공) 가 설정에서 등록된 url, password 등의 정보를 가지고 드라이버 목록을 인식함
- 라이브러리에 등록된 Driver들이 connection 규격을 확인한 후 DB 에 접속해서 커넥션을 반환함

Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);

2) Connection Pool
[커넥션 발생 과정]
- DB driver와 DB 는 TCP/IP 커넥션을 하는데, 그때 id, password 등이 전달된다
- DB는 내부 인증이 완료되면, 내부에 DB 세션을 생성한 후 응답하고
- DB driver는 그 응답을 받아 커넥션 객체를 생성해 반환한다
- 새로 커넥션을 만드는 일은 복잡하고 시간이 많이 생성되는 일
- "커넥션을 한번에 생성해두고 사용하는 방법" 을 떠올림
- "어플리케이션을 시작" 하는 시점에 커넥션 풀에 필요한 세션 (보통 10개)를 확보해둠
- Driver가 이미 DB에서 커넥션을 확보해둔 상태
- 의존관계가 DriverManager 에서 Conenction Pool (HikariPool)로 변경됨

-> JDBC API 안에 DataSource와 Driver가 속해있음
-> DriverManager/Hikari가 구현하는 JDBC는 같음
-> JDBC 인터페이스는 많은 기능을 가지고 있다
💥 의문점
- 그렇다면 JPA 와 같은 ORM 기술을 사용할 땐 HikariPool 사용하지 않는 것?
- 여기엔 Datasource와 같은 것도 없을 텐데
https://jiwondev.tistory.com/291
JDBC Connection 에 대한 이해, HikariCP 설정 팁
JDBC가 무엇인지 아예 모른다면 [10분 테코톡] 코코닥의 JDBC 영상을 한번 보고 오시면 좋습니다. 🍀 데이터베이스의 시작은 결국 JDBC 더보기 JVM을 사용한다면 스프링이건 JPA를 쓰건 결국 마지막
jiwondev.tistory.com
3) DataSource
- DriverManager가 아니라 HikaripPool에서 connection을 얻고 싶은 경우에 관련 코드를 변경해야 하므로
- DataSource라는 인터페이스를 구현하고, 이를 구현하여 Connection을 연결하도록 함

DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
useDataSource(dataSource);
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaximumPoolSize(10);
dataSource.setPoolName("MyPool");
useDataSource(dataSource);


3. Transaction의 개념과 적용
[트랜잭션]
- 데이터베이스와 Connection을 요청하면 "세션"을 DB 내부에 만듦
- 한 세션 내에서 데이터가 변경되는 시점에는, 다른 세션에게는 변경사항이 조회되지 않아야함
- 요청과 데이터 변화가 완료되는 연산의 묶음(거래) 을 transaction이라고 함
- 먼저 트랜잭션이 시작된 세션이 Lock을 획득하게 되면서 다른 세션에서 데이터를 변경하지 못하도록 함
[트랜잭션의 위치]
- 만약, 로직에 문제가 있을시 한꺼번에 취소가 되어야하므로, "비즈니스" 로직이 있는 서비스 계층에 위치해야함
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
Connection con = dataSource.getConnection(); > 커넥션 필요
try {
con.setAutoCommit(false); //트랜잭션 시작
//비즈니스 로직
bizLogic(con, fromId, toId, money);
con.commit(); //성공시 커밋
} catch (Exception e) {
con.rollback(); //실패시 롤백 << exception 뱉으면 이쪽에서 rollback
throw new IllegalStateException(e);
} finally {
release(con);
}
}
private void validation(Member toMember) {
if (toMember.getMemberId().equals("ex")) {
throw new IllegalStateException("이체중 예외 발생"); ** 예외가 상위로 전파 **
}
}
[트랜잭션 추상화]
- 만약 JDBC 기술을 더이상 사용하지 않고, JPA 기술을 사용할 경우, 코드의 변경이 많아짐
- 이를 위해 트랜잭션 기능을 추상화하는 TransactionManager 사용

💥 의문점
- JPA 도 JDBC를 구현하여 쓰는 것으로 알고 있는데
- 여기서 JPA TransactionManager는 JDBC 구현하는 것과 별개의 일일까?
- JDBC를 구현한 JPA는 또 다른 transactionManager 를 필요로 하는 건가?
* JDBC의 단점을 개선하기 위해서 등장한 개념이 ORM
* ORM의 종류로는 JPA와 SQL Mapper가 있음
지금까지 계속해서 오류가 있었던 것 같다.
JDBC와 ORM은 엄연히 데이터를 엑세스 하는데 다른 기술이었다.
https://velog.io/@murphytklee/Spring-ORM-JPA-Hibernate-JDBC-%EC%B4%9D%EC%A0%95%EB%A6%AC
[@Transactional]
- 서비스 계층 (비즈니스 로직) 이전에 트랜잭션 커넥션을 얻어주는 중간 객체 프록시를 도입
- 서비스 코드에 트랜잭션 코드를 완전히 제거할 수 있음

@Transactional
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
bizLogic(fromId, toId, money);
}'SERVER > Spring' 카테고리의 다른 글
| [Spring : Design Pattern] 1. Template Method (Abstract Class) (0) | 2024.10.02 |
|---|---|
| Thread와 ThreadLocal (0) | 2024.10.02 |
| 데이터는 어떻게 주고 받을까? - 2. 데이터 매핑과 응답 (0) | 2024.09.15 |
| 데이터는 어떻게 주고 받을까? - 1. 데이터 전달하기 (0) | 2024.09.15 |
| Spring Security의 로직 (0) | 2024.08.16 |