인프런 커뮤니티 질문&답변
OAuth 프로필 생성 관련 질문입니다.
작성
·
25
0
안녕하세요 강의 정말 잘 듣고있습니다.
현재 강의를 무한 중첩 댓글 구현하기까지 수강했습니다!
테스트를 위해 여러가지 사항들을 직접 체크하고있는데 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를 호출하여, 유효한 프로필이 생성되지 않도록 하는 것도 방법입니다.
다른 유사한 질문과 해결 방법은 아래 링크에서 확인해 볼 수 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.




