본문 바로가기
Back end/Spring

[Spring] 타임리프(Thymeleaf)

by 더 이프 2023. 7. 25.
728x90

목차

    1. Thymeleaf

    ■ Thymeleaf란?

    Thymeleaf는 웹 및 웹이 아닌 환경 모두에서 작동할 수 있는 템플릿 엔진입니다. 보통 자바에서 웹 개발시에는 JSP(Java Server Page)를 이용하는데 <% %>형태의 스크립트릿을 사용하여 자바 문법을 HTML에서 사용가능하게 해주는데 이 방식은 스크립트릿과 HTML이 섞인 상태가 되어 더 수정하기 어렵습니다. 이러한 상태를 해결하기 위해 템플릿 엔진을 사용하는데 템플릿 엔진은 HTML과 데이터를 결합한 결과물을 만들어 주는 도구입니다. 템플릿 엔진은 최초 한번 전체 페이지를 다 불러오고 응답데이터만 렌더링하는 SSR(Server Side Rendering) 방식입니다.

    ■ 설치

    1. MVN REPOSITORY에서 Thymeleaf를 검색하여 Spring Boot Starter Thymeleaf를 선택
    2. 아무 버전이나 Dependency를 pom.xml에 추가
    3. 추가 후 버전 부분을 지워주면 알아서 버전을 선택하여 적용
    4. 적용이 되면 templates 폴더 추가

     

    2. Templates

    ■ AddUser

    • $.ajax(request)로 요청을 보냄
    • request에는 type, url, contentType, data, dataType, success, error 등을 요청
    • 해당 정보를 데이터베이스에 등록
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    </head>
    <body>
    	<div>
    		<input class="username">
    	</div>
    	<div>
    		<input class="password">
    	</div>
    	<div>
    		<input class="name">
    	</div>
    	<div>
    		<input class="email">
    	</div>
    	<button type="button" class="send-button">등록</button>
    
    	<script>
    		window.onload = () => {
    			addSendButtonEvent();
    		}
    	
    		function addSendButtonEvent(){
    			const sendButton = document.querySelector(".send-button");
    			sendButton.onclick = () => {
    				send();
    			}
    		}
    	
    		function send() {
    			const username = document.querySelector(".username").value;
    			const password = document.querySelector(".password").value;
    			const name = document.querySelector(".name").value;
    			const email = document.querySelector(".email").value;
    
    			const userObj = {
    					username,
    					password,
    					name,
    					email
    			}
    			
    			const request = {
    					type:"post", //method
    					url: "http://localhost:8080/api/user/addition",
    					contentType: "application/json", // 요청 데이터 타입
    					data: JSON.stringify(userObj), //요청 데이터
    					dataType: "json", //응답 데이터 타입
    					//응답 성공시에 실행될 메소드 정의
    					success: (response) => {
    						console.log(response);
    					},
    					//요청 또는 응답 실패시에 실해오딜 메소드 정의
    					error: (error) => {
    						console.log(error);
    					}
    			}
    			
    			$.ajax(request);
    		}
    	</script>
    </body>
    </html>

    ■ FindUser

    • 데이터베이스에 등록된 정보를 등록된 userId로 조회
    • userId는 정보 등록 시 자동으로 설정
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script src="https://code.jquery.com/jquery-latest.min.js"></script>
    </head>
    <body>
    	<input placeholder="조회 할 id 입력" class="user-id">
    	<button type="button" class="search-button">조회</button>
    
    	<div class="result-container"></div>
    
    	<script type="text/javascript">
    	window.onload = () => {
    		addSearchButtonEvent()
    	}
    	
    	function addSearchButtonEvent() {
    		const searchButton = document.querySelector(".search-button");
    		searchButton.onclick = () => {
    			search();
    		}
    	}
    	
    	function search() {
    		const userId = document.querySelector(".user-id").value;
    		const resultContainer = document.querySelector(".result-container");
    		
    		const request = {
    				type: "get",
    				url: "http://localhost:8080/api/user/" + userId,
    				dataType:"json",
    				success: response => {
    						resultContainer.innerHTML = `
    						<div>username: ${response.data.username}</div>
    						<div>password: ${response.data.password}</div>
    						<div>name: ${response.data.name}</div>
    						<div>email: ${response.data.email}</div>
    						`;
    				},
    				error: error  => {
    					alert(error.responseJSON.message);
    					resultContainer.innerHTML = ``;
    				}
    		}
    		
    		$.ajax(request);
    	}
    	
    	</script>
    </body>
    </html>

    ■ UserList

    • 데이터베이스에 등록된 정보들을 테이블 형태로 모두 가져옴
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>Insert title here</title>
    		<style type="text/css">
    			table {
    				margin: 50px auto;
    				border: 1px solid #121212;
    				border-collapse: collapse;
    				width: 400px;
    			}
    			
    			th, td {
    				border: 1px solid #121212;
    				padding: 10px;
    				text-align: center;
    			}
    		</style>
    		<script src="https://code.jquery.com/jquery-latest.min.js"></script>
    	</head>
    	<body>
    		<table class="user-table">
    
    		</table>
    
    		<script type="text/javascript">
    			window.onload = () => {
    				getUsers();
    			}
    
    			function getUsers() {
    				$.ajax({
    					type: "get",
    					url: "http://localhost:8080/api/users",
    					dataType:"json",
    					success: response =>{
    						const userTable = document.querySelector(".user-table");
    						
    						console.log(response);
    						
    						userTable.innerHTML = ``;
    						
    						response.data.forEach(user => {
    							userTable.innerHTML += `
    								<tr>
    									<td>${user.username}</td>
    									<td>${user.password}</td>
    									<td>${user.name}</td>
    									<td>${user.email}</td>
    								</tr>
    							`;
    						});
    	
    					},
    					error: error => {
    						console.log(error);
    					}
    				});
    			}
    		</script>
    	</body>
    </html>

     

    3. Controller

    ■ UserPageController

    • 웹페이지를 구현하기 위해 Get 요청으로 해당 uri에 templates폴더 내 HTML의 파일명을 리턴하여 해당 HTML 구현
    package com.web.study.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class UserPageController {
    
    	@GetMapping("/page/user/addition")
    	public String addUser() {
    		return "AddUser";
    	}
    	
    	@GetMapping("/page/user/search")
    	public String userSearch() {
    		return "FindUser";
    	}
    	
    	@GetMapping("/page/users")
    	public String getUsers() {
    		return "UserList";
    	}
    }

    ■ UserRestController

    package com.web.study.controller;
    
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.web.study.dto.DataResponseDto;
    import com.web.study.dto.ErrorResponseDto;
    import com.web.study.dto.ResponseDto;
    import com.web.study.dto.request.UserAdditionDto;
    
    class UserStore {
    	public static Map<Integer, UserAdditionDto> userMap = new HashMap<>();
    }
    
    @RestController
    public class UserRestController {
    
    	@PostMapping("/api/user/addition")
    	public ResponseEntity<? extends ResponseDto> addUser(@RequestBody UserAdditionDto userAdditionDto) {
    		Map<Integer, UserAdditionDto> userMap = UserStore.userMap;
    
    		System.out.println(userMap.get(1));
    		int maxKey = 0;
    		if (!userMap.keySet().isEmpty()) {
    			maxKey = Collections.max(userMap.keySet());
    		}
    		userMap.put(maxKey + 1, userAdditionDto);
    		System.out.println(userMap);
    
    		return ResponseEntity.ok().body(DataResponseDto.of(userMap));
    	}
    
        // userMap에서 해당 id를 가진 객체를 응답
        // 만약에 해당 id가 존재하지 않으면 ErroResponse를 응답으로 준다. errorMessage = 존재하지 않는 id입니다.
    	@GetMapping("api/user/{id}")
    	public ResponseEntity<? extends ResponseDto> getUser(@PathVariable int id) {
    		Map<Integer, UserAdditionDto> userMap = UserStore.userMap;
    
    		if (!userMap.keySet().contains(id)) {
    			try {
    				throw new RuntimeException("존재하지 않는 id입니다.");
    			} catch (Exception e) {
    				return ResponseEntity.badRequest().body(ErrorResponseDto.of(HttpStatus.BAD_REQUEST, e));
    			}
    		}
    
    		return ResponseEntity.ok().body(DataResponseDto.of(userMap.get(id)));
    	}
    
    	@GetMapping("/api/users")
    	public ResponseEntity<? extends ResponseDto> getUsers() {
    		
    		return ResponseEntity.ok().body(DataResponseDto.of(UserStore.userMap.values()));
    	}
    }

     

    4. Dto

    ■ UserAdditionDto

    • 등록할 유저 정보를 멤버 변수로 하여 전달하기 위한 dto
    package com.web.study.dto.request;
    
    import lombok.Data;
    
    @Data
    public class UserAdditionDto {
    	private String username;
    	private String password;
    	private String name;
    	private String email;
    }