# **데이터 처리와 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를 활용하면 **효율적인 데이터 처리와 유지보수성 높은 애플리케이션을 만들 수 있습니다!**