728x90

React 가 대세라서 React 학습을 해보는 중이다.

인프런 사이트 강좌도 들어보고 fastcampus 강좌도 들어보고 있다. 사이트마다 장단점이 있는 거 같다.

전체적인 개념을 잡으면서 하는 것은 fastcampus 강좌가 좋은데, 최근에 변경된 것을 반영하지 않은 것이 있다보니 따라하기 실습을 해보면 잘 동작되지 않아서 진도 나기가기 쉽지 않아 중도에 멈춤 상태이다.

React 동영상 강좌를 가급적이면 2022년에 나온 걸 중심으로 학습하는게 정신 건강에 좋은 듯 싶다.

 

Back-End는 지금까지 배워왔던 PHP 로 해보는게 좋을 듯 싶어서 유투브 동영상 강좌를 검색하니 인도 개발자가 올린 동영상 강좌가 괜찮은 거 같아서 따라서 해보기로 하고 어제 동영상을 멈춰가면서 따라하기를 해보았다. 아쉽게도 소스코드를 Github 에 공개하지 않아서 일일이 타이핑을 하는 수고를 해야 한다.

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

 

프로젝트 생성 : npx create-react-app react-php

프로젝트로 이동 : cd react-php

 

모듈 추가

npm install --save bootstrap
npm install --save react-router-dom@6
npm install --save axios

 

동영상 강좌에서 bootsrap 모듈을 추가하라고 나오는 건 없다. 아직 bootstrap 모듈 추가한 것에 대한 기능을 제대로 사용할 줄 모른다. 나중에 사용법을 익힐 것을 감안하고 모듈 추가를 해두었다.

 

구글에서 boostrap cdn 을 입력하고 css 버튼을 눌러 하단의 HTML 코드를 복사하여 public 폴더 index.html 파일 헤더 부분에 붙여넣기 한다.

 

App.js

회원 가입과 로그인 기능을 보여주는 메인화면 구성을 하기 위한 App.js 파일 구성이다.

import "bootstrap/dist/css/bootstrap.min.css"
import './App.css';
import Header from "./Header";
import {BrowserRouter, Routes, Route} from "react-router-dom";
import Home from "./Home";
import Login from "./Login";
import Register from "./Register";
 
function App() {
    return (
        <BrowserRouter>
            <div className="container">
                <Header/>
                <Routes>
                    <Route path="/" element={<Home/>}/>
                    <Route path="/login" element={<Login/>}/>
                    <Route path="/register" element={<Register/>}/>
                </Routes>
            </div>
        </BrowserRouter>
    );
}
 
export default App;

 

Header.js

header.js 구성을 위해서 구글에서 bootstrap navbar 검색하고 Navbar text with an inline element 복사하여
Header.js 에 붙여넣기 한다. Webstorm에서 class 는 자동으로 className 으로 변경해 주더라.

동영상 보면 Visual Studio Code(vscode)에서 class 자동 변경은 안되는거 같더라.

import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
const Header = () => {
    return (
        <nav className="navbar navbar-expand-lg bg-light">
            <div className="container-fluid">
                <a className="navbar-brand" href="#">Navbar w/ text</a>
                <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
                        aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
                <div className="collapse navbar-collapse" id="navbarText">
                    <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                        <li className="nav-item">
                            {/*<a className="nav-link active" aria-current="page" href="#">Home</a>*/}
                            <Link to="/" className="nav-link active">Home</Link>
                        </li>
                        <li className="nav-item">
                            <Link to="/register" className="nav-link">Register</Link>
                        </li>
                        <li className="nav-item">
                            <Link to="/login" className="nav-link">Login</Link>
                        </li>
                    </ul>
                    <span className="navbar-text">
                    </span>
                </div>
            </div>
        </nav>
    )
}
 
export default Header;

 

 

<a className="nav-link active" aria-current="page" href="#">Home</a>

부분을

<Link to="/" className="nav-link active">Home</Link>

로 변경하면 된다.

 

