2023년 1월 1일
08:00 AM
Buffering ...

최근 글 👑

Spring JPA 뭐하는 키워드지..?

2024. 8. 24. 03:34ㆍ스프링

하루 4개씩 기초지식!

더보기

1. Index는 뭐고 장/단점은 뭐가 있을까?

  • Index란 테이블을 처음부터 끝까지 검색하는 방법인 FTS(Full table Scan)과는 달리 인덱스를 검색하여 해당 자료의 테이블을 엑세스 하는 방법!
    • 예를 들어, DB를 책으로 비유하자면 데이터는 책의 내용일 것이고, 데이터가 저장된 레코드의 주소는 index 목록에 있는 페이지 번호일 것이다!

  • 인텍스는 항상 정렬된 상태를 유지하기에 원하는 값을 검색하는데 빠르지만, 새로운 값을 추가하거나 삭제, 수정하는 경우에는 쿼리문 실행 속도가 느려집니다.

  • 즉! 인덱스는 데[이터의 저장 성능을 희생하고 그 대신 데이터의 검색 속도를 높이는 기능이라 할 수 있다!

2. 정규화?

  • 하나의 릴레이션에 하나의 의미만 존재하도록 릴레이션을 분해하는 과정이며, 데이터의 일관성, 최소한의 데이터 중복, 최대한의 데이터 유연성을 위한 방법입니다
    • 릴레이션?
      • 릴레이션이란 관계형 데이터 베이스에서 정보를 구분하여 저장하는 기본 단위

  • 제1 정규형 : 테이블의 컬럼이 원자 값(Atomic Value; 하나의 값)을 갖도록 분해합니다.
  • 제2 정규형: 제1 정규형을 만족하고, 기본키가 아닌 속성이 기본키에 완전 함수 종속이도록 분해합니다.
    ※ 여기서 완전 함수 종속이란 기본키의 부분집합이 다른 값을 결정하지 않는 것을 의미

  • 제3 정규형 : 제2 정규형을 만족하고, 이행적 함수 종속을 없애도록 분해합니다.
    ※ 여기서 이행적 종속이란 A → B, B → C가 성립할 때 A → C가 성립되는 것을 의미

  • BCNF 정규형 : 제3 정규형을 만족하고, 함수 종속성 X → Y가 성립할 때 모든 결정자 X가 후보키가 되도록 분해합니다.

 

  • 장점
    • 1. 데이터베이스 변경 시 이상현상이 발생하는 문제점을 해결할 수 있다.

    • 2. 데이터베이스 구조 확장 시 정규화된 데이터베이스는 그 구조를 변경하지 않아도 되거나 일부만 변경해도 된다.

  • 단점
    • 릴레이션의 분해로 인해 릴레이션 간의 연산(JOIN 연산)이 많아진다. 이로인해 질의에 대한 응답 시간이 느려질 수 있다.

      + 정규화를 수행한다는 것은 이상현상을 제거하는 것이다. 데이터의 중복 속성을 제거하고 결정자에 의해 동일한 의미의 일반 속성이 하나의 테이블로 집약되므로 한 테이블의 데이터 용량이 최소화되는 효과가 있다. 따라서 정규화된 테이블은 데이터를 처리할 때 속도가 빨라질 수도 있고 느려질 수도 있는 특성이 있다.

3. 이상 현상의 종류가 뭐가 있을까?

  • 이상 현상은 테이블을 설계할 때 잘못 설계하여 데이터를 삽입,삭제,수정할 때 생기는 논리적 오류를 말합니다.
  • 삽입 이상 : 자료를 삽입할 때 특정 속성에 해당하는 값이 없어 NULL을 입력해야 하는 현상

  • 갱신 이상 : 중복된 데이터 중 일부만 수정되어 데이터 모순이 일어나는 현상

  • 삭제 이상 : 어떤 정보를 삭제하면, 의도하지 않은 다른 정보까지 삭제되어버리는 현상

  • 이러한 이상 현상을 예방하고 효과적인 연산을 하기 위해 데이터 정규화를 합니다.

4. SQL Injection이 무엇인지 설명해주세요.

 

  • SQL Injection이란 공격자가 악의적인 의도를 갖는 SQL 구문을 삽입하여 데이터베이스를 비정상적으로 조작하는 코드 인젝션 공격 기법입니다.

2. JPA에 대해서 한번 알아볼까?

 


1. ORM?

  • Object- Relational Mapping 이름 그대로 객체와 DB의 관계를 매핑 해주는 도구!

    • 객체 즉, 자바의 클래스와 DB의 데이터를 직접 매핑 하려면 앞서 살펴본 것 처럼 매우 번거롭고 많은 작업들이 필요했지만 ORM을 사용하면 이를 자동으로 처리해준다..!!!!!!

  • 장점

    • 객체와 테이블 간의 매핑을 자동으로 처리해 개발 속도가 빨라진다!
    • ORM 프레임 워크를 사용하면 동일한 엔티티 클래스를 여러 프로젝트에서 재사용?!!

  • 단점 

    • 복잡성 : 복잡한 매핑과 연관 관계를 다룰 때 복잡해질 수 있다...

    • 대용량 데이터 처리 시, ORM이 자동으로 생성한 쿼리의 성능이 떨어질 수 있다!

  • 종류

    •  Hibernate : 가장 널리 사용되는 JPA 구현체로, 다양한 기능을 제공한다!
    • EclipseLink : JPA의 참조 구현체!
    • Apache OpenJPA : 아파치 프로젝트에서 제공하는 JPA 구현체!
예시 코드
@Entity  // 이 클래스가 JPA 엔티티임을 나타냄. 데이터베이스 테이블에 매핑됨.
public class User {

    @Id  // 이 필드가 엔티티의 고유 식별자(Primary Key)임을 나타냄.
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // Primary Key 값을 자동으로 생성해줌.
    private Long id;  // 데이터베이스 테이블의 "id" 컬럼에 매핑됨.

    private String username;  // 데이터베이스 테이블의 "username" 컬럼에 매핑됨.
    private String email;  // 데이터베이스 테이블의 "email" 컬럼에 매핑됨.

    // 기본 생성자. JPA는 엔티티 클래스를 인스턴스화할 때 기본 생성자를 사용함.
    public User() {}

    // 모든 필드를 초기화하는 생성자.
    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }

    // Getter와 Setter 메서드. JPA가 필드 값을 읽고 쓸 때 사용함.
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

2. ORM이랑 JPA랑 무슨 관련이 있어요..?

  • JPA(Java Persistence API)는 Java 진영의 ORM 기술 표준으로 채택된 인터페이스 모음!

JPA는 애플리케이션과 JDBC 사이에서 동작되고 있습니다!

 

  • 장점은 뭘까요?
    • SQL을 직접 작성하지 않고도 데이터베이스 작업을 할 수 있다! 따라서 코드 간결! 생산성 증가!

    • 객체지향적인 코드 작성으로 인한 유지 보수 쉬움!

    • JPQL과 같은 추상화된 쿼리 언어를 사용해 특정 DBMS에 종속되지 않아!

  • 그럼 단점은..?

    • 복잡한 데이터 처리 작업에서는 SQL보다 성능이 떨어질 수 있다..

    • JPA의 개념과 동작 원리를 이해하는데 초기 비용이 필요!

3. JPA에서 관리하는 객체? 바로 Entity

DB의 테이블과 매핑되어 JPA에 의해 관리된다!

 

  • 특징이랄까

    • 엔티티 클래스는 데이터베이스 테이블에 매핑되어, 클래스의 각 필드는 테이블의 컬럼과 매핑!

    • 각 엔티티는 고유 식별자가 있어야 하고, 이 식별자는 기본 키로 사용!

  • 장점

    • 엔티티 클래스는 데이터베이스 테이블 구조를 명확히 표현할 수 있다!

    • JPA가 엔티티의 상태를 자동으로 관리해, 데이터베이스와의 동기화가 쉬워진다!

  • 그럼 단점은??

    • 복잡한 매핑이나 특수한 요구사항이 있는 경우 추가적인 설정이 필요!

    • 앤타타 설계까 잘못되면 데이터베이스와의 상호작용이 어려워질 수 있다!

  • 종류로는 무엇이 있을까?

    • 단일 엔티티 : 하나의 테이블과 매핑되는 기본적인 엔티티!
    • 상속 엔티티 : 테이블 간의 상속 관계를 매핑하는 엔티티 (@Inheritance 어노테이션 사용!)

    • 임베디드 엔티티 : 엔티티 내에 포함되는 엔티티로, 별도의 테이블에 매핑되지 않고 포함된 엔티티의 필드가 동일한 테이블에 매핑된다! ( @Embedded 어노테이션 사용!)

  • 어노테이션

    • @Entity : JPA가 관리할 수 있는 Entity 클래스로 지정할 수 있습니다.

      • @Entity(name = "Memo") : Entity 클래스 이름을 지정할 수 있습니다. (default: 클래스명)

      • JPA가 Entity 클래스를 인스턴스화 할 때 기본 생성자를 사용하기 때문에 반드시 현재 Entity 클래스에서 기본 생성자가 생성되고 있는지 확인해야 합니다.

    • @Table : 매핑할 테이블을 지정해줍니다.

      • @Table(name = "memo") : 매핑할 테이블의 이름을 지정할 수 있습니다. (default: Entity 명)

    • @Column :

      • @Column(name = "username") : 필드와 매핑할 ****테이블의 컬럼을 지정할 수 있습니다. (default: 객체의 필드명)

      • @Column(nullable = false) : 데이터의 null 값 허용 여부를 지정할 수 있습니다. (default: true)

      • @Column(unique = true) : 데이터의 중복 값 허용 여부를 지정할 수 있습니다. (default: false)

      • @Column(length = 500) : 데이터 값(문자)의 길이에 제약조건을 걸 수 있습니다. (default: 255)

    • @Id : 테이블의 기본 키를 지정해줍니다.

      • 이 기본 키는 영속성 컨텍스트에서 Entity를 구분하고 관리할 때 사용되는 식별자 역할을 수행합니다.

        • 따라서 기본 키 즉, 식별자 값을 넣어주지 않고 저장하면 오류가 발생합니다.

      • @Id 옵션만 설정하면 기본 키 값을 개발자가 직접 확인하고 넣어줘야 하는 불편함이 발생합니다.

    • @GeneratedValue 옵션을 추가하면 기본 키 생성을 DB에 위임할 수 있습니다.

      • @GeneratedValue(strategy = GenerationType.IDENTITY**)**

      • id bigint not null auto_increment : auto_increment 조건이 추가된 것을 확인할 수 있습니다.

      • 해당 옵션을 추가해주면 개발자가 직접 id 값을 넣어주지 않아도 자동으로 순서에 맞게 기본 키가 추가됩니다.
<예시 코드>
@Entity //JPA가 관리할 수 있는 Entity 클래스 지정
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private double price;

    // Getter, Setter, Constructor
}

