반응형
Spring Boot + Thymeleaf로 레거시 프로젝트 마이그레이션 및 JPQL 문제 해결 (주니어/1인 개발자 가이드)
이 글은 Spring MVC + JSP + MyBatis 레거시 프로젝트를 Spring Boot + JPA + Thymeleaf로 마이그레이션하고, JPQL(@Query) 문제를 해결하는 과정을 주니어 개발자와 1인 개발자가 이해하기 쉽도록 정리한 가이드입니다. 하루 동안 진행한 모든 내용을 빠짐없이 담았습니다.
1️⃣ 기존 레거시 구조 분석
- Spring MVC + JSP + MyBatis + XML 설정
- JSP 기반 뷰와 SQL 매퍼(XML) 사용
- MariaDB 기반 DB, 주요 테이블: CATEGORY_CODE
2️⃣ 마이그레이션 목표 및 진행
- Spring Boot 3.5.0 + JPA(Hibernate) + Thymeleaf
- Maven 빌드, WAR 패키징
- JSP → Thymeleaf 변환 (Layout Dialect 적용)
- DB 연결: MariaDB
- Entity 매핑: CategoryCode
3️⃣ CATEGORY_CODE 테이블 정의 및 Entity
테이블 DDL
CREATE TABLE CATEGORY_CODE (
seq_category int(11) AUTO_INCREMENT PRIMARY KEY,
category_code varchar(20),
category_code_up varchar(20),
category_code_nm varchar(100),
category_del varchar(5)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CategoryCode Entity
package com.chopping.adminbridge.recipe.entity;
@Entity
@Table(name = "CATEGORY_CODE")
public class CategoryCode {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "seq_category")
private Integer seqCategory;
@Column(name = "category_code")
private String categoryCode;
@Column(name = "category_code_up")
private String categoryCodeUp;
@Column(name = "category_code_nm")
private String categoryCodeNm;
@Column(name = "category_del")
private String categoryDel;
// getters, setters, toString()
}
4️⃣ JPQL(@Query) 문제 및 정상화 시도
JPQL 코드
@Query("SELECT c FROM CategoryCode c WHERE c.categoryDel <> 'Y' AND (c.categoryCodeUp = :category OR c.categoryCode = :category)")
List<CategoryCode> findActiveCategoryCodes(@Param("category") String category);
문제 원인
- JPQL은 Entity 필드명을 기반으로 작성, Hibernate 메타정보와 동기화 필요
- 하지만 ddl-auto: update 상태에서 Hibernate가 DB 스키마 메타정보를 잘못 인식 가능성
- DB에서는 정상 동작하지만 Hibernate Prepared Statement에서는 데이터 조회 실패
5️⃣ Native Query 적용 (JPQL 대안)
Native Query 코드
@Query(value = "SELECT * FROM CATEGORY_CODE WHERE category_del <> 'Y' AND (category_code_up = :category OR category_code = :category)", nativeQuery = true)
List<CategoryCode> findActiveCategoryCodes(@Param("category") String category);
Native Query 결과
- Hibernate 로그: result.size() = 6 (category), result.size() = 9 (timeInfo)
- DB와 동일하게 동작, JPQL의 문제를 우회
6️⃣ Hibernate 설정 및 ddl-auto: none 예제
spring:
jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate.format_sql: true
hibernate.use_sql_comments: true
ddl-auto를 none으로 설정하면 Hibernate가 스키마를 변경하지 않아 메타정보 문제 방지
7️⃣ Native Query vs JPQL 비교
구분 | Native Query | JPQL |
---|---|---|
문법 | SQL 그대로 | Entity 필드명 기반 |
동작 | DB 직접 실행 | Hibernate SQL 생성 |
성능 | 복잡 SQL에서 유리 | 단순 쿼리 효율적 |
유연성 | DB별 최적화 가능 | DB 독립적 |
단점 | DB 종속 | 메타정보 동기화 필요 |
8️⃣ Thymeleaf Layout Dialect 적용
- 레이아웃 구성: layout.html 파일 생성
- Thymeleaf fragment: <div th:replace="~{fragments/navigation :: navigation}">
- layout:decorate="~{layout}"으로 공통 레이아웃 적용
9️⃣ 정리 및 추천
- Entity 매핑은 정상이나 JPQL(@Query)에서는 Hibernate 메타정보 동기화 문제 발생
- Native Query로 동작 확인 및 데이터 정상 반환
- JPQL 정상화를 위해 ddl-auto: none, show-sql, format_sql 설정 추천
- 복잡 쿼리에서는 Native Query 유지도 좋은 선택
도움되셨다면 댓글과 공감 부탁드려요!
반응형
'1인개발자에서 살아남는법! > 시리즈' 카테고리의 다른 글
[#6 Spring boot] Spring Boot + Ajax 파일 업로드 가이드 (0) | 2025.06.02 |
---|---|
[#5 spring boot] 기능 구현 예제 적용 – 레시피 게시판 CRUD 및 Thymeleaf 연동 (0) | 2025.06.01 |
[#3 spring boot] JSP 기반 레거시 프로젝트, Spring Boot + Thymeleaf로 마이그레이션하기 (0) | 2025.05.30 |
[#2 spring boot] application.yml 구성 및 MariaDB 연동 – Spring Boot 설정 완벽 가이드 (0) | 2025.05.24 |
[#1 Spring Boot] 프로젝트 생성 및 WAR 설정 (0) | 2025.05.24 |