그럼에도 불구하고

👨‍💻

[React] firebase 이용하기 본문

React/React basics

[React] firebase 이용하기

zenghyun 2023. 5. 31. 21:10

 

오늘은 firebase를 이용하여 react와 연동된 애플리케이션을 만들어 보겠습니다.

 

 

 

[ 브라우저와 데이터베이스는 직접 소통하면 안 됩니다. ]

 

브라우저에서 실행되는 자바스크립트 코드가 데이터베이스와 직접 통신하면 안 됩니다. 리액트 앱이 있고, 어떤 종류의 데이터베이스가 있다면 이런 데이터베이스를 데이터베이스 서버에서 실행하는 것은 문제가 되지는 않습니다.

 

하지만, 매우 불안정하거나 잘못 작성된 애플리케이션이 아니고서야 앱으로 직접 데이터를 가져오거나 저장하고, 연결을 맺는 행위는 외부 환경에서는 절대 해서는 안 되는 일 중 하나입니다.

 

기술적으로는 어려울 수 있겠지만, 클라이언트 내부에서 데이터베이스에 직접 연결을 하거나, 브라우저의 자바스크립트 코드를 통해 직접 연결을 한다면 이는 이 코드를 통해 데이터베이스의 인증 정보를 노출시킬 수 있는 행위입니다. 

 

잊지 말아야 할 것은 브라우저에서 실행되는 모든 자바스크립트 코드는 브라우저뿐만이 아니라 웹 사이트의 사용자들도 접근하고 읽을 수 있다는 것입니다.

 

따라서 리액트 앱 코드 내부에서 데이터베이스에 직접적으로 통신하는 방식은 보안 이슈 사항에서 큰 문제가 있기 때문에 다른 방법을 사용해야 합니다. 

 

예를 들어 Node js나 PHP, ASP, NET 등과 같은 백엔드 애플리케이션이 있습니다.

 

데이터베이스와 통신하는 백엔드 애플리케이션은 사용자가 이 백엔드 코드를 확인할 수 없기 때문에 데이터베이스의 인증 정보를 안전하게 저장할 수 있습니다. 또한, 코드가 다른 서버에 있기 때문에 웹사이트 사용자는 이 코드를 절대 볼 수 없습니다. 

 

따라서, 리액트 앱은 일반적으로 해당 백엔드 서버, 또는 백엔드 API라고 불리는 서로 다른 URL로의 요청을 전송하는 서버와 통신하게 됩니다. 

 

 

 

[ firebase ]

코드 작성 없이도 사용 가능한 무료 백엔드 데이터베이스 입니다.

 

https://firebase.google.com/?gad=1&gclid=Cj0KCQjw4NujBhC5ARIsAF4Iv6f6RzoCKb5baNIce7Unq9s8tZXkAVqJQocGdBMyCEo-BrJQVKXCI2IaAhtcEALw_wcB&gclsrc=aw.ds&hl=ko 

 

Firebase

Firebase는 고품질 앱을 빠르게 개발하고 비즈니스를 성장시키는 데 도움이 되는 Google의 모바일 플랫폼입니다.

firebase.google.com

 

 

시작하기를 누른 후,

 

 

 

프로젝트 추가를 눌러주세요

 

프로젝트 추가 후, 

 

 

 

 

빌드에서 Realtime Database를 이용하면 됩니다. 

 

 

 

 

그러면 이렇게 예시로 생성된 데이터베이스 주소를 받을 수 있습니다. 

 

 


 

 

📌 App.js

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import React, { useState, useEffect, useCallback } from "react";
 
import MoviesList from "./components/MoviesList";
import "./App.css";
import AddMovie from "./components/AddMovie";
 
