[Spring] 프로젝트에 간단한 redis 적용하기

한지연·2024년 1월 15일
post-thumbnail

🔍 구현한 기능

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


⚙️ 구현방법

❗️ docker에 redis가 이미 돌아가고 있다는 가정하에 글을 작성했습니다.

0. redis에 key value 생성해주기


1. docker ps 명령어를 사용하여 docker에서 사용중인 redis의 컨테이너 아이디 확인
2. docker exec -it [redis container id redis cli 명령어 실행
3. set [key] [value] 설정

1. build.gradle

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'

2. Repository

  • interface 선언
    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"));
    }
}

3. controller


	// 현재 종량제 봉투의 개수
	@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);
    }

4. service

@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를 사용해준다!

profile
배우고 활용하는 것을 즐기는 개발자, 한지연입니다!

0개의 댓글