알린홈마의 코드친구들
article thumbnail

깉이보면 좋은글

 

2023.09.06 - [JS/Next.js] - [Error] auth/invalid-api-key, Next.js 에서 환경변수

 

[Error] auth/invalid-api-key, Next.js 에서 환경변수

원인: Next.js Node환경 환경변수 발단 firebase를 이용해서 로그인 기능을 구현중 계속 `{code: "auth/invalid-api-key", message: "Your API key is invalid, please check you have copied it correctly."}` 에러메세지가 호출되었다

aliencoding.tistory.com

Firebase Authentication 

파이어베이스로 사용자 로그인을 해보자!

SDK 설치 및 Firebase 초기화

파이어베이스 SDK를 설치해주자

npm install firebase

그런 다음 초기화

import { initializeApp } from 'firebase/app';

const firebaseConfig = {
  //...
};

const app = initializeApp(firebaseConfig);

const auth = getAuth(app);

 

Email과 비밀번호를 이용해서 로그인

 

firebase 예시

import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";

const auth = getAuth();
createUserWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    // Signed in 
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
    // ..
  });

 

타입스크립트를 이용해 구현

export async function createUser(
  email: string,
  password: string,
  userName: string
) {
  try {
    const userCredential = await createUserWithEmailAndPassword(
      auth,
      email,
      password
    );
    const user = userCredential.user;

    await updateProfile(user, { displayName: userName });
    await setUserData(user);
    return user; // 여기에서 user 객체를 반환합니다.
  } catch (error) {
    console.error("Error creating user:");
    throw error;
  }
}

try catch 문을 이용해 에러를 잡아내고 `createUserWithEmailAndPassword()` 함수에 참조값과 이메일과 비밀번호를 전달한 후에 생성된 유저정보를 받아와 `createUserWithEmailAndPassword()`로 생성된 유저정보에는 displayName값이 없기 때문에`updateProfile()`을 이용해 생성된 정보위에 displayName 값을 받아온 userName 값으로 변경해주고, 파이어베이스 파이어스토 유저 컬렉션에 해당 유저 정보를 전달하는 `setUserData(user)` 을 실행하고 user을 리턴하도록 하였다.

 

//SignupModal.tsx
"use client";

import { useState } from "react";
import { FirebaseError } from "firebase/app";
import { createUser } from "@/app/api/firebase";
import { User } from "firebase/auth";

type SignupModalProps = {
  handleSignUpModalState: () => void;
  handleSetUser: (user: User) => void;
};

export default function SignupModal({
  handleSignUpModalState,
  handleSetUser,
}: SignupModalProps) {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [userName, setUserName] = useState(""); // 추가
  const [errorMessages, setErrorMessages] = useState("");

  const handleSignUp = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      await createUser(email, password, userName).then((user) => {
        handleSignUpModalState();
        handleSetUser(user);
      });
    } catch (error) {
      if (error) {
        const firebaseError = error as FirebaseError;
        switch (firebaseError.code) {
          case "auth/email-already-in-use":
            setErrorMessages("이미 사용중인 이메일입니다.");
            break;
          case "auth/invalid-email":
            setErrorMessages("유효하지 않은 이메일입니다.");
            break;
          case "auth/weak-password":
            setErrorMessages("비밀번호는 6자리 이상이어야 합니다.");
            break;
          default:
            setErrorMessages("회원가입에 실패했습니다.");
        }
        setTimeout(() => {
          setErrorMessages("");
        }, 3000);
      }
      console.log(error);
    }
  };

  return (
    <div className="flex flex-col items-center justify-center h-full gap-4">
      <div className='w-full flex justify-center relative'>
        <h1>Login</h1>
        <button onClick={handleSignUpModalState} type="button" className='absolute right-0'>
          X
        </button>
      </div>
      <form onSubmit={handleSignUp}>
        <div className="flex flex-col gap-4">
          <input
            type="email"
            placeholder="email"
            onChange={(e) => setEmail(e.target.value)}
            required
            className='border border-neutral-300 p-2 rounded-md'
          />
          <input
            type="password"
            placeholder="password"
            onChange={(e) => setPassword(e.target.value)}
            required
            className='border border-neutral-300 p-2 rounded-md'
          />
          <input
            type="text"
            name="userName"
            id="userName"
            placeholder="userName"
            onChange={(e) => setUserName(e.target.value)}
            required
            className='border border-neutral-300 p-2 rounded-md'
          />
          <button
            type="submit"
            className={`btn_default ${
              !email || !password || !userName ? "disabled" : ""
            }`}
          >
            회원가입
          </button>
          {errorMessages && <span>{errorMessages}</span>}
        </div>
      </form>
    </div>
  );
}

 form 문에서 e.preventDefault()을 실행시키기 위해서는 이벤트 타입으로 리액트에서 제공하는 `e: React.FormEvent` 를 사용해야 한다.

try catch문을 사용해 error를 핸들링 할때 swich 문을 이용해 에러코드에 해당하는 메세지를 유저에게 전달하고 `setTImeout()`을 이용해 일정시간뒤에 메세지가 사라지도록 하였다.

 

유저 생성시 데이터베이스에 유저정보 따로 저장하기

// firestore.ts

// db는 firebase.ts에서 가져옴
// export const db = getFirestore(app);

import { db } from "./firebase";
import axios from "axios";
// ...


export async function setUserData(user: User): Promise<void> {
  await setDoc(doc(db, "account", user.uid), {
    email: user.email,
    displayName: user.displayName,
    photoURL: user.photoURL,
    uid: user.uid,
  });
}

firebase setDoc을 이용해 유저정보 저장을 따로 해주었다.

2023.08.25 - [JS/React] - "나의 일지"프로젝트(5)_handsontable, 파이어스토어 데이터 베이스

 

"나의 일지"프로젝트(5)_handsontable, 파이어스토어 데이터 베이스

이제 첫 리포트를 생성해보자~!! 작업일지 리포트는 테이블형태(엑셀)로 작성하고 엑셀과 csv 파일로 내보내고 불러오게 가능하도록 구상을 했다. 마침 테이블 형태 관련해서 좋은 글과 좋은 라

aliencoding.tistory.com

여기에서 파이어스토어를 다루는 법에 대해 적어두었다.

 

profile

알린홈마의 코드친구들

@알린팬클럽홈마

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...