4. 영속성 컨텍스트! (PErsistence Context)

 

  • Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간!
  • 영속성 컨텍스트에서 동일한 엔티티는 동일성을 보장해, 즉, 같은 엔티티는 동일한 메모리 참조를 가진다!

  •  EntiryManager? 갑자기 이게 뭐죠..?
    • 영속성 컨텍스트에 접근하여 Entity 객체들을 조작하기 위해서는 EntityManager가 필요하다!

    • EntityManager를 사용해서 Entity를 조회하고 저장하고 수정하고 삭제할 수 있다!

    • EntityManager는 EntityManagerFactory를 통해 생성하여 사용할 수 있다!

  • EntityManagerFactory는 또 뭐야,,,

 

  • EntityManagerFactory는 일반적으로 DB 하나에 하나만 생성되어 애플리케이션이 동작하는 동안 사용된다!

  • EntityManagerFactory를 만들기 위해서는 DB에 대한 정보를 전달해야 한다!
<예시 코드>
EntityManager em = ...;  // EntityManager는 JPA의 핵심 클래스. 엔티티를 관리하고 데이터베이스 작업을 수행함.

em.getTransaction().begin();  // 트랜잭션을 시작함. JPA는 트랜잭션 내에서 작업을 처리함.

Customer customer = new Customer("Winter", "winter@sm.com");  // 새로운 Customer 엔티티 객체를 생성함.
em.persist(customer);  // 생성한 엔티티를 영속성 컨텍스트에 저장함. 이제 이 엔티티는 영속 상태가 됨.

