[Java] ORM과 JPA 기본 개념

jina·2024년 5월 26일
0

Java

목록 보기
8/10
post-custom-banner

📌 Persistence Framework

Persistence Framework는 애플리케이션이 데이터를 지속적으로 저장하고 관리하기 위해 사용하는 Spring의 소프트웨어 라이브러리입니다. 개발자가 데이터베이스와 쉽게 상호작용할 수 있도록 여러 기능을 제공합니다.

  • JDBC: SQL을 자바 코드로 실행하기 위한 가장 기본적인 API
  • MyBatis: SQL을 직접 작성해서 자바 객체와 매핑하는 SQL 매퍼
  • Hibernate: JPA 스펙에 맞춰 객체와 데이터베이스를 자동으로 매핑하는 ORM 프레임워크

📌 JDBC

JDBC (Java Database Connectivity)는 자바 애플리케이션을 데이터베이스와 연결하는 SQL 쿼리를 실행하기 위한 표준 API입니다. SQL 쿼리를 직접 작성하면 그 결과를 자바 객체로 매핑할 수 있지만, 이 과정을 개발자가 직접 진행해야 합니다. 많은 보일러플레이트 코드를 반복해서 작성해야 하는 번거로움이 있습니다.

  • JDBC는 수동으로 SQL을 작성하고 처리
  • JPA는 자동으로 SQL을 생성하고 관리

📌 ORM(Object-Relational Mapping)

ORM은 객체와 관계형 데이터베이스를 연결하는 기술입니다. 자바 같은 객체 지향 프로그래밍 언어에서 사용하는 객체(클래스)데이터베이스의 테이블을 자동으로 매핑해줍니다. 이를 통해 개발자는 SQL문을 직접 작성하지 않고도 데이터베이스와 상호작용할 수 있습니다.

ORM이 하는 일을 이렇게 정리할 수 있습니다.

  • 자바 애플리케이션이 데이터를 객체로 관리
  • 데이터베이스 시스템이 데이터를 테이블로 관리
  • ORM이 이러한 객체와 테이블을 자동으로 매핑

즉, 객체를 통해 데이터베이스를 조작할 수 있게 하는 기술을 말합니다.

📌 JPA (Java Persistence API)

JPA는 자바에서 ORM의 사용 방법을 표준화한 스펙입니다. JPA를 사용하면 ORM 프레임워크를 따를 수 있는 규칙을 제공받을 수 있습니다. 영속성 컨텍스트, 엔티티 매니저,트랜잭션 관리 등의 규칙을 제공합니다. JPA는 자체적으로 구현되지 않습니다. Hibernate와 같은 ORM 프레임워크가 이러한 JPA 스펙을 구현합니다.

  • JPA는 표준 스펙을 의미하고, Hibernate는 스펙을 구현하는 구현체의 한 종류

📌 MVC 패턴

MVC 패턴은 애플리케이션의 구조를 세 부분으로 나누어 설계하는 디자인 패턴입니다. JPA 스펙을 사용해 어플리케이션을 개발할 때 MVC 패턴을 적용해 설계할 수 있습니다.

  • Model: 데이터와 비즈니스 로직을 담당합니다.
  • View: 사용자 인터페이스를 담당합니다.
  • Controller: 사용자 입력을 처리하고, 서비스 계층에 명령을 전달합니다.

JPA는 데이터베이스와 상호작용하면서 데이터를 관리할 수 있도록 도와주는 도구이기 때문에, Model, View, Controller 중 Model 계층에 사용됩니다. 예를 들어, JPA는 사용자 정보를 'User' 클래스와 같은 엔티티에 저장하고, CRUD 작업을 쉽게 처리하는 데이터 관리 기능을 제공합니다.

📌 JPA의 주요 기능

✅ 어노테이션: 자바 객체와 데이터베이스 테이블을 매핑하는데 사용합니다. @Entity, @Table, @Id, @Column 등의 어노테이션을 사용하여, 클래스와 필드가 데이터베이스 테이블과 컬럼에 매핑됨을 나타냅니다.
✅ 엔티티: 데이터베이스의 테이블에 매핑되는 자바 객체로, 엔티티 기능을 사용해 CRUD 작업을 쉽게 처리할 수 있습니다.
✅ DTO: 데이터를 전송하는 자바 객체로, 엔티티와 뷰 사이에서 데이터를 전달하는 역할을 합니다.

📌 JPA의 Spring Data JPA 활용

✅ Entity 클래스 정의
데이터베이스 테이블과 매핑되며, 각 필드가 테이블 칼럼에 해당합니다.

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class User {
    @Id // 기본키 지정
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 데이터베이스 기본키 값을 MySQL 같은 데이터베이스에서 자동으로 생성하도록 지정
    private Long id;
    private String name;
    private String email;
    // lombok을 사용해 getter, setter, constructor 쉽게 추가 가능
}