function App() {
  const [movies, setMovies] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
 
  const fetchMoviesHandler = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const response = await fetch(
        "내 데이터베이스 주소/movies.json"
      );
      if (!response.ok) {
        throw new Error("Something went wrong!");
      }
      const data = await response.json();
 
      const loadedMovies = []; 
 
      for(const key in data) {
        loadedMovies.push({
          id:key,
          title: data[key].title,
          openingText: data[key].openingText,
          releaseDate: data[key].releaseDate,
        });
      }
    
      setMovies(loadedMovies);
      setIsLoading(false);
    } catch (error) {
      setError(error.message);
    }
    setIsLoading(false);
  }, []);
 
  useEffect(() => {
    fetchMoviesHandler();
  }, [fetchMoviesHandler]);
 
  async function addMovieHandler(movie) {
      const response = await fetch(
        "내 데이터베이스 주소/movies.json",
        {
          method: "POST",
          body: JSON.stringify(movie),
          headers: {
            "Content-Type""application/json",
          },
        }
      );
      const data = await response.json();
  }
 
  let content = <p>Found no movies.</p>;
 
  if (movies.length > 0) {
    content = <MoviesList movies={movies} />;
  }
 
  if (error) {
    content = <p>{error}</p>;
  }
 
  if (isLoading) {
    content = <p>Loading...</p>;
  }
 
  return (
    <React.Fragment>
      <section>
        <AddMovie onAddMovie={addMovieHandler} />
      </section>
      <section>
        <button onClick={fetchMoviesHandler}>Fetch Movies</button>
      </section>
      <section>{content}</section>
    </React.Fragment>
  );
}
 
export default App;
 
cs

 

 

1
2
3
4
5
6
7
8
9
10
const response = await fetch("firebase를 통해 생성한 가상 데이터베이스 주소/movies.json");
 
 
 
**firebase를 통해 생성한 가상 데이터베이스 주소** 
- firebase를 통해 생성한 실시간 데이터베이스 주소 
 
**/movies.json**
- 데이터 베이스 이름 : movie 
- 저장 양식 : json 
cs

 

 

 

📌 AddMovie.js 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import React, { useRef } from 'react';
 
import classes from './AddMovie.module.css';
 
function AddMovie(props) {
  const titleRef = useRef('');
  const openingTextRef = useRef('');
  const releaseDateRef = useRef('');
 
  function submitHandler(event) {
    event.preventDefault();
 
    // could add validation here...
 
    const movie = {
      title: titleRef.current.value,
      openingText: openingTextRef.current.value,
      releaseDate: releaseDateRef.current.value,
    };
 
    props.onAddMovie(movie);
  }
 
  return (
    <form onSubmit={submitHandler}>
      <div className={classes.control}>
        <label htmlFor='title'>Title</label>
        <input type='text' id='title' ref={titleRef} />
      </div>
      <div className={classes.control}>
        <label htmlFor='opening-text'>Opening Text</label>
        <textarea rows='5' id='opening-text' ref={openingTextRef}></textarea>
      </div>
      <div className={classes.control}>
        <label htmlFor='date'>Release Date</label>
        <input type='text' id='date' ref={releaseDateRef} />
      </div>
      <button>Add Movie</button>
    </form>
  );
}
 
export default AddMovie;
 
cs

 

 

 

📌 MoviesList.js

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react';
 
import Movie from './Movie';
import classes from './MoviesList.module.css';
 
const MovieList = (props) => {
  return (
    <ul className={classes['movies-list']}>
      {props.movies.map((movie) => (
        <Movie
          key={movie.id}
          title={movie.title}
          releaseDate={movie.releaseDate}
          openingText={movie.openingText}
        />
      ))}
    </ul>
  );
};
 
export default MovieList;
 
cs

 

 

 

📌 Movie.js

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
 
import classes from './Movie.module.css';
 
const Movie = (props) => {
  return (
    <li className={classes.movie}>
      <h2>{props.title}</h2>
      <h3>{props.releaseDate}</h3>
      <p>{props.openingText}</p>
    </li>
  );
};
 
export default Movie;
 
cs
Comments