본문 바로가기

React&React-Native/React

[#. React] React + Firebase Instagram Clone, 인스타그램 클론 프로젝트 1 (프로젝트 생성, Firebase 설정, 라우팅)

반응형

 

 

 

 

 

$ yarn create react-app instagram
$ yarn add date-fns
$ yarn add firebase
$ yarn add react-loading-skeleton

 

 

📁public에서 favicon.ico, index.html 파일만 남기고

📁src에서 App.js, index.js 파일만 남기고 정리한다

 

 

폴더를 아래 구조와 같이 생성해 준다

 

📁public

  • 📁images
    • 📁avatars
    • 📁users

 

 

📁public

  • 📄index.html

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Instagram</title>
    <style>
      body {
        background-color: #fafafa;
      }
    </style>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

 

📁src

  • 📄App.js

 

function App() {
  return (
    <p>Hello</p>
  );
}

export default App;

 

 

📁src

  • index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

 

 

📁src

  • 📁components
  • 📁constants
  • 📁context
  • 📁helpers
  • 📁hooks
  • 📁lib
  • 📁pages
  • 📁services
  • 📄seed.js

 

📁src

  • 📄seed.js

 

https://github.com/karlhadwen/instagram에서 seed.js  파일을 복사해서 내용을 붙여 넣는다
 
 
/* eslint-disable no-plusplus */
// NOTE: replace 'NvPY9M9MzFTARQ6M816YAzDJxZ72' with your Firebase auth user id (can be taken from Firebase)
export function seedDatabase(firebase) {
  const users = [
    {
      userId: 'NvPY9M9MzFTARQ6M816YAzDJxZ72',
      username: 'karl',
      fullName: 'Karl Hadwen',
      emailAddress: 'karlhadwen@gmail.com',
      following: ['2'],
      followers: ['2', '3', '4'],
      dateCreated: Date.now()
    },
    {
      userId: '2',
      username: 'raphael',
      fullName: 'Raffaello Sanzio da Urbino',
      emailAddress: 'raphael@sanzio.com',
      following: [],
      followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
      dateCreated: Date.now()
    },
    {
      userId: '3',
      username: 'dali',
      fullName: 'Salvador Dalí',
      emailAddress: 'salvador@dali.com',
      following: [],
      followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
      dateCreated: Date.now()
    },
    {
      userId: '4',
      username: 'orwell',
      fullName: 'George Orwell',
      emailAddress: 'george@orwell.com',
      following: [],
      followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
      dateCreated: Date.now()
    }
  ];

  // eslint-disable-next-line prefer-const
  for (let k = 0; k < users.length; k++) {
    firebase.firestore().collection('users').add(users[k]);
  }

  // eslint-disable-next-line prefer-const
  for (let i = 1; i <= 5; ++i) {
    firebase
      .firestore()
      .collection('photos')
      .add({
        photoId: i,
        userId: '2',
        imageSrc: `/images/users/raphael/${i}.jpg`,
        caption: 'Saint George and the Dragon',
        likes: [],
        comments: [
          {
            displayName: 'dali',
            comment: 'Love this place, looks like my animal farm!'
          },
          {
            displayName: 'orwell',
            comment: 'Would you mind if I used this picture?'
          }
        ],
        userLatitude: '40.7128°',
        userLongitude: '74.0060°',
        dateCreated: Date.now()
      });
  }
}

 

 

 

 

firebase 설정

 

 

https://console.firebase.google.com/

 

프로젝트 생성 후

 

Firestore Database -> 데이터베이스 만들기 

 

 

개발 규칙/운영 규칙은 아래와 같지만

현재는 개발 규칙을 그대로 사용한다

 

// development rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if
          request.time < timestamp.date(2022, 9, 3);
    }
  }
}

// production rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read;
      allow write: if request.auth.uid != null;
    }
  }
}

 

 

 

 

 

Authentication -> 시작하기

 

Sign-in method 이메일/전화번호 사용 설정

 

 

 

 

 

 

 

참고로 firebase 9 버전 이상이다

firebase: "^9.9.1"

 

 

📁src

  • 📁context
    • 📄firebase.js

 

 

import { createContext } from 'react';

const FirebaseContext = createContext(null);
export default FirebaseContext;

 

 

📁src

  • 📁lib
    • 📄firebase.js

 

 

import Firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

// here I want to import the seed file

const config = {};

const firebase = Firebase.initializeApp(config);
const { FieldValue } = Firebase.firestore;

// here is where I want to call the seed file (only ONCE!)
// seedDatabase(firebase);

export { firebase, FieldValue };

 

 

📁src

  • 📄index.js

 

 

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import FirebaseContext from './context/firebase';
import { firebase, FieldValue } from './lib/firebase';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <FirebaseContext.Provider value={{ firebase, FieldValue }}>
   <App />
  </FirebaseContext.Provider>
);

 

 

 

프로젝트 개요->설정 버튼->프로젝트 설정

 

 

 

 

 

하단에 내 앱-> </> 클릭한다

 

 

 

앱 닉네임을 입력해 주고 앱 등록 버튼을 누르면 

 

 

 

 

 

아래와 같이 뜰 거고 firebaseConfig에 있는 내용을 복사해서

 

 

 

📁lib

  • 📄firebase.js