✅ Repository 인터페이스 정의
Spring Data JPA가 제공하는 JPARepository를 상속받아 기본적인 CRUD 메소드와 커스텀 쿼리 메소드를 사용하게 해줍니다.

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
}
// 관리할 엔티티 클래스명 -> User
// 해당 엔티티의 기본키 타입 -> Long
// 커스텀 쿼리 메소드 -> findByName
// 'name'필드와 인자 값이 일치하는 모든 User 엔티티를 검색
// 메소드 이름을 기반으로 SQL 쿼리를 자동 생성
// 추후에 컨트롤러나 서비스 클래스에서 이 메소드를 호출하면 사용자 목록을 가져올 수 있다.

✅ Controller 클래스 정의
사용자가 웹브라우저를 통해 입력하는 내용을 서비스 계층에 전달합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController // 모든 메소드의 응답을 JSON이나 XML로 변환
@RequestMapping("/users") // 모든 메소드가 사용하는 기본 경로 설정
public class UserController {

@Autowired // 아래 클래스의 객체가 필요하다고 선언 -> 이후 메소드에서 변수
private UserService userService;
    
// 1. 클라이언트가 JSON 형식으로 데이터를 보낼 때
// API 호출이나 프론트엔드 프레임워크와의 통신에 적합
@PostMapping // 필요하면 추가 경로 지정 ("/{new}")
public User createUser(@RequestBody UserDTO userDTO) { // 클라이언트가 JSON 데이터를 서버로 보내면 'UserDTO' 객체로 변환해서 사용하겠다는 뜻
    User user = new User(); // 새 사용자 객체 생성
    user.setId(userDTO.getId());
    user.setName(userDTO.getName());
    user.setEmail(userDTO.getEmail());
    return userService.saveUser(user); // 결과 반환
}

💡 @Autowired 란?
Spring은 애플리케이션을 실행할 때 필요한 객체들을 미리 만들어서 관리하는데, 이러한 객체들을 '빈'이라고 부릅니다. 필요한 객체로 지정하기 위해서는 어노테이션을 해당 클래스에 붙여야 합니다.

@Component: 일반적인 스프링 빈
@Service: 서비스 계층을 나타내는 빈
@Repository: 데이터 접근 계층을 나타내는 빈
@Controller: 웹 컨트롤러를 나타내는 빈

Spring은 클래스에 붙은 어노테이션을 확인 후, 해당 클래스를 빈으로 생성해서 관리하게 됩니다. 즉, @Autowired를 사용한다는 것은 해당 타입의 '빈'을 자동으로 주입한다는 것을 의미합니다. 별도로 객체를 생성할 필요 없이, Spring이 이미 만들어 놓은 객체를 코드에서 필요한 곳에 자동으로 넣어줄 수 있습니다.

// 2. 클라이언트가 URL 파라미터로 데이터를 보낼 때
// 검색 필터링이나 간단한 폼 데이터 전송에 적합
@PostMapping
public User createUser(@RequestParam Long id, @RequestParam String name, @RequestParam String email) {
    User user = new User(); // 새 사용자 객체 생성
    user.setId(id);
    user.setName(name);
    user.setEmail(email);
    return userService.saveUser(user); // 결과 반환
}

UserDTO는 User 엔티티와 비슷하지만, 사용 목적에 따라 다르게 구성할 수 있습니다.

public class UserDTO {
    private Long id;
    private String name;
    private String email;

✅ Service 클래스 정의
비즈니스 로직을 처리하는 클래스로, Controller와 Repository 사이를 연결하며 데이터베이스와 상호작용합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public User saveUser(User user) {
        return userRepository.save(user);
    }

데이터 변경 작업을 트랜잭션 내에서 안전하게 수행하기 위해서 @Transactional 어노테이션을 사용할 수 있습니다.

💬 정리

ORM (Object-Relational Mapping)

  • 데이터베이스 테이블을 자바 객체로 매핑해주는 기술
  • SQL을 직접 작성하지 않고, 자바 객체를 통해 데이터베이스를 조작

JPA (Java Persistence API)

  • ORM의 표준 규칙을 정의한 스펙으로 Hibernate같은 구현체가 필요
  • 자바 객체를 데이터베이스에 쉽게 저장하고 불러오는 작업 수행

Spring Data JPA

  • JPA를 더 쉽게 사용할 수 있도록 도와주는 Spring의 모듈
  • 기본적인 CRUD 작업과 쿼리 메서드 자동 생성을 지원
profile
오늘의 기록은 내일의 보물
post-custom-banner

0개의 댓글