Persistence Framework는 애플리케이션이 데이터를 지속적으로 저장하고 관리
하기 위해 사용하는 Spring의 소프트웨어 라이브러리입니다. 개발자가 데이터베이스와 쉽게 상호작용할 수 있도록 여러 기능을 제공합니다.
JDBC (Java Database Connectivity)는 자바 애플리케이션을 데이터베이스와 연결하는 SQL 쿼리를 실행
하기 위한 표준 API입니다. SQL 쿼리를 직접 작성하면 그 결과를 자바 객체로 매핑할 수 있지만, 이 과정을 개발자가 직접 진행해야 합니다. 많은 보일러플레이트 코드를 반복해서 작성해야 하는 번거로움이 있습니다.
ORM은 객체와 관계형 데이터베이스를 연결하는 기술입니다. 자바 같은 객체 지향 프로그래밍 언어에서 사용하는 객체(클래스)
와 데이터베이스의 테이블
을 자동으로 매핑해줍니다. 이를 통해 개발자는 SQL문을 직접 작성하지 않고도 데이터베이스와 상호작용할 수 있습니다.
ORM이 하는 일을 이렇게 정리할 수 있습니다.
객체
로 관리 테이블
로 관리즉, 객체를 통해 데이터베이스를 조작할 수 있게 하는 기술을 말합니다.
JPA는 자바에서 ORM의 사용 방법을 표준화한 스펙
입니다. JPA를 사용하면 ORM 프레임워크를 따를 수 있는 규칙을 제공받을 수 있습니다. 영속성 컨텍스트
, 엔티티 매니저
,트랜잭션 관리
등의 규칙을 제공합니다. JPA는 자체적으로 구현되지 않습니다. Hibernate
와 같은 ORM 프레임워크가 이러한 JPA 스펙을 구현합니다.
MVC 패턴은 애플리케이션의 구조를 세 부분으로 나누어 설계하는 디자인 패턴입니다. JPA 스펙을 사용해 어플리케이션을 개발할 때 MVC 패턴을 적용해 설계할 수 있습니다.
JPA는 데이터베이스와 상호작용하면서 데이터를 관리할 수 있도록 도와주는 도구이기 때문에, Model, View, Controller 중 Model 계층
에 사용됩니다. 예를 들어, JPA는 사용자 정보를 'User' 클래스와 같은 엔티티에 저장하고, CRUD 작업을 쉽게 처리하는 데이터 관리 기능을 제공합니다.
✅ 어노테이션: 자바 객체와 데이터베이스 테이블을 매핑하는데 사용합니다. @Entity, @Table, @Id, @Column
등의 어노테이션을 사용하여, 클래스와 필드가 데이터베이스 테이블과 컬럼에 매핑됨을 나타냅니다.
✅ 엔티티: 데이터베이스의 테이블에 매핑되는 자바 객체로, 엔티티 기능을 사용해 CRUD 작업을 쉽게 처리할 수 있습니다.
✅ DTO: 데이터를 전송하는 자바 객체로, 엔티티와 뷰 사이에서 데이터를 전달하는 역할을 합니다.
✅ 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)
JPA (Java Persistence API)
Spring Data JPA