오늘은 트랜젝션에 대해서 알아보고자 합니다. 

물론! 트랜젝션의 원론적인 개념과 여러 데이터베이스의 핵심 개념까지 모두 이해하는게 맞지만, 오늘은 찍먹해보는게 목표이기 때문에

이해하기 쉬운 수준에서 아 이 정도면 트랜젝션이란 단어가 들어간 문장을 이해할 수 있겠다! 정도로 정리해보도록 하겠습니다.

 

개발 유튜브나 컨퍼런스, 블로그등을 보면 언급되는 단어들 중 트랜젝션(Transaction) 이라는 단어를 제일 많이 듣는것 같습니다.

트랜젝션 안에서 처리해야한다, 트랜젝션이 끝나기 전에 ~~, 트랜젝션을 걸었나 말았나 등등.. 항상 들을때마다 궁금했습니다.

 

트랜젝션이 뭐지? 뭔가 데이터베이스에다가 데이터들을 저장.. 뭐 이런걸 하는거라고는 알겠는데.. 어떤 부분을 의미하는것인가!

항상 궁금했습니다, 그러다 열심히 김영한님의 강의들 듣던중 JPA 프로그래밍편에서 처음으로 트랜젝션에 대한 이해를 하게 되었습니다

 

이전에도 구글에 트랜젝션에 대해서 많이 검색해봤지만 대부분 ACID로 시작하는 설명글이 대부분이였습니다.

물론 트랜젝션의 특징인 ACID도 알아야 하지만 이제 트랜젝션을 이해하는 입문자들에겐 감을 잡는것이 중요한데 텍스트들이 이해를 방해할 것 같은 느낌이 들었습니다. 저 역시도 비슷한 케이스로 감을 못 잡았습니다. (물론 지식 습득 방법은 사람마다 다릅니다)

트랜젝션이란 무엇인가

정확한 개념을 알려주는 다른 블로그들과는 다르게 제가 이해했던 부분을 조금은 추상적으로 설명드리겠습니다.

트랜젝션이란 데이터베이스에 데이터를 추가, 수정, 삭제를 하는 하나의 큰 "작업 단위" 라고 생각합니다.

 

이해하기 쉽도록 그림과 코드로 보여드리겠습니다.

아직 트랜젝션을 모르고 계신분들은 지금까지 어플리케이션과 데이터베이스간의 관계를 딱 이 정도로 이해하고 계실거라고 생각합니다.

어플리케이션에서는 SQL을 날리고 데이터베이스는 그것을 받아서 저장하고 필요할때마다 조회해서 돌려준다고 말이죠.

 

하지만 저 화살표안에는 더 많고 작고 디테일한 작업단위들이 있습니다.

저 그림에 트랜젝션이라는 개념을 한번 대입시켜서 그려보겠습니다.

JDBC, Mybatis, JPA, TypeORM 등 어떤 기술 스택을 사용하는지에 따라 세부적인 모양은 모두 달라질 수 있습니다.

하지만 트랜젝션이라는 개념이 처음이고 감을 잡기 어려운 분들은 아~ 저 정도의 작업단위를 트랜젝션이라 부르는구나 라고 이해하시면 될것 같습니다. 저 부분들을 더 자세히 설명하려면 영속성 컨텍스트부터 시작해서 알아야할것이 많습니다. 전 JPA 기준으로 공부해서 다른 ORM들은 어떻게 동작하는지 모르기도 해서 잘못된 정보를 전달할 수도 있고 이번 주제는 찍먹이니 깊게 설명하지는 않겠습니다.

 

또한 항상 어플리케이션과 데이터베이스 사이에는 JDBC, JPA, Mybatis등의 데이터베이스 사용을 도와주는 친구들이 있는것을 까먹어선 안됩니다. 위 이미지를 봤을땐 1번에 처음 어플리케이션이 시작될때 데이터베이스를 찾아서 연결을 해놓고 7번까지는 JDBC와 상호작용을 하다가 커밋 요청이 들어오면 JDBC에서 상호작용하면서 가지고 있던 변경사항을을 데이터베이스에 반영하는 모습을 볼 수 있습니다.

 

저 그림상에서는 4번부터 7번까지가 트랜젝션이라고 볼 수 있습니다.

마지막아 커밋을 해서 변경사항들을 데이터베이스에 반영하게 된다면 하나의 트랜젝션 단위가 수행되었다고 볼 수 있습니다.

 

간혹 데이터베이스 커넥션을 가져오고 놓아주는 과정도 트랜젝션 안에 속한다고 생각하시는 분들이 계시는데 그것은 절대 아닙니다.

 

간단하게 코드를 한번 보겠습니다. 제일 기본이 되는 JDBC 형태의 코드를 가져왔습니다. ORM의 트랜젝션은 다른 글에서 다루겠습니다.

Connection conn = getConnection(); // 커넥션 가져오기

conn.setAutoCommit = false; // 자동 커밋 사용 안함 (기본값이 사용함)

PreparedStatement psmt = conn.prepareStatement("insert into member values (?)"); 
psmt.setInt(1, 1); // 요청에 따른 SQL 생성

psmt.executeUpdate(); // 데이터베이스에 회원 데이터를 삽입하는 쿼리를 실행

conn.commit(); //트랜젝션을 커밋하여 데이터베이스에 변경사항을 반영

conn.close(); // 커넥션 놓아주기

JDBC를 이용한 예제입니다. 위 그림과 맞게 같이 주석도 달아줬습니다.

평소에 보던 코드에는 setAutoCommit이 없고 conn.commit()도 없었을겁니다.

이 코드에 중점적으로 봐야할것은 setAutoCommmit과 conn.commit() 입니다.

 

원래 데이터베이스는 sql을 실행하더라도 commit을 해주지 않으면 데이터베이스에 변경사항이 반영되지 않았습니다.

하지만 요즘엔 AutoCommit, 즉 자동커밋 기능으로 인하여 SQL만 실행하게 되면 바로 변경사항이 같이 반영되는것이죠.

 

그래서 기본으로 설정되어 있는 setAutoCommit을 false로 바꿔줬습니다.

이렇게 되면 executeUpdate를 실행하여도 데이터베이스에는 변경사항이 반영되지 않습니다.

 

그렇기 때문에 마지막에 conn.commit()을 함으로써 데이터베이스에 최종적으로 변경사항들을 반영하는것 입니다.

그리고 try-catch문을 이용하여서 만약 commit이 실패하였을시 conn.rollback()등을 이용하여 실행된 sql을 롤백할 수도 있습니다.

위 다이어그램의 화살표를 자세히 따라가 보시면 활동을 시작으로 조금의 실패라도 있으면 무조건 취소로 빠지는것을 볼 수 있습니다.

한마디로 트랜젝션은 하나라도 무언가 실패된다면 아무것도 없던일처럼 작동하지 않는다고 볼 수 있습니다.

 

이러한 트랜젝션이라는 개념 덕분에 우리는 데이터베이스 성능을 튜닝 할 수 있고 여러가지 변수에 대처하는 코드들을 작성 할 수 있습니다.

그리고 데이터베이스와 직접적인 상호작용을 담당하는 작업단위이기 때문에 그만큼 중요하기도 하죠.

 

여러 부가적인 개념들이 항상 트랜젝션에 따라 붙지만 오늘은 찍먹!이기 때문에 이 정도만 하도록 하겠습니다.

관련하여 데이터베이스 성능 튜닝, 영속성 컨텍스트등의 내용은 다른 글에서 다루도록 하겠습니다!

반응형
복사했습니다!