Spring boot, Java 17, Mybatis, PostgreSQL ์ธํ ๋ฆฌ์ ์ด ํ๊ฒฝ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋ ๊ธ ์ ๋๋ค.
Spring boot ํ๋ก์ ํธ ์์ฑํ๊ธฐ
1. ํ๋ก์ ํธ ์์ฑ

File - Project์์ Spring Boot๋ฅผ ์ ํํ ํ
Dependencies๋ Spring Web, PostgreSQL, Thymleaf, Loombok ๋ฑ์ ์ ํํด ์ฃผ๊ณ Create๋ฒํผ์ ํด๋ฆญํ์ฌ ์์ฑํด์ค๋๋ค.
(์ด์ฐจํผ ๋์ค์ ์ถ๊ฐํ ์ ์๊ธฐ๋๋ฌธ์ ํฌ๊ฒ ์ค์ํ์ง ์์ต๋๋ค.)
2. DB์ฐ๊ฒฐ์ ํ์ํ ์ค์ ํ๊ธฐ
postgres
build.gradle ์ถ๊ฐ
runtimeOnly 'org.postgresql:postgresql'
properties ์ค์
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://์ฃผ์:ํฌํธ๋ฒํธ/DB์ด๋ฆ
spring.datasource.username=postgres
spring.datasource.password=๋น๋ฐ๋ฒํธ
์ด๋ ๊ฒํ๋ฉด DB์ฐ๊ฒฐ์ ์ ์์ ์ผ๋ก ์๋ฃ๋์์ต๋๋ค.
mybatis
build.gradle ์ถ๊ฐ
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4'
properties ์ค์
mybatis.mapper-locations=classpath:mapper/*.xml
Application ํด๋์ค์ MapperScan ์ถ๊ฐ
@SpringBootApplication
@MapperScan("๊ธฐ๋ณธ๊ฒฝ๋ก.**.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Mapper ํ์ผ์ @Mapper ์ด๋ ธํ ์ด์ ๋ถ์ด๊ธฐ
@Mapper
public interface MemberMapper {
3. ๋ก๊ทธ์ธ ๊ตฌํํ๊ธฐ
ํ ์ด๋ธ ์์ฑ
๋ก๊ทธ์ธ์ ๊ตฌํํ๊ธฐ ์ํด์ ํ์ํ ์ด๋ธ์ ๋จผ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
dbeaver script๋ฅผ ํตํด ํด๋น ์คํค๋ง์ ํ ์ด๋ธ์ ์ถ๊ฐํ์ต๋๋ค.
create table weeks.users (
user_id INT GENERATED ALWAYS AS IDENTITY PRIMARY key,
id varchar(30) not null,
pw varchar(100) not null,
name varchar(20) not null,
phone varchar(15)
);
DTO ์์ฑ
Login๊ณผ ๋ฐ๋ก DTO๋ฅผ ๋๋ด๋๋ฐ ๊ท์ฐฎ์ผ์๋ฉด MemberDTO ํ๋๋ง ์จ๋ ๋ฉ๋๋ค.
LoginDTO
public class LoginDTO {
private String id;
private String pw;
}
MemberDTO
public class MemberDTO {
@NotBlank(message = "์์ด๋๋ ํ์์
๋๋ค.")
private String id;
@NotBlank(message = "๋น๋ฐ๋ฒํธ๋ ํ์์
๋๋ค.")
private String pw;
@NotBlank(message = "์ด๋ฆ์ ํ์์
๋๋ค.")
private String name;
private String phone;
}
@Valid๋ฅผ ์ฌ์ฉํด์ ์ ํจ์ฑ์ ๋ฃ๊ณ ์์ด์ @NoBlank๋ผ๋ ์ด๋ ธํ ์ด์ ์ด ๋ถ์ด์์ต๋๋ค.
๋ธ๋ก๊ทธ ๋ด์์ ๊ด๋ จ ๊ฒ์๊ธ์ด ์์ผ๋ ์ฐธ๊ณ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
enum
public enum LoginResult {
SUCCESS,
NO_ID,
WRONG_PASSWORD
}
Mapper ์์ฑ
์ธํฐํ์ด์ค
@Mapper
public interface MemberMapper {
// ํ์ ํ์ธ
LoginDTO selectUserById(String id);
}
xml
org.example.weeks๋ ๋ณธ์ธ ํ๋ก์ ํธ ๊ฒฝ๋ก๋๋ก ๋ฐ๊ฟ์ผ ํฉ๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.weeks.member.mapper.MemberMapper">
<!--ํ์ ํ์ธ-->
<select id="selectUserById" parameterType="string" resultType="org.example.weeks.member.dto.LoginDTO">
select
id,
pw
from weeks.users
where id= #{id}
</select>
</mapper>
Service ์์ฑ
์ธํฐํ์ด์ค
public interface MemberService {
// ํ์ ํ์ธ
LoginResult login(LoginDTO dto);
}
์๋น์ค์ํ
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberMapper memberMapper;
// ํ์ ํ์ธ
@Override
public LoginResult login(LoginDTO dto) {
LoginDTO member = memberMapper.selectUserById(dto.getId());
if (member == null){
return LoginResult.NO_ID;
}
if (member != null && member.getPw().equals(dto.getPw())) {
return LoginResult.SUCCESS;
}
return LoginResult.WRONG_PASSWORD;
}
}
Controller ์์ฑ
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@GetMapping("/login")
public String login() {
return "member/login";
}
@PostMapping("/login")
public String login(LoginDTO dto, Model model, HttpSession session) {
LoginResult result = memberService.login(dto);
switch (result){
case NO_ID:
model.addAttribute("msg", "๋ฑ๋ก๋ ์์ด๋๊ฐ ์์ต๋๋ค.");
return "member/login";
case WRONG_PASSWORD:
model.addAttribute("msg", "๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.");
return "member/login";
case SUCCESS:
session.setAttribute("loginId", dto.getId());
return "redirect:/";
}
return "member/login";
}
}
HTML ์์ฑ
ํ์๋ฆฌํ
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<p th:if="${msg}" th:text="${msg}" style="color:red;"></p>
<form action="#" th:action="@{/member/login}" method="post">
<input type="text" name="id" placeholder="์์ด๋">
<input type="password" name="pw" placeholder="๋น๋ฐ๋ฒํธ">
<button type="submit">๋ก๊ทธ์ธ</button>
</form>
<a th:href="@{/member/register}">ํ์๊ฐ์
</a>
</body>
</html>
๊ฒฐ๊ณผ ํ๋ฉด

์ด ๋ค์์ผ๋ก๋ ๋ก๊ทธ์์, ํ์๊ฐ์ ๊ธฐ๋ฅ์ ์ ์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.