OAuth 프로필 생성 관련 질문입니다.
안녕하세요 강의 정말 잘 듣고있습니다.
현재 강의를 무한 중첩 댓글 구현하기까지 수강했습니다!
테스트를 위해 여러가지 사항들을 직접 체크하고있는데 Github로 로그인한 사용자의 정보들(avatar_url, name)들은 기본적으로 사용하지 않고 랜덤한 닉네임과 기본 아바타 이미지가 나오는게 정상 동작일까요?
제가 이해한 흐름은 다음과 같습니다.
1. Github(OAuth) 로그인
2. Supabase Authentication > Users에 사용자 생성 (profile 테이블에는 아직 생성 되지 않음)
3. SessionProvider에서 useProfileData 호출
export default function SessionProvider({ children }: { children: ReactNode }) {
const session = useSession();
const setSession = useSetSession();
const isSessionLoaded = useIsSessionLoaded();
const { data: profile, isLoading: isProfileLoading } = useProfileData(
session?.user.id,
);
useEffect(() => {
supabase.auth.onAuthStateChange((event, session) => {
setSession(session);
});
}, []);
if (!isSessionLoaded) return <GlobalLoader />;
if (isProfileLoading) return <GlobalLoader />;
return children;
}4. fetchProfile(userId) 실행
export async function fetchProfile(userId: string) {
const { data, error } = await supabase
.from("profile")
.select("*")
.eq("id", userId)
.single();
if (error) throw error;
return data;
}Supabase Table Editor > profile 에는 아무런 결과가 저장되어 있지 않기 때문에
PostgrestError: PGRST116 에러 발생
useProfileData catch 블록 실행 → createProfile 호출
랜덤한 닉네임 + avatar_url이 기본으로 저장
만약 제가 이해한 흐름이 맞다면 어떤 방법을 써야할까요?
제일 먼저 드는 생각은 createProfile에 session을 매개변수로 받아서 session.user.user_metadata.full_name과 avatar_url을 insert에 넣는걸 생각했습니다.
createProfile
export async function createProfile(userId: string, session?: Session) {
const { data, error } = await supabase
.from("profile")
.insert({
id: userId,
// ↓ 여기 수정 했어용
nickname: session?.user.user_metadata?.full_name || getRandomNickname(),
avatar_url: session?.user.user_metadata?.avatar_url || null,
})
.select()
.single();
if (error) throw error;
return data;
}
use-profile-data.ts
export function useProfileData(userId?: string) {
const session = useSession();
const isMine = userId === session?.user.id;
return useQuery({
queryKey: QUERY_KEYS.profile.byId(userId!),
queryFn: async () => {
try {
const profile = await fetchProfile(userId!);
return profile;
} catch (error) {
if (isMine && (error as PostgrestError).code === "PGRST116") {
return await createProfile(userId!, session!); // 여기 session 추가 했어용
}
throw error;
}
},
enabled: !!userId,
});
}
이렇게 코드를 수정하고 profile table을 삭제한 후 다시 Github로 로그인 하면 사용자의 프로필 이미지와 이름이 받아와졌습니다.
더 효율적이거나 더 좋은 방법이 있을까요? 혹은 제가 잘못 알고 있는게 있을까요?
답변 2
0
안녕하세요 jjk5050123님 이정환입니다.
우선 GitHub의 정보를 이용하지 않고 서비스 자체의 랜덤한 닉네임을 사용하는것은 본 서비스의 의도된 동작입니다. 무조건 연동 로그인 된 서비스의 계정 정보를 불러와 채워넣을 필요는 없습니다 😀
이 과정에서 만약 GitHub의 정보를 이용해 기본 정보를 채워넣도록 수정하고 싶으시다면 올려주신 코드대로 기능을 수정해 이용하시면 됩니다.
0
안녕하세요, 인프런 AI 인턴입니다. jjk5050123님.
Supabase와 OAuth를 활용한 프로필 생성 과정에서의 흐름과 구현에 대한 질문을 주셨네요. 설명한 흐름은 전반적으로 올바르게 이해하고 계신 것 같습니다. Github와 같은 OAuth 서비스를 통해 로그인한 사용자의 데이터를 Supabase로 가져올 때 부딪히는 문제와 작업 흐름을 설명할 수 있습니다. 핵심 사항을 요약하고 몇 가지 추가적인 정보를 제공하겠습니다.
현재 구현 방식
OAuth 로그인: 사용자 인증이 이루어지고, 이러한 정보는 Supabase Authentication에 저장됨.
사용자 정보 로딩:
SessionProvider가useProfileData를 호출해 사용자 정보를 프로필 테이블에서 조회합니다.프로필 생성 로직:
fetchProfile함수는 프로필 테이블을 조회하고, 해당 프로필 정보가 없을 경우 에러를 발생시킵니다. 에러가 발생하면createProfile함수를 통해 사용자 프로필을 생성합니다.프로필 데이터 삽입:
createProfile함수가 호출되면서 Github에서 제공하는 데이터(full_name과avatar_url)을 통해 프로필이 생성됩니다.
개선 및 검토 사항
초기 프로필 데이터 활용:
- 종종 OAuth 제공자가 제공하는 메타데이터(예:
full_name,avatar_url) 정보를 초기 프로필 생성 시 활용하는 것이 일반적입니다. 이미 구현하신 방법대로createProfile함수에서 이를 호출하여 처리하면 무난할 것입니다.
- 종종 OAuth 제공자가 제공하는 메타데이터(예:
에러 핸들링 및 로깅:
- 사용자의 프로필을 만들기 전에
PostgrestError를 포함하여 오류 상황을 잘 핸들링하며 로그를 남기는 것도 좋은 방식입니다. 이렇게 하면 문제 발생 시 추적이 용이합니다.
- 사용자의 프로필을 만들기 전에
성능 최적화:
- 프로필을 미리 판단하여 로딩 시점을 최적화하거나, 언제 프로필을 생성할 지에 대한 로직을 재검토할 수 있습니다. 사용자가 앱에 처음 접근할 때 미리 생성해두어 많은 HTTP 요청을 줄일 수도 있습니다.
- 프로필을 미리 판단하여 로딩 시점을 최적화하거나, 언제 프로필을 생성할 지에 대한 로직을 재검토할 수 있습니다. 사용자가 앱에 처음 접근할 때 미리 생성해두어 많은 HTTP 요청을 줄일 수도 있습니다.
보안 고려사항:
- 프로필 생성 시 사용하기 전, 외부에서 온 데이터를 검증하고 유효성을 검사하는 것도 중요합니다. 이는 데이터 무결성과 보안을 보장하는 데 필수적입니다.
- 프로필 생성 시 사용하기 전, 외부에서 온 데이터를 검증하고 유효성을 검사하는 것도 중요합니다. 이는 데이터 무결성과 보안을 보장하는 데 필수적입니다.
다른 개선 방안:
- 초기 로그인 시점에 한 번 Create API를 호출하여, 유효한 프로필이 생성되지 않도록 하는 것도 방법입니다.
- 초기 로그인 시점에 한 번 Create API를 호출하여, 유효한 프로필이 생성되지 않도록 하는 것도 방법입니다.
다른 유사한 질문과 해결 방법은 아래 링크에서 확인해 볼 수 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
회원가입 구현 (구현 후 최종 화면 출력 X)
0
40
2
(6.11) 회원가입시 프로필 정보 자동 생성하기 Q. 호출 순서 문의
0
36
1
명시적 타입 선언(콜론 타입 선언)과 as 타입 단언 차이
0
37
2
useMutation 적용 후 새로운 글 등록시 content가 안보여요
0
48
2
6.8 zustand 세션 질문입니다.
0
92
2
next.js 강의에서도 리액트 라이브러리들을 다뤄주시나요?
0
79
2
shadcn에서 radix ui와 base ui 차이는 뭔가요?
1
319
2
updateTodo 함수 생성시 화살표 함수 사용 안하는 이유
0
75
2
4.11 바로 투두 삭제가 안됨 질문
0
85
3
매개변수 updatedTodo 관련 질문
0
66
3
인증 정보가 만료되었을 때 라우트 가드 처리가 궁금합니다!
0
78
2
supabase를 사용하지 않을 경우 세션 데이터의 변경을 감지하고 스토어에 보관하는 방법이 궁금합니다!
0
69
2
4.6 id를 string으로 변경시 오류
0
64
2
리액트 타입스크립트 관련 질문있습니다.
0
62
1
소셜 로그인 구현하기 관련하여 질문이 있습니다!
0
98
2
ui 파일 질문드립니다.
0
76
1
tanstack query devtools에서 질문있습니다!
0
66
2
댓글 삭제 시 isPending 질문
0
64
2
두번째 예외상황에 대해 질문있습니다!
0
65
1
리액트 쿼리 질문입니다
1
72
2
개발자도구에서 components 가 안보입니다.
0
94
3
state 관리에 대한 정리
0
79
3
[(2.4) Shadcn/ui를 소개합니다] 강의 Shadcn 세팅 관련 질문 있습니다.
0
176
3
like 테이블에서 왜 create_at이 필요한지 궁금합니다.
0
78
1





