Spring Boot로 게시판이나 커뮤니티 서비스를 만들다 보면 데이터를 저장하고 조회하는 기능이 반드시 필요하다.
회원가입을 하면 회원 정보를 저장해야 하고, 로그인을 할 때는 아이디로 회원을 찾아야 한다.
게시글을 작성하면 게시글 데이터를 저장해야 하고, 댓글을 작성하면 댓글 데이터도 데이터베이스에 남겨야 한다.
이처럼 대부분의 웹 애플리케이션은 데이터베이스와 연결되어 동작한다.
처음에는 SQL을 직접 작성해서 데이터를 저장하고 조회할 수도 있다.
SELECT * FROM user_entity WHERE user_id = 'test123';하지만 프로젝트가 커질수록 SQL을 직접 관리하는 방식은 점점 복잡해진다.
이때 Spring에서 많이 사용하는 기술이 바로 JPA다.
이번 글에서는 JPA가 무엇인지, 그리고 Spring Boot 프로젝트에서 JpaRepository가 어떤 역할을 하는지 정리해보려고 한다.
JPA란 무엇일까?JPA는 Java Persistence API의 줄임말이다.
쉽게 말하면 자바 객체와 데이터베이스 테이블을 연결해서 관리할 수 있도록 도와주는 기술이다.
일반적으로 데이터베이스에는 테이블이 있고, 자바에는 객체가 있다.
예를 들어 회원 테이블은 이런 구조를 가질 수 있다.
user_entity - id - user_name - user_id - password - role자바에서는 이 테이블을 엔티티 클래스로 표현할 수 있다.
@Entity public class UserEntity { @Id private Long id; private String userName; private String userId; private String password; }JPA는 이 자바 객체와 데이터베이스 테이블을 연결해준다.
즉, 개발자가 객체를 저장하면 JPA가 적절한 SQL을 만들어 데이터베이스에 저장하고, 데이터베이스에서 조회한 결과를 다시 객체로 바꿔준다.
JPA를 사용하는 이유JPA를 사용하는 가장 큰 이유는 반복적인 SQL 작업을 줄일 수 있기 때문이다.
예를 들어 회원을 저장한다고 생각해보자.
JPA를 사용하지 않으면 직접 SQL을 작성해야 한다.
INSERT INTO user_entity (user_name, user_id, password) VALUES ('홍길동', 'hong123', '1234');반면 JPA를 사용하면 자바 객체를 저장하는 방식으로 처리할 수 있다.
userRepository.save(userEntity);개발자는 객체 중심으로 코드를 작성하고, 실제 SQL 생성과 실행은 JPA가 처리한다.
물론 JPA가 SQL을 완전히 몰라도 되는 기술이라는 뜻은 아니다.
실제 서비스에서는 성능 문제나 복잡한 조회가 생길 수 있기 때문에 SQL과 데이터베이스에 대한 이해도 필요하다.
다만 기본적인 저장, 조회, 수정, 삭제 작업을 더 객체지향적으로 처리할 수 있게 해준다는 점에서 JPA는 매우 유용하다.
ORM이란 개념도 함께 알아야 한다JPA를 설명할 때 자주 나오는 말이 ORM이다.
ORM은 Object Relational Mapping의 줄임말이다.
말 그대로 객체와 관계형 데이터베이스를 매핑한다는 뜻이다.
Object - 자바 객체 Relational - 관계형 데이터베이스 Mapping - 서로 연결해주는 것자바에서는 객체를 사용하고, 데이터베이스에서는 테이블을 사용한다.
두 세계는 구조가 다르기 때문에 중간에서 연결해주는 기술이 필요하다.
JPA는 자바에서 ORM을 사용할 수 있도록 정해둔 표준 방식이라고 볼 수 있다.
JPA, Hibernate, Spring Data JPA의 차이처음 공부할 때 가장 헷갈리는 부분이 있다.
바로 JPA, Hibernate, Spring Data JPA의 차이다.
간단히 정리하면 다음과 같다.
JPA - 자바 ORM 표준 인터페이스 - 이런 방식으로 동작해야 한다는 규칙에 가깝다 Hibernate - JPA를 실제로 구현한 대표적인 구현체 - Spring Boot에서 많이 사용된다 Spring Data JPA - JPA를 더 편하게 사용할 수 있도록 도와주는 Spring 프로젝트 - Repository 인터페이스만으로 기본 CRUD를 쉽게 사용할 수 있다비유하면 JPA는 규칙이고, Hibernate는 그 규칙을 실제로 구현한 도구이며, Spring Data JPA는 그 도구를 더 편하게 사용할 수 있도록 감싸주는 기능이라고 볼 수 있다.
실제 Spring Boot 프로젝트에서는 보통 JpaRepository를 많이 사용한다.
실제 Repository 코드 예시내 프로젝트에서는 회원 데이터를 다루기 위해 다음과 같은 Repository를 사용했다.
public interface UserRepository extends JpaRepository<UserEntity, Long> { Optional<UserEntity> findByUserName(String username); Optional<UserEntity> findByUserId(String userId); boolean existsByUserName(String username); boolean existsByUserId(String userId); }이 코드가 처음에는 신기하게 느껴질 수 있다.
분명 SQL을 직접 작성하지 않았는데도 회원 이름으로 조회하거나, 아이디가 이미 존재하는지 확인할 수 있기 때문이다.
여기에 실제 UserRepository 코드 캡처 이미지를 넣으면 좋다.
실제 프로젝트에서 사용한 UserRepository 코드 예시
JpaRepository는 어떤 역할을 할까?다음 부분을 보자.
public interface UserRepository extends JpaRepository<UserEntity, Long>여기서 JpaRepository<UserEntity, Long>은 이 Repository가 UserEntity를 다룬다는 뜻이다.
뒤에 있는 Long은 엔티티의 기본 키 타입이다.
즉, 이 코드는 다음과 같은 의미를 가진다.
UserRepository는 UserEntity를 데이터베이스에 저장하고 조회하는 Repository다. UserEntity의 ID 타입은 Long이다.JpaRepository를 상속하면 기본적인 CRUD 기능을 바로 사용할 수 있다.
예를 들면 다음과 같은 기능이다.
userRepository.save(user); userRepository.findById(1L); userRepository.findAll(); userRepository.delete(user);직접 SQL을 작성하지 않아도 저장, 단건 조회, 전체 조회, 삭제 같은 기본 기능을 사용할 수 있다.
메서드 이름만으로 쿼리가 만들어지는 이유Spring Data JPA의 편리한 점 중 하나는 메서드 이름을 분석해서 쿼리를 만들어준다는 점이다.
예를 들어 이 메서드를 보자.
Optional<UserEntity> findByUserId(String userId);이 메서드는 이름 그대로 userId 필드를 기준으로 회원을 찾는 기능이다.
SQL로 생각하면 대략 이런 의미다.
SELECT * FROM user_entity WHERE user_id = ?;또 다른 예시도 있다.
boolean existsByUserId(String userId);이 메서드는 특정 userId가 이미 존재하는지 확인한다.
회원가입을 할 때 이미 사용 중인 아이디인지 검사하는 상황에서 사용할 수 있다.
if (userRepository.existsByUserId(request.getUserId())) { throw new IllegalArgumentException("이미 사용 중인 아이디입니다."); }이처럼 Spring Data JPA는 정해진 규칙에 맞게 메서드 이름을 작성하면, 그 이름을 분석해서 필요한 쿼리를 만들어준다.
Optional을 사용하는 이유코드를 보면 조회 결과 타입이 Optional<UserEntity>로 되어 있다.
Optional<UserEntity> findByUserId(String userId);Optional은 값이 있을 수도 있고 없을 수도 있다는 것을 표현하는 타입이다.
예를 들어 로그인할 때 사용자가 입력한 아이디로 회원을 찾는다고 생각해보자.
아이디가 존재하면 UserEntity가 조회된다.
하지만 존재하지 않는 아이디라면 조회 결과가 없을 수 있다.
이런 경우 null을 그대로 다루면 NullPointerException 같은 문제가 생길 수 있다.
Optional을 사용하면 조회 결과가 없을 수 있다는 사실을 코드에서 명확하게 표현할 수 있다.
UserEntity user = userRepository.findByUserId(userId) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회원입니다."));이렇게 하면 회원이 없을 때 예외를 던지는 흐름을 명확하게 작성할 수 있다.
JPA를 사용하면 무조건 SQL을 몰라도 될까?그렇지는 않다.
JPA는 반복적인 SQL 작성을 줄여주는 강력한 도구지만, 데이터베이스를 완전히 몰라도 되는 기술은 아니다.
실제 서비스에서는 다음과 같은 문제를 고민해야 한다.
어떤 SQL이 실행되는가? 조회 성능은 괜찮은가? 불필요한 쿼리가 많이 나가지는 않는가? 연관관계 로딩 방식은 적절한가? 트랜잭션 범위는 올바른가?JPA를 사용하면 기본 CRUD는 편해지지만, 복잡한 조회나 성능 최적화가 필요한 상황에서는 SQL과 JPA 동작 원리를 함께 이해해야 한다.
즉, JPA는 SQL을 대체하는 마법이 아니라, 객체와 데이터베이스 사이의 반복 작업을 줄여주는 도구라고 보는 것이 좋다.
JPA를 사용했을 때의 장점JPA의 장점은 여러 가지가 있다.
첫 번째는 반복적인 SQL 코드가 줄어든다는 점이다.
기본적인 저장, 조회, 수정, 삭제는 Repository를 통해 간단하게 처리할 수 있다.
두 번째는 객체 중심으로 개발할 수 있다는 점이다.
데이터베이스 테이블만 바라보는 것이 아니라, 자바 엔티티를 중심으로 비즈니스 로직을 작성할 수 있다.
세 번째는 유지보수에 도움이 된다는 점이다.
Repository, Entity, Service 계층을 나누면 데이터 접근 로직과 비즈니스 로직을 분리할 수 있다.
네 번째는 Spring Data JPA를 함께 사용하면 개발 속도가 빨라진다는 점이다.
메서드 이름만으로 간단한 조회 쿼리를 만들 수 있고, 기본 CRUD 기능도 이미 제공되기 때문에 초반 개발 속도가 빨라진다.
하지만 실제로는 객체와 데이터베이스 사이의 차이를 줄이고, 반복적인 데이터 접근 코드를 줄여주는 기술에 가깝다.
JPA를 제대로 사용하려면 엔티티, Repository, DTO, 트랜잭션, SQL 동작 방식까지 함께 이해하는 것이 좋다.
게시판이나 커뮤니티 프로젝트를 만들면서 JPA를 사용해보면, 데이터 저장과 조회가 어떻게 객체 중심으로 바뀌는지 자연스럽게 이해할 수 있다.
댓글 0개
실시간 인기글






