๋ณธ๋ด์ฉ์ ํ์์ " React&Python์ผ๋ก ์น๊ฐ๋ฐ(๋งํฌ์๋น์ค) " ์นดํ
๊ณ ๋ฆฌ ๊ฐ๋ฐ์์ค์ ์ถ๊ฐํ๋ ๋ฐฉ์์ผ๋ก ์งํํฉ๋๋ค.
( ์์ค ํด๋๋ ์ ์นดํ
๊ณ ๋ฆฌ๋ฅผ ์ ์ฝ์ด๋ณด๊ณ , git ์์ค๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค. )
์ง๋ํธ์์๋ http://localhost:3000 ์ ๊ทผ์ ๋ฐ๋ก ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋์ค๋๋ก ์ฒ๋ฆฌํ๊ณ ,
์ด๋ฒํธ์๋ admin ๋ฒํผ ํด๋ฆญ ํน์ ๋ก๊ทธ์ธ ์์ด์ฝ์ ํด๋ฆญ ํ ๋ Keycloak ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋์ค๋๋ก ์์ ํด๋ณด์.
์ด์ ์ material-icons๋ฅผ ํตํ menu.jsx๋ฅผ ์ ์ํ๋ค. ์๋ ์ด์ ๊ธ ์ฐธ๊ณ ๋ฐ๋๋๋ค.
#14. material-icons ๋ฅผ ํตํ ๋ฉ๋ดํ๋ฉด
#14. material-icons ๋ฅผ ํตํ ๋ฉ๋ดํ๋ฉด
๋ฑ๋กํ๋ฉด์ ์๋ฃ๋์์ผ๋, ์ด์ ํธ์งํ๋ฉด์ ๊ฐ๋ฐํด ๋ณด์. #13. ๋ฑ๋กํ๋ฉด์์ ๋ด์ฉ ์ ์ฅ ๋ฐ ์ด๋ฏธ์ง ์ ์ฅ ๊ธฐ๋ฅ ๊ตฌํ #13. ๋ฑ๋กํ๋ฉด์์ ๋ด์ฉ ์ ์ฅ ๋ฐ ์ด๋ฏธ์ง ์ ์ฅ ๊ธฐ๋ฅ ๊ตฌํ #12. React์์ Drag & Drop์
firstvalue.tistory.com
๊ธฐ์กด menu.jsx ์ SettingsIcon ํด๋ฆญ์ Keycloak์ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํ๋๋ก ์์ ํ๋ค.
์ด 3๊ฐ์ ์์ค๋ฅผ ์์ ํ ์์ ์ด๋ค.
1. menu.jsx
2. App.js
3. index.js
โ menu.jsx ( ์์น : linkservice/client/src/component/menu.jsx )
---------------------------------------------------------------------------------------------------
์ฐ์ react-keycloak/web ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ตฌ์ฑ์์๊ฐ Keycloak์ Accessํด์ผํ๋ ๊ฒฝ์ฐ
useKeycloak Hook๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
import { useKeycloak } from "@react-keycloak/web";
useKeycloak๊ตฌ์กฐํ๋ ๊ฐ์ฒด๋ฅผ Destructuring ํ์ฌ ๊ฐ๋ณ์ ์ธ ๋ณ์์ ํ ๋นํ๋ค.
const { keycloak } = useKeycloak();
์ด๋ ๊ฒ ํจ์ผ๋ก์จ, ๋ชจ๋ keycloak ๋ฉ์๋ ๋ฐ ๋ณ์์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
handleIcon ์ด๋ฒคํธ์ keycloak.authenticated (์ธ์ฆ์ด๋์๋์ง) ์ ๋ฐ๋ผ ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ํธ์ถํด๋ณด์.
// keycloak์ ๋ก๊ทธ์ธ์ด ๋์ด ์์ง ์๋ค๋ฉด, keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ
if (!keycloak.authenticated) {
alert("๋ก๊ทธ์ธ์ด ํ์ํ ์๋น์ค์
๋๋ค.")
// keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ
keycloak.login();
}
์์ ๊ฐ์ด handle ์ด๋ฒคํธ์ ๋ฐ๋ผ ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ํธ์ถํ ์์์ผ๋ฉฐ,
์ด๋ฏธ ๋ก๊ทธ์ธ์ด ๋์๋ค๋ฉด ๊ด๋ฆฌ์ ํ๋ฉด์ผ๋ก ๋ฐ๋ก ์ด๋์ด ๊ฐ๋ฅํ๋ค.
์ ๋ด์ฉ์์ ์ถ๊ฐ์ ์ผ๋ก keycloak.login() ํ ๊ธฐ๋ณธ redirect-uri ์ด http://localhost:3000 ์ด๋ค.
์ฆ, ๊ด๋ฆฌ์ ํ๋ฉด์ผ๋ก ์ด๋์ ๋ก๊ทธ์ธ ํ ๋ฐ๋ก ์ด๋์ด ์๋๊ณ , ์ดํ๋ฉด์ด ๋์จ๋ค๋ ๋ป์ด๋ค.
๊ทธ๋์ redirect-uri๋ฅผ ๊ด๋ฆฌ์ ํ๋ฉด์ผ๋ก ์ง์ ์ด ๊ฐ๋ฅํ๋ค.
// keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ์ redirectUri๋ฅผ ๊ฐ์ธํ๊ฐ ๊ฐ๋ฅํ๋ค.
keycloak.redirectUri= window.location.href + '/manager'
์์ ๋ menu.jsx
import HomeIcon from '@mui/icons-material/Home';
import SettingsIcon from '@mui/icons-material/Settings';
import { useNavigate } from 'react-router-dom';
// useKeycloak import
import { useKeycloak } from "@react-keycloak/web";
export default function MenuIcon(props) {
const navigator = useNavigate()
// Using Object destructuring
const { keycloak } = useKeycloak();
const handleIcon = (e) => {
switch (e) {
case 'A' :
// keycloak์ ๋ก๊ทธ์ธ์ด ๋์ด ์์ง ์๋ค๋ฉด, keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ
if (!keycloak.authenticated) {
alert("๋ก๊ทธ์ธ์ด ํ์ํ ์๋น์ค์
๋๋ค.")
// keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ์ redirectUri๋ฅผ ๊ฐ์ธํ๊ฐ ๊ฐ๋ฅํ๋ค.
keycloak.redirectUri= window.location.href + '/manager'
// keycloak ๋ก๊ทธ์ธ ํ์ด์ง ํธ์ถ
keycloak.login();
}
return navigator('/manager')
case 'M' : return navigator('/')
default : return navigator('/')
}
}
return (
<>
<div className='menu-wrap'>
<div className='menu-box'>
<HomeIcon fontSize='large' color="secondary"
onClick={() => handleIcon('M')}
/>
<SettingsIcon fontSize='large' color="secondary"
onClick={() => handleIcon('A')}
/>
</div>
</div>
</>
)
}
โ App.js ( ์์น : linkservice/client/src/App.js )
---------------------------------------------------------------------------------------------------
์ด์ App.js ์์ค๋ด์์๋ ReactKeycloakProvider์ initOptions ์ ์ ์ธํ๋ค.
onEvent={onKeycloakEvent} ๋ ์ ์ธํด๋ ๋๋, ๊ฐ๋ฐ์ ๋ชจ๋์์ refressToken๊ฐ ํ์ธ ์ฐจ์์์
๋ฐ์ํด ๋๋ค.
์์ ๋ App.js
import React from "react"
import { BrowserRouter, Route, Routes } from "react-router-dom"
import LinkMain from "./component/links"
import LinkCreateMain from "./component/links.create"
import ManagerHome from "./component/manager"
import MenuIcon from "./component/menu"
import LinksList from "./component/links.list"
import LinkEdit from "./component/links.edit"
import { ReactKeycloakProvider } from "@react-keycloak/web";
import keycloak, { onKeycloakEvent } from "./keycloak";
import PrivateRoute from "./PrivateRoute";
// import { onKeycloakEvent } from "./keycloak"
function App() {
return (
// ๊ธฐ์กด BrowserRouter ๋ฐ์ ReactKeycloakProvider๋ฅผ ์ ์ธํ๋ค.
// initOptions์ ์ํด์ http://localhost:3000 ์ผ๋ก ์ ์์ keycloak ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋๋๋ค.
<ReactKeycloakProvider authClient={keycloak} onEvent={onKeycloakEvent} >
{/* initOptions={initOptions} > ์ ์ธ์ํจ๋ค. */}
<BrowserRouter>
<Routes>
<Route exact path="/" element={<LinkMain />} />
{/* PrivateRoute๋ฅผ ํตํด ๋ก๊ทธ์ธ์ด ๋ ์ํ์์๋ง ํ์ด์ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ฒ ์ฒ๋ฆฌ */}
<Route exact path="/create" element={<PrivateRoute> <LinkCreateMain /> </PrivateRoute>} />
<Route exact path="/manager" element={<PrivateRoute> <ManagerHome /> </PrivateRoute>} />
<Route exact path="/links/list" element={<PrivateRoute> <LinksList /> </PrivateRoute>} />
<Route exact path="/link/edit/:id" element={<PrivateRoute> <LinkEdit /> </PrivateRoute>} />
</Routes>
<MenuIcon />
</BrowserRouter>
</ReactKeycloakProvider>
);
}
export default App;
โ index.js ( ์์น : linkservice/client/src/index.js )
---------------------------------------------------------------------------------------------------
๊ธฐ์กด index.js์์ <React.StrictMode> ๋ง ์ ์ธํ๋ค.
StrictMode๊ฐ ์์ผ๋ฉด http://localhost:3000 ์ ์์ ๋ฌดํ๋ก๋ฉ์ด ๋๋ฏ๋ก, ํด๋น StictMode๋ฅผ ๋นผ์ค๋ค.
์์ ๋ index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
// import './index.css';
import App from './App';
// import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// <React.StrictMode> ์ ์ธ์ํจ๋ค.
<App />
// </React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
// reportWebVitals();
๊ทธ๋ผ ์๋ฒ๋จ๊ณผ ํด๋ผ์ด์ธํธ๋จ์ ์คํํด์ ์ ์์ ์ผ๋ก ๋ฐ์์ด ๋์๋์ง ํ์ธํด๋ณด์.
linkservice ํ๋ฉด
์ ์์ ์ธ ํ์ด์ง๊ฐ ๋์จ๋ค๋ฉด ํ๋จ SettingIcon์ ํด๋ฆญํ๋ค.
linkservice ํ๋ฉด
ํ์ธ์ ๋๋ฅด๋ฉด Keycloak์ ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋์ค๋๊ฒ์ ํ์ธํ ์ ์๋ค.
keycloak ๊ธฐ๋ณธ ๋ก๊ทธ์ธ ํ๋ฉด
๋ค์์๋ ๋ก๊ทธ์ธํ token๊ฐ ๋ฐ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋๊ฒ์ ์์๋ณด์.