관리 메뉴

CASSIE'S BLOG

[비공개] 3차 프로젝트 api, client, admin 각각 프로젝트 취합 회고록 본문

PROGRAMMING/프로젝트

[비공개] 3차 프로젝트 api, client, admin 각각 프로젝트 취합 회고록

ITSCASSIE1107 2024. 1. 15. 22:49

어드민 아이디 비밀번호인지 클라이언트 에서 서버로 데이터를 보내서 확인이 되면 그 다음에 라우팅을 할 수 있는거야? window.location.href를 이용해서

 

로그인 기능을 구현하고, 서버에서 아이디와 비밀번호를 확인한 후에 클라이언트에서 원하는 페이지로 리다이렉션할 수 있습니다. 일반적으로는 로그인 요청이 서버로 전송되고, 서버에서는 해당 정보를 확인한 후 토큰이나 세션 등의 방법을 사용하여 로그인 상태를 유지합니다.

다음은 간단한 예시입니다:

 

 


// 예시: 로그인 함수
const handleLogin = async () => {
  try {
    // 로그인 요청 서버로 전송
    const response = await fetch('https://yourserver.com/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        username: 'admin',
        password: 'admin123',
      }),
    });

    // 서버 응답 확인
    if (response.ok) {
      // 로그인 성공 시 서버에서 받은 정보에 따라 처리
      const data = await response.json();

      // 예시: 서버에서 받은 토큰을 사용하여 로그인 상태 유지
      // setToken(data.token);

      // 로그인 후 클라이언트 사이드 라우팅
    } else {
      // 로그인 실패 처리
      console.error('로그인 실패');
    }
  } catch (error) {
    console.error('로그인 에러', error);
  }
};

 

 

위의 코드는 클라이언트에서 서버로 로그인 요청을 보내고, 서버에서는 해당 정보를 확인한 후 로그인이 성공하면 클라이언트를 어드민 페이지로 리다이렉션하는 예시입니다. 로그인이 성공하면 서버에서 받은 정보를 활용하여 로그인 상태를 유지하고, 그에 따라 클라이언트 사이드 라우팅을 진행합니다.

 

일반적인 방식이라고 함.

 

이 코드는 클라이언트에서 서버로 사용자 인증 정보를 전송하여 로그인을 시도하고, 서버에서 응답에 따라 클라이언트를 리다이렉션하는 일반적인 방식의 예시입니다. 이러한 방식은 주로 서버 측에서 사용자의 신원을 확인하고, 성공 시 토큰 등을 발급하여 클라이언트 측에서 상태를 유지하는 방법 중 하나입니다.

여기서 주요 포인트는:

  1. 로그인 요청:
    • fetch 함수를 사용하여 서버에 로그인 요청을 보냅니다.
    • POST 메서드를 사용하고, Content-Type 헤더를 통해 JSON 형식의 데이터를 전송합니다.
  2. 서버 응답 확인:
    • response.ok를 통해 서버의 응답 상태를 확인합니다.
    • 응답이 성공적이면 로그인이 성공했다고 가정하고 처리를 진행합니다.
  3. 클라이언트 리다이렉션:
    • 성공적인 로그인 후, 서버에서 받은 정보에 따라 클라이언트 사이드에서 리다이렉션을 수행합니다.
    • 여기서는 window.location.href를 사용하여 새로운 URL로 이동합니다.
  4. 에러 처리:
    • try-catch 블록을 사용하여 비동기 작업 중 발생할 수 있는 에러를 처리합니다.
    • 로그인 실패 시에는 콘솔에 에러 메시지를 출력하고 추가적인 처리를 수행할 수 있습니다.

이러한 방식은 많은 웹 어플리케이션에서 사용되는 일반적인 패턴 중 하나입니다. 다만, 실제로는 더 복잡한 로그인 시나리오와 보안적인 고려 사항을 고려하여 구현되어야 합니다. 특히, 비밀번호 보안, 토큰의 안전한 저장 및 전송, 세션 관리 등에 대한 신경을 써야 합니다.

 

각각 배포하고 해야할 일. 

admin, client일단 배포할 것 github pages 둘다 url필요하니까. 

 

아니..! 고친 것들 여기에 정리함

 

4시간 날렸다 ㅠㅠㅠㅠ

 

🎈client 사이드 🎈

 

 

heroku logs --tail 에러 계속 났는데 

 

🎈해결법 1 client사이드에 proxy 설정 (heroku 설정)

계속 heroku에서 push 해서 client 홈페이지 모양이 안나오는데 당연한거임

왜냐면 백엔드만 heroku에 배포했기 때문임.

 

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.12.3",
    "@material-ui/icons": "^4.11.2",
    "@reduxjs/toolkit": "^1.6.1",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "axios": "^1.6.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-error-overlay": "6.0.9",
    "react-redux": "^7.2.5",
    "react-router-dom": "^6.0.0",
    "react-scripts": "4.0.3",
    "react-stripe-checkout": "^2.6.3",
    "redux-persist": "^6.0.0",
    "styled-components": "^5.3.1",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/plugin-proposal-private-property-in-object": "^7.21.11"
  }
}

 

 

Error: ENOENT: no such file or directory, stat '/app/client/build/index.html'

 

이 에러가 미친듯이 남.

 

api사이드 최종으로 이렇게 함. 근데 이게 중요한게 아니라 

컴포넌트 별로 axios로 local port 연결된 부분 다 heroku 주소로 옮겨야함

 

