Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 로그인 페이지 구현 #286

Merged
merged 9 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class AuthController {
this.cookieInsertJWT(response, userId);
}

@Post('guest/login')
@Get('guest/login')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q:
cors 에러가 발생한다면 main.ts에서 cors 설정을 진행해주면 되는 것 아닌가요? 메서드를 변경한 이유가 있을까요?

Copy link
Collaborator Author

@simeunseo simeunseo Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cors 설정을 해도 해결되지 않는 문제였습니다. 잠깐 알아보니 상당히 복잡하더라구요... 일단 로그인이 지금 저희가 집중해야할 중요한 부분은 아니라고 생각해서 빠른 조치를 취하게 되었습니다. 현재 로그인 방식이 GET에 어울리기도 하구요..!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://www.milk717.com/gomterview-2

우연히 발견한게 또 곰터뷰 개발자분의 아티클인데 ㅋㅋㅋ 상당한 트러블 슈팅이 있었던것으로 보입니다 흠 이 부분을 집중해서 해결해봐야할지 고민이 됩니다...

@ApiOperation({ summary: '게스트 로그인' })
@ApiResponse({ status: 302, description: '홈으로 리다이렉션' })
@UseGuards(ThrottlerGuard)
Expand Down
5 changes: 4 additions & 1 deletion apps/api/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ export class AuthService {

async createGuestUser() {
const randomNum = Math.floor(Math.random() * 10000);
const response = await fetch('https://api.thecatapi.com/v1/images/search');
const catImageUrl = (await response.json())[0].url;

const guestUser = {
username: `guest_${randomNum}`,
password: `guest_password_${randomNum}`,
email: `[email protected]`,
nickname: `guest_${randomNum}`,
introduce: `게스트 사용자입니다. `,
profileImageUrl: `https://cataas.com/cat?${Date.now()}`,
profileImageUrl: catImageUrl,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p2:
기본 프로필 이미지에 경우 nullable하게 변경하거나 /으로 접근시 web/public의 정적 파일에 접근할 수 있는 것을 이용하는 것은 어떨까요? (ex: /cat-image.png, vite에 경우 /로 바로 public 폴더에 접근 가능합니다)

이미지를 가져오기 위해 fetch 요청을 할 이유가 없다고 생각합니다

Copy link
Collaborator Author

@simeunseo simeunseo Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 이건 여러 게스트 유저를 만들어서 더미를 쌓아놓을 때 기본 이미지보다는 랜덤한 고양이 이미지 들어오는게 단순히 귀엽고 보기 좋을거같아서 넣기는 했습니다 😅 혹시 우려되는 문제가 있을까요? 🥲

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http 요청으로 인해 성능상 좋지 않을 것으로 생성되지만... 고양이 귀엽죠... 우선 두고 테스트 진행하며 문제 발생시 변경해도 좋을 것 같습니다!!! 고양이 지켜!!

};
const user = await this.userService.findUserByUsername(guestUser.username);
if (!user) {
Expand Down
11 changes: 8 additions & 3 deletions apps/web/src/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axiosInstance from '@/api/axios';
import { ENV } from '@/constants/env';

type SignUpDto = {
username: string;
Expand All @@ -23,8 +24,12 @@ const signOut = async () => {
await axiosInstance.post('/auth/logout');
};

const oauthLogin = async (provider: 'google' | 'github') => {
await axiosInstance.get(`/auth/${provider}/login`);
const guestLogin = () => {
window.location.href = `${ENV.API_URL}/auth/guest/login`;
};

export { logIn, signUp, oauthLogin, signOut };
const oauthLogin = (provider: 'google' | 'github') => {
window.location.href = `${ENV.API_URL}/auth/${provider}/login`;
};
Comment on lines -26 to +33
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p1:
axios를 통해 요청을 진행하지 않는건가요? location을 직접 변경하는 이유가 무엇인가요?

Copy link
Collaborator Author

@simeunseo simeunseo Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로그인 버튼을 눌렀을 때 해당 주소에서 GET을 해야하기 때문에 axios GET 요청이 아닌 링크 이동으로 구현하게 되었습니다!


export { logIn, signUp, oauthLogin, guestLogin, signOut };
4 changes: 2 additions & 2 deletions apps/web/src/assets/icons/chevron-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions apps/web/src/assets/icons/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions apps/web/src/assets/icons/google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion apps/web/src/assets/ticle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions apps/web/src/components/auth/GuestLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { guestLogin } from '@/api/auth';
import ChevronRight from '@/assets/icons/chevron-right.svg?react';

function GuestLogin() {
const handleGuestLogin = () => {
guestLogin();
};

return (
<span
className="mt-3 flex items-center gap-1.5 text-title2 text-main"
onClick={handleGuestLogin}
>
게스트 로그인
<ChevronRight className="w-2 fill-black" />
</span>
);
}

export default GuestLogin;
43 changes: 43 additions & 0 deletions apps/web/src/components/auth/OAuthLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { cva } from 'class-variance-authority';

import { oauthLogin } from '@/api/auth';
import GithubIc from '@/assets/icons/github.svg?react';
import GoogleIc from '@/assets/icons/google.svg?react';

const oauthButton = cva('flex w-96 justify-center gap-3 rounded-lg py-4 shadow-normal', {
variants: {
type: {
github: 'bg-black text-white',
google: 'border border-main bg-white text-alt',
},
},
defaultVariants: {
type: 'github',
},
});

const OAUTH_LABEL = {
github: 'Github',
google: 'Google',
} as const;

type OAuthType = keyof typeof OAUTH_LABEL;

interface OAuthLoginProps {
type: OAuthType;
}

function OAuthLogin({ type }: OAuthLoginProps) {
const onLoginBtnClick = (type: OAuthType) => {
oauthLogin(type);
};

return (
<button type="button" className={oauthButton({ type })} onClick={() => onLoginBtnClick(type)}>
{type === 'github' ? <GithubIc /> : <GoogleIc />}
<span className="text-head3">{OAUTH_LABEL[type]} 계정으로 로그인</span>
</button>
);
}

export default OAuthLogin;
24 changes: 24 additions & 0 deletions apps/web/src/components/auth/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import TicleCharacterBadge from '@/assets/images/ticle-character-badge.png';
import TicleLogo from '@/assets/ticle.svg?react';

import GuestLogin from './GuestLogin';
import OAuthLogin from './OAuthLogin';

function Auth() {
return (
<div className="flex h-dvh w-full flex-col items-center justify-center gap-16">
<div className="flex flex-col items-center gap-6">
<img src={TicleCharacterBadge} alt="티클 캐릭터" width={150} height={150} />
<TicleLogo className="fill-primary" width={190} />
<span className="text-head3 text-alt">작은 지식이 모여 큰 성장이 되는 곳</span>
</div>
<main className="flex flex-col items-center gap-4">
<OAuthLogin type="github" />
<OAuthLogin type="google" />
<GuestLogin />
</main>
</div>
);
}

export default Auth;
7 changes: 6 additions & 1 deletion apps/web/src/components/common/Dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ReactNode } from '@tanstack/react-router';
import { cva } from 'class-variance-authority';
import { AnimatePresence, motion } from 'framer-motion';
import { useRef } from 'react';
import { MouseEvent, useRef } from 'react';

import CloseIc from '@/assets/icons/close.svg?react';
import useOutsideClick from '@/hooks/useOutsideClick';
Expand All @@ -25,6 +25,10 @@ function DialogRoot({ isOpen, onClose, children, className }: DialogRootProps) {

if (!isOpen) return null;

const handleInnerClick = (e: MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};

return (
<Portal portalId="dialog">
<AnimatePresence>
Expand All @@ -41,6 +45,7 @@ function DialogRoot({ isOpen, onClose, children, className }: DialogRootProps) {
className={cn('relative w-80 rounded-lg bg-white px-6 py-7 shadow-normal', className)}
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
onClick={handleInnerClick}
>
{children}
</motion.div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ticle/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function TicleList() {
<div className="flex h-80 w-full items-center justify-center">
<Loading color="primary" />
</div>
) : data?.pages.length === 0 ? (
) : data?.pages[0].ticles.length === 0 ? (
<Empty />
) : (
data?.pages.map((page) => (
Expand Down
8 changes: 1 addition & 7 deletions apps/web/src/hooks/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';

import { logIn, signUp, oauthLogin, signOut } from '@/api/auth';
import { logIn, signUp, signOut } from '@/api/auth';

export const useLogIn = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -35,9 +35,3 @@ export const useSignOut = () => {
},
});
};

export const useOauthLogin = () => {
return useMutation({
mutationFn: (provider: 'google' | 'github') => oauthLogin(provider),
});
};
13 changes: 4 additions & 9 deletions apps/web/src/routes/auth/oauth.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import { createFileRoute, Link } from '@tanstack/react-router';
import { createFileRoute } from '@tanstack/react-router';

import Auth from '@/components/auth';

export const Route = createFileRoute('/auth/oauth')({
component: RouteComponent,
});

function RouteComponent() {
return (
<div className="flex">
OAuth 로그인
<Link to="/auth/login" className="border border-main p-5">
로컬 로그인
</Link>
</div>
);
return <Auth />;
}
Loading