6. (실습) Spring MVC로 HTTP 실습

박은서's avatar
Jan 29, 2026
6. (실습) Spring MVC로 HTTP 실습

1. 프로젝트 생성

notion image
notion image
notion image
notion image
notion image
프로젝트명
프로젝트명
앞에 입력한 내용 맞는지 다시 확인
앞에 입력한 내용 맞는지 다시 확인
notion image
notion image
notion image
프로젝트 저장 위치
프로젝트 저장 위치

2. 개발 시작

1) mustache 파일 생성

C:\workspace\spring_lab\prodspringapp\src\main\resources\templates
notion image

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=true

6) 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
notion image

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); } }

결과

메인 홈페이지

notion image

상품 삭제

notion image
notion image

상품 등록

notion image
notion image
notion image

상품 상세 보기

notion image
notion image
notion image
notion image
Share article