Programming🧑‍💻/JPA

JPA에서 엔티티 식별자를 사용하는 이유

생각 깎는 아이 2023. 8. 19. 01:23

일반적으로 서비스 이용자와 서비스 제공자 간의 요청응답의 흐름은 다음과 같다.
이용자가 서비스에 글 보기, 댓글 조회하기와 같은 서비스를 이용하기 위하여 요청을 보내면 
제공자는 이용자의 요청을 식별하고 이에 해당하는 응답을 제공하기 위해 필요한 데이터(글, 댓글)를 데이터베이스로부터 조회한다. 
조회한 데이터를 서비스의 특성에 맞게 가공하여(몇 개까지 보여줄 건지, 어떻게 보여줄 건지) 사용자에게 전달한다. 
또한 이용자가 글이나 댓글을 작성하기와 같은 요청을 보내면 제공자는 이용자에게 전달받은 데이터를 사전에 설계한 데이터베이스 설계에 맞게 저장하고 이에 대한 결과를 사용자에게 전달한다. 
즉 서비스 이용자와 제공자 간의 요청, 응답 흐름에서 서비스와 데이터베이스 간의 통신이 필요하다. 

 
서비스와 데이터베이스 간의 통신을 위해서는 다음 과정을 거친다. 
1. 커넥션을 연결한다 : 데이터베이스와 서비스사이에 TCP / IP 통신을 통하여 데이터가 왔다 갔다 할 수 있는 길을 내놓는다. 
2. 쿼리를 전달한다 : 서비스에서 데이터베이스에 조회, 저장, 삭제, 변경과 같은 동작을 요청하기 위해 데이터 베이스가 이해 가능한 언어로 원하는 동작을  설명한다. 
3. DB는 설명받은 동작을 실행 후 요청한 서비스 측에 결과(성공, 실패)를 전달한다. 

위와 같이 서비스와 데이터베이스 간의 통신을 위해서는 연결을 맺고, 쿼리를 전달하고, 전달한 쿼리에 대한 응답을 받아야 한다. 
문제는 데이터베이스 종류가 다양하기 때문에 각 데이터 베이스에 따라 위의 과정이 모두 제각기 다르다. 따라서 새로운 데이터베이스를 이용하기 위해서는 해당 데이터 베이스가 요구하는 사항을 준수해야기 때문에 데이터베이스에 따라 서비스에서 통신을 담당하는 부분의 변경이 요구된다. 

각 데이터베이스가 요구하는 통신방법을 지켜야 하는 것은 피할 수 없다.  그러면 데이터베이스를 이용하는 서비스들이 이로 인해 겪는 어려움을 해결하기 위해서는 데이터베이스 이용자가 규칙을 준수하게 하는 것이 아니라 데이터베이스 제공자가 규칙을 준수하게 만들면 된다. 
자바 진영에서는 JDBC(Java DataBase Conectivity)라는 서비스와 데이터베이스 통신에 관련한 인터페이스를 사전에 정의하여 여기에 커넥션 연결, 쿼리의 전달과 응답에 대한 스펙을 기재해 놓고 데이터베이스 제공자가 이를 지키도록 하였다. 따라서 각 데이터베이스 제공자는 해당 인터페이스에 맞는 드라이버를 제공함으로써 데이터베이스 이용자들은 JDBC에만 맞게 개발을 하면 된다. 

 JDBC를 도입함으로써 각 데이터베이스에 따라 달라지는 통신 방법에 대한 부분은 해결했지만 여전히 데이터 베이스에 원하는 동작을 전달하기 위해서는 데이터베이스가 알아듣는 언어로 쿼리를 날려야 한다. 이는 매우 귀찮은 일이었으므로 이를 완화시키고자 개발한  ORM(Object Relational Mapping)은 객체와 데이터베이스의 테이블 사이를 연결해 준다. 이로써 시스템상에서 상호작용하는 객체들과 데이터베이스 테이블 간의 관계가 좀 더 명확해지고 간단한 CRUD(Create Read Update Delete)의 경우에는 쿼리를 직접 작성하지 않아도 SQL의 동적으로 구성하여 데이터베이스에게 전달해 준다. 대표적인 ORM 기술로는 JPA의 구현체인 하이버네이트가 있다. 
객체와 요구사항을 JPA에 던지면 JPA는 객체를 분석하고 요구사항에 맞는 쿼리를 생성하여 JDBC에 전달한다. 

 
JPA는 서비스측으로부터의 요청을 수행을 위한 객체를 분석단계에서 내부적으로 엔티티매니저(EntityManager)를 사용한다. 
엔티티 매니저는 요청이 들어왔을 때 커넥션 풀에 접근하여 커넥션을 획득한 뒤에 해당 커넥션을 이용하여 데이터베이스에 동작을 전달한다. 
* 커넥션 풀 : Database와 연결을 맺는데 시간이 걸리기 때문에 미리 여러 개의 커넥션(연결)을 만들고 데이터베이스와 통신이 필요한 작업에서 가져다 쓸 수 있도록 커넥션들을 모아둔 곳 

엔티티 매니저는 각 객체를 관리하기 위해 영속 컨텍스트를 이용한다.
영속 컨텍스트에 객체를 영속(persist)하게 되면 이때부터는 해당 객체는 영속 컨텍스트가 관리하는 상태인 영속 상태가 된다. 
이때 영속 컨텍스트가 각 객체들을 관리하기 위해서는 이들을 구별할 수 있는 식별자값이 필요하다. 
따라서 객체와 테이블을 매핑하기 위해 @Entity를 사용하기 위해서는 각 객체에는 테이블의 기본키와 매핑되어 있는 @Id가 필요하다. 

@Entity
public class Article{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;