이 코드로 테스트를 해보니 PC화면에서는 버튼 기능이 잘 동작되는데 모바일 크기 사이즈로 화면을 축소하면 메뉴 선택하는 부분이 동작되지 않는 현상이 있다.

단순하게 bootstrap 5 코드를 React 로 변경만 했기 때문에 생기는 문제점으로 Navbar 가 제대로 동작되지 않는 듯 하다.

이 부분은 bootstrap 모듈 추가한 방식으로 다시 한번 테스트를 해볼 예정이다.

지금은 React - PHP 간 연동 처리하는 부분이 중점이라 그 부분에 치중하고 글을 작성해두는 것이다.

 

 

Home.js

const Home = () => {
    return (
        <div>
            Welcome to Home page
        </div>
    )
}
export default Home;

이 코드는 형태만 보여주는 수준이다.

Login.js 파일도 이와 같은 형태라서 보여주는 건 생략한다.

 

Register.js

구글에서 bootstrap form 으로 검색하면 https://mdbootstrap.com/docs/standard/forms/overview/ 가 검색된다.

여기서 적당한 것을 복사하여 붙여넣기를 하고 불필요한 부분은 수정한다.

제공된 기본 Form 에서 name, 상태변화값 onChangeInput, value 를 추가하고 id 값도 알기 쉽게 변경한다.

아래와 같이 코드를 작성하면 React 버전 회원가입 기본 폼이 완성된다.

PHP 로 submit 결과를 전송하기 위해서 axio.post 로 전달하고 결과를 돌려받도록 코드를 작성한다.

이 부분이 jQuery ajax 로 전송하는 것과 좀 다르다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
 