Customer foundCustomer = em.find(Customer.class, customer.getId());  
// 영속성 컨텍스트에서 Customer 엔티티를 ID로 조회함. 영속성 컨텍스트에 이미 존재하면 1차 캐시에서 반환됨.

foundCustomer.setName("Karina");  
// 조회된 엔티티의 값을 변경함. 영속성 컨텍스트는 이 변경을 감지하고, 트랜잭션 커밋 시점에 데이터베이스에 반영함.

em.getTransaction().commit();  // 트랜잭션을 커밋함. 이 시점에 변경된 사항이 데이터베이스에 반영됨.

 


5. JPA 트랜젝션 ,, 뭐가 이렇게 많지,,?

 

 

  • 우선 트랜젝션이 뭐지?
    • 트랜잭션은 DB 데이터들의 무결성과 정합성을 유지하기 위한 하나의 논리적 개념! (어렵다;)
      • 쉽게 표현하자면 DB의 데이터들을 안전하게 관리하기 위해서 생겨난 개념이다!
    • 가장 큰 특징은 여러개의 SQL이 하나의 트랜잭션에 포함될 수 있다는 점이다!

    • 모든 SQL이 성공적으로 수행이 되면 DB에 영구적으로 변경을 반영하지만 SQL 중 단 하나라도 실패한다면 모든 변경을 되돌린다..?

    • 명령어
      • JPA에서 이러한 트랜잭션의 개념을 적용하기 위해서는 EntityManager에서 EntityTransaction을 가져와 트랜잭션을 적용할 수 있습니다.

      • EntityTransaction et = em.getTransaction();

      • 해당 코드를 호출하여 EntityTransaction을 가져와 트랜잭션을 관리할 수 있습니다.

      • et.begin();
        • 트랜잭션을 시작하는 명령어입니다.
      • et.commit();
        • 트랜잭션의 작업들을 영구적으로 DB에 반영하는 명령어입니다.

      • et.rollback();
        • 오류가 발생했을 때 트랜잭션의 작업을 모두 취소하고, 이전 상태로 되돌리는 명령어입니다!.
