영속성 컨텍스트는 왜 논리적인 개념인가?
blog.naver.com
필자의 블로그 [커리어리 글을 작성하는 것이 다소 익숙하지 않기에, 아래 블로그로 가면 가독성이 더욱 좋을 것 입니다.]
https://blog.naver.com/PostView.naver?blogId=gomets_journey&logNo=223272292286&parentCategoryNo=&categoryNo=26&viewDate=&isShowPopularPosts=false&from=postList
영속성 컨텍스트(Persistence Context)는 데이터베이스와 같은 영속 저장소에 객체를 저장하고 관리하는 데 사용되는 논리적인 개념이라고 한다. 이러한 개념을 이용하여 얻을 수 있는 이점은 다음과 같다.
1. 데이터 지속성 유지 : 영속성 컨텍스트는 데이터베이스와의 상호작용을 관리하여 객체의 상태를 데이터베이스에 영구적으로 저장하거나 수정할 수 있도록 지원한다. 이를 통해 애플리케이션에서 관리되는 객체들의 지속성을 보장한다.
2. 논리적인 단위 : 영속성 컨텍스트는 트랜잭션 단위로 객체를 관리한다. 이는 논리적인 단위로 작업을 처리하여 일관성을 유지하고, 트랜잭션의 커밋 또는 롤백에 따라 데이터베이스와의 상호작용을 조절한다.
3. 객체 관리 : 영속성 컨텍스트는 객체의 생명주기를 관리한다. 데이터베이스에서 가져온 객체를 추적하고, 변경 사항을 감지하여 적절한 시점에 데이터베이스에 반영한다.
4. 성능 향상 : 영속성 컨텍스트는 1차 캐시를 통해 데이터베이스 접근을 최적화하고, 필요한 경우 쓰기 지연 등의 방식으로 효율적인 데이터베이스 작업을 수행한다.
5. 객체지향적 관리 : 객체를 데이터베이스에 매핑할 때 발생하는 복잡성을 줄이고, 객체지향 프로그래밍의 개념을 유지하면서 데이터를 영속화할 수 있도록 지원한다.
이는 어떻게 보면 트랜잭션과 상당히 유사해 보인다. 우선 트랜잭션의 특징에 대해서 이야기해보려한다.
1. 원자성(Atomicity) : 트랜잭션의 모든 단계가 완전히 실행되거나 전혀 실행되지 않아야한다. 트랜잭션이 중간 단계에서 실패하면, 데이터베이스는 트랜잭션 이전의 상태로 롤백되어야 한다.
2. 일관성(Consistency) : 트랜잭션이 실행된 후에도 데이터베이스는 일관된 상태여야 한다. 즉, 트랜잭션이 데이터베이스의 일관성 규칙을 준수해야 한다.
3. 고립성(Isolation) : 여러 트랜잭션이 동시에 실행될 때 각각의 트랜잭션은 다른 트랜잭션의 영향을 받지 않아야 한다. 즉, 한 트랜잭션이 실행 중일 때 다른 트랜잭션에서의 변경이 그 트랜잭션에 영향을 미치지 않아야 함을 의미한다.
4. 지속성(Durability or Permanenty) : 성공적으로 완료된 트랜잭션의 결과는 영구적으로 반영되어야 한다. 즉, 시스템 장애 또는 전원이 꺼져도 트랜잭션의 결과는 보존되어야한다.
얼핏보면 트랜잭션과 영속성 컨텍스트는 상당히 밀접한 관련을 갖고 있으면서도 유사해 보일 수 있다. 즉 서로의 차이가 무엇인지 인지하지 못할 수가 있다. 우선 둘의 차이를 구분하는 것에서 시작해보려고 한다.
트랜잭션은 데이터베이스에서의 작업 단위를 나타내는 개념으로 ACID 속성을 가지고 있다. 반면에 영속성 컨텍스트는 객체 관리를 위한 개념으로, 객체와 데이터베이스 간의 매핑, 관리, 상태 유지를 담당한다. 즉, 트랜잭션은 데이터베이스와의 직접적인 처리에 중점을 두고있고, 영속성 컨텍스트는 객체 관리 및 상태 변화를 추상화하는 것에 중점을 두고 있다는 것이다. (지속적으로 객체라는 얘기가 나와 추후 객체에 대해서 정리를 해보려고 한다.)
그렇다면 이제 드는 의문이다. 영속성 컨텍스트는 '논리적', '1차 캐시' 두 단어를 강조하는 것으로 보인다. 과연 어떠한 이유로 영속성 컨텍스트는 논리적인 개념이라 하는지, 1차 캐시는 왜 언급이 되는지에 대해서 이야기해보고자 한다.
우선 논리적인 개념에 대해서 얘기를 해보고자 한다.
영속성 컨텍스트의 1차 캐시는 데이터베이스에서 가져온 엔티티(Entity) 객체들을 저장하는 곳으로, 메모리 상에 위치하는 일종의 캐시이다. 이 캐시는 영속성 컨테스트가 관리하는 객체들을 저장하며, 애플리케이션이 실행되는 동안에만 유효하다. 즉 휘발성이라는 것이다. 이로써 우리는 이 1차 캐시가 RAM이라는 것을 알게 되었다.
1차 캐시의 동작은 다음과 같다.
1. 엔티티 매핑 : 영속성 컨텍스트는 데이터베이스 테이블과 매핑된 엔티티 클래스의 객체를 저장한다. 이때, 데이터베이스에서 읽어온 엔티티 객체들은 1차 캐시에 저장된다.
2. 엔티티 캐시 : 영속성 컨텍스트는 내부에 있는 캐시이기 때문에, 애플리케이션 실행 중에만 유지된다. 데이터베이스에서 엔티티를 조회하거나 변경하면, 그 결과는 1차 캐시에 저장된다.
3. 지연 로딩(Lazy Loading) 및 변경 감지(Dirty Checking) : 영속성 컨텍스트의 1차 캐시는 지연 로딩과 변경 감지를 가능하게 한다. 이는 필요할 때 엔티티를 가져오거나 변경 사항을 감지하여 데이터베이스에 동기화한다.
4. 컨텍스트 내 고유성 보장 : 같은 엔티티 식별자(ID)를 가진 객체가 영속성 컨텍스트 내에 있으면, 그 객체는 고유한 것으로 취급된다. 따라서 동일한 엔티티를 반복적으로 데이터베이스에서 조회해야 할 경우, 1차 캐시에서 빠르게 찾을 수 있다. 우리는 "1차 캐시에서 빠르게 찾을 수 있다." 이 부분을 통해서 다시 한 번 캐시의 특징을 상기할 수 있었다.
또한 "변경 감지(Dirty Checking)"의 작동 원리에 대해서 생각한다면 SNAPSHOT에 대해서 알 수 있게 된다.
SNAPSHOT은 데이터베이스에서 사용되는 트랜잭션 격리 수준(Isolation Level) 중 하나이다. 트랜잭션 격리 수준은 여러 트랜잭션이 동시에 실행될 때 데이터의 일관성을 유지하기 위한 방법을 정의한다.
SNAPSHOT 격리 수준은 다른 트랜잭션에서 변경 중인 데이터에 대한 읽기를 허용하지만, 트랜잭션이 시작될 때의 일정 시점(스냅샷)에서 데이터베이스의 상태를 가져와서 일관성 있는 데이터를 읽는다. 이후 다른 트랜잭션에 의해 변경된 내용은 현재 트랜잭션에 반영되지 않고, 트랜잭션이 시작된 시점의 일관된 데이터를 유지한다.
SNAPSHOT 격리 수준의 특징은 다음과 같다.
1. 일관성 있는 데이터 읽기 : 트랜잭션이 시작된 시점의 데이터 스냅샷을 유지하므로, 해당 트랜잭션에서 읽는 데이터는 일관된 상태를 유지한다.
2. 읽기 인관성과 병행성 : 다른 트랜잭션에서의 변경을 허용하면서도 현재 트랜잭션은 특정 시점의 데이터를 보장하기 때문에 일관성 있는 읽기가 가능하다. 이로써 병행성(concurrency)을 높일 수 있다.
3. Write Skew 문제 해결 : Wirte Skew는 일부 데이터를 읽고 기반 데이터를 변경하는 동시에, 다른 트랜잭션이 해당 변경된 데이터를 조작하는 상황을 말한다. SNAPSHOT 격리 수준은 이러한 문제를 해결하기 위해 사용된다.
자 다시 본론으로 돌아가서 나는 위를 통해 1차 캐시는 RAM이라는 것을 알게 되었다. 그렇다면 이 RAM은 DRAM일까 SRAM일까? 이는 다음의 말로 정리할 수 있을 것 같다.
"캐시" 메모리는 주로 메인 메모리의 DRAM보다 작고 빠른 "SRAM"으로 만들어진 메모리로, 자주 사용하는 데이터를 메인 메모리보다 더 빠른 캐시 메모리에 위치시켜 CPU의 데이터 접근 성능을 높이기 위해 사용된다. 즉, 일반적으로 영속성 컨텍스트의 1차 캐시는 메모리 계층 구조 중에서 보다 빠른 액세스 속도를 제공하는 SRAM을 사용한다는 것이다.
1차 캐시는 애플리케이션이 실행될 때 메모리에 생성되고, 영속성 컨텍스트가 객체를 관리하는 동안 해당 메모리 공간에 존재한다. 이 메모리 공간은 일반적으로 프로그램의 힙(heap) 영역에 할당되어져 있다. 힙은 동적으로 할당되는 메모리 영역으로, 객체의 생성 및 삭제에 사용된다. 따라서 1차 캐시도 이 힙 영역에 할당되어 객체들을 관리한다.
이제 자주 언급되는 힙(heap)에 대해서 좀 더 자세히 알아가보고자 한다. 힙은 위에서 써놓은 것처럼 동적으로 할당되는 메모리 영역으로, 프로그램 실행 중에 필요에 따라 메모리를 할당하고 해체할 수 있는 영역을 나타낸다. 이것은 프로그램이 실행될 때 운영체제에 의해 할당되며, 메모리의 높은 주소에서 낮은 주소 방향으로 확장된다.
힙의 특징은 다음과 같다.
1. 동적 메모리 할당 : 힙은 프로그램 실행 중에 동적으로 할당 될 수 있는 메모리 영역으로, Java에서는 new, C에서는 malloc과 같은 함수를 통해 필요한 크기의 메모리를 요청하고 할당받는다.
이를 통해 우리는 1차 캐시는 객체들을 메모리에 저장하는데, 이때 객체들이 저장되는 메모리 공간은 일반적으로 힙영역에 할당된다는 것과 영속성 컨텍스트는 객체의 생명주기를 관리하고, 객체를 필요할 때 1차 캐시에 저장한다는 것을 알게 되었다. 또한 이때 1차 캐시에 저장되는 객체들은 힙 영역에 할당되며, 이는 객체가 동적으로 메모리에 저장되고 관리되는 데 사용된다는 것을 알게되었다. 이로써 우리는 힙이 논리적이라는 것 그를통해 1차 캐시가 논리적이라는 것 최종적으로 영속성 컨텍스트가 논리적인 개념이라는 것을 알게되었다.
다음 내용이 궁금하다면?
이미 회원이신가요?
2024년 3월 13일 오후 4:25
1. 관리자 업무 중 상당한 부분을 차지하는 일은 인력, 돈, 자본 등의 자원을 할당하는 것이다.
기
... 더 보기최
... 더 보기