[23.12.13] TIL

yy·2023년 12월 13일

개발일지

목록 보기
59/122

또 다시 찾아온 페이지네이션. 커서 기반으로 한다고 했지만 사실 해보니까 where문으로 충분한거 아닌가라는 생각이 들었다.

router.get("/posts", async (req, res, next) => {
  try {
    const { page, lastSeenPage, categoryName, districtName } =
      req.query;

    const findCategory = await prisma.categories.findFirst({
      where: { categoryName },
    });

    const findDistrict = await prisma.districts.findFirst({
      where: { districtName },
    });

    const parsedPage = +page || 24;// 조회할 게시글 수

    let posts;
    if (!lastSeenPage) {
      posts = await prisma.posts.findMany({
        select: {
          User: {
            select: {
              nickname: true,
              imgUrl: true,
            },
          },
          Location: {
            select: {
              storeName: true,
              address: true,
              starAvg: true,
            },
          },
          postId: true,
          imgUrl: true,
          content: true,
          likeCount: true,
          commentCount: true,
          createdAt: true,
        },
        orderBy: { postId: "desc" },
        take: parsedPage,
        where: {
          ...(findCategory?.categoryId && {
            CategoryId: findCategory.categoryId,
          }),
          ...(findDistrict?.districtId && {
            Location: { DistrictId: findDistrict.districtId },
          }),
          updatedAt: {
            lt: new Date(), // 조회 당시 시간으로 또다른 사용자가 작성한 글 보지 않도록 하기.
          },
        },
      });
    } else {
      posts = await prisma.posts.findMany({
        select: {
          User: {
            select: {
              nickname: true,
              imgUrl: true,
            },
          },
          Location: {
            select: {
              storeName: true,
              address: true,
              starAvg: true,
            },
          },
          postId: true,
          imgUrl: true,
          content: true,
          likeCount: true,
          commentCount: true,
          createdAt: true,
        },
        orderBy: { postId: "desc" },
        take: parsedPage,
        where: {
          ...(findCategory?.categoryId && {
            CategoryId: findCategory.categoryId,
          }),
          ...(findDistrict?.districtId && {
            Location: { DistrictId: findDistrict.districtId },
          }),
          updatedAt: {
            lt: new Date(),
          },
          postId: {
            lt: +lastSeenPage
          }
        },
      });
    }

    if (!posts) {
      return res.status(400).json({ message: "존재하지 않는 게시글입니다." });
    }

    // 이미지 배열로 반환하는 로직
    const imgUrlsArray = posts.map((post) => post.imgUrl.split(","));
    const paramsArray = imgUrlsArray.map((urls) =>
      urls.map((url) => ({
        Bucket: bucketName,
        Key: url,
      })),
    );

    const signedUrlsArray = await Promise.all(
      paramsArray.map(async (params) => {
        const commands = params.map((param) => new GetObjectCommand(param));
        const urls = await Promise.all(
          commands.map((command) => getSignedUrl(s3, command)),
        );
        return urls;
      }),
    );

    for (let i = 0; i < posts.length; i++) {
      posts[i].imgUrl = signedUrlsArray[i];
    }

    return res.status(200).json({ posts });
  } catch (error) {
    console.error(error);
    res.status(400).json({ error: "서버가 닫혔습니다." });
  }
});

페이지네이션에 레디스를 적용시키려고 했다. EC2에 레디스를 깔아서 연결을 하려했으나 실패했다.
대체 무엇이 문제인고...
그러다가 ioredis의 존재를 알게되었고,,, 정말 간단하게 연결을 했다.

우선 app.js에 입력해서 실험을 해봤다.
dotenv를 통해 .env 파일에 redis host, redis port, redis password를 넣어준다.

//app.js
import Redis from "ioredis";

dotenv.config();

// ioredis 클라이언트 생성
const redisClient = new Redis({
  host: process.env.REDIS_HOST, // Redis 서버 호스트
  port: process.env.REDIS_PORT,         // Redis 포트 번호
  password: process.env.REDIS_PASSWORD,         // Redis 포트 번호
});

await redisClient.set('name', 'test');
//router.js
import Redis from "ioredis";

//app.js에 redisClient가 있어서 redisClient를 지워도 되는줄 알았는데 아니었디;
const redisClient = new Redis({
  host: process.env.REDIS_HOST, // Redis 서버 호스트
  port: process.env.REDIS_PORT,         // Redis 포트 번호
  password: process.env.REDIS_PASSWORD,         // Redis 포트 번호
}); 

await redisClient.set('post', JSON.stringify({ key: 'value' }));

그러고 app.js를 실행하고 ec2서버에 있는 redis를 확인해보니 데이터가 들어간걸 확인할 수 있었다.
ioredis를 쓰니 이렇게 쉽다니..!

참고
https://www.npmjs.com/package/ioredis
https://velog.io/@jjmoon4682/%EC%BA%90%EC%8B%B1-feat.-Redis

profile
시간이 걸릴 뿐 내가 못할 건 없다.

0개의 댓글