React ๋ก๊ทธ์ธ ์ฒ๋ฆฌ๋ ํ์์ " React&Python์ผ๋ก ์น๊ฐ๋ฐ(๋งํฌ์๋น์ค)" ์นดํ ๊ณ ๋ฆฌ ๊ฐ๋ฐ์์ค์
์ถ๊ฐํ๋ ๋ฐฉ์์ผ๋ก ์งํํฉ๋๋ค.
( ์์ค ํด๋๋ ์ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ ์ฝ์ด๋ณด๊ณ , git ์์ค๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค. )
1. ์ฌ์ฉ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค
โถ๏ธ keycloak-js
โถ๏ธ @react-keycloak/web
์ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๋ค.
์๋ ํฌ์คํ ์์ ํด๋๊ตฌ์กฐ๋ฅผ ํ์ธํ๊ณ , ํฐ๋ฏธ๋ ์ ์ด์ด ~>linserver/client ์์ react ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๋ค.
#4. ํ๋ก์ ํธ ํด๋ ๊ตฌ์กฐ ๋ฐ ํ๊ฒฝ์ค์
#4. ํ๋ก์ ํธ ํด๋ ๊ตฌ์กฐ ๋ฐ ํ๊ฒฝ์ค์
1.1. ํ๋ก์ ํธ ํด๋ ๊ตฌ์กฐ ๋ฐ ํ๊ฒฝ์ค์ ํ๋ก์ ํธ ํด๋ ๊ตฌ์กฐ๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๋ฅผ ๋๋๊ณ ์ client / server๋ก ๊ตฌ๋ถ ํ๋ค. โฎํ๋ก์ ํธ ํด๋ : linkserver/ |-------- client ( React ๊ตฌ์กฐ) |-------- server ( Python๊ตฌ
firstvalue.tistory.com
$ yarn add keycloak-js
$ yarn add @react-keycloak/web
2. React์ Keycloak ์ค์
โ keyclaok.js ( ์์น: linkservice/client/src/keycloak.js)
----------------------------------------------------------------------------------------------
keyclaok์ค์ ์ ์ํด์ keycloak.js ํ์ผ์ ์์ฑํ๋ค.
import Keycloak from "keycloak-js";
//์ด์ ํฌ์คํ
์ Keycloak ์ฌ์ฉ์ ์์ด๋์ ํด๋ผ์ด์ธํธ ์์ฑ์ ์ฐธ๊ณ ํ์ฌ ์๋ ์ค์
const keycloak = new Keycloak({
realm: 'aip',
url: 'http://localhost:8080/',
clientId: 'testClient',
});
// initOption ์ง์
export const initOptions = {
onLoad: 'login-required',
checkLoginIframe: false,
};
export const onKeycloakEvent = (event, error) => {
// console.log('keycloak event ', event, error);
switch (event) {
case 'onAuthLogout':
keycloak.logout();
break;
case 'onAuthRefreshError':
keycloak.logout();
break;
case 'onAuthRefreshSuccess':
//๊ฐ๋ฐ๊ณ์์๋ง ์ฌ์ฉ, ์ค์ ์ด์๊ณ์์๋ ์ ์ธ
console.log('auth token: ' + keycloak.token);
console.log('refresh token: ' + keycloak.refreshToken);
break;
default:
break;
}
};
export default keycloak;
const keycloak = new Keycloak({
realm: 'aip',
url: 'http://localhost:8080/',
clientId: 'testClient',
});
ํด๋น ์ค์ ์ ์๋ ์ด๋ฏธ์ง์ฒ๋ผ keycloak ์ Client์์ ์ค๋ฅธ์ชฝ ์๋จ Action ํ์ ํ์ดํ๋ฅผ ํด๋ฆญํ๋ฉด "Download adapter config ํ๋ฉด์์ ํ์ธ์ด ๊ฐ๋ฅํ๋ค. ( reaml, url, clientid ํค ๋ช ์นญ์ด ๋ค๋ฅด์ง๋ง ๋ฌธ์ ์๋ค. )

initOptions๊ณผ onKeycloakEvent๋ App.js์์ ReactKeycloakProvider ์ ์ถ๊ฐํ๊ธฐ ์ํด์ ์ ์ธํ๋ค.
initOptions
keycloak ๋ก๊ทธ์ธ๋ฐฉ์์ ๋ํด์ ์ค์ ์ผ๋ก onLoad
- login-required : ์ฌ์ฉ์๊ฐ Keycloak์ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ๋ฅผ ์ธ์ฆํ๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ํ์.
- check-sso : ์ด๋ฏธ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ์๋ง ํด๋ผ์ด์ธํธ๋ฅผ ์ธ์ฆํ๊ณ , ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ์ง ์์ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ๋ค์ ๋ฆฌ๋๋ ์ ๋๊ณ ์ธ์ฆ๋์ง ์์ ์ํ๋ก ์ ์ง.
์ฌ๊ธฐ๋ App.js์ ReactKeycloakProvider ํํ๋ก ์ ๊ณตํ๊ธฐ ์ํด์ login-required ๋ก ์ฒ๋ฆฌํ๋ค.
( ์ฆ, ํน์ ํ์ด์ง ์ด๋์ ๋ก๊ทธ์ธ์ด ์๋์ด ์์ผ๋ฉด ๋ก๊ทธ์ธ ํ์ด์ง๋ฅผ ํ์ํ๋๋ก ์ฒ๋ฆฌ )
onKeycloakEvent
keycloak event๋ฅผ ์ค์ ํ๋ฉฐ, Provider์ ์ง์ ํ์ฌ event์ ๋ง๋ค ์ฒ๋ฆฌ ๋ด์ฉ์ ์ ์ธํ๋ค. ์๋ default๊ฐ์ผ๋ก ๊ทธ๋๋ก ๋ฐ์ํด๋ ๋ฌด๋ฐฉํ๋ค.
3. PrivateRoute.js ์์ฑ
โ PrivateRoute.js ( ์์น: linkservice/client/src/PrivateRoute.js)
----------------------------------------------------------------------------------------------
Keycloak์ ๋ก๊ทธ์ธ์ด ๋์ด ์๋์ง ํ์ธํ๊ณ ์ Route๋ฅผ ์ง์ ํ๊ธฐ ์ํด์ ์์ฑํ๋ค.
import { useKeycloak } from "@react-keycloak/web";
const PrivateRoute = ({ children }) => {
const { keycloak } = useKeycloak();
//keycloak์ ๋ก๊ทธ์ธ์ด ๋์ด ์๋์ง ํ์ธํ๋ค.
const isLoggedIn = keycloak.authenticated;
return isLoggedIn ? children : null;
};
export default PrivateRoute;
3. App.js ์ ReactKeyclaokProvider ์ PrivateRoute ๋ฐ์
โ App.js ( ์์น: linkservice/client/src/App.js)
----------------------------------------------------------------------------------------------
๊ธฐ์กด 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 , { initOptions, onKeycloakEvent } from "./keycloak";
import PrivateRoute from "./PrivateRoute";
function App() {
return (
// ๊ธฐ์กด BrowserRouter ๋ฐ์ ReactKeycloakProvider๋ฅผ ์ ์ธํ๋ค.
// initOptions์ ์ํด์ http://localhost:3000 ์ผ๋ก ์ ์์ keycloak ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋๋๋ค.
<ReactKeycloakProvider authClient={keycloak}
initOptions={initOptions} onEvent={onKeycloakEvent}>
<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;
๊ทธ๋ผ http://localhost:3000 ์ผ๋ก ์ ์ํ๋ฉด Keycloak์ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ ๋๋ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
์ฌ๊ธฐ์์ ๊ธฐ์กด์(์ด์ ํฌ์คํธ์์) ์์ฑํ๋ ์ฌ์ฉ์๋ก ๋ก๊ทธ์ธ์ ํ๋ฉด ๋๋ค.

๋ค์ํธ์๋ http://localhost:3000 ์ ๊ทผ์ ๋ฐ๋ก ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋์ค์ง ์๊ณ ,
admin ๋ฒํผ ํด๋ฆญ ํน์ ๋ก๊ทธ์ธ ์์ด์ฝ์ ํด๋ฆญ ํ ๋ ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ๋์ค๋๋ก ์์ ํด๋ณด์.