사람들에게 하루 100개의 종량제 봉투를 나눠주는 기능을 만들었다. 이때 기능을 만들며고민한 포인트는 db에 테이블을 따로 구현하고 트랜잭션을 이용하여 기능을 만드는 것이 효율적인가 하는 것이었다. 그래서 내가 생각해낸 방법은 redis를 이용하는 것이었다.
❗️ docker에 redis가 이미 돌아가고 있다는 가정하에 글을 작성했습니다.

1. docker ps 명령어를 사용하여 docker에서 사용중인 redis의 컨테이너 아이디 확인
2. docker exec -it [redis container id redis cli 명령어 실행
3. set [key] [value] 설정
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'
public interface RedisRepository extends JpaRepository<User, Long> {
}@Repository
@RequiredArgsConstructor
public class RedisRepositoryImpl {
// RedisTemplate 선언
private final RedisTemplate<String, String> redisTemplate;
// plastic_bag이라는 key의 값을 감소시켜줌
public Long decrease() {
return redisTemplate.opsForValue().decrement("plastic_bag");
}
// plastic_bag의 현재 값을 가져옴
public Integer getCount() {
return Integer.parseInt(redisTemplate.opsForValue().get("plastic_bag"));
}
}
// 현재 종량제 봉투의 개수
@GetMapping("/total-plasticbag-count")
public Integer getTotalPlasticCount() {
return userService.totalPlasticBag();
}
// 내가 가진 종량제 개수 카운트
@GetMapping("/my-bag-count")
public Integer getMyPlasticCount(@Param("userId") String userId) {
return userService.getMyPlasticCount(userId);
}
// 종량제 봉투 얻기를 클릭 했을 때 작동하는 api
@GetMapping("/get-plasticbag")
public void getPlasticbag(@RequestParam("userId") String userId) {
userService.addCountPlasticBag(userId);
}
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserService{
private final UserRepository userRepository;
private final PasswordEncoder bcryptEncoder;
private final RedisRepositoryImpl redisRepository;
// 현재 내가 가진 종량제 봉투 개수
public Integer getMyPlasticCount(String userId) {
User user = userRepository.findByUserStrId(userId);
return user.getPlasticBagCount();
}
// 유저가 종량제 봉투 한 개를 요청 했을 때 작동하는 함수
@Transactional
@Async
public void addCountPlasticBag(String userId) {
User user = userRepository.findByUserStrId(userId);
if(redisRepository.getCount() > 0) {
redisRepository.decrease();
user.incrementPlasticBagCount();
} else {
throw new IllegalArgumentException("요청을 수행할 수 없습니다.");
}
}
// 현재 redis에 저장된 plastic_bag의 value를 가져오기
public int totalPlasticBag(){
return redisRepository.getCount();
}
}
public class RedisRepositoryImpl {
private final RedisTemplate<String, String> redisTemplate;
private String key = "plastic_bag";
private String value = "100";
@Scheduled(fixedDelay = 24 * 60 * 60 * 1000)
public void setPlasticBagCountCount() {
log.info("- - - plastic bag count reset - - -, {}", LocalDateTime.now());
redisTemplate.opsForValue().set(key, value);
}
public Long decrease() {
return redisTemplate.opsForValue().decrement(key);
}
public Integer getCount() {
return Integer.parseInt(redisTemplate.opsForValue().get(key));
}
}
@Scheduled를 사용해준다!