Spring Framework (3) - 타임리프, Mybatis 환경설정 Day 50

jaehoon ahn·2025년 11월 28일

Spring boot

목록 보기
3/20
post-thumbnail

요청 위임된 request에 존재하는 파라미터 출력하기

    ${param.key}

    - request에 존재하는 parameter 값 얻어와 출력
    - 요청 URL에 쿼리스트링(GET)이나 폼 데이터(POST)로 전달된 파라미터 값을
    직접 req에 세팅하지 않아도 바로 접근할 수 있도록 해줌
<ul>
      <li th:text="${param.inputName}">제출된 이름</li>
      <li th:text="${param.inputAge}">제출된 나이</li>
      <!-- 같은 name 속성값(key)을 가진 파라미터는 배열로 전달 -->
      <li th:text="${param.color}">제출된 색상</li>
      <!-- 전달된 파라미터값이 없으면 null == 빈문자열임 -->
      <!-- 타임리프에서는 null값을 빈문자열("")로 처리함 -->

      <!-- 반복할 배열/리스트가 존재하지 않으면 반복 자체를 안함 -->
      <li th:each="c : ${param.color}" th:text="${c}"></li>
    </ul>

th:text / th:utext

        th:text = "속성값"
        - 해당 태그에 "속성값"을 내용으로 출력
        - 단, html 태그, 특수문자는 해석하지 못함

        th:utext = "속성값"
        - 해당 태그에 "속성값"을 내용으로 출력
        - 단, html 태그, 특수문자 해석 o (innerHTML)
<div>
      <h4>th:text (HTML 태그 해석 X)</h4>
      <th:block th:text="${str}">str</th:block>
    </div>
    <div>
      <h4>th:utext (HTML 태그 해석 O)</h4>
      <th:block th:utext="${str}">str</th:block>
    </div>

th:text / th:utext 출력 시 변수에 저장된 값이 아닌 임의 내용

        1. th:text="|문자열 ${}|"
        - 해당 요소의 내용으로 "문자열" + 변수값 출력

        또는
        2. + 연산으로 이어쓰기도 가능
<p th:text="|th:text의 str 값 => ${str}|"></p>
    <p th:utext="|th:utext의 str 값 => ${str}|"></p>
    <p th:text="${str} + 짠"></p>

th:text / th:utext 대신하는 특수 기호

<p>입력 받은 이름 : [[${param.inputName}]]</p>
    [(${str})]

meesages.properties(보류)

⇒ 서버 실행 안됨 ⇒ 문제 해결하기

타임리프를 이용한 쿼리스트링 작성법

링크(url) 조합에 사용되는 Spring EL (@{})

<a href="/board?key=제목&query=검색어">게시판(/board)</a>
// 위 형태를 다음과 같이 작성해준다

=>  
<a th:href="@{/board(key=${key}, query=${query})}">게시판(/board)</a>

타임리프를 이용한 요청 주소 작성법

<a th:href="@{/example/ex3/{number}(number=${boardNo})}">
/example/ex3/10</a>

PathVariable

⇒ PathVariable : 주소 중 일부분을 변수값처럼 사용

 <li><a href="/example/ex3/1">/example/ex3/1</a></li>
 <li><a href="/example/ex3/2">/example/ex3/2</a></li>
 <li><a href="/example/ex3/3">/example/ex3/3</a></li>
@GetMapping("ex3/{path}")
	public String pathVariableTest(@PathVariable("path") int path) {
		// controller에서 해야하는 로직이 동일한 경우에
		// example/ex3/1, example/ex3/2, example/ex3/3 ...
		// 주소 중 {path} 부분의 값을 가져와서 매개변수로 저장
		// 이 매개변수 값을 controller 단의 메서드에서
		// 사용할 수 있도록 해줌 (이 값을 Service -> DAO -> DB)
		// + Request scope에 자동 세팅됨
		// 변수명=값 => 변수명은 {변수명}이 변수명이 됨
		// 즉, forward한 view에서 path를 사용할 수 있다는 의미
		return "example/testResult";
	}

