네이버 쇼핑 API를 사용하여 나만의 셀렉샵을 만들어 보았다. 프로젝트 구조는 다음과 같다.
1. 네이버 쇼핑 API 신청하기
네이버 쇼핑 API 를 사용하기 위해서는 API 사용 신청을 해야 한다. 다음 링크에서 신청할 수 있다.
https://developers.naver.com/docs/search/shopping/
다음과 같은 양식으로 API 이용 신청을 한다.
신청이 끝나면 Client ID 와 Client Secret 를 발급받을 수 있다.
2. Repo(Domain, Repository)
- Repo 는 가장 안쪽 부분을 의미하고, DB와 맞닿아 있다.
먼저 Product.java 파일을 생성한다. 이 파일을 관심 상품을 의미하고 DB의 테이블 역할을 하는 클래스이다.
@Getter // Lombok이 getter 자동 생성
@NoArgsConstructor // 기본 생성자 자동 생성
@Entity // 이 클래스는 DB의 테이블 역할
public class Product extends Timestamped{ // 생성,수정 시간을 자동으로 생성하도록 상속받음
// 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;
}
// 최저가(관심가격) 변경 시
public void update(ProductMypriceRequestDto requestDto) {
this.myprice = requestDto.getMyprice();
}
// 예약된 시간에 가격 변경 시
public void updateByItemDto(ItemDto itemDto) {
this.lprice = itemDto.getLprice();
}
}
TimeStamped.java 파일을 생성하여 생성/수정 시간을 자동으로 업데이트 되도록 한다.
@Getter
@MappedSuperclass // 상속했을 때, 컬럼으로 인식하게 함
@EntityListeners(AuditingEntityListener.class) // 생성/수정 시간을 자동으로 업데이트 함
public abstract class Timestamped { // abstract - 직접 생성은 불가하고 상속만 가능함
@CreatedDate
private LocalDateTime createdAt; // 생성 시간
@LastModifiedDate
private LocalDateTime modifiedAt; // 수정 시간
}
생성/수정 시간을 JPA 가 자동으로 업데이트 하고, 스케줄러가 작동할 수 있도록 Application 에 어노테이션을 추가해준다.
@EnableScheduling // 스프링 부트에서 스케줄러가 작동하게 함
@EnableJpaAuditing // 시간 변경을 자동으로
@SpringBootApplication
public class Week04Application {
public static void main(String[] args) {
SpringApplication.run(Week04Application.class, args);
}
}
ProductRepository.java 파일을 생성한다. 이 파일은 DB의 SQL 역할을 하는 인터페이스이다. JPA를 사용하기 위해 JpaRepository<domain 클래스, id의 type> 을 상속받는다.
public interface ProductRepository extends JpaRepository<Product, Long> {
}
3. DTO
- 테이블에 값을 넣을 때 클래스를 직접 사용하는 것은 좋지 않다. 그래서 완충재로 활용하는 것이 DTO 이다.
ProductRequestDto 는 관심 상품을 등록할 때 사용하는 DTO 이다.
@Getter
public class ProductRequestDto {
private String title;
private String link;
private String image;
private int lprice;
}
ProductMypriceRequestDto 는 자신이 설정한 최저가(관심가격)을 변경할 때 사용하는 DTO 이다.
@Getter
public class ProductMypriceRequestDto {
private int myprice;
}
ItemDto 는 API 를 통해 검색된 결과를 가져올 때 사용하는 DTO 이다. 검색 결과가 String 으로 들어오기 때문에 화면에 보여주기 위해서는 DTO를 사용해야 한다.
@Getter
public class ItemDto {
private String title;
private String link;
private String image;
private int lprice;
public ItemDto(JSONObject itemJson) {
this.title = itemJson.getString("title");
this.link = itemJson.getString("link");
this.image = itemJson.getString("image");
this.lprice = itemJson.getInt("lprice");
}
}
4. Service
- Service 는 중간 부분이고, 실제 중요한 동작이 많이 일어나는 부분이다.
ProductService.java 파일을 생성하고 추가적으로 필요한 동작을 정의한다.
@RequiredArgsConstructor // 꼭 필요한 요소(final) 자동 생성
@Service // 이 클래스가 서비스임을 알려줌
public class ProductService {
// final 은 꼭 필요한 요소임을 명시하는 것, 값이 변경 될 수 없음
private final ProductRepository productRepository;
@Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌, 자동으로 DB에 업데이트 됨
public Long update(Long id, ProductMypriceRequestDto requestDto) {
Product product = productRepository.findById(id).orElseThrow(
() -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
);
product.update(requestDto); // 관심 가격 변경
return id;
}
@Transactional
public Long updateBySearch(Long id, ItemDto itemDto) {
Product product = productRepository.findById(id).orElseThrow(
() -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
);
product.updateByItemDto(itemDto); // 예약된 시간에 가격 변경
return id;
}
}
5. Controller
- Controller 는 가장 바깥 부분이고, 요청/응답을 처리한다.
ProductRestController 는 관심 상품 관련 요청/응답을 처리하는 controller 이다.
@RequiredArgsConstructor // 꼭 필요한 요소(final) 자동 생성
@RestController // JSON 으로 응답하기 위한 RestController 라는 의미
public class ProductRestController {
private final ProductService productService;
private final ProductRepository productRepository;
// 등록된 전체 관심 상품 조회
@GetMapping("/api/products")
public List<Product> getProducts() {
return productRepository.findAll();
}
// 관심 상품 등록
@PostMapping("/api/products")
public Product createProduct(@RequestBody ProductRequestDto requestDto) {
Product product = new Product(requestDto);
productRepository.save(product);
return product;
}
// 최저가(관심가격) 변경
@PutMapping("/api/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) {
return productService.update(id, requestDto);
}
}
SearchRequestController 는 상품 검색 관련 요청을 처리하는 controller 이다.
@RequiredArgsConstructor // 꼭 필요한 요소(final) 자동 생성
@RestController // JSON 으로 응답하기 위한 RestController 라는 의미
public class SearchRequestController {
private final NaverShopSearch naverShopSearch;
// Naver 쇼핑 API를 사용하여 검색된 상품 조회
@GetMapping("/api/search")
public List<ItemDto> getItems(@RequestParam String query) {
String resultString = naverShopSearch.search(query);
return naverShopSearch.fromJSONtoItems(resultString);
}
}
'Back-end > Spring' 카테고리의 다른 글
[SpringBoot] 5주차 스터디 (AWS RDS, EC2) (0) | 2021.09.16 |
---|---|
[SpringBoot] 4주차 스터디 ② (나만의 셀렉샵 만들기, 네이버 쇼핑 API) (0) | 2021.09.09 |
[SpringBoot] 3주차 스터디 (메모장 만들기, Spring JPA) (0) | 2021.09.02 |
[SpringBoot] 2주차 스터디 (JPA, domain, repository, DTO, service, controller) (1) | 2021.08.28 |
[SpringBoot] 1주차 스터디 (RestController) (0) | 2021.08.19 |