'React/React-PHP'에 해당되는 글 4건

728x90

React 에서 RSA 암호화를 하여 패스워드를 Back-End(PHP)로 전송하고, PHP에서 복호화 처리를 해봤다.

npm install jsencrypt@3.2.1

로 모듈을 추가하고 아래와 같이 코드를 전송하면 된다.

jsencrypt 버전은 3.2.1 에서 정상동작함을 확인했다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
import { JSEncrypt } from "jsencrypt"// npm install jsencrypt
 
const Login = () => {
    // PHP 를 이용하여 Web에서 생성한 공개키 : 실제 길이는 훨씬 더 길다.
    const publicKey = `MIGfMA0GCSqGSIb3DQEBED/dKAJT7vdgzXooBzzTyUHwVJGyA1mKYDCIyU5/IQIDAQAB`;
    const encrypt = new JSEncrypt(); // Start our encryptor.
    encrypt.setPublicKey(publicKey); // Assign our encryptor to utilize the public key.
 
    const navigate = useNavigate();
    const initData = {
        userID: '',
        password: ''
    }
 
    const [formData, setFormData] = useState(initData);
    const [users, setUsers] = useState([]);
    // 첫번째 원소 : 현재 상태, 두번재 원소 : 상태를 바꾸어 주는 함수
    const [error, setError] = useState(null);
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        // e.target.name 은 해당 input의 name을 가리킨다.
        //console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const params = {
            userID: formData.userID,
            password: encrypt.encrypt(formData.password)
        }
        console.log(params);
        axios.post('/reactSample/loginChk.php', params)
            .then((res) => {
                console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    setUsers(res.data.userinfo);
                    navigate('/');
                } else {
                    console.log(res.data.message);
                    setError(true);
                }
            })
            .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">Sign In</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userID">userID</label>
                                    <input type="text" name="userID" onChange={onChangeInput} id="userID"
                                           className="form-control form-control-lg" value={formData.userID}
                                           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>
 
                                { error &&
                                <div className="alert alert-danger" role="alert">
                                    로그인 정보를 확인하세요!
                                </div>
                                }
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-primary btn-block btn-lg gradient-custom-3 text-body">로그인
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/register" className="fw-bold text-body"><u>회원가입</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Login;
cs

 

 

PHP 에서 RSA 공개키 얻는 방법

 
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: application/json; charset=UTF-8");
 
$pubkey = get_publickey();
echo $pubkey;
 
