혼자 적어보는 노트

프로그래머스 데브코스 TIL - Day 74 본문

스터디

프로그래머스 데브코스 TIL - Day 74

jinist 2022. 7. 2. 21:26

 

✅ 오늘의 학습

📌 React 심화(6)

 

- Strapi + Apollo + GraphQL+ Next.js

 


 

이해가 잘 안되었던 부분이나 처음 알게된 부분 위주로 정리했다

 

 

1. Strapi Relation

 

 

 

유저는 여러개의 포스트를 가지기 때문에 일대 다의 관계를 가짐
post에서는 user를 가지고 user에서는 posts를 가진다.

지정한 field가 어떤 것인지 잘 확인해야 함.

 

 

2. Strapi User 데이터 연결

 

테스트를 통해 게시물을 등록해보면 relations에 user가 자동으로 연결되지 않는다.

해당 게시물의 주인을 구분할 수 없으니 create/update/delete를 모든 유저가 할 수 있게 된다.

 

-> 그래서 strapi 서버 파일에서 직접 설정해주어야 한다. (복잡주의)

 

REST API의 경우 각각의 api 폴더에 있는 각각의 controllers를 수정하면 되는데

GraphQL에서는 resolve를 수정하기 위해서는 index.js부분의 register를 수정해야 한다.

 

module.exports = {
  register({ strapi }) {
    const extensionService = strapi.plugin("graphql").service("extension"); 

    const extension = () => ({
      resolvers: {
        Mutation: {
          // ctx == context. request정보나 header 정보가 담겨있다. 토큰이 담기면 state에 유저 정보가 자동으로 담긴다.
          createPost: async (_, args, ctx) => {
            const { toEntityResponse } = strapi // response를 위한 함수를 받아오기
              .plugin("graphql")
              .service("format").returnTypes;

            console.log({ ...args.data, user: ctx.state.user.id }, "data");
            const post = await strapi.entityService.create("api::post.post", {
              data: { ...args.data, user: ctx.state.user.id }, // post create 시 user의 id를 함께 반환
            });

            return toEntityResponse(post);
          },
          // post update시 자기 게시물이 아닐 경우 에러 반환
          updatePost: async (_, args, ctx) => {
            const { toEntityResponse } = strapi
              .plugin("graphql")
              .service("format").returnTypes;
            const post = await strapi.entityService.findOne(
              // post객체를 가지고 오기
              "api::post.post",
              args.id,
              { populate: { user: true } }
            );

            if (post.user.id !== ctx.state.user.id) {
            // 유저가 다르면 에러 반환
              throw new Error("You are not authorized to update this post");
            }

            const updatePost = await strapi.entityService.update(
              "api::post.post",
              args.id,
              args
            );
            return toEntityResponse(updatePost);
          },
        },
      },
    });

    extensionService.use(extension);
  },

delete도 update와 비슷하게 처리해주면 되고 comment나 다른 정보들도 위처럼 처리를 해주면 된다.

Node.js기반이라 그런지 패턴이 뭔가 낯익은 느낌이 들었다.

 

 

Apollo HTTP 인증 헤더

 

공식문서: Authentication

 

HTTP 리퀘스트를 보낼 때 인증 헤더와 함께 보내야 하는 요청들이 있는데
Apollo Links를 사용하여 모든 HTTP요청에 인증 헤더를 추가할 수 있다.

 

공식문서 내용처럼 httpLink와 authLink를 추가해주면 된다.

 

 

NextJs Link passHref

Next에서 Link 사용 시 passHref를 사용하여 링크를 아래 a태그에 넘겨줄 수 있다.

<Link key={post.id} href="/post/[id]" as={`/posts/${post.id}`} passHref>
  <a>
    <h4>{post.attributes.title}</h4>
  </a>
</Link>

React Router의 Link로 감쌀경우 자동으로 a태그로 감싸지는데 next는 passHref로

자식인 a태그에 따로 지정해줄 수 있었다,

 

 

Nookies 라이브러리

 

npm: nookies

 

Next.js용 쿠키 라이브러리.

쿠키의 설정 및 client는 물론 서버측에서도 작동한다.

const { token } = nookies.get();

간단 그 자체!

 

Nokies를 사용하여 토큰 내려주기

MyApp.getInitialProps = async (appCtx: AppContext) => {
  const { token } = nookies.get(appCtx.ctx);
  return { pageProps: { token } };
};

getInitialProps을 통해 쿠키에 담긴 토큰을 _app에 내려줄 수 있다.

 

✍ 느낀 점

 

어제까지만 해도 strapi 좋다~ 했는데 데이터를 받아와서 relation으로 user 데이터를 사용하는 과정에서

data와 attributes 때문에 한없이 깊어지는 데이터의 뎁스 형태를 보고나니 마음이 불편했다....

강의에서도 말하기를 어쩔수 없다고 했지만 어떻게 줄일 수 있는 방법이 없을까 검색을 했는데

공식적인 방법은 없는 듯 했다..😢 이 부분이 매우 아쉬웠지만 감안하고 진행해야겠다.

Comments