240617 백오피스 프로젝트 - 프로젝트 마무리

노재원·2024년 6월 17일
0

내일배움캠프

목록 보기
62/90

프로젝트 마무리

주말중에 대부분 기능 구현은 끝냈고 오늘은 내일 발표를 위한 최종 테스트, 시연 영상을 찍고 발표 자료와 Readme를 작성하는 시간이 길었다.

주말을 조금 쓰긴 했지만 일정 관리 자체는 굉장히 잘한 것 같아 다행이고 팀원 분들의 불만사항도 다른 주차에 비해 현저히 적은 걸로 느껴져서 많이 기쁜 프로젝트가 된 것 같다.

물론 정말 프론트만 있으면 실제 서비스로 내놓을 수 있을 만큼 정책이 완벽하게 설정되어 있거나 한 건 아니다. 하지만 학습 주차 프로젝트의 목적인 협업 경험과 복습의 측면에서는 정말 훌륭한 시간이 됐다고 스스로 생각하기로 했다.

챌린지반 - Redis 기초

프로젝트가 점점 험난해져서 기술 스택을 늘리기 위한 강의로 방향성이 약간 바뀌게 되었다. 그 중에서도 오늘은 두고두고 써먹는 Redis에 대해 진행하게 됐다.

간단 설명

Key-Value 구조로 데이터를 저장하는 비관계형 데이터베이스로 NoSQL로 구분된다. 이럴땐 쿼리가 아니라 커맨드 기반으로 동작한다고 본다.

특징은 Disk가 아닌 Memory를 쓰는 In-memory DB인 점이고 휘발성에 속도 빠른 점인데 이건 요즘 많이 접해봐서 이 특징이 체감되는 것 같다.

추가로 Single Thread로 동작한다고 하는데 이거는 이번에 처음 알게 됐다.

이렇게 3가지 키워드를 Redis의 상징적인 특징으로 여긴다고 한다.

Redis가 지원하는 자료구조

Value 에 어떤 자료구조가 올 수 있는지에 대해 알아봤는데 이메일 인증때 알아본 것 처럼 굉장히 다양하게 설정할 수 있는 것 같다.

기본적으로 Expire 용도로 쓰는 TTL(Time To Live)는 Key에만 설정 가능하다고 한다.

  • String
    • get, set은 기본 지원이고 mset, mget, setnx 커맨드도 지원한다.
  • List (연결리스트)
    • lpush, lpop, rpush, rpop 으로 데이터를 리스트의 양 끝에서만 뺄 수 있다.
    • 길이를 조회하는 llen, 길이로 자르는 ltrim 커맨드도 있다.
    • 대기열 구현, 최근 방문글 구현에 도움이 된다.
  • Set (집합)
    • 데이터의 순서는 보장하지 않고 중복을 허용하지 않는 익숙한 Collection이다.
  • Hash
    • Hask Key를 Key로 사용하는 Key 안에 다시 Key-value를 저장할 수 있는 자료구조다.
    • 그냥 Map같지만 TTL을 걸 수 있는건 Hash Key밖에 안된다.
    • 대부분 시간복잡도가 O(1)이라 굉장히 빠르고 메모리도 효율적이다.
    • 코인의 시세 정보등을 저장하는 활용이 가능하다.
      • 두 거래소의 시세를 가져올 때 각 거래소를 HashKey로 두고 Value에 시세를 넣어놓는 것이다.
  • SortedSet (ZSet)
    • 정렬된 Set고 정렬의 기준이 필요하기 때문에 (member, score) 쌍으로 이루어지고 score가 기준이 된다.
      • Hash + Set로 볼 수도 있다.
    • 미리 정렬이 되어있어야 하는 순위를 보여주는 리더보드, 많이본 주식등을 구현할 때 쓸 수 있다.

여기까지만 다뤘고 이외에도 다양한 자료구조가 제공된다. 그렇기에 비즈니스 요구사항 구현을 위해 Redis를 쓸 때는 적절한 자료구조를 결정하기 위해 고민이 필요하다.

Redis의 활용 시기

기술을 사용할 때 근거가 필요한 것은 항상 중요하다.

Cache 저장소

In-memory로 빠르고 TTL을 지원하고 다양한 자료구조를 지원하기 때문에 Remote Cache Server로 많이 사용된다. 그리고 기술적으로 충분한 성숙을 이뤄서 안정적이기도 하다.