function get_publickey() {
    // 경로 : 절대경로로 설정 필요
    $rsakeyfile = '/home/rsa/key/rsa_pub.pem';
    
    $fp = fopen($rsakeyfile,"r");
    $key = "";
    while(!feof($fp)) {
        $key .= fgets($fp,4096);
    } 
    fclose($fp);
 
    $key = preg_replace('/\r\n|\r|\n/','',$key);
    $key = str_replace('-----BEGIN PUBLIC KEY-----','',$key);
    $key = str_replace('-----END PUBLIC KEY-----','',$key);
    return $key;
 
/*
CentOS 리눅스 에서 RSA 공개키, 개인키 생성 방법
mkdir -p /home/rsa/key/
cd /home/rsa/key/
 
# Private Key 생성
openssl genrsa -out rsa_pri.pem 1024
 
# Public Key 생성
openssl rsa -pubout -in rsa_pri.pem -out rsa_pub.pem
 
*/
?>

 

 

PHP loginChk.php

- RSA 복호화 처리 함수는 LoginClass.php 파일에 포함되어 있다.

<?php
// 파일을 직접 실행하는 비정상적 동작을 방지 하기 위한 목적
if(isset($_POST&& $_SERVER['REQUEST_METHOD'== "POST"){
    $_POST = json_decode(file_get_contents("php://input"),true); 
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID&& !empty($userID&& isset($password&& !empty($password)) {
        require_once 'phpclass/config.php';
        require_once 'phpclass/dbconnect.php';
        require_once 'phpclass/loginClass.php';
        $c = new LoginClass();
 
        header("Cache-Control: no-cache, must-revalidate");
        header("Content-type: application/json; charset=UTF-8");
 
        $password = $c->rsa_decrypt($password);
 
        $user = $c->getUser($userID$password);
        if($user['idx'== 1){ // 로그인 정보가 일치하면
            $_SESSION['userID'= $user['userID'];
            $_SESSION['userNM'= $user['userNM'];
            $_SESSION['admin'= $user['admin'];
 
            $row = array("userNM"=>$user['userNM'],"mobileNO"=>$user['mobileNO'],"profileImg"=>$user['idx']);
 
            $status = "success";
            $message = "";
            $userinfo = $row;
        } else {
            $status = "로그인 에러";
            $message = "다시 한번 시도하시기 바랍니다.";
            $userinfo = null;
        }
 
        $result = array(
            'status' => $status,
            'message' => $message,
            'userinfo' => $userinfo
        );
        echo json_encode($result);
 
    }
else { // 비정상적인 접속인 경우
    echo 0// loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>
 

 

 

 

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

React + PHP Login 처리  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
728x90

React 에서 로그인 처리하는 걸 테스트하고 적어둔다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
 
const Login = () => {
    const navigate = useNavigate();
    const initData = {
        status: '',
        message: '',
        userinfo: {
            userNM: '',
            mobileNO: '',
            profileImg: ''
        }
    }
 
    const [formData, setFormData] = useState(initData);
    const [users, setUsers] = useState([]);
    // 첫번째 원소 : 현재 상태, 두번재 원소 : 상태를 바꾸어 주는 함수
    const [error, setError] = useState(null);
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        // e.target.name 은 해당 input의 name을 가리킨다.
        //console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const params = {
            userID: formData.userID,
            password: formData.password
        }
        console.log(params);
        axios.post('/reactSample/loginChk.php', params)
            .then((res) => {
                console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    setUsers(res.data.userinfo);
                    navigate('/');
                } else {
                    console.log(res.data.message);
                    setError(true);
                }
            })
            .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">Sign In</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userID">userID</label>
                                    <input type="text" name="userID" onChange={onChangeInput} id="userID"
                                           className="form-control form-control-lg" value={formData.userID}
                                           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>
 
                                { error &&
                                <div className="alert alert-danger" role="alert">
                                    로그인 정보를 확인하세요!
                                </div>
                                }
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-primary btn-block btn-lg gradient-custom-3 text-body">로그인
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/register" className="fw-bold text-body"><u>회원가입</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Login;

간혹 보면 "아이디가 존재하지 않는다", "비밀번호가 틀렸다" 라는 문구를 출력하는 경우가 있는데 이런 경우 해커에게 빌미를 제공하는 것이다. 아이디가 있건 없건, 비밀번호가 틀렸든 간에 "로그인 정보가 일치하지 않는다"는 문구 하나로 처리해야 안전하다. (모의 해킹 시 지적사항)

 

Login.js
0.00MB

 

 

아직 전역 상태관리 처리까지는 못해봤다.

전역 상태관리 기준으로 테스트하게되면 업데이트할 예정이다.

 

PHP 로그인 처리 코드

- PHP 코드 결과로 만들어진 JSON 구조를 토대로 useState 초기값 구조를 작성한다.

<?php
// 파일을 직접 실행하는 비정상적 동작을 방지 하기 위한 목적
if(isset($_POST&& $_SERVER['REQUEST_METHOD'== "POST"){
    $_POST = json_decode(file_get_contents("php://input"),true); 
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID&& !empty($userID&& isset($password&& !empty($password)) {
        require_once 'phpclass/dbconnect.php';
        require_once 'phpclass/loginClass.php';
        $c = new LoginClass();
 
        header("Cache-Control: no-cache, must-revalidate");
        header("Content-type: application/json; charset=UTF-8");
 
        $user = $c->getUser($userID$password);
        if($user['idx'== 1){ // 로그인 정보가 일치하면
            $_SESSION['userID'= $user['userID'];
            $_SESSION['userNM'= $user['userNM'];
            $_SESSION['admin'= $user['admin'];
 
            $row = array("userNM"=>$user['userNM'],"mobileNO"=>$user['mobileNO'],"profileImg"=>$user['idx']);
 
            $status = "success";
            $message = "";
            $userinfo = $row;
        } else {
            $status = "로그인 에러";
            $message = "다시 한번 시도하시기 바랍니다.";
            $userinfo = null;
        }
 
        $result = array(
            'status' => $status,
            'message' => $message,
            'userinfo' => $userinfo
        );
        echo json_encode($result);
    }
else { // 비정상적인 접속인 경우
    echo 0// loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>
 

 

 

 

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

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
728x90

json 데이터 구조

{
  "result": [
    {
      "idx"1,
      "userNM""개발자",
      "mobileNO""01000010001",
      "telNO""0234560001",
      "photo""1.jpg"
    },
    {
      "idx"2,
      "userNM""이정은",
      "mobileNO""01001230001",
      "telNO""",
      "photo""2.jpg"
    },
    {
      "idx"3,
      "userNM""김홍길",
      "mobileNO""01001230002",
      "telNO""",
      "photo"""
    },
    {
      "idx"4,
      "userNM""최신형",
      "mobileNO""01001230003",
      "telNO""",
      "photo""4.jpg"
    },
  ]
}

 

React useEffect 함수

const initData = {
    result: {
        idx: 0,
        userNM: '',
        mobileNO: '',
        telNO: '',
        photo: ''
   }
}
const [arrayData, setArrayData] = useState(initData);
 
useEffect( () => {
    const params = {
        idx: 1
    }
    axios.post('http://localhost/reactSample/getContact.php', params)
        .then(res => {
            //console.log(res);
            if (res.status === 200) {
                // console.log(res.data.result);
                setArrayData(res.data.result);
            }
        })
        .catch(error => {
            console.log(error.response)
        });
}, []);
 

구글링을 하면 axios post 방식으로 params 를 넘기는 방식이 다양하게 나오는데 테스트를 해보니 안되더라.

위와 같이 하면 된다.

PHP 에서는 변수를 $data['idx'] 로 인식되더라.

유투브 강의 자료 따라서 할 때 변수를 잘못 인식할 수도 있으니 반드시 테스트가 필요하다.

 

 

npm install 및 import

//npm install --save axios
 
import {useEffect, useState} from "react";
import axios from "axios";

 

 

실전형 REST API 예제

- React 에서 전달받은 데이터를 처리하는 PHP 파일

<?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: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
 
$data = json_decode(file_get_contents("php://input"),true);
 
require_once 'phpclass/config.php';
require_once 'phpclass/dbconnect.php';
require_once 'phpclass/loginClass.php';
$c = new LoginClass();
 
//키워드 확인
if(!isset($data['keyword']) || empty($data['keyword'])){
    $result = array(
        'status' => "fail",
        'message' => "no keyword",
        'addrinfo' => null
    );
    echo json_encode($result);
    exit;
}
 
$keyword=$data['keyword'];
//키워드 일치 확인
if(strcmp($keyword,$mykey)<>0){
    $result = array(
        'status' => "keyfail",
        'message' => "서버와 단말의 KEY가 일치하지 않습니다.",
        'addrinfo' => null
    );
    echo json_encode($result);
    exit;
}
 
 
$column ="idx,userNM,mobileNO,telNO,photo";
$sql = "select idx,userNM,mobileNO,telNO,photo from Person";
if(!empty($search)) {
    $where = "userNM LIKE '%".$search."%' or mobileNO LIKE '%".$search."%'";
else {
    $where = "";
}
 
if(strlen($where> 0){
    $sql .= " where ".$where;
}
 
$R = array(); // 결과 담을 변수 생성
$result = $c->putDbArray($sql);
while($row = $result->fetch_assoc()) {
    $path = "./photos/".$row['photo'];
    if(!file_exists($path)) {
        $row['photo'= "";
    } else {
        $row['photo'];
    }
    array_push($R$row);
}
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: application/json; charset=UTF-8");
 
$status = "success";
$message = "";
$addrinfo = $R// 전체 ArrayList 데이터
 
$result = array(
    'status' => $status,
    'message' => $message,
    'addrinfo' => $addrinfo
);
echo json_encode($result);//배열-문자열등을 json형식의 '문자열'로 변환
?>
 
cs

 

위와 같은 JSON 데이터를 처리하기 위한 React POST 전송 코드 구현 사항

import {useEffect, useState} from "react";
import axios from "axios";
import moment from 'moment';
import * as config from './config';
 
const ListData = () => {
    const today = moment().format('YYYYMMDD');
    const initData = {
        status:'',
        message:'',
        addrinfo: {
            idx: 0,
            userNM: '',
            mobileNO: '',
            telNO: '',
            photo: ''
       }
    }
    const [arrayData, setArrayData] = useState(initData);
 
    useEffect( () => {
        const params = {
            keyword: config.URLKEY + today,
        }
        axios.post('http://localhost/reactSample/getContact.php', params)
            .then(res => {
                //console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    console.log(res.data.addrinfo);
                    setArrayData(res.data.addrinfo);
                } else {
                    console.log(res.data.message);
                }
            })
            .catch(error => {
                console.log(error.response)
            });
    }, []);
 
    // 화면 UI 구성은 생략
    return (
        <div className="container h-100 mt-5">
        </div>
    )
}
 
export default ListData;

 

모듈 설치 사항

npm install --save axios
npm install moment --save

 

 

주의사항

Android APP 과 PHP 간에 주고받은 PHP 파일 형식과 React 대응 PHP 파일 형식이 다르다.

Android/jQuery POST 변수 인식 방법은

if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){

}

로 하면 GET 방식으로 실행하면 내용을 확인할 수가 없다.

그런데 React 대응 PHP 코드는 GET 방식으로도 실행이 된다.

그러므로 keyword 또는 session 처리를 잘 구현해서 PHP 코드를 작성해야 할 것 같다.

 

ListData.js
0.00MB

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

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React + PHP Login 처리  (0) 2022.08.27
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
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- 

 

'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

,