Files
spring-boot-examples/docs/07_데이터 처리와 JPA.md
2025-04-08 19:56:24 +09:00

213 lines
7.4 KiB
Markdown

# **데이터 처리와 JPA**
웹 애플리케이션에서 **데이터 처리(Data Processing)**는 필수적인 요소이며, 이를 효율적으로 다루기 위해 ORM 프레임워크인 **JPA (Java Persistence API)**가 널리 사용됩니다.
이번 글에서는 **JPA의 기본 개념, 주요 기능, 실무 적용 방법**을 살펴보겠습니다.
---
## **1. 데이터 처리란?**
데이터 처리는 애플리케이션이 데이터를 **생성(Create), 읽기(Read), 수정(Update), 삭제(Delete)**하는 과정(**CRUD**)을 의미합니다.
Spring Boot에서는 **JPA와 Spring Data JPA**를 활용하여 효율적인 데이터 처리를 구현할 수 있습니다.
**📌 전통적인 JDBC 방식과 JPA 방식 비교**
| 방식 | 특징 | 코드 복잡도 | 유지보수성 |
|------|------|------------|------------|
| **JDBC (기본 SQL 사용)** | SQL 쿼리를 직접 작성 | 높음 | 낮음 |
| **JPA (ORM 방식)** | 객체 중심의 데이터 처리 | 낮음 | 높음 |
---
## **2. JPA란?**
**JPA (Java Persistence API)**는 객체지향적인 방식으로 데이터베이스를 다룰 수 있도록 도와주는 **ORM(Object-Relational Mapping) 기술**입니다.
JPA를 사용하면 SQL을 직접 작성하지 않고, **엔티티(Entity) 객체를 이용하여 데이터베이스를 조작**할 수 있습니다.
### **📌 JPA의 핵심 개념**
1. **엔티티(Entity):** 데이터베이스 테이블과 매핑되는 클래스
2. **리포지토리(Repository):** 데이터 저장 및 조회를 담당하는 계층
3. **트랜잭션(Transaction):** 데이터 변경 작업을 하나의 단위로 처리
4. **JPQL(Java Persistence Query Language):** 객체를 대상으로 하는 쿼리
---
## **3. JPA 실무 적용**
### **📌 1) Entity (데이터 모델 정의)**
JPA에서는 `@Entity` 어노테이션을 사용하여 **클래스를 데이터베이스 테이블과 매핑**합니다.
```java
import jakarta.persistence.*;
@Entity // User 엔티티는 DB의 users 테이블과 매핑됨
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 ID
private Long id;
@Column(nullable = false) // name 컬럼은 null을 허용하지 않음
private String name;
@Column(nullable = false)
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getter & Setter 생략
}
```
**`@Entity`**: 해당 클래스가 데이터베이스 테이블과 연결됨
**`@Table(name = "users")`**: 테이블명을 `users`로 지정
**`@Id`**: 기본 키(Primary Key) 설정
**`@GeneratedValue(strategy = GenerationType.IDENTITY)`**: 자동 증가(AUTO_INCREMENT) 설정
**`@Column(nullable = false)`**: `null`을 허용하지 않도록 설정
---
### **📌 2) Repository (데이터 접근 계층)**
JPA에서는 **Spring Data JPA**의 `JpaRepository` 인터페이스를 사용하면, 기본적인 CRUD 기능을 자동으로 구현할 수 있습니다.
```java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 기본 CRUD 기능 제공
}
```
**`JpaRepository<User, Long>`**: `User` 엔티티를 관리하며, 기본 키 타입은 `Long`
`findById(id)`, `save(entity)`, `deleteById(id)` 등 기본적인 데이터 처리 메서드 제공
---
### **📌 3) Service (비즈니스 로직 계층)**
데이터 처리 로직을 서비스 계층에서 구현하여 컨트롤러와 분리합니다.
```java
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 createUser(String name, int age) {
if (age < 0) {
throw new IllegalArgumentException("나이는 0 이상이어야 합니다.");
}
return userRepository.save(new User(name, age));
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
```
**서비스 계층을 사용하여 비즈니스 로직을 분리**
**`@Transactional`을 사용하여 트랜잭션 관리**
---
### **📌 4) Controller (요청 처리 계층)**
사용자의 요청을 받아 서비스 계층을 호출하고 응답을 반환합니다.
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@RequestParam String name, @RequestParam int age) {
return ResponseEntity.ok(userService.createUser(name, age));
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return ResponseEntity.ok(userService.getAllUsers());
}
}
```
**`@RestController`**: JSON 형식으로 데이터를 반환하는 컨트롤러
**`@RequestMapping("/users")`**: `/users` 경로의 API를 처리
**`@PostMapping`**: 새로운 사용자 생성
**`@GetMapping`**: 모든 사용자 조회
---
## **4. JPA에서 데이터 조회 (JPQL & Native Query)**
### **📌 1) JPQL (Java Persistence Query Language)**
JPA에서는 SQL 대신 **JPQL**을 사용하여 객체 중심의 쿼리를 작성할 수 있습니다.
```java
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Long> {
// 이름으로 사용자 찾기
@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findByName(@Param("name") String name);
}
```
✔ SQL과 유사하지만, **테이블명이 아니라 엔티티 클래스명을 사용**
---
### **📌 2) Native Query (SQL 직접 사용)**
기본 SQL 쿼리를 직접 사용할 수도 있습니다.
```java
@Query(value = "SELECT * FROM users WHERE age >= :age", nativeQuery = true)
List<User> findUsersByAge(@Param("age") int age);
```
✔ 복잡한 SQL 쿼리를 그대로 활용 가능
---
## **5. JPA의 장점과 단점**
### **📌 JPA의 장점**
**SQL을 직접 작성할 필요 없음** → 생산성 증가
**객체지향적인 데이터 처리 가능** → 코드의 가독성과 유지보수성 향상
**트랜잭션 관리가 용이함**
**캐싱 및 성능 최적화 기능 제공**
### **📌 JPA의 단점**
❌ 초기 학습 비용이 존재
❌ 복잡한 SQL 튜닝이 필요한 경우 SQL보다 불리할 수 있음
❌ 데이터베이스 변경 시, 마이그레이션이 필요
---
## **6. 정리**
**JPA는 객체지향 방식으로 데이터를 처리하는 ORM 기술**
**Entity, Repository, Service, Controller 구조로 데이터 처리를 설계**
**JPQL 및 Native Query를 활용하여 데이터 조회 가능**
**트랜잭션을 활용하여 데이터 일관성을 유지**
JPA를 활용하면 **효율적인 데이터 처리와 유지보수성 높은 애플리케이션을 만들 수 있습니다!**