2025/01: 29개의 글

[SpringBoot] @RequestBody 애노테이션

Posted by nkjok
2025. 1. 24. 14:40 낙서장[1]/2. SpringBoot
반응형

@RequestBody 어노테이션은 주로 REST API 개발에서 사용되며, HTTP 요청 본문(body)을 지정된 Java 객체로 자동으로 직렬화(serialize)하거나 역직렬화(deserialize)하는 역할을 한다. 이를 통해 클라이언트가 보내는 JSON 데이터를 자바 객체로 쉽게 매핑할 수 있다.

 

 
@RestController
public class UserController {

    @PostMapping("/api/users")
    public ResponseEntity<?> saveUser(@RequestBody User user) {
        // 사용자 정보 처리 로직
        return new ResponseEntity<>(user, HttpStatus.CREATED);
    }
}

 

위 코드에서 @RequestBody 어노테이션은 클라이언트가 보내는 JSON 데이터를 User 객체로 매핑한다. 이렇게 하면 클라이언트가 보낸 데이터를 쉽게 사용할 수 있다

반응형

[JPA] JPQL 쿼리 설명

Posted by nkjok
2025. 1. 24. 13:59 낙서장[1]/3. JPA
반응형

 

String jpql = "SELECT o FROM Order o JOIN o.customer c ON o.customer_id = c.id"

 

 

이 쿼리에서 Order 테이블과 Customer 테이블을 조인할 때 사용되는 컬럼은 Order 테이블의 customer_id 컬럼과 Customer 테이블의 id 컬럼이다. 

 

조인 관계

Order 테이블                      Customer 테이블
| id | order_date | total_amount | customer_id |   JOIN   | id | name | email | phone |
|----|------------|--------------|-------------|    ON    |----|------|-------|-------|
| 1  | 2023-01-01 | 10000        | 101         |   <-->   | 101| John | john@example.com | 123-4567 |
| 2  | 2023-01-02 | 20000        | 102         |          | 102| Jane | jane@example.com | 234-5678

Order 테이블의 customer_id 컬럼과 Customer 테이블의 id 컬럼을 기준으로 조인하는 것을 알 수 있다. customer_id 값이 Customer 테이블의 id 값과 일치하는 레코드를 찾아서 조인한다는 의미다

 

해설) o.customer는 Order 엔티티에서 Customer 엔티티와 연관된 필드를 나타낸다

Order 엔티티에는 Customer 엔티티와의 연관 관계를 나타내는 필드가 있다. 이 필드는 보통 ManyToOne 어노테이션을 사용하여 매핑되며, 이는 여러 개의 Order가 하나의 Customer에 속할 수 있다는 것을 의미한다

반응형

[JPA] 일반 JOIN과 FETCH JOIN을 지연 로딩(LAZY)과 즉시 로딩(EAGER)과 접목한 차이와 장단점

Posted by nkjok
2025. 1. 24. 09:51 낙서장[1]/3. JPA
반응형

Java Persistence API(JPA)를 사용하면서 JOIN을 활용하여 여러 엔티티 간의 연관된 데이터를 조회하는 경우가 많다. 이 글에서는 JPA에서 일반 JOIN과 FETCH JOIN을 지연 로딩(LAZY)과 즉시 로딩(EAGER)과 접목했을 때의 차이와 각자의 장단점을 예시와 함께 살펴보겠다.

1. 일반 JOIN + 지연 로딩(LAZY)

일반 JOIN은 두 개 이상의 테이블을 조인하여 데이터를 조회하는 방법이다. 지연 로딩(LAZY)은 연관된 엔티티를 실제로 사용할 때까지 로딩하지 않는 방법이다.

 

public List<Order> findOrdersWithCustomerLazy() {
    String jpql = "SELECT o FROM Order o JOIN o.customer c ON o.customer_id = c.id";
    return entityManager.createQuery(jpql, Order.class).getResultList();
}

 

장점:

  • 성능 최적화: 필요할 때만 데이터를 로딩하여 성능을 최적화할 수 있다.
  • 메모리 절약: 사용되지 않는 데이터를 로딩하지 않기 때문에 메모리 사용을 절약할 수 있다.

