
만약 서비스 계층이 JDBCRepository 구현체에 의존하고 있는 상황에서, 향후 JPA와 같은 다른 데이터 접근 기술로 변경하면 서비스 계층의 트랜잭션 관련 코드도 모두 변경해주어야 합니다.JDBC 트랜잭션 의존JDBC -> JPA로 변경이 문제를 해결하기 위해서는 트랜잭션 기능을 추상화하면 됩니다. 단순하게 생각해보면 아래와 같이 인터페이스를 만들어서 사용하면 될 것 입니다.public interface TxManager { begin(); commit(); rollback();}트랜잭션 추상화와 의존관계서비스는 특정 트랜잭션 기술에 직접 의존하는 것이 아니라, TxManager라는 추상화된 인터페이스에 의존하고 있습니다. 이제 원하는 구현체를 DI를 통해서 주입받기만 하면 되는데..

데이터베이스 연결 구조사용자는 웹 애플리케이션 서버(WAS)나 DB 접근 툴 같은 클라이언트를 사용해서 데이터베이스 서버에 접근할 수 있다. 클라이언트는 데이터베이스 서버에 연결을 요청하고 커넥션을 맺게 되는데, 이때 데이터베이스 서버는 내부에 세션이라는 것을 만든다. 이후 커넥션을 통한 모든 요청은 이 세션을 통해 실행된다.개발자가 클라이언트를 통해 SQL을 전달하면 현재 커넥션에 연결된 세선이 SQL을 실행한다. 세션은 트랜잭션을 시작하고, 커밋 또는 롤백을 통해 트랜잭션을 종료한다. 사용자가 커넥션을 닫거나, 세션을 강제로 종료하면 세션이 종료된다.커넥션 풀이 10개의 커넥션을 생성하면, 세션도 10개가 만들어진다.트랜잭션 개념 이해하기아래 예제(격리 수준: READ_COMMITED)는 트랜잭션 개..

트랜잭션에 관한 내용은 여기에서 확인하실 수 있습니다. 잠금은 여러 커넥션에서 동시에 동일한 자원(레코드나 테이블)을 요청할 경우 순서대로 한 시점에는 하나의 데이터만 변경할 수 있게 해주는 역할을 한다. MySQL 엔진의 잠금 MySQL에서 사용되는 잠금은 크게 스토리지 엔진 레벨과 MySQL 엔진 레벨로 나눌 수 있다. MySQL 엔진은 MySQL 서버에서 스토리지 엔진을 제외한 나머지 부분으로 이해하면 되는데, MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미치지만, 스토리지 엔진 레벨의 잠금은 스토리지 엔진 간 상호 영향을 미치지는 않는다. MySQL 엔진에서는 테이블 데이터 동기화를 위한 테이블 락 이외에도 테이블의 구조를 잠그는 메타데이터 락(Metadata Lock), 사용자의 ..

트랜잭션은 작업의 안정성을 보장해주는 것이다. 즉, 논리적인 작업 셋을 모두 완벽하게 처리하거나, 처리하지 못할 경우에는 원 상태로 복구해서 작업의 일부만 적용되는 현상(Partial update)이 발생하지 않게 만들어주는 기능이다. 잠금(Lock)과 트랜잭션은 서로 비슷한 개념 같지만 사실 잠금은 동시성을 제어하기 위한 기능이고, 트랜잭션은 데이터의 정합성을 보장하기 위한 기능이다. 하나의 회원 정보 레코드를 여러 커넥션에서 동시에 변경하려고 하는데 만약 잠금이 없다면 하나의 데이터를 여러 커넥션에서 동시에 변경할 수 있게 되고, 결국 해당 레코드의 값은 예측할 수 없는 상태가 된다. 트랜잭션 지금은 많이 달라졌지만 여전히 MySQL 서버에서는 MyISAM이나 MEMORY 스토리지 엔진이 더 빠르다고..

