📌 기본 정보
- 주차/주제: 5주차 - 데이터베이스 연동 기초
📚 학습 내용 요약
1. JPA와 Hibernate의 관계 및 주요 개념
JPA(Java Persistence API)
- 자바 객체와 관계형 데이터베이스를 연결하기 위한 표준 인터페이스(API)
- 주요 기능
- 엔티티 매핑: 자바 클래스 ↔ DB 테이블
- 엔티티 관리: 객체 상태(비영속, 영속, 분리, 삭제) 추적 및 CRUD 자동 처리
- 트랜잭션 관리: 커밋·롤백 처리
- 쿼리 언어(JPQL): 객체 지향적인 방식으로 데이터베이스에 쿼리를 날릴 수 있도록 해주는 JPQL(Java Persistence Query Language)
- JPA를 구현한 대표적 ORM (Object-Relational Mapping) 프레임워크
- 추가 기능
- 영속성 컨텍스트
- 1차 캐시: 조회 시 메모리 캐시 우선 사용
- 쓰기 지연(Write-Behind): 트랜잭션 커밋 전에 SQL을 모아 한 번에 실행
- 변경 감지(Dirty Checking): 커밋 시점에 변경된 엔티티를 자동 반영
- 지연 로딩(Lazy Loading): 실제 사용할 때만 관련 데이터를 조회
- 자동 생성 SQL: 직접 SQL 작성 없이도 CRUD 가능
- 영속성 컨텍스트

- 주요 기능
JPA는 “무엇을 할지” 규격만 정의하고, Hibernate는 “어떻게 할지” 실제 동작을 구현한 라이브러리