단점:

  • N + 1 문제: 일반 JOIN을 사용할 때 연관된 엔티티를 개별적으로 조회하기 때문에 다수의 쿼리가 발생할 수 있다.
  • 초기화 문제: 연관된 엔티티를 접근할 때 LazyInitializationException이 발생할 수 있다.

2. 일반 JOIN + 즉시 로딩(EAGER)

일반 JOIN은 두 개 이상의 테이블을 조인하여 데이터를 조회하는 방법이다. 즉시 로딩(EAGER)은 엔티티를 조회할 때 연관된 엔티티도 함께 로딩하는 방법이다.

예시:

public List<Order> findOrdersWithCustomerEager() {
    String jpql = "SELECT o FROM Order o JOIN o.customer c ON o.customer_id = c.id";
    return entityManager.createQuery(jpql, Order.class).getResultList();
}

장점:

  • 즉시 사용 가능: 조회 시점에 모든 데이터가 로딩되므로 바로 사용할 수 있다.
  • 간단함: 단일 쿼리로 연관된 데이터를 모두 조회할 수 있다.

단점:

  • 성능 저하: 불필요한 데이터를 모두 로딩하기 때문에 성능이 저하될 수 있다.
  • 메모리 사용: 모든 데이터를 로딩하므로 메모리 사용량이 늘어날 수 있다.

3. FETCH JOIN + 지연 로딩(LAZY)

FETCH JOIN은 조인과 동시에 연관된 엔티티를 한 번에 로딩하는 방법이다. 지연 로딩(LAZY)은 연관된 엔티티를 실제로 사용할 때까지 로딩하지 않는 방법이다.

예시:

public List<Order> findOrdersWithCustomerFetchLazy() {
    String jpql = "SELECT o FROM Order o JOIN FETCH o.customer c ON o.customer_id = c.id";
    return entityManager.createQuery(jpql, Order.class).getResultList();
}

장점:

  • 성능 최적화: 연관된 엔티티를 한 번에 로딩하여 N + 1 문제를 해결하고, 필요할 때만 데이터를 로딩하여 성능을 최적화할 수 있다.
  • 메모리 절약: 사용되지 않는 데이터를 로딩하지 않기 때문에 메모리 사용을 절약할 수 있다.

단점:

  • 복잡성: 쿼리 작성이 복잡할 수 있으며, 주의가 필요하다.
  • 초기화 문제: 연관된 엔티티를 접근할 때 LazyInitializationException이 발생할 수 있다.

4. FETCH JOIN + 즉시 로딩(EAGER)

FETCH JOIN은 조인과 동시에 연관된 엔티티를 한 번에 로딩하는 방법이다. 즉시 로딩(EAGER)은 엔티티를 조회할 때 연관된 엔티티도 함께 로딩하는 방법이다.

예시:

public List<Order> findOrdersWithCustomerFetchEager() {
    String jpql = "SELECT o FROM Order o JOIN FETCH o.customer c ON o.customer_id = c.id";
    return entityManager.createQuery(jpql, Order.class).getResultList();
}

장점:

  • 성능 향상: 연관된 엔티티를 한 번에 로딩하여 N + 1 문제를 해결한다.
  • 즉시 사용 가능: 조회 시점에 모든 데이터가 로딩되므로 바로 사용할 수 있다.

단점:

  • 성능 저하: 불필요한 데이터를 모두 로딩하기 때문에 성능이 저하될 수 있다.
  • 메모리 사용: 모든 데이터를 로딩하므로 메모리 사용량이 늘어날 수 있다.

5. 결론

JPA에서 일반 JOIN과 FETCH JOIN을 지연 로딩(LAZY)과 즉시 로딩(EAGER)과 접목했을 때는 각각의 장단점이 있다. 일반 JOIN과 FETCH JOIN은 각각의 상황에 따라 적절히 선택하여 사용할 수 있으며, 지연 로딩(LAZY)과 즉시 로딩(EAGER)을 통해 성능과 메모리 사용을 조절할 수 있다. 상황에 맞게 적절한 방법을 선택하여 효과적으로 JPA를 활용 할 수 있다

반응형

[JPA] 데이터베이스와 상호작용하는 객체 지향 프로그래밍 JPA 기초

Posted by nkjok
2025. 1. 24. 09:27 낙서장[1]/3. JPA
반응형