타임리프 조건문 [1] - th:if / th:unless

      th:if=${조건식}
      - 조건식이 true인 경우에만 해당 속성이 작성된 요소를
      화면에 출력

      th:unless=${조건식}
      - 조건식이 false인 경우에만 해당 속성이 작성된 요소를
      화면에 출력
<h3 th:if="${std}">std 있음!!!</h3>
<h3 th:unless="${std}">std 없음!!!</h3>

타임리프 조건문 [2] - th:switch / th:case

<th:block th:switch="${num}">
      <h3 th:case="100">100 이다</h3>
      <h3 th:case="200">200 이다</h3>
      <h3 th:case="300">300 이다</h3>
      <!-- th:case="*" == default는 나머지의 경우와 같다 -->
      <h3 th:case="*">나머지...</h3>
 </th:block>

삼항 연산자

      - 타임리프 속성 (th:)에
      삼항 연산자(조건식 ? 참 : 거짓) 작성 가능

서른아님

Elvis 연산자 ( ?: )

      [작성법]
      값 ?: 값이 없을 때

      - 삼항 연산자에서 조건식 자리에 값(변수)만 작성
      ( == , != 등의 연산자 사용 X)

      - 왼쪽 값이 존재하면 해당 값을 출력, 없으면 오른쪽 값이 출력

No-Operation 연산자 (값 ?: _ )

      - 왼쪽 값이 없을 경우 타임리프 코드를 해석하지 않는 연산자에서
      - 타임리프 코드 해석 X
      -> 일반 HTML 태그로 동작
      -> HTML 태그 사이 내용이 화면에 출력

th:inline="javascript" 속성 쓸 수 있음

        - script 태그에 작성하는 속성
        - 타임리프 문법으로 출력된 내용/값을 JS에 알맞은 타입으로 변환
<h4 class="deco" th:classappend="${num1 gt 10000} ? green : red">
      th:classappend 테스트 중...
    </h4>

안전 탐색 연산자 ${객체?.필드명}

        객체가 null인지 판단 후, null이 아닌 경우에 수행하는 것
<h4 th:text="${member?.memberNo}">회원번호</h4>

