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(11) NOT NULL,
`name` varchar(50) CHARACTER SET utf8mb3 NOT NULL,
`email` varchar(50) CHARACTER SET utf8mb3 NOT NULL,
`password` varchar(200) CHARACTER 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(11) NOT NULL AUTO_INCREMENT, AUTO_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 |