JPA 기초 가이드: 데이터베이스와 상호작용하는 객체 지향 프로그래밍

Java Persistence API(JPA)는 객체 지향 프로그래밍 언어인 Java와 관계형 데이터베이스 사이의 데이터를 관리하는 표준 방법이라고 한다. JPA를 사용하면 데이터베이스의 종속성을 최소화하고, 객체를 쉽게 데이터베이스에 저장하거나 조회할 수 있다. 이 글에서는 JPA의 기초 개념과 함께 Dialect에 대해 알아보겠다.

 

1. JPA란 무엇인가?

JPA는 Java EE(Enterprise Edition) 플랫폼의 표준 API로, 자바 객체를 데이터베이스에 매핑하고 관리하는 역할을 한다. JPA를 사용하면 직접 SQL 쿼리를 작성하지 않고도 데이터베이스와 상호작용할 수 있어 개발 생산성을 높일 수 있다.

 

2. JPA의 주요 구성 요소

  • Entity: 데이터베이스 테이블에 매핑되는 자바 클래스이다. 각 엔티티는 데이터베이스의 테이블, 그리고 엔티티의 각 필드는 테이블의 열(Column)에 대응한다.
  • Entity Manager: 엔티티의 생명주기를 관리하는 인터페이스로, 엔티티를 데이터베이스에 저장하거나 조회하는 역할을 한다.
  • Persistence Unit: 하나 이상의 엔티티 클래스를 포함하는 논리적 그룹으로, persistence.xml 파일에서 정의된다.

 

3. JPA의 동작 원리

JPA는 기본적으로 ORM(Object-Relational Mapping) 프레임워크로 동작한다. ORM은 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑하는 기술이다. 이를 통해 개발자는 객체 지향적인 방법으로 데이터베이스 작업을 수행할 수 있다.

 

4. Dialect란 무엇인가?

각 데이터베이스는 고유한 SQL 문법과 기능을 가지고 있다. JPA는 이러한 각 데이터베이스별 고유한 기능을 지원하기 위해 Dialect라는 개념을 도입했다.

  • Dialect: 특정 데이터베이스에 종속되지 않고 다양한 데이터베이스와 상호작용하기 위한 SQL 방언을 의미한다. 예를 들어, MySQL, Oracle, PostgreSQL 등 각 데이터베이스별로 고유한 SQL 방언이 존재하며, JPA는 이러한 방언을 지원하기 위해 Dialect 클래스를 제공한다.

 

5. JPA 설정

JPA 설정은 주로 persistence.xml 파일에서 이루어진다. 이 파일은 META-INF 폴더에 위치하며, 데이터베이스 연결 정보와 엔티티 매핑 정보를 포함한다.

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <persistence-unit name="exampleUnit">
        <class>cohttp://m.example.Entity</class>
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mydb"/>
            <property name="javax.persistence.jdbc.user" value="username"/>
            <property name="javax.persistence.jdbc.password" value="password"/>
            <property name="javax.persistence.jdbc.driver" value="cohttp://m.mysql.jdbc.Driver"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
        </properties>
    </persistence-unit>
</persistence>

JPA를 Spring Boot와 함께 사용할 때는, 대부분의 설정을 application.properties 또는 application.yml 파일에서 처리한다. 이는 Spring Boot가 기본적으로 설정을 자동으로 구성해주기 때문에 persistence.xml 파일을 따로 작성할 필요가 없게 되는 거다.

하지만 persistence.xml 파일이 어디에 쓰이는지 이해하는 것도 중요하다. persistence.xml 파일은 JPA 표준을 따르는 Java EE 어플리케이션에서 주로 사용되며, 데이터베이스와 엔티티 매핑 정보를 정의한다.

 

Spring Boot에서 JPA 설정하기

Spring Boot에서는 application.properties 파일을 통해 JPA 설정을 할 수 있다. 예를 들어, 데이터베이스 연결 정보와 Hibernate Dialect 설정을 이렇게 한다:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=cohttp://m.mysql.cj.jdbc.Driver

spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

 

