본문 바로가기
React TIL

[React] Day_44 데일리 정리

by 림졍 2024. 11. 19.

 

 

얼라리 하고 계정 가입이 안되어서…밤새우면서 뭐지 하고 원인 찾다

알고보니 내 권한 밖의 일이라 결국 오전에 해결할 수 밖에 없던 일이었던것을 알고 멘붕 온 사람?

..That's me.

오늘도 강제 야근인 림졍은 오늘도 챌린지 강의 정리 할겁니다.

가보자고, goyo.

 

 

챌린지반 강의 정리 - Database 기초

야 DB... 앞으로 친하게 지내자?

 

아 친하게 지내자고 ㅋㅋ

 

 

DB(데이터베이스) 

데이터를 체계적으로 저장하고 관리하는 시스템

단순히 파일로 저장 X, 대량의 데이터를 빠르고 안전하게 처리할 수 있도록 도와주는 시스템!

 

DB의 역할

  • 데이터를 안전하게 보관
  • 데이터를 빠르게 검색 및 수정 가능
  • 여러 사용자가 동시 사용 가능.
  • 데이터 무결성과 보안을 유지한다.

💡 Tip

  • “데이터 무결성”이란 데이터의 정확성과 일관성을 유지하는 특성이다!

 

 

DB 종류

 

1) 관계형 데이터베이스 (RDB)

 데이터를 테이블 구조로 저장하고, 테이블 간의 관계를 정의한다.

 

- RDB의 특징

  • 데이터를 행(Row)과 열(Column)로 구조화.
  • 데이터를 관리하기 위해 SQL 언어를 사용함.
  • ACID(원자성, 일관성, 격리성, 지속성) 특성을 지켜 데이터 안정성을 보장.

예시

 

1. 학생(students) 테이블

StudentID  Name Major Year
101 Alice Johnson Computer Science 3
102 Bob Smith Mathematics 2
103 Charlie Brown Physics 4

 

2. 과목(courses) 테이블

CourseID CourseName   Credits
201 Data Structures 4
202 Linear Algebra 3
203 Quantum Mechanics 4

 

3. 수강신청(enrollments) 테이블

EnrollmentID StudentID CourseID Grade
1 101 201 A
2 102 202 B+
3 103 203 A-

 

💡 용어 정리

  • Primary Key: 고유하게 식별 가능한 열!
  • Foreign Key: 다른 테이블의 기본 키를 참조하는 열.

 

2) 비관계형 데이터베이스 (NoSQL)

정해진 테이블 구조 없이 데이터를 다양한 형식으로 저장.

 

- NoSQL의 특징

  • 유연한 데이터 구조를 가짐.
  • 대규모 데이터와 실시간 처리에 유리.
  • JSON 형식의 데이터를 주로 사용.

 

예시

 

1. MongoDB의 문서(Document) 구조

{
  "StudentID": 101,
  "Name": "Alice Johnson",
  "Major": "Computer Science",
  "Year": 3,
  "Courses": [
    {
      "CourseID": 201,
      "CourseName": "Data Structures",
      "Grade": "A"
    },
    {
      "CourseID": 202,
      "CourseName": "Linear Algebra",
      "Grade": "B+"
    }
  ]
}

 

💡 특징

  • 하나의 문서에 학생 정보와 수강 과목 정보를 중첩 형태로 저장.
  • 관계형 데이터베이스와 달리 데이터를 한 번의 쿼리로 가져올 수 있음.

 

2. Firebase의 키-값(Key-Value) 구조

{
  "students": {
    "101": {
      "name": "Alice Johnson",
      "major": "Computer Science",
      "year": 3
    },
    "102": {
      "name": "Bob Smith",
      "major": "Mathematics",
      "year": 2
    }
  },
  "courses": {
    "201": {
      "name": "Data Structures",
      "credits": 4
    },
    "202": {
      "name": "Linear Algebra",
      "credits": 3
    }
  }
}

 

💡 특징

  • 데이터를 키-값 쌍으로 저장하며, 계층적 구조로 접근.
  • 데이터를 동적으로 추가하거나 삭제하기 쉬움.

 

RDB vs NoSQL

RDB와 NoSQL의 주요 특징

