Act99 기술블로그

[Nextjs] 주식사이트 만들기-4 채팅 프론트엔드(Apollo client, graphQL, useQuery) 본문

개발팁저장소/nextjs

[Nextjs] 주식사이트 만들기-4 채팅 프론트엔드(Apollo client, graphQL, useQuery)

Act99 2021. 12. 13. 11:48

 

먼저, Graphql Query문을 만들어주었다. (localhost/xxxx/graphql 에서 쿼리상태 확인 가능)

 

const GET_CHAT = gql`
  query frontChatQuery {
    chats {
      createdAt
      updatedAt
      user
      text
    }
  }
`;

 

다음 query 변수의 타입들을 설정해주었다. (apollo codegen 사용하면 편리.)

export interface frontChatQuery_Chat {
  __typename: "Chat";
  createdAt: Date | undefined;
  updatedAt: Date | undefined;
  user: string;
  text: string;
}

export interface frontChatQuery {
  chat: frontChatQuery_Chat[];
}

 

다음은 채팅 메시지 구현이다. 처음에는 useEffect를 서버에서 데이터가 update 될 때 마다 리렌더 시켜주는 형태로 만드려고 했지만 apollo client 에서 제공하는 useQuery 에서는 자동으로 useEffect와 같은 효과를 만든다고 한다. (Stackoverflow에서 읽은 글이기 때문에 실제로 테스트를 해봐야겠다.)

 

- chat.tsx

 

const Messages: React.FC<Props> = ({ width, height }) => {
  const { data, loading } = useQuery<frontChatQuery>(GET_CHAT, {
    variables: {},
  });

  console.log(data);

  return <div></div>;
};

export default Chat;

 

 

결과

 

 

콘솔에 postgresql 에 저장되어있는 채팅 메시지가 잘 나오는 것을 확인할 수 있다.

 

** 지금 해볼 것은 스텍오버플로우에서 나온대로 데이터가 업데이트 될 때마다 리렌더링 되는지 확인하는 것이다.**

 

먼저 메시지 코드를 작성했다.

 

-chat.tsx

const Messages: React.FC<Props> = ({ width, height }) => {
  const { data, loading } = useQuery<frontChatQuery>(GET_CHAT, {
    variables: {},
  });
  // const chatData = data?.chat.map((item) => item);
  // const chatDummyArray: any[] | undefined = [];
  // chatData?.forEach((item) => chatDummyArray.push(item));

  console.log(data?.chats.map((item) => item.user));

  return (
    <ul>
      {data?.chats.map((item, index) => {
        return (
          <li key={index} className="flex flex-row">
            <h3 className=" mx-2 text-white">{item.user}: </h3>
            <h3 className=" text-white">{item.text}</h3>
          </li>
        );
      })}
      <li></li>
    </ul>
  );
};

 

그 결과

 

역시 f5(새로고침) 하지 않으면 리렌더링이 되지 않는다.

 

자 여기서 문제점은 새로고침을 하지 않으면 리렌더링이 되지 않는다는 것이며,

실시간으로 db 연동을 원한다면 subscription (구독) 기능을 이용해야 한다.

 

하지만 저번시간에 Websocket을 이용하려고 하던 중 많은 오류가 생겨 실시간 db 연동을 제외한 나머지 작업부터 먼저 하려했으며, 동시에 subscription 없이 실시간 db 연동이 가능할수도 있겠다고 생각이 들었었다.

 

그래서 db 길이를 state로 놓고 state 가 변할때마다 refresh를 시켜주도록 코드도 짜봤지만

console.log 에서 확인해보면 수많은 에러가 발생하며 (보통 undefined 문제가 많이 발생했다.) 깜빡거리는 현상이 나왔다.

 

따라서 다시 Websocket을 이용해서 작업할 예정이다.