"백엔드 개발자한테 UI가 왜 필요한데?!"
백엔드 개발을 하다보면 주로 칙칙한 검은 화면이나 Postman을 통해 내가 구현한 API를 테스트하는 경우가 많다,,, 하지만 UI를 활용하여 시각적으로 표현한다면 API가 동작하는 과정도 더 직관적으로 이해할 수 있을 것이다.
Thymeleaf
는 Java 템플릿 엔진으로 주로 스프링 프레임워크에서 HTML, XML, JavaScript, CSS 문서를 처리하는 기능을 수행한다.
이처럼 HTML 템플릿 내에서 자바 코드를 자연스럽게 통합할 수 있는 기능을 제공하여 개발자가 웹 어플리케이션을 유연하게 구성할 수 있도록 한다.
1. 템플릿 표현식(Expressions): ${...} 형식을 사용하여 변수 표현식 출력
ex) ${user.name}
2. 속성 바인딩(Attribute Binding): 타임리프 속성을 사용하여 HTML 요소의 속성 값을 동적으로 설정
ex) : <a th:href="@{/home}">Home</a>
3. 반복(Iteration):
th:each
를 사용하여 리스트나 배열과 같은 컬렉션의 요소를 반복적으로 출력ex) <li th:each="item : ${items}" th:text="${item}"></li>
4. 조건문(Conditional Statements):
th:if
,th:unless
,th:switch
,th:case
등을 사용하여 조건부로 HTML 요소 출력ex) <div th:if="${user.isAdmin()}">Admin</div>
5. 레이아웃(Layout): 여러 페이지에서 공통된 레이아웃을 정의하고 확장
ex) <div th:replace="layout/header :: header"></div>
6. 이벤트 처리(Event Handling):
th:onclick
,th:attr
등을 사용하여 클라이언트 측 이벤트 처리ex) <button th:onclick="'submit()'" th:text="#{button.submit}"></button>
- 템플릿 변수(Temporal Variables):
th:with
를 사용하여 템플릿 내에서 임시 변수 정의ex) <div th:with="varName=${expression}"></div>
스프링부트 웹어플리케이션을 동작하기위한 spring boot web
을 포함해서 thymeleaf
와 java mail
관련한 의존성을 추가해주었다.
// spring boot web
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// java mail
implementation 'org.springframework.boot:spring-boot-starter-mail'
application.yml에 필요한 설정을 추가하는데
username
과 password
는 각자에 맞는 값을 입력해주어야 한다.
spring:
thymeleaf:
cache: false
check-template-location: true
prefix: classpath:/templates/
suffix: .html
mail:
host: smtp.gmail.com
port: 587
username: {SMTP 인증에 사용될 이메일 계정 - 발신자}
password: {SMTP 인증에 사용될 이메일 계정의 password}
properties:
mail:
smtp:
auth: true
starttls:
enable: true
각각에 대한 설명의 아래와 같다.
spring.thymeleaf.cache: Thymeleaf 템플릿 캐싱 비활성화
spring.thymeleaf.check-template-location: 템플릿 파일 위치를 확인하여 유효성을 검사
spring.thymeleaf.prefix: Thymeleaf 템플릿 파일이 위치한 디렉토리 경로 지정
spring.thymeleaf.suffix: Thymeleaf 템플릿 파일의 확장자 지정
spring.mail.host: 이메일을 보낼 SMTP 서버의 호스트 주소 지정
spring.mail.port: SMTP 서버의 포트 번호 지정
spring.mail.username: SMTP 인증에 사용될 이메일 계정 지정 (발신자)
spring.mail.password: SMTP 인증에 사용될 이메일 계정의 password 지정
spring.mail.properties.mail.smtp.auth: SMTP 인증 활성화
spring.mail.properties.mail.smtp.starttls.enable: STARTTLS를 통한 보안 연결 활성화
위 설정에서 템플릿 파일을 프로젝트의 classpath에 있는 templates
디렉토리에서 찾게 지정해두었다.
따라서src/main/resources/templates
디렉토리 안에 index.html
를 만들었다.
이미지도 사용해보기 위해 src/main/resources/static
디렉토리 안에 images
디렉토리를 만들고 사용할 이미지 파일을 넣어주었다.
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>입력 폼</title>
<style>
.container {
width: 300px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
.subject-group{
text-align: center;
}
.form-group {
margin-bottom: 10px;
}
label {
display: block;
font-weight: bold;
}
input,
textarea {
width: calc(100% - 10px);
padding: 8px;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
margin-top: 3px;
}
button{
width: 100%;
padding: 10px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 16px;
}
</style>
</head>
<body>
<div class="container" >
<div class="subject-group">
<h1>입력 폼</h1>
<img th:src="@{/images/email.png}" style="height:60px" alt="email"/>
</div>
<form th:action="@{/submit}" method="post">
<div class="form-group">
<label for="name">이름:</label>
<input type="text" id="name" name="name">
</div>
<div class="form-group">
<label for="email">이메일:</label>
<input type="email" id="email" name="email">
</div>
<div class="form-group">
<label for="message">메시지:</label>
<textarea id="message" name="message"></textarea>
</div>
<button type="submit">전송</button>
</form>
<div th:if="${successMessage}" class="success-message" th:text="${successMessage}"></div>
</div>
</body>
</html>
스타일 관련 속성은
css
문서를 따로 만들어서 관리해도 되지만<style>
태그를 사용해서html
문서 안에 같이 써주었다.
아래는Thymeleaf
를 사용하여 작성된HTML
템플릿 파일에 대한 설명이다.<html xmlns:th="http://www.thymeleaf.org"> // hymeleaf 네임스페이스를 사용하기 위해 HTML 문서에 선언
<img th:src="@{/images/email.png}" style="height:60px" alt="email"/> // 이미지를 표시하는 <img> 요소 정의
<form th:action="@{/submit}" method="post"> // 폼 요소의 액션을 지정하고 HTTP 메소드를 POST로 설정. // @{/submit}는 컨텍스트 상대 URL로, /submit으로 요청을 보낼 것을 의미.
<input type="text" id="name" name="name"> // 이름을 입력하는 텍스트 필드를 정의. id와 name 속성을 사용하여 식별.
<button type="submit">전송</button> ///폼을 제출하는 버튼 정의. 이 버튼을 클릭하면 폼 데이터가 서버로 전송된다.
<div th:if="${successMessage}" class="success-message" th:text="${successMessage}"></div> // 요청 성공 시 성공 메시지를 출력하는 <div> 요소를 정의
작성한 HTML 템플릿을 실행해보기 위해 컨트롤러를 작성하여 index.html
파일을 웹에 띄워보았다.
package com.example.thymeleaf;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.ui.Model;
@RequiredArgsConstructor
@Controller
public class MessageController {
private final MessageService messageService;
@GetMapping("/")
public String index(){
return "index";
}
이제 http://localhost:8080/에 접속해보자. 입력 폼이 잘 뜨는 것을 확인할 수 있다.
만들어놓은 입력폼이 동작하도록
이메일 전송 API
를 구현해보자.
thymeleaf를 활용하여 입력폼에서 전송 버튼을 클릭하면 폼 데이터가 서버로 전송되며 /submit
으로 요청보내도록 HTML 문서를 작성하였다.
따라서 /submit
엔드포인트에 대한 컨트롤러와 서비스 코드를 작성해야한다.
package com.example.thymeleaf;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.ui.Model;
@RequiredArgsConstructor
@Controller
public class MessageController {
private final MessageService messageService;
@GetMapping("/")
public String index(){
return "index";
}
@PostMapping("/submit")
public String submitForm(String name, String email, String message, Model model) {
// 이메일 보내기
messageService.sendEmail(email, "새로운 메시지가 도착했습니다.", message);
// 성공 메시지
model.addAttribute("successMessage", "메시지가 성공적으로 전송되었습니다.");
return "index";
}
}
JavaMailSender
를 주입받아 이메일을 보내는 sendEmail 메서드를 구현하였다.
이메일의 수신자, 제목, 내용을 설정하여 이메일을 전송하고 있다.
package com.example.thymeleaf;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
@RequiredArgsConstructor
@Service
public class MessageService {
private final JavaMailSender emailSender;
public void sendEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to); // 보낼 대상
message.setSubject(subject); // 제목
message.setText(text); // 내용
emailSender.send(message);
}
}
값을 넣고 전송 버튼을 눌러보자
❗이 때 이메일은 실제로 유효한 이메일로 바꿔서 입력해줘야한다❗
실행 결과는?!
❌❌❌ 인증 관련한 에러가 발생하였는데 이메일을 전송하기 위한 계정의 인증에 실패했다는 것을 의미한다. => Google의 보안 정책으로 인해 액세스를 허용을 거부당한 것이다.
구글 계정 설정하러가기 링크 클릭 > 발신자로 설정했던 구글 계정으로 로그인 > 보안 클릭 > 보안 수준이 낮은 앱의 액세스
사용으로 변경
인증 관련 이슈를 해결한 후 다시 실행해보자
그러면 해당 이메일 계정과 내가 설정한 제목과 내용으로 이메일이 전송되는 것을 확인할 수 있다
전송이 완료된 후 입력 폼에서도 성공 메세지를 확인할 수 있다!
오늘은 Thymeleaf
를 사용하여 스프링부트 프로젝트 내에서 사용자 인터페이스
와 이메일을 전송하는 API
를 구현해보았다 ✨✨
추가적인 활용 방안
회원 가입 시 이메일 인증, 소셜로그인 UI 화면 구성 및 기능 구현하는 데 활용할 수 있다!