config를 채워준다

 

const config = {
  apiKey: "",
  authDomain: "",
  projectId: "i,
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: ""
};

 

그리고 seed.js 파일에 있는 데이터를 넣어줘야 한다

추가 주석이 달려있는 코드 두 줄을 추가하고 seed.js 파일에 있는 데이터를 firebase DB에 최초 한 번 밀어넣은 후

코드는 다시 주석 처리해 준다

 

import Firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

// here I want to import the seed file
import { seedDatabase } from '../seed';	// 추가

const config = {
// 채워준다
};

const firebase = Firebase.initializeApp(config);
const { FieldValue } = Firebase.firestore;

// here is where I want to call the seed file (only ONCE!)
seedDatabase(firebase);	// 추가

export { firebase, FieldValue };

 

 

 

 

 

 

$ yarn add react-router-dom

"react-router-dom": "^6.3.0",

react-router-dom이 버전 6이고

버전 6에서는 Switch를 지원하지 않는다 Switch -> Routes로 바뀌었다

또한 component->element로 바꼈다.

 

 

📁pages

  • 📄login.js

 

export default function Login() {
  return(
    <p>Login Page</p>
  );
}

 

 

📄App.js

 

import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

const Login = lazy(() => import ('./pages/login'));

function App() {
  return (
    <Router>
      <Suspense fallback={<p>Loading...</p>}>
        <Routes>
          <Route path="/login" element={<Login />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

 

 

📁constants

  • 📄routes.js

 

export const DASHBOARD = '/';
export const LOGIN = '/login';
export const SIGN_UP = '/signup';
export const PROFILE = '/p/:username';
export const NOT_FOUND = '/not-found';

 

📄App.js

 

import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import * as ROUTES from './constants/routes';	// 추가

const Login = lazy(() => import ('./pages/login'));

function App() {
  return (
    <Router>
      <Suspense fallback={<p>Loading...</p>}>
        <Routes>
          <Route path={ROUTES.LOGIN} element={<Login />} />	// 수정
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

 

 

 

📁pages

  • 📄login.js

 

기존에 react-router-dom 6 버전 미만에서 사용하던 useHistoryuseNavigate로 바뀌었다

 

import { useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import FirebaseContext from '../context/firebase';

export default function Login() {
  const navigate = useNavigate();
  const { firebase } = useContext(FirebaseContext);

  const [emailAddress, setEmailAddres] = useState('');
  const [password, setPassword] = useState('');

  const [error, setError] = useState('');
  const inInvalid = password === '' || emailAddress === '';

  const handleLogin = () => {};

  useEffect(() => {
    document.title = 'Login - Instagram';
  }, [])

  return(
    <p>Login Page</p>
  );
}

 

 

 

 

$ yarn add tailwindcss -D
$ yarn add prop-types -D
$ yarn add postcss-cli -D
$ yarn add npm-run-all -D
$ yarn add autoprefixer -D
$ yarn add postcss -D
$ yarn install

 

 

 

📄packages.json

 

  "scripts": {
    "build:css": "postcss src/styles/tailwind.css -o src/styles/app.css",
    "watch:css": "postcss src/styles/tailwind.css -o src/styles/app.css --watch",
    "react-scripts:start": "sleep 5 && react-scripts start",
    "start": "run-p watch:css react-scripts:start",
    "build": "run-s build:css react-scripts:build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

 

 

 

📁styles

  • 📄tailwind.css

 

@tailwind base;
@tailwind components;
@tailwind utilities;

 

$ yarn start

 

📁styles에 📄app.css 파일이 생성될 것이다

 

 

 

 

📁src

  • 📄index.js

 

import './styles/app.css';	// 추가

 

 

📁pages

  • 📄login.js

 

import { useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import FirebaseContext from '../context/firebase';

export default function Login() {
  const navigate = useNavigate();
  const { firebase } = useContext(FirebaseContext);

  const [emailAddress, setEmailAddres] = useState('');
  const [password, setPassword] = useState('');

  const [error, setError] = useState('');
  const inInvalid = password === '' || emailAddress === '';

  const handleLogin = () => {};

  useEffect(() => {
    document.title = 'Login - Instagram';
  }, [])

  return(	// 아래 부분 수정
    <div className="container flex mx-auto max-w-screen-md items-center h-screen">
      <p>I Hava no idea!</p>
    </div>
  );
}

 

 

📄postcss.config.js

 

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}

 

 

📄tailwind.config.js

 

module.exports = {
  content: ["./src/**/*.{html,js}"],
  future: {
    removeDeprecatedGapUtilities: true
  }
}

 

 

 

 

postcss + tailwind 조합 설정은 아래 사이트를 참고하면 된다

 

https://tailwindcss.com/docs/installation/using-postcss

 

Installation: Using PostCSS - Tailwind CSS

Documentation for the Tailwind CSS framework.

tailwindcss.com

 

 

 

아래 이미지와 같이 텍스트가 중앙으로 옮겨졌다면 설정 완료!

 

 

 

 

 

https://www.youtube.com/watch?v=mDgEqoQUBgk 

 

 

 

https://github.com/karlhadwen

 

karlhadwen - Overview

karlhadwen has 30 repositories available. Follow their code on GitHub.

github.com

 

반응형