회원등급을 구현해보자.
현재 users에 만들어둔 role이라는 열을 이용해서 레벨을 구현하려고 한다. 하지만, 문제가 있다고 생각했다.
등급에 따라 상품의 가격을 깎아주는 형태가 아닌 등급마다 받을 수 있는 쿠폰이 있으며, 이를 발급받아 사용할 수 있도록 한다.
문제점?
가장 처음 생각한 방법은 이를 컨트롤러 부분에서 등급을 비교하여 응답을 보내는 것이다. 하지만 이 방법을 사용하면 등급이 많으면 많을수록 복붙코드가 많아진다(같은 로직이지만 등급마다 하나의 함수를 매핑시켜주어야함)
즉, 컨트롤러에서 하나하나 비교해주는 것이 아니라 하나의 함수를 두고, 그 함수가 돌아가면 자동적으로 자신의 등급에 맞는 쿠폰을 받을 수 있도록 하고싶다. 그렇게 설계하여야 나중에 수정이 필요할 때 훨씬 편할 것이다.
생각해본 방법
쿠폰에도 등급을 저장해둘 수 있는 열을 추가해서 해당 등급을 통해서 쿠폰리스트를 만들 수 있도록한다면 등급에 맞는 쿠폰들을 가져올 수 있을 것 같다!
쿠폰에 등급을 추가해야되는게 약간 아쉽긴한데 내가 생각한 방법중에는 최선인 것 같다..
쿠폰에 정수형으로 level열을 추가했다. 정수형으로 추가한 이유는 메모리를 최대한 적게쓰기 위해서이며, user의 role을 정수형으로 변형하여 사용할 수 있기 때문이다. 엔티티에도 마찬가지로 정수형으로 level을 추가해주자
그 후에는 level을 enum으로 선언하여 하나의 타입으로 사용할 수 있도록 코드를 작성해주자
package com.shoppingmall.dto;
public enum Level {
BASIC(1), NORMAL(2), VIP(3), VVIP(4), admin(999); // enum 오브젝트 정의
private final int value;
Level(int value) { // 생성자 만들기
this.value = value;
}
public int getValue() { // 값을 가져오는 메소드
return value;
}
// 문자열을 받아 해당하는 enum을 반환하는 메서드
public static Level fromString(String status) {
for (Level s : Level.values()) {
if (s.name().equalsIgnoreCase(status)) {
return s;
}
}
throw new IllegalArgumentException("Unknown status: " + status);
}
// 문자열을 받아 정수값을 반환하는 메서드
public static int toInt(String level) {
return fromString(level).getValue();
}
}
이제 level을 통해 쿠폰을 찾을 수 있도록 하는 함수를 작성하자. 이전에 작성한 코드에서 sql문만 바꾸면 만들 수 있다
public List<Coupon> findByLevel(int level){
TypedQuery<Coupon> query = em.createQuery("SELECT u FROM Coupon u WHERE u.level = :level", Coupon.class);
query.setParameter("level", level);
return query.getResultList();
}
리포지토리에 추가한 함수를 서비스를 통해 제공할 수 있도록 하자
public List<Coupon> findCouponByLevel(int level) { return couponRepository.findByLevel(level); }
마지막으로 컨트롤러를 통해 해당 함수를 이용하여 사용자가 원하는 동작을 할 수 있도록 하자
이전에 만들어둔 event 쿠폰 발급 코드를 수정했다.
@GetMapping("/event")
public String eventCouponPage(@AuthenticationPrincipal UserDetails userDetails, Model model){
Users users = userService.findById(userDetails.getUsername());
int level = Level.toInt(users.getRole());
List<Coupon> coupons = couponService.findCouponByLevel(level);
model.addAttribute("coupons", coupons);
model.addAttribute("level", users.getRole());
return "/event";
}
또한 model에 level을 추가해서 level을 html에 표시할 수 있도록 하여 테스트 결과가 확실한지 확인해보기로 했다
실험용 데이터베이스
BASIC 등급으로 로그인 시,
VIP 등급으로 로그인 시,
성공적으로 작동했음을 확인할 수 있다. 아쉬운 점이라면 리스트를 percent를 기준으로 오름차순 정렬을 해두는 것이 미관상 더 좋아보일 것 같다. (물론 사용자의 쿠폰함이 기준이라면 유효기간을 기준으로 정렬하는 것이 나을 수도 있다)
아무튼 회원등급을 추가해서 해당 등급에 맞는 쿠폰을 발급 받을 수 있도록 했다. 점점 기능들이 쉽고 빠르게 추가되는 것 같다. 스프링에 익숙해지니 스프링이 얼마나 편한 것인지 몸소 체감을 하고있는 것 같다.
다음 시간에는 리뷰기능을 추가해보자! 물건을 구매했다면 리뷰를 남길 수 있도록하고, 이를 다른 사용자가 볼 수 있도록 만들어보자.