๋ณธ๋‚ด์šฉ์€ ํ•„์ž์˜ " 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๊ฐ’ ๋ฐ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๊ฒƒ์„ ์•Œ์•„๋ณด์ž.

+ Recent posts