728x90
💻 AllInOneController.java
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class AllInOneController {
// 신규 상품 등록
@PostMapping("/api/products")
public Product createProduct(@RequestBody ProductRequestDto requestDto) throws SQLException {
// 요청받은 DTO 로 DB에 저장할 객체 만들기
Product product = new Product(requestDto);
// DB 연결
Connection connection = DriverManager.getConnection("jdbc:h2:mem:springcoredb", "sa", "");
// DB Query 작성
PreparedStatement ps = connection.prepareStatement("select max(id) as id from product");
ResultSet rs = ps.executeQuery();
if (rs.next()) {
// product id 설정 = product 테이블의 마지막 id + 1
product.setId(rs.getLong("id") + 1);
} else {
throw new SQLException("product 테이블의 마지막 id 값을 찾아오지 못했습니다.");
}
ps = connection.prepareStatement("insert into product(id, title, image, link, lprice, myprice) values(?, ?, ?, ?, ?, ?)");
ps.setLong(1, product.getId());
ps.setString(2, product.getTitle());
ps.setString(3, product.getImage());
ps.setString(4, product.getLink());
ps.setInt(5, product.getLprice());
ps.setInt(6, product.getMyprice());
// DB Query 실행
ps.executeUpdate();
// DB 연결 해제
ps.close();
connection.close();
// 응답 보내기
return product;
}
// 설정 가격 변경
@PutMapping("/api/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) throws SQLException {
Product product = new Product();
// DB 연결
Connection connection = DriverManager.getConnection("jdbc:h2:mem:springcoredb", "sa", "");
// DB Query 작성
PreparedStatement ps = connection.prepareStatement("select * from product where id = ?");
ps.setLong(1, id);
// DB Query 실행
ResultSet rs = ps.executeQuery();
if (rs.next()) {
product.setId(rs.getLong("id"));
product.setImage(rs.getString("image"));
product.setLink(rs.getString("link"));
product.setLprice(rs.getInt("lprice"));
product.setMyprice(rs.getInt("myprice"));
product.setTitle(rs.getString("title"));
} else {
throw new NullPointerException("해당 아이디가 존재하지 않습니다.");
}
// DB Query 작성
ps = connection.prepareStatement("update product set myprice = ? where id = ?");
ps.setInt(1, requestDto.getMyprice());
ps.setLong(2, product.getId());
// DB Query 실행
ps.executeUpdate();
// DB 연결 해제
rs.close();
ps.close();
connection.close();
// 응답 보내기 (업데이트된 상품 id)
return product.getId();
}
// 등록된 전체 상품 목록 조회
@GetMapping("/api/products")
public List<Product> getProducts() throws SQLException {
List<Product> products = new ArrayList<>();
// DB 연결
Connection connection = DriverManager.getConnection("jdbc:h2:mem:springcoredb", "sa", "");
// DB Query 작성 및 실행
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from product");
// DB Query 결과를 상품 객체 리스트로 변환
while (rs.next()) {
Product product = new Product();
product.setId(rs.getLong("id"));
product.setImage(rs.getString("image"));
product.setLink(rs.getString("link"));
product.setLprice(rs.getInt("lprice"));
product.setMyprice(rs.getInt("myprice"));
product.setTitle(rs.getString("title"));
products.add(product);
}
// DB 연결 해제
rs.close();
connection.close();
// 응답 보내기
return products;
}
}
💻 ProductRequestDto.java : 관심상품 등록 요청 DTO
import lombok.AllArgsConstructor;
import lombok.Getter;
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class ProductRequestDto {
// 관심상품명
private String title;
// 관심상품 썸네일 image URL
private String image;
// 관심상품 구매링크 URL
private String link;
// 관심상품의 최저가
private int lprice;
}
💻 Product.java : 관심상품DB 테이블에 대응되는 Entity
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
@Setter
@Getter // get 함수를 일괄적으로 만들어줍니다.
@NoArgsConstructor // 기본 생성자를 만들어줍니다.
@Entity // DB 테이블 역할을 합니다.
public class Product {
// ID가 자동으로 생성 및 증가합니다.
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
// 반드시 값을 가지도록 합니다.
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String image;
@Column(nullable = false)
private String link;
@Column(nullable = false)
private int lprice;
@Column(nullable = false)
private int myprice;
// 관심 상품 생성 시 이용합니다.
public Product(ProductRequestDto requestDto) {
this.title = requestDto.getTitle();
this.image = requestDto.getImage();
this.link = requestDto.getLink();
this.lprice = requestDto.getLprice();
this.myprice = 0;
}
}
💻 ProductMypriceRequestDto.java : 관심상품 최저가 업데이트 요청 DTO
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class ProductMypriceRequestDto {
private int myprice;
}
🔒 AllInOneController 문제점
1. 한개의 클래스에 너무 많은 양의 코드가 존재함
- 코드 이해가 어렵다 : 처음부터 끝까지 다 읽어야 코드 내용을 이해할 수 있음
2. 현업에서는 코드 추가 혹은 변경 요청이 계속 생김
[ 변경 요청의 예 ]
a. 신규 상품 등록 시 Client에게 응답(Response)하는 값 변경
- 등록된 Product 전체 정보 ⇨ 등록된 Product의 id
b. 최저가(MyPrice) 업데이트 조건 변경
- Client가 최저가를 0원 이하로 입력 ⇨ error
c. DB테이블 이름 변경
- Product 테이블의 lprice ⇨ lowprice 변경
🔑 추천 프로그래밍 방식
절차적 프로그래밍 ⇨ 객체지향 프로그래밍 으로 리팩토링
💡 리팩토링이란?
: 기능 상의 변경 없이 프로그래밍 구조를 개선하는 것
1) 하나의 파일에 너무 많은 코드가 들어가지 않게
2) 역할별로 코드 분리
3) 코드를 좀 더 읽기 편하게 (가독성)
📌 절차적 프로그래밍(Procedural P-) vs 객체지향 프로그래밍(Object-Oriented P-)
- 절차적 프로그래밍"
- 초기 프로그래밍 방식
- 컴퓨터가 해야할 일들을 쭈~욱 순차적으로 나열해 놓는 코딩 방식
- 예) AllInOneController 클래스의 각 API 처리내용
- "객체지향 프로그래밍"
- 소프트웨어의 규모가 점점 커지면서 필요성이 부각이 됨
- 대부분의 사람들은 한 번에 여러가지 다른 생각을 하는데 취약
- 하나의 사물 (객체) 에 하나의 의미를 부여하는 것처럼 프로그래밍하게 됨
- 예)
- 뭔가 자를 것이 필요하면 '✂️' 를 떠올림 (class Sciccors)
- 종이에 적을 게 필요하면 '✏️' 을 떠올림 (class Pen)
- "하나의 역할" → 객체
- 예)
728x90
'🛠 BackEnd > Spring' 카테고리의 다른 글
[ Spring ] Table 'batch.batch_job_instance' doesn't exist / 에러 해결방법 (SpringBoot 2.5 이상) (0) | 2022.11.30 |
---|---|
[ Spring ] @Scheduled 스케줄러 사용법 (0) | 2022.11.02 |
[ Spring ] - Spring Security 인증 절차 인터페이스 UserDetails, UserDetailsService (0) | 2022.10.09 |
[ Spring ] Controller, Service Repository 코드 분리 (2/2) (1) | 2022.10.08 |
Springframework (0) | 2022.10.06 |
댓글