ABOUT ME

-

  • [ Next ] Redis 사용하여 캐시 관리
    Front/Next 2025. 9. 28. 02:09
    반응형

    네이버랑 카카오 api를 활용하여 데이터를 가져오는 프로젝트를 하고 있는데

    이 경우에 계속 api를 호출하면 횟수가 금방 줄어들기때문에 이를

    redis를 활용하여 캐시 관리하여 횟수를 줄이고자 했다.

     

    upstash를 활용하여 redis를 사용하기로 했다.

    Upstash는 RedisKafka를 서버리스 방식으로 사용할 수 있는 서비스이다.

    https://upstash.com/

     

    Upstash: Serverless Data Platform

    Upstash is a serverless data platform providing low latency and high scalability for real-time applications. Optimize your data infrastructure with Upstash's managed services for Redis, Vector, QStash, and other key data technologies.

    upstash.com


    Installment

    upstash redis를 사용하기 위해 npm install을 해준다.

    npm install @upstash/redis

    Initialized

    upstash에서 새로운 데이터베이스를 만들면

    해당 url과 token값을 준다.

     

    그럼 이 값을 .env.local에 환경변수로 등록

     

    그럼이제 redis의 연결을 위해 redis.ts파일을 만들어 환경변수에 저장된 변수들을 가져와 redis연결을 시켜준다.

    import {Redis} from "@upstash/redis";
    
    export const redis = new Redis({
        url: process.env.UPSTASH_REDIS_REST_URL!,
        token: process.env.UPSTASH_REDIS_REST_TOKEN!,
    })

    Useage

    우선 KAKAO api 호출을 기준으로

     

    api를 호출하면 우선 어떠한 key값으로 캐시에 저장할지 key를 생성한다

    kakao 장소 api를 활용하기 때문에 검색한 키워드와 카테로리를 기준으로 캐시 키를 생성했다.

     

    이후 해당 캐시 키를 통해 현재 해당 캐시 키가 존재하는지 데이터를 가져오고

    데이터가 존재하면 캐시 데이터를 전달하고, 

    없다면 api를 호출한다.

     

    이때 캐시값은 json.parser되서 알아서 데이터를 가져오므로 그냥 캐시값을 return 시켜주면된다.

        const key = `kakao:${keyword}-${category}`
    
        const cached: string | null = await redis.get(key)
        if (cached != null) {
            return NextResponse.json({code: 200, data: cached, cached: true})
        }

     

    그럼 이제 api를 호출할때 캐시를 저장해야한다.

    캐시를 저장할때는 string값으로 저장해야하므로 json.stringify로 string으로 바꿔주고

    유지시간 ttl시간은 장소 검색이므로 하루동안 유지되도록 처리했다.

    어떠한 데이터냐에 따라서 ttl 시간을 잘 설정해야하는데 장소의 경우에는 항상 새로운 장소가 나오더라도 하루기준으로 나올거 같아서 하루로 설정했다.

            await redis.set(key,JSON.stringify(currentPlace),{ex: 86400})
    
            return NextResponse.json({code: 200, data: currentPlace})
    export async function GET(request: NextRequest) {
        const {searchParams} = new URL(request.url)
        const keyword = searchParams.get("keyword")
        const category = searchParams.get("category")
    
        if(!keyword) {
            return NextResponse.json({code: 400,msg: '검색어가 없습니다.'})
        }
    
        const key = `kakao:${keyword}-${category}`
    
        const cached: string | null = await redis.get(key)
        if (cached != null) {
            return NextResponse.json({code: 200, data: cached, cached: true})
        }
    
        try {
            const currentPlace= [];
    
            for (let page = 1; page <= 1; page++) {
                const response = await fetch(`https://dapi.kakao.com/v2/local/search/keyword.json?query=${encodeURIComponent(keyword)}&category_group_code=${category}&page=1&size=15`, {
                    headers: {
                        "Authorization": `KakaoAK ${process.env.KAKAO_REST_API_KEY}`
                    }
                })
    
                const data = await response.json();
                if(data.documents && data.documents.length > 0) {
                    currentPlace.push(...data.documents)
                } else {
                    break;
                }
            }
    
            await redis.set(key,JSON.stringify(currentPlace),{ex: 86400})
    
            return NextResponse.json({code: 200, data: currentPlace})
        } catch (e: any) {
            return NextResponse.json({code: 400,msg: e.message})
        }
    }

     

    그럼 api요청을 했을때 해당 요청 결과가 upstash data browser를 보면 잘 저장되어있는 것을 확인 할 수 있다.

    이러면 같은 장소가 검색된다면 자연스럽게 캐시에 저장된 값을 가져와서 api호출을 줄일 수 있다.

    728x90
    반응형