구분 관계형 데이터베이스 (RDB) 비관계형 데이터베이스 (NoSQL)
데이터 구조 정형화된 테이블 구조 (행과 열 기반) 유연한 데이터 구조 (문서, 키-값, 그래프 등)
스키마 고정된 스키마 필요 스키마가 없거나 유연
데이터 관계 테이블 간 관계를 명확히 정의 데이터 간 관계가 없거나 간접적으로 관리
확장성 수직적 확장 (더 강력한 서버로 업그레이드) 수평적 확장 (서버 추가로 용량 및 처리 속도 증가)
데이터 처리 속도 복잡한 조건에서도 효과적으로 데이터를 검색 및 처리 가능 단순한 데이터 검색, 빠른 읽기 및 쓰기에 적합
데이터 일관성 높은 데이터 무결성과 일관성을 보장 (*ACID 준수) 유연한 구조지만 일관성은 데이터베이스 종류에 따라 다름
사용 사례 금융, ERP, 전자상거래 등 데이터 정확성이 중요한 시스템 빅데이터 분석, 소셜 네트워크, IoT, 실시간 처리 시스템 등

 

+) ACID

RDB에서 트랜잭션의 안전성을 보장하는 4가지 속성

  1. 원자성 (Atomicity): 트랜잭션의 모든 작업이 성공적으로 완료되거나, 하나라도 실패하면 모든 작업이 취소된다.
  2. 일관성 (Consistency): 트랜잭션 후 데이터베이스는 항상 일관된 상태를 유지해야 한다.
  3. 격리성 (Isolation): 여러 트랜잭션이 동시에 실행되더라도 서로 간섭하지 않고 독립적으로 처리된다.
  4. 지속성 (Durability): 트랜잭션이 완료되면 시스템 오류가 발생하더라도 그 결과는 영구적으로 데이터베이스에 저장된다.

 

RDB와 NoSQL, 뭐가 좋을까?

 

RDB가 적합한 경우

  • 데이터 간 관계가 중요할 때.
  • 데이터 정확성과 무결성이 필수일 때.

 

NoSQL이 적합한 경우

  • 대규모 데이터를 처리하거나, 빠른 읽기/쓰기가 필요할 때.
  • 데이터 구조가 자주 변경될 때.

 

이미지 업로드 / URL 처리

왜 DB에 직접 저장하지 않고 URL을 사용하는 걸까?

 

1) 효율성

  • 이미지 크기 문제
    이미지를 데이터베이스에 직접 저장하면 데이터 용량이 커져 성능이 느려질 수 있음.
  • 전송 속도 문제
    이미지를 DB에서 읽어서 전송하면 네트워크 대역폭을 과도하게 사용함.
    → URL을 사용하면 CDN(Content Delivery Network)을 통해 빠르게 로드 가능!

 

2) 저장소 최적화

  • awSupabase Storage는 이미지 저장에 특화된 기능을 제공하고,
    CDN을 통해 빠른 데이터 전송을 보장함.
  • 데이터베이스는 텍스트 같은 메타데이터를 관리하고, 이미지는 스토리지에서 관리!

 

3) 확장성과 유지보수

  • 대규모 이미지 데이터를 다룰 때 스토리지가 더 효율적.
  • URL만 저장하면 관리가 훨씬 간편하고 비용도 절감 가능.

 

 

- Supabase로 이미지 업로드 구현하기

import { supabase } from "../supabase/supabaseClient";
import { v4 as uuidv4 } from "uuid";

export const uploadImage = async (file) => {
  try {
    // 1. 이미지 업로드
    const { data: storageData, error: uploadError } = await supabase.storage
      .from("images")
      .upload(`uploads/${uuidv4()}.png`, file);

    if (uploadError) throw new Error(uploadError.message);

    // 2. 업로드된 이미지의 공개 URL 가져오기
    const { data: publicUrlData } = supabase.storage
      .from("images")
      .getPublicUrl(storageData.path);

    return publicUrlData.publicUrl;
  } catch (error) {
    console.error("Error uploading image:", error);
    throw error;
  }
};

 

활용 예시

  • 사용자 프로필 이미지 업로드
  • 게시물 사진 첨부
  • 전자상거래 상품 이미지 관리

 

회원가입과 로그인 처리

왜 비밀번호를 user 테이블에 직접 저장하면 안 되는 걸까?

 

1) 보안상의 이유

  • 비밀번호를 평문으로 저장하면 해킹 시 사용자 정보가 노출될 위험이 큼.
  • 비밀번호는 반드시 해시(Hash) 처리 후 저장해야 함.
  • 예시: bcrypt, SHA-256

 