JPA vs Hibernate vs Spring Data JPA
JPA (Java Persistence API)
• 자바 객체와 관계형 DB를 연결하는 ORM 표준 인터페이스
• SQL 지식 없이도 엔티티 객체를 통해 DB 조작 가능
• 비즈니스 로직에 집중, DB 종속성 감소
• 복잡·무거운 쿼리는 어려움
Hibernate
• JPA 인터페이스 대표 구현체
• JDBC API 위에서 동작하는 자바용 ORM 프레임워크
• 영속성 컨텍스트
• 1차 캐시 (조회 시 캐시 활용)
• 쓰기 지연 (트랜잭션 커밋 전 배치 실행)
• 변경 감지 (커밋 시 자동 반영)
• 지연 로딩 (필요 시 쿼리 실행)
Spring Data JPA
• 스프링이 JPA 위에 편리 기능을 추가한 모듈
• PagingAndSortingRepository 상속한 JpaRepository 제공
• 인터페이스 선언만으로 기본 CRUD + 페이징·정렬 기능 자동 제공
public interface MemberRepository extends JpaRepository<Member, Long> {
} // 기본 CRUD 사용 가능
2. Entity·Repository 관련 어노테이션
어노테이션용도| @Entity | 클래스가 DB 테이블과 매핑되는 JPA 엔티티임을 선언 |
| @Id | 해당 필드를 엔티티의 PK(기본 키)로 지정 |
| @GeneratedValue | PK 값을 자동 생성 전략(IDENTITY, SEQUENCE 등)으로 지정 |
| @Table | 엔티티가 매핑될 테이블 이름·스키마 등 커스터마이징 |
| @Column | 컬럼 이름·제약조건·길이 등을 커스터마이징 |
| @Repository | 해당 클래스를 JPA 데이터 액세스 계층 빈으로 등록, 예외를DataAccessException으로 변환 |
| @Transactional | 메서드 또는 클래스 단위로 트랜잭션 시작·커밋·롤백 자동 관리 |
| @PersistenceContext | EntityManager 주입 시 사용 (JPA 표준) |
| @Autowired | Spring 컨텍스트에서 EntityManager 또는 Repository 빈 주입 시 사용 |
@Entity : 클래스가 DB 테이블과 매핑되는 JPA 엔티티임을 선언
@Id : 해당 필드를 엔티티의 PK(기본 키)로 지정
@GeneratedValue : PK 값을 자동 생성 전략(IDENTITY, SEQUENCE 등)으로 지정
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
@Repository : 해당 클래스가 JPA 데이터 액세스 계층임을 나타내는
@Repository // @Component와 동일한 역할
public class MemberRepository {
// 데이터베이스와의 상호작용 구현
}
@Transactional : 메서드 또는 클래스 단위로 트랜잭션 시작·커밋·롤백 자동 관리
@Transactional
public void saveMember(Member member) {
memberRepository.save(member);
}
@Table
@Entity
@Table(name = "members")// 이 엔티티는 members 테이블에 매핑된다
public class Member {
...
// 컬럼 이름을 username 으로 지정
@Column(name = "username",
// 아무 속성 없이 쓰면, 필드명이 컬럼명이 된다
@Column
private String email;
@PersistenceContext
@PersistenceContext
private EntityManager em; // JPA 표준 EntityManager
@Autowired 대신 @PersistenceContext를 써야 영속성 컨텍스트가 올바르게 연결
H2 JDBC URL 모드별 차이
모드URL 예시설명| 로컬 파일 모드 (Embedded File) | jdbc:h2:~/test | - 홈 디렉터리(~)에 test.mv.db 파일로 영구 저장- 애플리케이션 프로세스가 꺼져도 데이터 유지 |
| TCP 서버 모드 (Server-TCP) | jdbc:h2:tcp://localhost/~/test | - 별도의 H2 서버 프로세스를 띄워 파일 모드 DB를 TCP로 공유- 다중 애플리케이션에서 같은 DB 접속 가능 |
| 인메모리 모드 (In-Memory) | jdbc:h2:mem:testdb | - 메모리 상에만 존재, 애플리케이션이 종료되면 사라짐- 빠른 테스트용, 별도 서버 불필요 |
http://localhost:8080/h2-console

gradle , 의존성 설정
# (1) datasource URL만으로 드라이버 자동 감지
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
# (2) Hibernate Dialect는 JPA 스타터가 자동 선택
spring.application.name=springboot-developer
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.defer-datasource-initialization=true
# Hibernate DDL
spring.jpa.hibernate.ddl-auto=update
# H2
spring.h2.console.enabled=true
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2' // 인메모리 데이터베이스
implementation 'org.projectlombok:lombok:1.18.22' // Add Lombok dependency
annotationProcessor 'org.projectlombok:lombok:1.18.22' // Add annotation processor
}
SQL
CREATE TABLE member (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50)
);
INSERT INTO member(name) VALUES('A'),('B');
SELECT * FROM member;
INSERT INTO article (title, content) VALUES ('제목 1', '내용 1');
INSERT INTO article (title, content) VALUES ('제목 2', '내용 2');
INSERT INTO article (title, content) VALUES ('제목 3', '내용 3');


💡 새롭게 알게 된 점 & 어려웠던 부분
- 관련 어노테이션을 찾아보면서, 몰랐던 기능과 잘못알고 있던 지식들을 바로 잡을 수 있게 되었다.
👥 스터디 피드백
Spring Data JPA를 사용하며 느꼈던 장단점
장점
- @Query 어노테이션사용 → JPQL 간단히 추가 가능
- JPARepository 상속으로 기본 CRUD 모두 제공 가능
- 트랜잭션, 예외처리가 자동 → 깔끔한 코드
단점
- 복잡한 JOIN쿼리 같은경우 코드가 지저분해 보일 수 있음
- 연관관계가 복잡할수록 N+1 문제가 쉽게 발생
엔티티 클래스에 비즈니스 로직을 추가하면 어떨까요?
관련 로직이 엔티티 안에 모여 있어 이해,유지보수가 용이하지만,
엔티티 내부 로직이 데이터 접근, 의존하게 되면 단위테스트가 어려울 수 있음
→ 단순 검증, 상태 전환 같은 핵심 비즈니스 로직은 엔티티 메서드로 구현해도 되지만
복잡하거나 외부 호출을 포함하는 비즈니스 로직은 서비스 계층에 두어 책임을 명확히 분리해야하지 않을까 싶음.
이 외에도 다른 팀원분들과의 토론을 진행했습니다.