ํ–ฅํ•ด99

STEP 13.์ฝ˜์„œํŠธ ํŠธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ + ํ† ํฐ ์ „๋žต (ํ–ฅํ•ด99 ๋ฐฑ์—”๋“œ 5๊ธฐ)

dev_0hoon 2024. 7. 31. 23:28

 ๐Ÿคท ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ ํ”„๋กœ๊ทธ๋žจ

์ผ๋ฐ˜์ ์œผ๋กœ ์ฝ˜์„œํŠธ๋ฅผ ์˜ˆ์•ฝํ•  ๋•Œ์—๋Š” '์ธ๊ธฐ๊ฐ€์ˆ˜'์˜ 'ํŒฌ'๋“ค์ด ๋ชฐ๋ฆฌ๊ฒŒ ๋˜๋ฉฐ ํŠธ๋ž˜ํ”ฝ์ด ๋ฐœ์ƒํ•œ๋‹ค. ๊ณง ์„œ๋ฒ„๊ฐ€ ๋ถ€ํ•˜๋ฅผ ๋ฐ›๊ฒŒ ๋œ๋‹ค. ์ ์€ ๋ถ€ํ•˜๋กœ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• ์ค‘ ์‚ฌ์šฉ ํ† ํฐ ์ „๋žต์ด ์žˆ๋‹ค.

 

Token (feat Redis)
in-memory ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ธ Redis๋ฅผ ์ด์šฉํ•œ token ๋Œ€๊ธฐ์—ด

 

 

์ฝ˜์„œํŠธ ์˜ˆ์•ฝํ”„๋กœ๊ทธ๋žจ์˜ ๋Œ€๊ธฐ์—ด ๋ฐฉ์‹์€

1. ์‚ฌ์šฉ์ž ์ฒ˜์Œ ๋“ฑ์žฅ -> ํ† ํฐ ์ƒ์„ฑ -> ํ† ํฐ ๋Œ€๊ธฐ์—ด๋กœ ๋“ค์–ด๊ฐ

2. ํ† ํฐ ๋Œ€๊ธฐ์—ด -> ์ˆœ๋ฒˆ์— ๋”ฐ๋ผ ํ™œ์„ฑํ™” ํ† ํฐ์œผ๋กœ ์ „ํ™˜ (์„œ๋ฒ„์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ์ •ํ•ด์ง)

3. ํ™œ์„ฑํ™” ํ† ํฐ -> ์˜ˆ์•ฝ, ๊ฒฐ์ œ ๋“ฑ์ด ๊ฐ€๋Šฅํ•ด์ง

 

์ด ์žˆ๋‹ค.

 

์ด๊ณณ์—์„œ ํ† ํฐ ๊ด€๋ฆฌ๋Š” ๋‘๊ฐ€์ง€๋กœ ๋‚˜๋ˆ„๊ฒŒ ๋œ๋‹ค.

  • ๋Œ€๊ธฐ์—ด ํ† ํฐ (Waiting Tokens)
  • ํ™œ์„ฑํ™” ํ† ํฐ (Active Tokens)

๋Œ€๊ธฐ์—ด ํ† ํฐ (Waiting Tokens)

๊ธฐ์กด์˜ ๋Œ€๊ธฐ์—ด ํ† ํฐ์€ ์ƒํƒœ๊ฐ’์— ๋”ฐ๋ผ DB์— ์ €์žฅํ•˜์—ฌ ๊ด€๋ฆฌํ–ˆ๋‹ค.

//ํ† ํฐ์กฐํšŒ
public TokenCommand.TokenCreateResDto getTokenInfo(String token) {

        Token findToken = tokenRepository.findByToken(token);

        if (findToken.getStatus() == TokenStatus.WAIT ){
            long order = findOrder(findToken);
            return TokenCommand.tokenInfo(findToken, order);
        }
        return TokenCommand.tokenInfo(findToken, 0L);
}