2) 비밀번호 해싱 원리

  • Salted Hashing
    비밀번호에 랜덤 문자열(Salt)을 추가하여 해싱하면 같은 비밀번호라도 다른 해시 값이 생성됨.
  • bcrypt는 해싱과 솔팅을 자동으로 처리하므로 안전함.

 

3) 비밀번호 관리와 인증 분리의 중요성

  • 해싱 로직 오류, DB 공격에 취약해질 위험 있음.
  • Supabase 같은 인증 서비스는 안전한 인증 흐름을 자동으로 처리해줌.

 

Supabase 인증 처리 흐름

  1. 사용자가 이메일/비밀번호 입력 → auth.signUp 또는 auth.signIn 호출
  2. Supabase가 비밀번호를 해싱하여 저장 + 인증 토큰 생성 후 반환
  3. 클라이언트가 API 요청 시 이 토큰을 포함 → 인증된 데이터만 접근 가능

 

Supabase 인증 처리 코드

 

1) 회원가입

export const signUp = async (email, password) => {
  try {
    const { data, error } = await supabase.auth.signUp({
      email,
      password,
    });

    if (error) throw new Error(`회원가입 실패: ${error.message}`);
    console.log("회원가입 성공:", data);
    return data;
  } catch (err) {
    console.error(err.message);
    return null;
  }
};

 

 

2) 로그인

export const signIn = async (email, password) => {
  try {
    const { data, error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });

    if (error) throw new Error(`로그인 실패: ${error.message}`);
    console.log("로그인 성공:", data);
    return data;
  } catch (err) {
    console.error(err.message);
    return null;
  }
};

 

 

3) 인증된 사용자 데이터 가져오기

export const getUserProfile = async () => {
  try {
    const {
      data: { session },
    } = await supabase.auth.getSession();
    if (!session) throw new Error("로그인된 사용자가 없습니다.");
    const { data, error } = await supabase
      .from("profiles")
      .select("*")
      .eq("user_id", session.user.id);
    if (error) throw new Error(`프로필 가져오기 실패: ${error.message}`);
    console.log("사용자 프로필:", data);
    return data;
  } catch (err) {
    console.error(err.message);
    return null;
  }
};

 

 

회원 관리 방법

 

방법 1: 기본 Authentication 서비스만 사용

  • 구조: Supabase에서 기본 제공하는 auth.users 테이블만 사용
  • 장점: 간단하고 빠르게 회원가입/로그인 구현 가능
  • 단점: 다른 테이블과의 join이 어려움

 

방법 2(추천): Authentication과 Users 테이블 분리

  • 구조
  • auth.users: 인증 정보 저장
  • users: 프로필 정보 저장 (ex. 닉네임, 생년월일)
  • 장점: join 쿼리 활용 가능 + 사용자 정보를 유연하게 관리

 

- 회원가입 로직 구현 예시

export const signUp = async ({ email, password, displayName }) => {
  try {
    const { user, error: authError } = await supabase.auth.signUp({
      email,
      password,
    });
    if (authError) throw new Error(authError.message);
    const { data: profileData, error: profileError } = await supabase
      .from("users")
      .insert({ id: user.id, displayName });
    if (profileError) throw new Error(profileError.message);
    return profileData;
  } catch (error) {
    console.error("Error during sign-up:", error);
    throw error;
  }
};

 

 

마무리 - 아 프로젝트 힘들다.

 

커밋 장난..???

챌린지반 정리 요약, 3줄로 정리하면 요렇습니당.

이미지? 스토리지 쓰자.

비밀번호? 안전하게 해시로 관리하자.

Supabase? 쓰면 편하고, 잘 쓰면 더 편하다.

 

와아 ^-^)b 이제 저는 프로젝트 하러갈게요...

(정말 하기싫다. ㅇTL)

 

KPT 회고

  • Keep :  수수수 수빠베이스.. 이제는 조금 알 것 같아요
  • Problem : 수면시간이 부족해요.
  • Try : ... 언제 잘 수 있죠? ㅠㅡㅠ
728x90
반응형

'React TIL' 카테고리의 다른 글

[React] Day_46 팀 프로젝트 후기  (1) 2024.11.22
[React] Day_45 데일리 정리  (0) 2024.11.21
[React] Day_43 데일리 정리  (1) 2024.11.18
[React] Day_42 개인 프로젝트 후기  (1) 2024.11.15
[React] Day_41 데일리 정리  (3) 2024.11.14