const Register = () => {
    const navigate = useNavigate();
    const [formData, setFormData] = useState({
        userNM: "",
        email: "",
        password: ""
    })
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const sendData = {
            userNM: formData.userNM,
            email: formData.email,
            password: formData.password
        }
        console.log(sendData);
        axios.post('http://localhost/php-react/insert.php', sendData)
            .then((res) => {
                console.log(res.data);
                navigate('/login');
            })
            .catch(error => {
                console.log(error.response)
            });
    }
 
    return (
        <div className="container h-100 mt-5">
            <div className="row d-flex justify-content-center align-items-center h-100">
                <div className="col-12 col-md-9 col-lg-7 col-xl-6">
                    <div className="card">
                        <div className="card-body p-5">
                            <h2 className="text-uppercase text-center mb-5">Create an account</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userNM">Your Name</label>
                                    <input type="text" name="userNM" onChange={onChangeInput} id="userNM"
                                           className="form-control form-control-lg" value={formData.userNM}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="email">Your Email</label>
                                    <input type="email" name="email" onChange={onChangeInput} id="email"
                                           className="form-control form-control-lg" value={formData.email}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="password">Password</label>
                                    <input type="password" name="password" onChange={onChangeInput} id="password"
                                           className="form-control form-control-lg" value={formData.password}
                                           required/>
                                </div>
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-success btn-block btn-lg gradient-custom-4 text-body">Register
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/login" className="fw-bold text-body"><u>로그인</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Register;

 

PHP DB 연결 코드 dbconnect.php

이 부분은 Legacy PHP 로 DB를 연결하는 방법이며, 내가 즐겨 사용하는 방식 중 하나다.

<?php
$db['server'= 'localhost';
$db['dbname'= 'studydb';
$db['user_name'= 'reactfox';
$db['password'= 'Wonderfull!';
$db['port'= "3306";
 
$db = isConnectDb($db);
 
function isConnectDb($db)
{
    $conn = mysqli_connect($db['server'],$db['user_name'],$db['password'],$db['dbname'],$db['port']);
    mysqli_set_charset($conn"utf8");  // DB설정이 잘못되어 euc-kr 로 되어 있으면 문제가 됨
    if (mysqli_connect_errno()) {
        echo "Failed to connect to MySQL: " . mysqli_connect_error();
        exit;
    } else {
        return $conn;
    }
}
 
/* 사용자 권한 등록
create database studydb default character set utf8;
 
use mysql;
create user reactfox@localhost identified by 'Wonderfull!';
grant all privileges on studydb.* to reactfox@localhost;
flush privileges;
quit
*/
?>
 
 

 

DB를 연결하기 위해 studydb 를 생성하고 DB 접속 권한을 부여하기 위한 걸 해준다.

이제 사용자 정보를 저장하기 위한 초간단 테이블을 구성한다. 이 테이블은 연동 과정을 보여주기 위한 것이지 실제 사용 수준의 테이블 스키마는 아니다.

CREATE TABLE `users` (
  `id` int(11NOT NULL,
  `name` varchar(50CHARACTER SET utf8mb3 NOT NULL,
  `email` varchar(50CHARACTER SET utf8mb3 NOT NULL,
  `password` varchar(200CHARACTER SET utf8mb3 NOT NULL
ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `email` (`email`);
 
ALTER TABLE `users`
  MODIFY `id` int(11NOT NULL AUTO_INCREMENTAUTO_INCREMENT=1;
COMMIT;

email 칼럼은 UNIQUE KEY 를 지정하여 중복 저장되지 않도록 했다.

 

 

insert.php

아래 코드 상단에 처리하는 기능에 대해서는 다 모른다. 이 부분에서 엄청난 삽질을 하면서 개고생을 좀 했다.

Access-Control-Allow-Headers : 가 된 것이 문제가 되는 줄 몰랐다.

Access-Control-Allow-Headers: 와 같이 공백이 있으면 절대 안되더라. ㅠㅠㅠ

이것 때문에 CORS 에러 메시지 숱하게 보이고 구글링 하면서 별의 별 것을 다 찾아보게 되었다.

덕분에 이 코드의 중요성에 대해서 알게 된 것 정도이다.

윈도우에서 localhost 로 PHP 도 설치하고, React 도 설치해서 동작시키는 것에서는 CORS 에러를 만날 일이 적은 듯 하다. 리눅스 버전을 설치하고 나서 Same IP, Different Port 로 크롬브라우저가 CORS 에러 메시지를 보여주는 걸 해결하기 위해 수많은 삽질 끝에(?) 해결을 하긴 했다. 테스트 해보니 더 코드를 정교하게 할 부분도 있기는 있는 듯 하다.

https://link2me.tistory.com/2228 에 CORS 에러 해결 방법이 있으니 참조하면 된다.

<?php
//header("Access-Control-Allow-Origin: http://localhost:3000");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 3600");
//header("Access-Control-Allow-Headers: Content-Type, Authorization");
//header("Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Allow-Headers, Authorization");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
 
$data = json_decode(file_get_contents("php://input"));
 
if(isset($data&& !empty($data)){
 
    require_once 'dbconnect.php';
 
    $name = $data->userNM;
    $email = $data->email;
    $password = $data->password;
    $sql = "INSERT INTO users (name,email,password) VALUES ('$name','$email','$password')";
    if(mysqli_query($db,$sql)){
        echo json_encode(["status" => "success""message" => "User Inserted"'response' => 200]);
    } else {
        echo json_encode(["status" => "fail""message" => "Unable to register the user!"'response' => 400]);
    }
}
?>

 

UI 구성 처리에 대한 사항은 bootstrap 모듈 연동 방법으로 다시 한번 테스트 해볼 생각이다.

샘플로서의 가치가 있을 수준이 되면 my github 에 올려두고 링크를 걸어둘 것이다.

이상으로 인도 개발자 유투브 동영상 참조 및  다른 코드를 찾아 수정하면서 React-PHP 연동에 성공했다는 뿌듯함에 적어뒀다.

 

최근에 알게된 코딩앙마님의 React 강좌가 좋은 듯하여 학습 중이다.

https://www.youtube.com/watch?v=05uFo_-SGXU&list=PLZKTXPmaJk8J_fHAzPLH8CJ_HO_M33e7- 

 

728x90

'React > React-PHP' 카테고리의 다른 글

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React + PHP Login 처리  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
블로그 이미지

Link2Me

,