const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const userRoute = require("./routes/user");
const authRoute = require("./routes/auth");
const productRoute = require("./routes/product");
const cartRoute = require("./routes/cart");
const orderRoute = require("./routes/order");
const stripeRoute = require("./routes/stripe");
const cors = require("cors");
const path = require("path");

dotenv.config();

mongoose
  .connect(process.env.MONGO_URL)
  .then(() => console.log("DB Connection Successful!"))
  .catch((err) => {
    console.log(err);
  });

app.use(cors());
app.use(express.json());
app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.use("/api/products", productRoute);
app.use("/api/carts", cartRoute);
app.use("/api/orders", orderRoute);
app.use("/api/checkout", stripeRoute);



if (process.env.NODE_ENV === 'production') {
  app.use(express.static( 'client/build'));

  app.get('*', (req, res) =>
    res.sendFile(
      path.resolve(__dirname, '../client', 'build', 'index.html')
    )
  );
} else {
  app.get('/', (req, res) => {
    res.send('200');
  });
}

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Backend server is running on port ${PORT}!`);
});

 

 

api 사이드 변경

🎈 처음에는 백엔드 주소만 연결했는데 /api/ 까지 설정을 해주어야했음 

 

 

🎈  products 컴포넌트도 백엔드 배포한 것으로 설정

 

 

 

240127

 

여기서 비밀번호 admin 아이디 admin으로 로그인하면 어드민탭이 생기고 어드민 프로젝트로 넘어가게해야해 데이터베이스 구조는 이거야 
isAdmin 속성으로 admin인지 아닌지 확인하고있어 

_id
65504472315cb9c975dd2536
username
"changeduser"
email
"cassie@gmail.com"
password
"U2FsdGVkX1/+gea/HmAGTCFIpcKkAnInYCFX7TQHrN8="
isAdmin
false
createdAt
2023-11-12T03:20:18.096+00:00
updatedAt
2023-11-12T08:26:17.989+00:00
__v
0

이건 코드야 뭐 어떤거를 추가해야하는지 조언 좀 해줘 

import { Badge } from "@material-ui/core";
import { Search, ShoppingCartOutlined } from "@material-ui/icons";
import React from "react";
import styled from "styled-components";
import { mobile } from "../responsive";
import { useDispatch, useSelector } from "react-redux";
import { Link, useNavigate } from 'react-router-dom';
import { logout } from "../redux/userRedux";




const Container = styled.div`
  height: 60px;
  ${mobile({ height: "50px" })}
`;

const Wrapper = styled.div`
  padding: 10px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  ${mobile({ padding: "10px 0px" })}
`;

const Left = styled.div`
  flex: 1;
  display: flex;
  align-items: center;
`;

const Language = styled.span`
  font-size: 14px;
  cursor: pointer;
  ${mobile({ display: "none" })}
`;

const SearchContainer = styled.div`
  border: 0.5px solid lightgray;
  display: flex;
  align-items: center;
  margin-left: 25px;
  padding: 5px;
`;

const Input = styled.input`
  border: none;
  ${mobile({ width: "50px" })}
`;

const Center = styled.div`
  flex: 1;
  text-align: center;
`;

const LogoLink = styled(Link)`
  text-decoration: none;
`;

const Logo = styled.h1`
  font-weight: bold;
  text-decoration: none;
  ${mobile({ fontSize: "24px" })}
`;
const Right = styled.div`
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  ${mobile({ flex: 2, justifyContent: "center" })}
`;

const MenuItem = styled.div`
  font-size: 14px;
  cursor: pointer;
  margin-left: 25px;
  ${mobile({ fontSize: "12px", marginLeft: "10px" })}
`;

const Navbar = () => {

  const dispatch = useDispatch();
  const user = useSelector((state) => state.user.currentUser);
  const quantity = useSelector(state => state.cart.quantity);
  const navigate = useNavigate();

  const handleSignInClickToLogin = () => {
    //NOTE: SIGN IN 클릭 시 /login 으로 이동
    navigate('/login');
  };

  const handleSignInClickToRegister = () => {
    //NOTE: SIGN IN 클릭 시 /login 으로 이동
    navigate('/register');
  };



  const handleLogout = () => {
    // 로그아웃 액션 디스패치
    dispatch(logout());
  };


  return (
    <Container>
      <Wrapper>
        <Left>
          <Language>EN</Language>
          <SearchContainer>
            <Input placeholder="Search" />
            <Search style={{ color: "gray", fontSize: 16 }} />
          </SearchContainer>
        </Left>
        <Center>
        <LogoLink to="/">
            <Logo>Cassie</Logo>
          </LogoLink>
        </Center>
        <Right>
          {user ? (
            <>
              {/* 로그인 된 경우에 표시되어야 할 JSX 코드 */}
              <MenuItem onClick={handleLogout}>LOGOUT</MenuItem>
            </>
          ) : (
            <>
              <MenuItem onClick={handleSignInClickToRegister} >REGISTER</MenuItem>
              <MenuItem onClick={handleSignInClickToLogin}>SIGN IN</MenuItem>
            </>
          )}
          <Link to="/cart">
            <MenuItem>
              <Badge badgeContent={quantity} color="primary">
                <ShoppingCartOutlined />
              </Badge>
            </MenuItem>
          </Link>
        </Right>
      </Wrapper>
    </Container>
  );
};

export default Navbar;


반응형

'PROGRAMMING > 프로젝트' 카테고리의 다른 글

자바스크립트 리팩토링 팁  (0) 2024.03.04
아이콘 사이트  (0) 2024.01.30
Swagger 사용법  (0) 2024.01.01
프로젝트 admin 페이지  (0) 2023.12.31
라우팅 회고  (0) 2023.12.28