<예시 코드>
@Service  // 이 클래스가 Spring 서비스 클래스임을 나타냄. 비즈니스 로직을 처리하는 곳임.
public class OrderService {

    @Autowired  // Spring이 EntityManager를 자동으로 주입하도록 함.
    private EntityManager em;  // EntityManager는 JPA의 핵심 인터페이스로, 엔티티 관리를 담당함.

    @Transactional  // 이 메서드가 트랜잭션 안에서 실행됨을 나타냄. 메서드 내 모든 작업은 하나의 트랜잭션으로 묶임.
    public void placeOrder(Long productId, int quantity) {
        Product product = em.find(Product.class, productId);  
        // 특정 ID로 Product 엔티티를 조회함. 영속성 컨텍스트에서 조회되며, 없으면 데이터베이스에서 조회됨.

        // 비즈니스 로직 처리 (예: 재고 확인, 가격 계산 등)
        // 이 부분에서 주문 처리에 필요한 추가 로직을 작성할 수 있음.

        em.persist(new Order(product, quantity));  
        // 새로운 Order 엔티티를 생성하고 영속성 컨텍스트에 저장함. 주문이 생성됨.

        // 트랜잭션이 종료될 때 (메서드 종료 시점) 변경사항이 자동으로 커밋되어 데이터베이스에 반영됨.
    }
}