${#numbers.sequence(시작, 끝 [,step])} : 번호 발생기

        - 시작 부터 끝 까지 번호로만 이루어진 숫자 배열 생성
        ex) ${#numbers.sequence(1, 5)} => [1, 2, 3, 4, 5]

        [왜 사용할까?]
        - 타임리프 반복문 th:each는 향상된 for문 형태로
          일반 for문의 동작(시작~끝까지 몇 씩 증가하면 반복)을 못하기 때문에
          이를 해결하기 위해서 사용
 <li th:each="i : ${#numbers.sequence(11, 20, 2)}" th:text="|테스트 ${i}|">
        테스트 번호
 </li>

fragments

<!-- fragment : 조각
    html 요소를 다른 html 파일에서 재사용 가능하게 함
-->

<div th:fragment="header">
  <ul>
    <li>공지사항</li>
    <li>자유게시판</li>
    <li>질문게시판</li>
    <li>FAQ</li>
    <li>1:1문의</li>
  </ul>
</div>
 <th:block th:replace="~{fragments/header::header}"></th:block>

fragment 지정해서 사용하기 (::)

<div th:fragment="footer1">
  <ul>
    <li>고객센터</li>
    <li>오시는길</li>
    <li>이용약관</li>
  </ul>
</div>

<h1 th:fragment="footer2">타임리프 fragment 확인 중</h1>
<th:block th:replace="~{fragments/header}"></th:block>
<th:block th:replace="~{fragments/footer :: footer2}"></th:block>

투두 프로젝트 세팅

mybatis

  • 데이터의 입력, 조회, 수정, 삭제를 보다 편하게 하기 위해 xml로 구조화한 Mapper 설정 파일을 통해서 JDBC를 구현한 프레임워크
  • 기존에 JDBC를 통해 구현했던 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 xml 설정을 통해 쉽게 구현할 수 있다
  • 기존에 JDBCTemplate을 통해 SQL을 실행하였다면 Mybatis는 해당 과정전용 라이브러리를 통해 대체하여 동작한다고 생각하면 됨.

Mybatis 내부 동작 구조

⇒ STS4는 XML 파일 생성 마법사가 없기 때문에 MarketPlace를 이용해서
Eclipse XML Editors and Tools 설치 필요!!

Mybatis를 이용하기 위한 XML 파일 DTD(Document Type Definition) 추가

  • Window - Preferences - XML - XML Catalog - User Specified Entries 클릭 – Add… 클릭

(아래 내용을 차례대로 추가)

mybatis-config.xml 생성

⇒ src/main/resources’폴더에 mybatis-config.xml 파일 생성

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
	<settings>
		<!-- Java -> DB로 INSERT,UPDATE 시 Java의 null 값을 DB의 NULL로 인식하도록 설정 -->
		<setting name="jdbcTypeForNull" value="NULL" />
		<!-- DB의 UnderScore (_) 표기법 <-> Java의 Camel 표기법 두 표기법이 서로 변환 될 수 있도록 매핑하여 
			Java 필드명(memberId)과 DB 컬럼명(MEMBER_ID)가 서로 연결되게 함 -->
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>
</configuration>

⇒ 위 내용을 mybatis-config.xml 내부에 작성하기

mapper 관련 폴더 만들기

1. HiKariCP(Hikari Connection Pool) 란?

  • 빠르고, 간단하고 믿을 수 있는 HikariCP는 "오버헤드 제로(처리 시간을 극단적으로 줄이는 것을 목표)"의 프로덕션 지원 JDBC Connection Pool로 다른 Connection에 비해 매우 가벼움.

2. Spring Boot 프로젝트에 DB 연결하기

⇒ src/main/resources에 만들기

xml 파일에 빨간줄이 나올 때

Download~ 체크하고 apply하기

config.properties에 붙여넣기

#오라클 DB 연결 정보
spring.datasource.hikari.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.hikari.jdbc-url=jdbc:oracle:thin:@IP주소:포트번호:DB이름

09_DB 연결하기 4

spring.datasource.hikari.username=계정명
spring.datasource.hikari.password=비밀번호
# HikariCP Connection Pool Properties
#풀이 연결을 사용할 수 있을 때까지 대기하는 최대 시간(ms)을 지정
spring.datasource.hikari.connection-timeout=30000
#풀의 최대 연결 수 설정
spring.datasource.hikari.maximum-pool-size=5
#연결이 풀에서 유휴 상태로 있을 수 있는 최대 시간(ms)을 지정
spring.datasource.hikari.idle-timeout=600000
#연결 풀의 이름을 지정
spring.datasource.hikari.pool-name=MyHikariCP
#자동 커밋 끄기
spring.datasource.hikari.auto-commit=false

DataSource 만들기

  • 만들어줘야 db와 연결된 프로젝트가 실행이 가능해짐

⇒ 클래스를 만들어준다

DBConfig.java

package edu.kh.todo.common.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

/*
 * @Configuration
 * - 스프링 설정용 클래스임을 명시 (스프링이 해당 클래스 설정 정보로 인식하고 사용)
 * + 객체로 생성해서 내부 코드를 서버 실행 시 모두 바로 실행
 * 
 * @PropertySource : properties 파일의 내용을 이용하겠다는 어노테이션
 * 다른 properties도 추가하고 싶으면 어노테이션을 계속 추가
 * */

@Configuration
//@PropertySource : properties 파일의 내용을 이용하겠다는 어노테이션
//다른 properties도 추가하고 싶으면 어노테이션을 계속 추가
@PropertySource("classpath:/config.properties")
// classpath : src/main/resources
public class DBConfig {
	// 필드
	@Autowired // (DI, 의존성 주입)
	private ApplicationContext applicationContext;
	// application scope 객체 : 즉, 현재 프로젝트 그 자체를 나타내는 객체
	// -> 현재 프로젝트의 전반적인 DB 설정과, Bean 관리에 접근할 수 있도록 해주는 객체
	// -> 스프링이 관리하고 있는 ApplicationContext 객체를 의존성 주입받는다.

	// @Bean
	// - 개발자가 수동으로 bean을 등록하는 어노테이션
	// - @Bean 어노테이션이 작성된 메서드에서 반환된 객체는
	// Spring Container가 관리함(IOC)

	// 메서드
	////////////////////////////// HikariCP 설정 //////////////////////////////

	@Bean
	// @ConfigurationProperties(prefix = "spring.datasource.hikari")
	// properties 파일의 내용을 이용해서 생성되는 bean을 설정하는 어노테이션
	// prefix를 지정하여 spring.datasource.hikari으로 시작하는 설정을 모두 적용
	@ConfigurationProperties(prefix = "spring.datasource.hikari")
	// hikariConfig에 모두 접두사에 해당하는 것들을 적용시키겠다는 의미
	public HikariConfig hikariConfig() {

		// -> config.properties 파일에서 읽어온
		// spring.datasource.hikari로 시작하는 모든 값이
		// 자동으로 HikariConfig라는 객체의 알맞은 필드에 세팅이 되어
		// 객체화 됨 -> Bean으로 등록까지
		return new HikariConfig();
	}

	@Bean
	public DataSource dataSource(HikariConfig config) {
		// 매개변수 HikariConfig config
		// -> 등록된 Bean 중 HikariConfig 타입의 Bean을 바인딩
		// -> DataSource 객체를 생성하는데 이용된다.

		DataSource dataSource = new HikariDataSource(config);

		// DataSource :
		// 애플리케이션이 데이터베이스에 연결할 때 사용하는 설정 객체임
		// 1) DB 연결 정보 제공(url, username, password)
		// 2) Connection pool 관리 (Connection 생성/생명주기 관리)
		// 3) 트랜잭션 관리
		return dataSource;
	}

//////////////////////////// Mybatis 설정 추가 ////////////////////////////
// Mybatis : Java 애플리케이션에서 SQL을 더 쉽게 사용할 수 있도록 도와주는 
// 영속성 프레임워크(Persistence Framework)는 애플리케이션의 데이터를
// 데이터베이스와 같은 저장소에 영구적으로 저장하고,
// 이를 쉽게 CRUD 할 수 있도록 도와주는 프레임워크

//SqlSessionFactory : SqlSession을 만드는 객체
	@Bean
	public SqlSessionFactory sessionFactory(DataSource dataSource) throws Exception {
		SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
		sessionFactoryBean.setDataSource(dataSource);

		// 세팅1. 매퍼 파일이 모여있는 경로 지정
		sessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mappers/**.xml"));

		// 세팅2. 별칭을 지정해야하는 DTO가 모여있는 패키지 지정
		// -> 해당 패키지에 있는 모든 클래스가 클래스명으로 별칭이 지정됨
		sessionFactoryBean.setTypeAliasesPackage("edu.kh.todo");
		// -> edu.kh.todo 세팅시 패키지 하위에 있는 모든 클래스가
		// 클래스명으로 별칭이 지정됨.
		// -> ex) edu.kh.todo.model.dto.Todo 클래스가 있다면 -> Todo가 별칭으로 등록됌

		// 세팅3. 마이바티스 설정 파일 경로 지정
		sessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis-config.xml"));

		// SqlSession 객체 반환
		return sessionFactoryBean.getObject();
	}

	// SqlSessionTemplate : 기본 SQL 실행 + 트랜잭션 처리
	@Bean
	public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sessionFactory) {
		return new SqlSessionTemplate(sessionFactory);
	}

	// DataSourceTransactionManager : 트랜잭션 매니저
	@Bean
	public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
}

0개의 댓글