//ํ† ํฐ์ƒ์„ฑ
public TokenCommand.TokenCreateResDto createToken(Long userId) {
    
        Token token = tokenRepository.findByUserId(userId);
        
        //ํ† ํฐ์ด ์ด๋ฏธ ์กด์žฌํ•  ๊ฒฝ์šฐ
        if (!ObjectUtils.isEmpty(token)) {
            //ํ† ํฐ์ด ์ด๋ฏธ active์ผ ๊ฒฝ์šฐ์—๋Š” updateAt ๋น„๊ต
            //ํ† ํฐ์ด Wait๋ผ๋ฉด accessTime ๋น„๊ต
            //5๋ถ„์ด ์ง€๋‚ฌ์œผ๋ฉด
            ...

            return TokenCommand.tokenInfo(token, order);
        } else {
            //ํ† ํฐ ๋ฐœ๊ธ‰
            Token saveToken = tokenRepository.save(Token.create(user, status));
            return TokenCommand.tokenInfo(saveToken, order);
        }
        
    }

 

์œ„์˜ ๋ฐฉ์‹์€ ํ† ํฐ์„ ์ƒ์„ฑ, ์กฐํšŒํ•  ๋•Œ๋งˆ๋‹ค DB์— ์ปค๋„ฅ์…˜ ๋˜๊ฒŒ ๋œ๋‹ค.

 

์ฆ‰ ์‚ฌ์šฉ์ž๊ฐ€ ๋ช‡๋งŒ๋ช…์ด ๋™์‹œ์— poliing์„ ํ•  ๊ฒฝ์šฐ DB์— ๊ฐ•ํ•œ ๋ถ€ํ•˜๋ฅผ ์ฃผ๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ค‘๊ฐ„์— In-Memory์ธ Redis๋ฅผ ๋‘์–ด ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐํ•ด์ฃผ๋ ค ํ•œ๋‹ค.

 

๐Ÿคท API  ๋ชฉ๋ก๋ณ„ ์กฐ์น˜ ๋ชฉํ‘œ

- ๋Œ€๊ธฐ์—ด ํ† ํฐ ๋“ฑ๋ก POST /token

1. ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

2. ํ† ํฐ์„ ์ƒ์„ฑ

3. ํ† ํฐ์„ redis์— ZADD ๋ช…๋ น์–ด๋กœ Waiting Tokens(Sorted Set ์ž๋ฃŒ๊ตฌ์กฐ)์— ๋จผ์ € ๋„ฃ๋Š”๋‹ค.

4. 'ZRANK Waiting Tokens ์‚ฌ์šฉ์ž' ๋ช…๋ น์–ด๋กœ ์ˆœ๋ฒˆ์„ ๊ตฌํ•ด์ค€๋‹ค.

5. ์ž”์—ฌ๋Œ€๊ธฐ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•ด ๋ฆฌํ„ดํ•œ๋‹ค.

 

- ํ† ํฐ ์‚ฌ์šฉ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์กฐํšŒ GET /token

1. ํด๋ผ์ด์–ธํŠธ์—์„œ ์ผ์ • ๊ธฐ๊ฐ„(5์ดˆ)๋งˆ๋‹ค ํ•ด๋‹น API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋Œ€๊ธฐ์ˆœ๋ฒˆ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค.(polling ๋ฐฉ์‹)

2. ํ† ํฐ์ด Active Tokens์— ์žˆ๋Š”์ง€ ํ™•์ธ

3. ์—†์„ ๊ฒฝ์šฐ, 'ZRANK Waiting Tokens ์‚ฌ์šฉ์ž' ๋ช…๋ น์–ด๋กœ ์ˆœ๋ฒˆ์„ ๊ตฌํ•ด์ค€๋‹ค.

5. ์ž”์—ฌ๋Œ€๊ธฐ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•ด ๋ฆฌํ„ดํ•œ๋‹ค.

 

-  ์ฝ˜์„œํŠธ ์ขŒ์„ ์กฐํšŒ GET /concert-seats

1. ํ† ํฐ์ด Active Tokens์— ์žˆ๋Š”์ง€ ํ™•์ธ

