Contents
1. 프로젝트 생성2. 개발 시작1) mustache 파일 생성2) list.mustache3) detail.mustache4) insert-form.mustache5) application.properties6) DBConnection.java7) Product 폴더 생성8) Product.java9) ProductRepository.java10) ProductService.java11) ProductController.java[참고] x-www-form-urlencoded 파싱12) list.mustache 수정13) detail.mustache 수정14) insert-form.mustache 수정15) main결과1. 프로젝트 생성











2. 개발 시작
1) mustache 파일 생성
C:\workspace\spring_lab\prodspringapp\src\main\resources\templates

2) list.mustache
C:\workspace\spring_lab\prodspringapp\src\main\resources\templates\list.mustache
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li><a href="#">상품목록</a></li>
<li><a href="#">상품등록</a></li>
</ul>
<h1>상품 목록</h1>
<hr>
<table border="1">
<tr>
<td>id</td>
<td>name</td>
<td>액션</td>
</tr>
<tr>
<td>1</td>
<td><a href="#">바나나</a></td>
<td>
<form action="#" method="post">
<button type="submit">삭제</button>
</form>
</td>
</tr>
</table>
</body>
</html>3) detail.mustache
C:\workspace\spring_lab\prodspringapp\src\main\resources\templates\detail.mustache
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.p_box {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<ul>
<li><a href="#">상품목록</a></li>
<li><a href="#">상품등록</a></li>
</ul>
<h1>상품 상세보기</h1>
<hr>
<div class="p_box">
<div class="p_box">id: 1</div>
<div class="p_box">name: 바나나</div>
<div class="p_box">price: 5000원</div>
<div class="p_box">qty: 10개</div>
</div>
</body>
</html>4) insert-form.mustache
C:\workspace\spring_lab\prodspringapp\src\main\resources\templates\insert-form.mustache
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li><a href="#">상품목록</a></li>
<li><a href="#">상품등록</a></li>
</ul>
<h1>상품등록</h1>
<hr>
<form action="#" method="post">
상품명 : <input type="text" name="name" required/> <br/>
가격 : <input type="text" name="price" required/> <br/>
개수 : <input type="text" name="qty" required/> <br/>
<button type="submit">상품등록</button>
</form>
</body>
</html>5) application.properties
C:\workspace\spring_lab\prodspringapp\src\main\resources\application.properties
spring.output.ansi.enabled=always
spring.mustache.servlet.expose-request-attributes=true6) DBConnection.java
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp\DBConnection.java
package com.example.prodspringapp;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBConnection {
// 책임 : 데이터베이스 연결 소켓을 리턴함
public static Connection getConnection() {
String url = "jdbc:mysql://localhost:3306/productdb";
String username = "root";
String password = "bitc5600!";
try {
// new 클래스명();
Class.forName("com.mysql.cj.jdbc.Driver");
// conn = 프로토콜이 적용된 소켓
Connection conn = DriverManager.getConnection(url, username, password);
// System.out.println("DB연결 성공");
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}7) Product 폴더 생성
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp

8) Product.java
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp\product\Product.java
package com.example.prodspringapp.product;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private Integer id;
private String name;
private Integer price;
private Integer qty;
}9) ProductRepository.java
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp\product\ProductRepository.java
package com.example.prodspringapp.product;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.example.prodspringapp.DBConnection;
public class ProductRepository {
Connection conn = DBConnection.getConnection();
// 1. insert(String name, int price, int qty)
public int insert(String name, int price, int qty) {
String sql = "insert into product(name, price, qty) values(?,?,?)";
try {
// 2. 버퍼달기
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setInt(2, price);
pstmt.setInt(3, qty);
// 3. 쿼리전송
int result = pstmt.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return -1; // -1, 0, 1이 머지? 정리!!
}
// 2. deleteById(int id)
public int deleteById(int id) {
String sql = "delete from product where id = ?";
try {
// 2. 버퍼달기
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
// 3. 쿼리전송
int result = pstmt.executeUpdate();
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return -1; // -1, 0, 1이 머지? 정리!!
}
// 3. findById(int id)
public Product findById(int id) {
try {
String sql = "select * from product where id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
// 조회해서 view로 응답받기
ResultSet rs = pstmt.executeQuery(); // select할때!!
// 커서 한칸 내리기
boolean isRow = rs.next();
// 행이 존재하면 프로젝션(열 선택하기)
if (isRow) {
int c1 = rs.getInt("id");
String c2 = rs.getString("name");
int c3 = rs.getInt("price");
int c4 = rs.getInt("qty");
Product product = new Product(c1, c2, c3, c4);
return product;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 4. findAll()
public List<Product> findAll() {
try {
String sql = "select * from product";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 조회해서 view로 응답받기
ResultSet rs = pstmt.executeQuery(); // select할때!!
// 행이 존재하면 프로젝션(열 선택하기)
List<Product> list = new ArrayList<>();
while (rs.next()) {
int c1 = rs.getInt("id");
String c2 = rs.getString("name");
int c3 = rs.getInt("price");
int c4 = rs.getInt("qty");
Product product = new Product(c1, c2, c3, c4);
list.add(product);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
}
return Arrays.asList();
}
}10) ProductService.java
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp\product\ProductService.java
package com.example.prodspringapp.product;
import java.util.List;
// 트랜잭션 관리
public class ProductService {
ProductRepository repo = new ProductRepository();
public void 상품등록(String name, int price, int qty) {
int result = repo.insert(name, price, qty);
if (result != 1)
throw new RuntimeException("상품등록이 완료되지 않았습니다");
}
public List<Product> 상품목록() {
return repo.findAll();
}
public Product 상품상세(int id) {
Product product = repo.findById(id);
if (product == null)
throw new RuntimeException("상품을 찾을 수 없어요 id를 확인하세요 : 명령어 get");
return product;
}
public void 상품삭제(int id) {
int result = repo.deleteById(id);
if (result != 1)
throw new RuntimeException("상품삭제가 완료되지 않았습니다");
}
}11) ProductController.java
C:\workspace\spring_lab\prodspringapp\src\main\java\com\example\prodspringapp\product\ProductController.java
package com.example.prodspringapp.product;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import jakarta.servlet.http.HttpServletRequest;
@Controller // view를 리턴
public class ProductController {
ProductService service = new ProductService();
// localhost:8080
// localhost:8080/
@GetMapping("/product")
public String list(HttpServletRequest req) {
List<Product> models = service.상품목록();
req.setAttribute("models", models);
return "list";
}
// localhost:8080/product/5
@GetMapping("/product/{id}")
public String detail(@PathVariable("id") int id, HttpServletRequest req) { // @PathVariable("GetMapping의 중괄호 내부")
Product model = service.상품상세(id);
req.setAttribute("model", model);
return "detail";
}
@GetMapping("/product/insert-form")
public String insertForm() {
return "insert-form";
}
@PostMapping("/product/insert")
public String insert(String name, int price, int qty) { // x-www-form 형태만 자동으로 파싱해줌
service.상품등록(name, price, qty);
return "redirect:/product";
}
@PostMapping("/product/{id}/delete")
public String delete(@PathVariable("id") int id) {
service.상품삭제(id);
return "redirect:/product";
}
}[참고] x-www-form-urlencoded 파싱
[참고] x-www-form-urlencoded 파싱12) list.mustache 수정
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li><a href="/product">상품목록</a></li>
<li><a href="/product/insert-form">상품등록</a></li>
</ul>
<h1>상품 목록</h1>
<hr>
<table border="1">
<tr>
<td>id</td>
<td>name</td>
<td>액션</td>
</tr>
{{#models}}
<tr>
<td>{{id}}</td>
<td><a href="/product/{{id}}">{{name}}</a></td>
<td>
<form action="/product/{{id}}/delete" method="post">
<button type="submit">삭제</button>
</form>
</td>
</tr>
{{/models}}
</table>
</body>
</html>13) detail.mustache 수정
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.p_box {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<ul>
<li><a href="/product">상품목록</a></li>
<li><a href="/product/insert-form">상품등록</a></li>
</ul>
<h1>상품 상세보기</h1>
<hr>
<div class="p_box">
<div class="p_box">id: {{model.id}}</div>
<div class="p_box">name: {{model.name}}</div>
<div class="p_box">price: {{model.price}}원</div>
<div class="p_box">qty: {{model.qty}}개</div>
</div>
</body>
</html>14) insert-form.mustache 수정
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li><a href="/product">상품목록</a></li>
<li><a href="/product/insert-form">상품등록</a></li>
</ul>
<h1>상품등록</h1>
<hr>
<form action="/product/insert" method="post">
상품명 : <input type="text" name="name" required/> <br/>
가격 : <input type="text" name="price" required/> <br/>
개수 : <input type="text" name="qty" required/> <br/>
<button type="submit">상품등록</button>
</form>
</body>
</html>15) main
package com.example.prodspringapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProdspringappApplication {
public static void main(String[] args) {
SpringApplication.run(ProdspringappApplication.class, args);
}
}결과
메인 홈페이지

상품 삭제


상품 등록



상품 상세 보기




Share article