이번에는 REQUIRES_NEW를 사용해서 문제 상황을 가정하고 해결해보도록 하자. 문제 상황 회원가입에 성공하면 회원 DB와 회원 이력 로그 DB에 저장하는 비지니스 로직을 수행해야 한다. 회원가입과 이력 로그를 저장하는 로직을 하나의 트랜잭션으로 묶어서 처리하던 중, 만약 이력 로그 저장에서 문제가 발생하면 회원가입 자체가 안 되는 상황이 발생한다. 실제 비지니스에서 이런 상황이 발생하면 많은 회원들이 이탈하는 문제가 발생할 것이기 때문에 요구 사항이 변경 되었다. "회원 가입을 시도한 로그를 남기는데 실패하더라도 회원 가입은 유지되게 해주세요." 단순하게 생각해보면 LogRepository에서 예외가 발생하면 그것을 MemberService에서 예외를 잡아서 처리하면 될 것 같다. 이렇게 하면 Me..

REQUIRES_NEW는 외부 트랜잭션과 내부 트랜잭션을 완전히 분리해서 각각 별도의 물리 트랜잭션을 사용하는 방법이다. 그렇기 때문에 커밋과 롤백도 각각 별도로 이루어지게 된다. 이 방법은 각각 독립된 트랜잭션이기 때문에, 내부 트랜잭션에 문제가 발생해서 롤백 되더라도 기본 설정인 REQUIRED처럼 외부 트랜잭션에는 영향을 주지 않는다. 반대로 외부 트랜잭션에 문제가 발생해도 내부 트랜잭션에 영향을 주진 않는다. 아래 예제를 보면서 작동 원리를 이해해보자! Test Code @Test void inner_rollback_required_new() { log.info("외부 트랜잭션 시작"); TransactionStatus outer = txManager.getTransaction(new Defaul..

@Transactional을 적용하면 프록시 객체가 요청을 먼저 받아서 트랜잭션을 처리하고, 실제 객체를 호출해준다. 때문에 트랜잭션을 적용하려면 항상 프록시를 통해서 대상 객체(Target)을 호출해야 한다. 이렇게 해야 프록시에서 먼저 트랜잭션을 적용하고, 이후에 대상 객체를 호출하게 된다. 만약 프록시를 거치지 않고 대상 객체를 직접 호출하게 되면 AOP가 적용되지 않고, 트랜잭션도 적용되지 않는다. AOP를 적용하면 스프링은 대상 객체 대신에 프록시를 스프링 빈으로 등록한다. 따라서 스프링은 의존관계 주입시에 항상 실제 객체 대신에 프록시 객체를 주입한다. 프록시 객체가 주입되기 때문에 대상 객체를 직접 호출하는 문제는 일반적으로 발생하지 않지만, 대상 객체의 내부에서 자신의 다른 메서드 호출이 ..
트랜잭션 트랜잭션은 ACID라 하는 원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 지속성(Durability)을 보장해야 한다. 원자성 : 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공 하거나 모두 실패해야 한다. 일관성 : 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다. 예를 들어 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다. 격리성 : 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. 예를 들어 동시에 같은 데이터를 수정하지 못하도록 해야 한다. 격리성은 동시성과 관련된 성능 이슈로 인해 트랜잭션 격리 수준(Isolation level) 을 선택할 수 있다. 지속성 : 트랜잭션을 성공..
- Total
- Today
- Yesterday
- kotlin
- Spring
- 스프링 부트
- mysql 8.0
- 노마드
- 스프링부트
- leetcode
- 백준
- webflux
- spring boot
- 스프링
- 파이썬
- 리팩토링
- 김영한
- 알고리즘
- 데이터베이스
- 문자열
- 코틀린
- MySQL
- 자료구조
- 인프런
- 정렬
- 코테
- 릿코드
- Real MySQL
- Algorithm
- 그리디
- 구현
- 노마드코더
- 북클럽
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |