초대 링크 만들기 (1)

halang·2022년 9월 19일
2

모도코 MODOCO

목록 보기
3/12
post-thumbnail

개요

구현한 것 gif
이전 포스팅에서 AWS lambda와 api gateway를 이용해 rest api를 만들었습니다. 이번에는 해당 api를 바탕으로 초대 링크 생성 및 해당 링크를 입력하였을 때 리다이렉션 되도록 설정해보겠습니다.

구현

Invite.tsx

Invite.tsx 컴포넌트 화면

초대하기 버튼 눌렀을 때 Invite.tsx 컴포넌트 화면

포스팅에서 설명하는 코드 이외에는 삭제하였습니다.

import axios from 'axios';
import { useState } from 'react';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import toast from 'react-hot-toast';
import styled from 'styled-components';
import { API } from '../config';

export default function Invite() {
  const [isInvited, setIsInvited] = useState(false);
  const [inviteCode, setInviteCode] = useState('');

  const onClickInviteButton = () => {
    const roomId = '123';
    axios.get((API.INVITE as string) + roomId).then((res) => {
      setIsInvited(true);
      setInviteCode(`${process.env.REACT_APP_LAMBDA_INVITE}/${res.data}`);
    });
  };

  return (
	    ...
        {!isInvited ? (
          <Button type="button" onClick={onClickInviteButton}>
            초대하기
          </Button>
        ) : (
          <>
            ...
            <CopyToClipboard
              text={inviteCode}
              onCopy={() => toast.success(`복사되었습니다. ${inviteCode}`)}
            >
              <Button>복사</Button>
            </CopyToClipboard>
            ...
          </>
        )}
  );
}

const Button = styled.button`
  color: white;
  font-size: 2rem;
  cursor: pointer;
  padding: 1rem;
  border-radius: 1.4rem;
  &:hover {
    color: #ffe2e2;
  }
`;

초대하기 버튼을 누르면 클릭 이벤트로 onClickInviteButton 함수가 실행됩니다. roomId는 임시로 123으로 지정하였고 axios를 이용해 get 요청을 하였습니다. 해당 링크로 요청을 보내면 api gateway를 통해 lambda 함수가 실행됩니다. 그러면 roomId에 대해 암호화를 한 후 response로 보내주게 됩니다. 해당 로직은 뒤에서 다시 설명드리겠습니다. 이후 setInviteCode로 초대링크를 설정해줍니다.

클립보드는 react-copy-to-clipboard 라이브러리를 이용하였습니다. onCopy, 즉 복사 버튼을 눌러 inviteCode가 복사 되었을 때 toast 알람이 나옵니다.

lambda

roomId에 대한 정보를 암호화 하여 보여주기 위해 crypto 라이브러리를 이용하였습니다. lambda에서 외부 라이브러리를 사용하기 위해 layer 설정을 추가로 해주었습니다.

우선 빈 폴더에 아래와 같이 crypto 라이브러리를 설치해줍니다.

npm install crypto-js

그리고 폴더에 있는 node_modules 파일을 nodejs라는 빈 폴더에 붙여넣어 줍니다.
nodejs 빈 폴더에 node_modules 폴더 붙여넣기

이를 zip 으로 압축하여 다음과 같이 업로드 하여 생성해주었습니다.
계층 생성

cipher.js

const crypto = require('crypto');
	...

const encoding = (text) => {
        const cipher = crypto.createCipher('aes-256-cbc', KEY);
        let encode = cipher.update(text, 'utf8', 'base64');
        encode += cipher.final('base64');
        return encode;
    }
    
const decoding = (text) => {
    const decipher = crypto.createDecipher('aes-256-cbc', KEY);
    let decode = decipher.update(text, 'base64', 'utf8');
    decode += decipher.final('utf8');
    return decode;
}

module.exports = {encoding, decoding}

crypto 라이브러리를 이용해 encoding, decoding 해주는 함수를 작성하였습니다.

index.js

	...
    
exports.handler = async (event, context) => { 
    let encodedRoomId;
    let roomToRedirect;
    const headers = {
        "Content-Type": "application/json" 
    };
    const payload = {
        headers,
    };

    try {
        switch (event.routeKey) {
            case "초대하기 버튼 눌렀을 때":
                encodedRoomId = encoding(event.pathParameters.roomId);
                encodedRoomId = encodeURIComponent(encodedRoomId);
                payload.statusCode = 200;
                payload.body = JSON.stringify(encodedRoomId);
                break;
            case "사용자가 url을 입력했을 때":
                const decodedRoom = decodeURIComponent(event.pathParameters.code);
                roomToRedirect = decoding(decodedRoom);
                payload.statusCode = 302;
                payload.headers = { Location: `${FE_URL}/${INVITION_ROUTE}/${roomToRedirect}` };
                break;
            ...
        }
    } catch (err) {
        payload.statusCode = 400;
        payload.body = JSON.stringify(err.message);
    } 
    return payload;
};

초대하기 버튼을 누르면 roomId를 만들어둔 endcoding 함수를 이용해 암호화 해줍니다. 이렇게 암호화한 roomIdencodeURIComponent를 이용해 ?,=,/,&,: 와 같은 문자를 다른 문자로 인코딩해줍니다.

사용자가 url을 입력했을 때는 decodeURIComponentdecoding 함수를 순차적으로 하여 원래 roomId로 디코딩해줍니다. 또한 statusCode를 302로 하여 Location으로 리다이렉션 해줍니다.

마무리

이렇게하여 초대링크를 생성하고 해당 링크로 참여할 수 있게 되었습니다👏 다음에는 실제 프로젝트에 적용하여 인증된 사용자인지 확인하기 등 세부 기능을 추가해보겠습니다.

0개의 댓글