ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [toy blog service] Next.js의 API와 json
    Web Dev/5. Projects 2021. 4. 19. 22:06
    728x90

    Next.js에서는 API 관련 기능을 제공한다. 

     

    여기를 보면 이런식으로 구성을 해서 /api/* 로 매핑이 된다. 얘들은 서버사이드에서만 번들링이 된다. 

     

    나는 여기서 공부를 위해서 여러 endpoint를 만들어봤는데, 아래는 /api/[username]/index 를 처리하는 파일은 아래와 같이 작성했다. 

    // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
    import type { NextApiRequest, NextApiResponse } from "next";
    import { selectData, insertData } from "../../../../utils/common";
    
    // http://localhost:3000/api/articles/hayoung
    // let r1 = await fetch("http://localhost:3000/api/articles/hayoung", { method: 'POST', body: JSON.stringify({ title: "title!!!", contents: "teststststs", viewCount: 1 }) })
    export default async (req: NextApiRequest, res: NextApiResponse) => {
      const username = req.query.username;
      if (req.method === "GET") {
        // get every article by this user
        const selectResult = await selectData("articles", {
          author: username as string,
        });
        res.status(200).json({ message: selectResult });
        return;
      }
    
      if (req.method === "POST") {
        // create a new article by this use
        // const reqData = JSON.parse(req.body);
        const reqData = JSON.parse(req.body);
        const createdData = await insertData("articles", {
          ...reqData,
          viewCount: "1",
          author: username,
        });
    
        if (createdData.length > 0) {
          res.setPreviewData(createdData[0], { maxAge: 10 });
          res.status(200).json({ message: createdData[0] });
        } else {
          res.status(200).json({ message: "something went wrong" });
        }
        return;
      }
    
      res.status(500).json({
        message:
          "Sorry, articles/username/articleId api only accepts GET or POST method",
      });
    };
    

     

    get, post 관련 처리를 위와 같이 쉽게 할 수 있다. 

     

     

     

    Json 관련 처리

    DB까지 달고 하다보면 공부범위가 너무 광범위 해지는 것같아 간단하게 fs 모듈로 json 데이터를 읽고 쓰는 방식으로 db를 흉내 내보았다. 

    const selectData = async (
      keyName: string,
      filterKey?: filterKeyForUsers | filterKeyForArticles
    ) => {
      const db = await openJsonFile();
    
      if (keyName === "intro") {
        return db[keyName];
      }
    
      if (keyName === "users") {
        if (!filterKey) {
          return db[keyName];
        }
    
        if (!instanceOfFilterDataForArticles(filterKey)) {
          const result = [];
          db[keyName].forEach((row: UserType) => {
            if (row.userId === filterKey.userId) {
              result.push(row);
            }
          });
    
          return result;
        }
      }
    
      if (keyName === "articles") {
        if (!filterKey) {
          let result = [];
          for (const [author, articles] of Object.entries(db[keyName])) {
            if (instanceOfArticleList(articles)) {
              result = [...result, ...articles];
            }
          }
          return result;
        }
    
        if (
          instanceOfFilterDataForArticles(filterKey) &&
          db[keyName][filterKey.author] &&
          !filterKey.articleId
        ) {
          const result = [];
    
          db[keyName][filterKey.author].forEach((row: ArticleType) => {
            result.push(row);
          });
          return result;
        }
    
        if (
          instanceOfFilterDataForArticles(filterKey) &&
          db[keyName][filterKey.author] &&
          filterKey.articleId
        ) {
          const result = [];
          db[keyName][filterKey.author].forEach((row: ArticleType) => {
            if (row.articleId === filterKey.articleId) {
              result.push(row);
            }
          });
          return result;
        }
      }
    
      return [];
    };
    
    const insertData = async (keyName: string, data: UserType | ArticleType) => {
      const db = await openJsonFile();
      if (keyName === "users" && !instanceOfArticle(data)) {
        db[keyName].push(data);
        await writeJsonFile(db);
        return [data];
      }
    
      if (keyName === "articles" && instanceOfArticle(data)) {
        if (!db[keyName][data.author]) {
          db[keyName][data.author] = [];
        }
        // calc ArticleID
        let articleId =
          db[keyName][data.author].length === 0
            ? 1
            : +db[keyName][data.author][db[keyName][data.author].length - 1]
                .articleId + 1;
        data.articleId = "" + articleId;
    
        if (!db[keyName][data.author]) {
          db[keyName][data.author] = [];
        }
    
        db[keyName][data.author].push(data);
        await writeJsonFile(db);
        return [data];
      }
    
      return [];
    };
    
    const updateArticle = async (
      username: string,
      articleId: string,
      data: { title: string; contents: string }
    ) => {
      const db = await openJsonFile();
      const result = [];
      try {
        db["articles"][username].forEach((row: ArticleType, index: number) => {
          if (row.articleId === articleId) {
            db["articles"][username][index]["title"] = data.title;
            db["articles"][username][index]["contents"] = data.contents;
            result.push(db["articles"][username][index]);
          }
        });
        await writeJsonFile(db);
        return result;
      } catch (err) {
        console.log(err);
        return [];
      }
    };
    

     

    내가 실제로 작성했던 코드는 위와 같다. 

     

    아래는 JSON데이터이다. 

    이를 보면 각 api에서 원래 db처리를 하는 곳에 insertData와 같은 json 처리 함수를 사용했다.

     

     

    후기

    json으로 직접 구현하면서 using type predicates 같은 개념도 다루고, JavaScript 자체를 좀 빡세게 본것 같다. API 기능자체는 엄청 편리하게 제공해서 필요한 경우에 요긴하게 사용할 것 같다. 

    댓글

Designed by Tistory.