2. ํ† ํฐ์˜ ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ํ™•์ธํ•˜๋ฉฐ, 5๋ถ„์ด ์ง€๋‚˜์ง€ ์•Š์•˜๋‹ค๋ฉด

3. concertSeats ์ •๋ณด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

 

- ์ฝ˜์„œํŠธ ์ขŒ์„ ์˜ˆ์•ฝ POST /seat

1. ํ† ํฐ์ด Active Tokens์— ์žˆ๋Š”์ง€ ํ™•์ธ

2. ํ† ํฐ์˜ ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ๊ตณ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด์œ ๋Š” ๊ฒฐ์ œ๊นŒ์ง€ ์™€์„œ ๋งŒ๋ฃŒ์‹œ๊ฐ„์œผ๋กœ ํŠ•๊ธธ ๊ฒฝ์šฐ ํ™”๊ฐ€ ๋งŽ์ด ๋‚  ๊ฒƒ์ด๋‹ค. (ํšŒ์‚ฌ ์ž…์žฅ์—์„œ๋„ ๋ˆ์„ ๋ฐ›๋Š”๊ฒŒ ๋” ์ค‘์š”ํ•  ๊ฑฐ๋ผ ์ƒ๊ฐ์ด ๋“ฌ feat.ํ•˜ํ—Œ์šฐ ์ฝ”์น˜๋‹˜ )

3. ๊ฒฐ์ œ ํ›„ Active Tokens์—์„œ ์ œ๊ฑฐํ•œ๋‹ค.

 

+ Active Token ์ „ํ™˜ ์Šค์ผ€์ฅด๋Ÿฌ

1. 10์ดˆ ๋งˆ๋‹ค 3,000๋ช… ์”ฉ Active Tokens์œผ๋กœ ์ „ํ™˜ํ•œ๋‹ค.

 

 

Redis์—์„œ ์‚ฌ์šฉ ๋  ์ž๋ฃŒ๊ตฌ์กฐ๋Š” 2๊ฐ€์ง€

sorted set (Waiting Tokens ์‚ฌ์šฉ)

  • zadd๋กœ ๋“ฑ๋ก ํ•œ๋‹ค (์˜ˆ์‹œ : zadd waitingTokens 20240901030101 tokenUUID)
  • score๋ถ€๋ถ„(20240901030101)์œผ๋กœ ์ˆœ์„œ๋ฅผ ๋งค๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์œ„ ํ”„๋กœ์ ํŠธ ๊ฐ™์€ ๊ฒฝ์šฐ ์ž…์žฅ ์ˆœ์œผ๋กœ ์ˆœ์„œ๋ฅผ ๋งค๊ธธ ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
  • zrank๋Š” ํ•œ value์˜ ์ˆœ๋ฒˆ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  • zrange๋Š” ์›ํ•˜๋Š” ์ˆœ๋ฒˆ์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ์— ์ ํ•ฉํ•˜๋‹ค.

set (Active Tokens ์‚ฌ์šฉ)

  • ์ปฌ๋Ÿผ๋‹น ์ถ”๊ฐ€, ์ œ๊ฑฐ, ์กด์žฌ ์œ ๋ฌด ์ฒดํฌ์˜ ์†Œ๋ชจ๋˜๋Š” ์‹œ๊ฐ„์ด ์ผ์ •ํ•˜๋ฉฐ ๋งค์šฐ ๋น ๋ฅด๋‹ค.
  • ์ตœ๋Œ€ ์š”์†Œ์˜ ์ˆ˜๊ฐ€ 42์–ต๊ฐœ๋ฅผ ๋„˜๊ธด๋‹ค๊ณ  ํ•œ๋‹ค.
  • sadd ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๋“ฑ๋ก์ด ๊ฐ€๋Šฅ (์˜ˆ์‹œ : sadd activeToken tokenUUID)
  • sadd activeToken tokenUUID:20240303010203 ์‹์œผ๋กœ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‹œ๊ฐ„์œผ๋กœ ๋‘๋ฉด ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ๊ตฌํ•˜๊ธฐ ์ˆ˜์›”ํ•  ๊ฒƒ์ด๋‹ค.