주요 설정 설명 (Spring Boot에서 JPA 설정하기)

  • spring.datasource.url: 데이터베이스 연결 URL
  • spring.datasource.username: 데이터베이스 사용자 이름
  • spring.datasource.password: 데이터베이스 비밀번호
  • spring.datasource.driver-class-name: JDBC 드라이버 클래스 이름
  • spring.jpa.database-platform: Hibernate Dialect 설정
  • spring.jpa.show-sql: SQL 쿼리 로그 출력 여부
  • spring.jpa.hibernate.ddl-auto: DDL(Data Definition Language) 자동 실행 설정 (update, create, create-drop, validate 중 하나)

이러한 설정들을 통해 JPA를 Spring Boot에서 쉽게 사용할 수 있다. persistence.xml 파일은 사용하지 않지만, 동일한 설정을 application.properties 파일에 정의함으로써 같은 효과를 얻을 수 있다.

 

6. JPA의 장점

  • 데이터베이스 독립성: JPA는 특정 데이터베이스에 종속되지 않으며, 다양한 데이터베이스와 상호작용할 수 있다.
  • 생산성 향상: JPA를 사용하면 SQL 쿼리를 직접 작성하지 않아도 되어 개발 생산성을 높일 수 있다.
  • 유지보수 용이성: 객체 지향적인 방식으로 데이터베이스 작업을 수행할 수 있어 코드의 가독성과 유지보수성이 향상된다.

 

7. 결론

JPA는 객체 지향 프로그래밍과 관계형 데이터베이스 간의 데이터를 관리하는 강력한 도구이다. Dialect를 통해 다양한 데이터베이스와 상호작용할 수 있어 데이터베이스 독립성을 확보할 수 있다. JPA를 활용하여 더 효율적이고 생산적인 데이터베이스 관리를 경험해보자.

반응형

[DataBase] ON 절과 WHERE 절을 사용하는 조인의 차이

Posted by nkjok
2025. 1. 23. 18:00 낙서장[1]/93. DataBase
반응형

ON 절과 WHERE 절을 사용한 조인의 차이에 대해 설명드릴게요. 정확한 결과를 가져오려면 ON 절에서 필터를 사용하는 것이 더 적절한 경우가 있습니다. 이 차이를 이해하기 위해 예제를 사용해 자세히 설명해 보겠습니다.

ON 절과 WHERE 절을 사용하는 조인의 차이

ON 절에서의 필터링

ON 절은 조인 조건을 지정하는 곳입니다. 테이블을 조인할 때 조건을 걸어 필터링을 수행합니다. 조인할 때마다 조건에 맞는 행만 결과 집합에 포함됩니다.

WHERE 절에서의 필터링

WHERE 절은 조인이 끝난 후 결과 집합에서 조건을 걸어 필터링을 수행합니다. 조인된 결과에서 조건에 맞는 행만 최종 결과 집합에 포함됩니다.

예제

데이터 준비

테이블 employees와 departments가 있다고 가정해보겠습니다.

ON 절을 사용하는 조인

ON 절을 사용하여 필터링하면 조인 조건이 먼저 적용됩니다. 예를 들어, dept_id = 10인 부서만 조인하려면:

SELECT e.emp_name, d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id AND d.dept_id = 10;

결과:

emp_namedept_name
Alice HR

 

WHERE 절을 사용하는 조인

WHERE 절을 사용하여 필터링하면 조인이 모두 이루어진 후 조건이 적용됩니다. 예를 들어, dept_id = 10인 부서만 결과에 포함하려면:

SELECT e.emp_name, d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_id = 10;

결과는 ON 절을 사용한 경우와 동일합니다:

emp_namedept_name
Alice HR

 

차이점 및 주의사항

  1. 조인된 행의 수: ON 절에서 필터링하는 경우, 조인 조건이 먼저 적용되므로 조건에 맞는 행만 조인됩니다. WHERE 절에서 필터링하는 경우, 모든 조인된 결과에서 조건을 적용하므로 더 많은 행이 처리될 수 있습니다.
  2. 성능 최적화: 조인 조건이 복잡한 경우, ON 절에서 필터링하면 성능이 더 좋을 수 있습니다. 이유는 조인할 때 조건이 적용되어 불필요한 조인을 방지할 수 있기 때문입니다.

요약하면, 정확한 결과를 얻으려면 ON 절을 사용하여 필터링하는 것이 좋습니다. 이를 통해 조인 조건이 먼저 적용되고, 결과 집합이 필터링됩니다.

반응형