본문 바로가기

SpringBoot/스파르타 스프링 심화

[스파르타 스프링 심화] 01.12. 관심사 별 코드 분리해보기

728x90
반응형

##AllInOneController -> 기능 별 controller,service,repository 3계층으로 리팩토링 하기

-아래의 코드는 절차지향이라 코드가 길고 복잡하게 보인다. 이것을 객체지향으로 바꾸자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.sparta_spring.sparta_springcore_week01;
 
 
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
 
@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다. @Controller , @ResponseBody 2개의 역할 합침
public class AllInOneController {
    // 등록된 전체 상품 목록 조회
    @GetMapping("/api/products")
    public List<Product> getProducts() throws SQLException {
        ArrayList<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.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
            product.setModifiedAt(rs.getTimestamp("modified_at").toLocalDateTime());
            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;
    }
 
    // 신규 상품 등록
    @PostMapping("/api/products")
    public Product createProduct(@RequestBody ProductRequestDto requestDto) throws SQLException {
        // 요청받은 DTO 로 DB에 저장할 객체 만들기
        Product product = new Product(requestDto);
        LocalDateTime now = LocalDateTime.now();
        product.setCreatedAt(now);
        product.setModifiedAt(now);
        // 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, created_at, modified_at) 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());
        ps.setString(7, product.getCreatedAt().toString());
        ps.setString(8, product.getModifiedAt().toString());
        // 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.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
            product.setModifiedAt(rs.getTimestamp("modified_at").toLocalDateTime());
            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 = ?, modified_at = ? where id = ?");
        ps.setInt(1, requestDto.getMyprice());
        ps.setString(2, LocalDateTime.now().toString());
        ps.setLong(3, product.getId());
        // DB Query 실행
        ps.executeUpdate();
        // DB 연결 해제
        rs.close();
        ps.close();
        connection.close();
        // 응답 보내기 (업데이트된 상품 id)
        return product.getId();
    }
}
cs

2.ProductController 역할 분리

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.sparta_spring.sparta_springcore_week01;
 
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
 
import java.sql.SQLException;
import java.util.List;
 
@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductController {
    // 등록된 전체 상품 목록 조회
    @GetMapping("/api/products")
    public List<Product> getProducts() throws SQLException {
        ProductService productService = new ProductService();
        List<Product> products = productService.getProducts();
        // 응답 보내기
        return products;
    }
 
    // 신규 상품 등록
    @PostMapping("/api/products")
    public Product createProduct(@RequestBody ProductRequestDto requestDto) throws SQLException {
        ProductService productService = new ProductService();
        Product product = productService.createProduct(requestDto);
        // 응답 보내기
        return product;
    }
 
    // 설정 가격 변경
    @PutMapping("/api/products/{id}")
    public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) throws SQLException {
 
        ProductService productService = new ProductService();
        Product product = productService.updateProduct(id, requestDto);
        return product.getId();
    }
}
cs

3.ProductService 역할 분리

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.sparta_spring.sparta_springcore_week01;
 
import java.sql.SQLException;
import java.util.List;
 
public class ProductService {
 
    public List<Product> getProducts() throws SQLException {
        ProductRepository productRepository = new ProductRepository();
        return productRepository.getProducts();
    }
 
    public Product createProduct(ProductRequestDto requestDto) throws SQLException {
        ProductRepository productRepository = new ProductRepository();
        // 요청받은 DTO 로 DB에 저장할 객체 만들기
        Product product = new Product(requestDto);
        productRepository.createProduct(product);
        return product;
    }
 
    public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) throws SQLException {
        // 최저가 0 미만 예외처리
        if(requestDto.getMyprice() < 0){
            throw new IllegalAccessError("최저가는 0 이상입니다.");
        }
 
        ProductRepository productRepository = new ProductRepository();
        Product product = productRepository.getProduct(id);
        if (product == null) {
            throw new NullPointerException("해당 아이디가 존재하지 않습니다.");
        }
        int myPrice = requestDto.getMyprice();
        productRepository.updateProductMyPrice(id, myPrice);
        return product;
    }
}
cs

4.ProductRepository 역할 분리

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package com.sparta_spring.sparta_springcore_week01;
 
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
 
public class ProductRepository {
    public Product getProduct(Long id) 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.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
            product.setModifiedAt(rs.getTimestamp("modified_at").toLocalDateTime());
            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 {
            return null;
        }
 
        return product;
    }
    public List<Product> getProducts() throws SQLException {
        ArrayList<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.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
            product.setModifiedAt(rs.getTimestamp("modified_at").toLocalDateTime());
            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;
    }
 
    public void createProduct(Product product) throws SQLException {
        LocalDateTime now = LocalDateTime.now();
        product.setCreatedAt(now);
        product.setModifiedAt(now);
 
        // 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 값을 찾아오지 못했습니다.");
        }
 
        // DB Query 작성
        ps = connection.prepareStatement("insert into product(id, title, image, link, lprice, myprice, created_at, modified_at) 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());
        ps.setString(7, product.getCreatedAt().toString());
        ps.setString(8, product.getModifiedAt().toString());
        // DB Query 실행
        ps.executeUpdate();
        // DB 연결 해제
        ps.close();
        connection.close();
    }
 
    public void updateProductMyPrice(Long id, int myPrice) throws SQLException {
        // DB 연결
        Connection connection = DriverManager.getConnection("jdbc:h2:mem:springcoredb""sa""");
        // DB Query 작성
        PreparedStatement ps = connection.prepareStatement("update product set myprice = ?, modified_at = ? where id = ?");
        ps.setInt(1, myPrice);
        ps.setString(2, LocalDateTime.now().toString());
        ps.setLong(3, id);
        // DB Query 실행
        ps.executeUpdate();
        // DB 연결 해제
        ps.close();
        connection.close();
    }
}
cs

 

##리팩토링 후 검증

1.리팩토링이란?

: 기능은 똑같이 하되 편의에 맞춰 내부구조나 코드를 바꾸는 것.

 

 

반응형