비슷한 역할로 In-memory인 memcached를 같이 고민해보면 좋다.

Scale-out 상황에서의 중앙 저장소

똑같은 일을 처리하는 서버를 여러대 추가해서 확장하는 Scale-out 상황에서 중앙 저장소로 쓰기에 좋다.

예를 들면 사용자가 세션 로그인을 인스턴스 A, B, C중 A에 했을 때 A에 세션을 저장해뒀지만 다음 접근이 C로 가게 되면 세션이 없으므로 문제가 생긴다. 그러니 이 Session을 각 인스턴스에 저장하지 않게 Session 저장소의 역할로 활용이 가능하다.

추가로 Scale-out은 요즘 굉장히 자주 다루지만 State의 저장, scheduler의 다중 실행 문제등 문제가 있으니 Scale-out 할 때는 미리 준비를 잘해야한다.

그리고 이런 단점때문에 Stateless가 뜨게 됐다.

데이터 저장 목적

In-memory 특성상 영속성적인 목적보다는 서버 사이에서 주고받을 데이터를 저장하는 것에 가깝다.

그리고 Redis는 Single thread로 동작하기 때문에 Race condition 이슈에서 자유롭고 빠르다.

예를 들면 코인 시세 조회 서비스가 있을 경우 코인 시세 조회 API 서버와 코인 시세 수집 서버를 나눠 수집 서버는 Redis에 저장하고 조회 서버는 Redis에서 조회하는 것이다.
빠른 것이 여전히 장점이다.

Redis가 영속성 기능을 제공하긴 하지만 잘 사용하지 않는다.

데이터 전송 목적

Redis는 Kafka와 유사한 Event Pub/Sub 기능을 제공한다.

이를 이용해 EDA(Event Driven Architecture)를 구현하는 활용 용도로 쓸 수 있다.

동시성 문제 해결

Redis는 Single thread 기반이므로 선착순 티켓팅같은 기능을 Lock을 구현하면 쉽게 해결 가능하다.

MySQL같은 것도 Lock을 구현할 수 있지만 기본적으로 Multi thread라 Lock 구현이 어렵다.

Redis clustering (H/A)

어려운 내용인데 강의에서는 보여주고만 가셨다. 써볼 일이 많이는 없어 이런 기능이 있다고 소개해주셨다.

Redis node를 1대로 운영하는 건 위험하다고 한다.
한 대만 꺼져도 해당 컴포넌트 자체가 모두 죽는 SPOF (Single Point Of Failure) 문제의 위험이 있다.

그래서 Redis Node를 1000개까지 확장할 수 있는 Redis Cluster 기능을 제공한다.

Spring boot에서 Redis 쓰기

Spring Data Repository를 이용하는 방법과 RedisTemplate를 이용하는 방법이 있는데 강의에선 RedisTemplate만 다루고 넘어갔다.

Spring Data Repository를 쓰면 추상화가 많이 이루어진다고 한다.

이는 의존성 추가하고 @Configuration Bean으로 만들고 RedisTemplate를 주입받아 사용하면 된다.

책임 분리

Redis를 다루는 법은 코드 몇줄이면 끝날 정도로 쉽지만 Service가 RedisTemplate를 직접 주입받는 건 여타 로직의 이유로 권장하지 않는다고 하셨다. 그래서 튜터님은 RedisRepository로 분리하는 걸 추천하셨다.

Redis의 Transcation

Redis는 Single thread 기반으로 각각의 커맨드에 대한 원자성(다른 커맨드가 끼어들지 못함)을 보장해준다.

그런데 여러 클라이언트에서 Redis 커맨드가 연달아 호출되면 Race condition 이슈가 존재할 수 있다.

이를 해결하는 방법은 위에서 말한 Lock도 있고 Redis의 Transaction을 이용하는 방법이 있다. -> MULTI 커맨드

MULTI 커맨드 실행 후 입력되는 커맨드를 Queue에 쌓다가 EXEC을 실행하면 여러 커맨드에 대한 원자성을 지키며 실행한다. (Rollback을 원하면 DISCARD를 쓰면 된다.)

Spring boot에서 설정하기

별도의 Transactional manager 구현체는 존재하지 않는다.

RedisTemplate bean configuration에서 redisTemplate.setEnableTransactionSupport(true) 만 처리해주면 된다. 이후 @Transactional 을 사용하면 Jpa의 Transactional manager가 구현해준다.

0개의 댓글