메소드 이름만으로 쿼리를 자동 생성해주는 기능
SQL이나 JPQL을 직접 작성하지 않아도, 정해진 네이밍 규칙대로 메소드를 작성하면 Spring이 알아서 쿼리를 만들어준다.
List<User> findByUsername(String username); 를 작성하면 Spring Data JPA는 자동으로
SELECT u FROM User u WHERE u.username = :username JPQL을 생성한다.
findBy | 필드명 | [조건]
| 메서드 이름 | 생성되는 쿼리 |
|---|---|
findByUsername(String name) | WHERE username = ? |
findByEmailAndStatus(String e, String s) | WHERE email = ? AND status = ? |
findByAgeGreaterThan(int age) | WHERE age > ? |
findByCreatedAtBetween(start, end) | WHERE created_at BETWEEN ? AND ? |
| 키워드 | 의미 |
|---|---|
And, Or | 논리 조건 연결 |
Between | 범위 조회 |
LessThan, GreaterThan | <, > 비교 |
Like, Containing, StartingWith, EndingWith | 문자열 검색 |
In, NotIn | 목록 포함 여부 |
IsNull, IsNotNull | null 체크 |
OrderBy | 정렬 조건 |
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByAgeGreaterThan(int age);
User findByEmailAndStatus(String email, String status);
List<User> findByNameContaining(String keyword);
List<User> findTop3ByOrderByCreatedAtDesc();
}
@Query나 Querydsl 사용 권장Spring Data JPA에서 쿼리를 직접 작성하고 싶을 때 사용하는 어노테이션
복잡한 조건이나 조인 등은 메소드 이름만으로 표현하기 어렵기 때문에 @Query를 사용해 직접 JPQL 또는 SQL을 작성한다.
@Query("SELECT u FROM User u WHERE u.username = :username")
User findByUsername(@Param("username") String username);
SELECT u FROM User u... → JPQL (엔티티 기준의 쿼리)
:username → 파라미터 바인딩
// JPQL
@Query("SELECT u FROM User u WHERE u.age >= :age")
List<User> findUsersOlderThan(@Param("age") int age);
// 네이티브 SQL
@Query(value = "SELECT * FROM users WHERE email = :email", nativeQuery = true)
User findByEmailNative(@Param("email") String email);
// LIKE 검색
@Query("SELECT u FROM User u WHERE u.name LIKE %:name%")
List<User> searchByName(@Param("name") String name);
데이터를 수정하거나 삭제할 경우
@Modifying과 함께 사용한다.
@Modifying
@Query("UPDATE User u SET u.status = 'INACTIVE' WHERE u.lastLogin < :date")
int deactivateOldUsers(@Param("date") LocalDate date);
이 경우 트랜잭션 처리를 위해 @Transactional도 함께 붙이거나, 서비스에서 트랜잭션을 관리해야한다.
자바 코드로 SQL처럼 타입 안정성 있는 쿼리를 작성할 수 있게 해주는 프레임워크
Spring Data JPA와 함꼐 사용되며, 복잡한 조건 쿼리를 안전하고 깔끔하게 처리한다.
기존의 JPQL이나 @Query는 문자열 기반이라 컴파일 시점에 오류를 잡을 수 없지만, Querydsl은 자바 코드로 작성되므로 컴파일 타임에 오류를 잡을 수 있고 IDE 자동완성도 지원한다.
QUser.java, QOrder.java 등)
@RequiredArgsConstructor
@Repository
public class UserQueryRepository {
private final JPAQueryFactory queryFactory;
public List<User> findByName(String name) {
QUser user = QUser.user;
return queryFactory
.selectFrom(user)
.where(user.name.eq(name))
.fetch();
}
}
// 일반 JPQL
@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findByAgeGreaterThan(@Param("age") int age);
// Querydsl
// QUser는 Querydsl이 User 엔티티로부터 자동 생성한 클래스
QUser user = QUser.user;
List<User> result = queryFactory
.selectFrom(user)
.where(user.age.gt(20))
.fetch();
.select(), .from(), .where() : SQL 유사한 문법으로 조건 설정.fetch() : 리스트 결과 반환, .fetchOne() 은 단일 결과where()에 포함 가능HTML을 기반으로 한 서버 사이드 템플릿 엔진
HTML, XML, JavaScript, CSS, 텍스트 등을 렌더링할 수 있는 템플릿 엔진으로, HTML 파일 안에 특별한 속성(attribute)이나 문법을 삽입해서 동적으로 데이터를 출력할 수 있다.
<!-- 변수 출력 -->
<p th:text="${name}">홍길동</p> <!-- name 변수가 가진 값 출력 -->
<!-- 조건문 -->
<p th:if="${age > 18}">성인입니다</p>
<!-- 반복문 -->
<ul>
<li th:each="item : ${itemList}" th:text="${item.name}"></li>
</ul>
<!-- 링크 처리 -->
<a th:href="@{/user/{id}(id=${user.id})}">프로필 보기</a>
| 속성 | 설명 |
|---|---|
th:text | 텍스트 출력 (HTML 이스케이프됨) |
th:utext | 텍스트 출력 (HTML 이스케이프 안 함) |
th:if / th:unless | 조건문 |
th:each | 반복문 |
th:href / th:src | 링크, 이미지 경로 바인딩 |
th:object, *{} | 폼 바인딩에 사용 |
| 항목 | JSP | Thymeleaf |
|---|---|---|
| 문법 | Java 코드 삽입 가능 (<%= %>) | HTML에 속성 방식으로 데이터 바인딩 (th:*) |
| 디자인 확인 | 브라우저에서 직접 보기 어려움 | HTML만으로 디자인 확인 가능 |
| 설정 복잡성 | 톰캣 + JSP 설정 필요 | Spring Boot에서 바로 사용 가능 |
| 학습 난이도 | Java와의 혼합 문법 | HTML 친화적 문법 |
| 레이아웃 재사용 | JSP include 태그 사용 | th:replace, th:fragment 등 유연한 구조 사용 |
오늘은 스프링에서의 쿼리 사용법과 타임리프에 대해 공부했다.
Querydsl은 조건이 많거나 동적으로 쿼리가 달라지는 경우에 유용하며, 성능 최적화를 위한 세밀한 쿼리 제어가 가능하다. 또한 타입 안정성과 자동완성 기능을 제공해 복잡한 쿼리를 안정적으로 작성할 수 있다.
타임리프는 정적 HTML 파일로도 열람이 가능해 템플릿 미리보기에 유리하며, 스프링 MVC와의 통합이 자연스럽다. 표현 방식이 직관적이고 읽기 쉬워 EL 표현식보다 가독성이 좋으며, Spring Form과 연동되어 폼 입력 처리에도 적합하다.