[프로젝트] 네가 꾸민 케이크 회고

뚜니어리·2023년 7월 18일
0

Project

목록 보기
2/2
post-thumbnail

🎂 프로젝트 소개

크리스마스 시즌마다 유행하던 내 트리를 꾸며줘 를 모티브로 생일인 사람에게 케이크를 주면서 생일축하해주는 롤링페이퍼 서비스 입니다.

현재 서버 닫힘
리팩토링 중 (commit history, testcode 추가예정)

[배포 사이트]
https://www.naekkukae.store/
[프론트 깃허브 주소]
https://github.com/ssu-uky/cake-front.git
[백엔드 깃허브 주소]
https://github.com/ssu-uky/cake-server.git
[API 문서]
https://birthday-cake.gitbook.io/naekkukae/


🛠️ 개발 시작

기간 : 3주
프론트엔드 1명, 백엔드 1명으로 진행
대면으로 개발 진행

핵심 기능

  • Simple JWT 사용으로 로그인 보안 강화
  • 로그인 시 보안을 위해 토큰을 local Storage 와 Session Storage 에 따로 분리
  • 이메일 가입 시 이메일 인증 필수
  • 카카오톡 소셜로그인 구현
  • 가입 한 type 구별
  • 본인의 편지만 오픈 가능
  • 비밀번호 변경 및 분실 시 이메일로 받은 인증 링크에서만 변경 가능
    (카카오톡으로 가입했을 경우, 카카오톡에 연동되어있는 이메일로 인증 요청 이메일이 보내집니다.)
  • 피드백 요청 기능
  • 비속어 작성 차단 기능

서비스 과정

  1. 사용자는 로그인을 한 후에 본인의 테이블을 원하는 색으로 만듭니다.
  2. 테이블은 만든 사람에게는 고유의 주소가 주어집니다.
  3. 그 주소를 복사하여, 다른 사람들에게 주면 로그인을 하지 않은 사람들도 케이크를 고른 후, 편지를 쓸 수 있습니다.
  4. 편지를 쓰면, 받은 편지(케이크)의 갯수와 방문자가 고른 케이크가 사용자의 테이블에 올려집니다.
    4-1. 비속어가 들어 있을 경우, 편지는 post 되지 않습니다.
  5. 받은 편지는 사용자만 읽을 수 있습니다.
  • 추가적으로 넣고 싶은 기능
    - 사용자의 피드백 받기 (완료)
    - 사용자의 생일을 입력받고 생일 당일 에 편지를 읽을 수 있게 하기
    (이런 서비스는 한 순간에 반짝 서비스로 .. 사용자가 1년동안 기다리다가 서비스 자체를 까먹을 것 같아서 일단 보류함)
    - 본인의 테이블에 편지가 업데이트 되면 카톡으로 알림 or 이메일로 알림 기능 넣기

아키텍처(Architecture)


💥 ISSUE

  • 소셜로그인을 도입하는 와중에 카카오 로그인을 백엔드에서 구현했는데 이 부분에서 3일은 헤맨 것 같다..
class KakaoSignView(APIView):
    def get(self, request):
        client_id = KAKAO_REST_API_KEY
        redirect_uri = "https://manage.naekkukae.store/auth/kakao/callback"
        return redirect(
            f"https://kauth.kakao.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code"
        )


class KakaoCallbackView(APIView):
    def get(self, request):
        try:
            code = request.GET.get("code")
            client_id = KAKAO_REST_API_KEY
            redirect_uri = "https://manage.naekkukae.store/auth/kakao/callback"
            token_request = requests.post(
                "https://kauth.kakao.com/oauth/token",
                data={
                    "grant_type": "authorization_code",
                    "client_id": client_id,
                    "redirect_uri": redirect_uri,
                    "code": code,
                },
            )
            token_json = token_request.json()

            error = token_json.get("error", None)

            if error is not None:
                return Response({"message": "INVALD_CODE"}, status=HTTP_400_BAD_REQUEST)

            access_token = token_json.get("access_token")
            refresh_token = token_json.get("refresh_token")

            profile_request = requests.get(
                "https://kapi.kakao.com/v2/user/me",
                headers={"Authorization": f"Bearer {access_token}"},
            )

            profile_json = profile_request.json()
            kakao_account = profile_json.get("kakao_account")
            email = kakao_account.get("email", None)
            nickname = kakao_account.get("profile").get("nickname", None)

        except KeyError:
            return Response({"message": "INVALID_TOKEN"}, status=HTTP_400_BAD_REQUEST)

        if User.objects.filter(email=email).exists():
            kakao_user = User.objects.get(email=email)
            tokens = RefreshToken.for_user(kakao_user)
            response = HttpResponseRedirect(
                f"https://naekkukae.store/KakaoLogin?refresh={str(tokens)}&access={str(tokens.access_token)}&user_pk={kakao_user.pk}"
            )
            return response

        else:
            if email:
                user = User.objects.create(
                    email=email,
                    name=nickname,
                    social_type="kakao",
                    is_active=True,  # 카카오로 회원가입 한 유저는 이메일 인증 필요없음 (항상 is_active=True로 설정)
                )

                tokens = RefreshToken.for_user(user)
                response = HttpResponseRedirect(
                    f"https://naekkukae.store/KakaoLogin?refresh={str(refresh_token)}&access={str(tokens.access_token)}&user_pk={user.pk}"
                )
                # return Response(response, id, status=HTTP_200_OK)
                return response
            else:
                return Response(
                    {"message": "카카오 아이디 혹은 카카오 이메일이 없습니다."},
                    status=HTTP_400_BAD_REQUEST,
                )

느낀 점

이번 프로젝트로 넥스트를 처음으로 접해보았는데 넥스트 완전 사기캐인 것 같다..
그래도 프론트를 직접 개발해보니 서버와의 이해도가 훨씬 높아졌다.

개발하다가 시간이 부족하고 더 넣고 싶은 기능이 많아서 프로젝트가 끝난 후에도 혼자서 손을 봤지만, 하다보니 계속 추가하고 싶은 기능이 생기고 있다.

시간이 나면 추가하고 싶은 기능들을 정리하고, 추가해서 개발해보아야겠다.

profile
삽질과 저장소의 그 중간

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

글 잘 봤습니다, 감사합니다.

답글 달기