React

[TIL/React] 2023/10/05

๋ฐ˜์‘ํ˜• ๐ŸŸขpx(ํ”ฝ์…€)๊ณผ ๊ฐ™์€ ๊ณ ์ • ๋‹จ์œ„๋ฅผ ์“ฐ๋ฉด ์œ„์™€ ๊ฐ™์ด ์ฒ˜์ฐธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.์ˆ˜์ • ํ›„ ๋ชจ์Šต ๐ŸŸข์ฝ”๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•œ๋ฐ, ์˜ค๋Š˜์€ ๋„์ €ํžˆ ํž˜์ด ๋‚˜์ง€ ์•Š๋Š”๋‹ค. handleDirectClick ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด, ๋กœ๊ทธ์ธ์ด ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด logi

2023๋…„ 10์›” 5์ผ2min read

๋ฐ˜์‘ํ˜• ๐ŸŸข

px(ํ”ฝ์…€)๊ณผ ๊ฐ™์€ ๊ณ ์ • ๋‹จ์œ„๋ฅผ ์“ฐ๋ฉด ์œ„์™€ ๊ฐ™์ด ์ฒ˜์ฐธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.

code
import React from "react";
import { useParams, useLocation, useNavigate } from "react-router-dom";
import styled from "@emotion/styled";
import { shoppingData } from "../data/ShoppingCategory_Pork";
import ComponentWrapper from "../components/common/ComponentWrapper";
import { useSelector } from "react-redux";

const ProductDetailPageBackgroundStyle = styled.div`
  background-color: #181818;
  width: 100%;
  /* height: 100vh; */
`;

const AllContentWrapper = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
  /* flex-grow: 1; */
  /* background-color: white; */
  @media (max-width: 900px) {
    flex-wrap: wrap;
    column-gap: 20px;
  }
`;

const ProductDetailPageImgWrapper = styled.div`
  /* height: 70%;
  width: 50%; */
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: white;
`;

const ProductImg = styled.img`
  width: 80%;
  height: 80%;
`;

const ProductDetailPageInfoWrapper = styled.div`
  /* width: 50%;
  height: 70%; */
  display: flex;
  flex-direction: column;
  background-color: blue;
`;

const ProductDetailPageInfoDataWrapper = styled.div`
  height: 30%;
`;

const InfoDataTitle = styled.p`
  font-size: 30px;
  color: white;
  font-weight: bolder;
`;

const InfoDataEtc = styled.p`
  font-size: 20px;
  color: white;
  font-weight: bolder;
`;

const OptionWrapper = styled.div`
  display: flex;
  align-items: center;
  column-gap: 20px;
  height: 20%;
  color: white;
`;

const AmountWrapper = styled.div`
  display: flex;
  align-items: center;
  column-gap: 20px;
  height: 20%;
  color: white;
`;

const ButtonWrapper = styled.div`
  width: 100%;
  background-color: orange;
  display: flex;
  height: 30%;
  justify-content: space-evenly;
  align-items: center;
`;

const ProductDetailPage = () => {
  const navigate = useNavigate();
  const { id } = useParams();
  const location = useLocation();
  const category = location?.state;
  const check = useSelector((state) => state.auth);
  console.log(check);

  const handleDirectClick = () => {
    if (check.isAuthenticated) {
      console.log("๊ฒฐ์ œํ™”๋ฉด์œผ๋กœ");
    } else {
      navigate("/login");
    }
  };

  const MapData = shoppingData[category];
  const DetailData = MapData.find((elem) => elem?.id === id);
  const ImgSrc = DetailData.image;

  console.log(location);
  console.log(DetailData);
  console.log(ImgSrc);

  return (
    <>
      <ProductDetailPageBackgroundStyle>
        {/*  */}
        <ComponentWrapper style={{ height: "100%" }}>
          <AllContentWrapper>
            {/* image area */}
            <ProductDetailPageImgWrapper>
              <ProductImg src={ImgSrc} />
            </ProductDetailPageImgWrapper>
            {/* info area */}
            <ProductDetailPageInfoWrapper>
              <ProductDetailPageInfoDataWrapper>
                <InfoDataTitle>{DetailData?.subtitle}</InfoDataTitle>
                <InfoDataEtc>
                  {DetailData?.price} ({DetailData?.weight})
                </InfoDataEtc>
                <p></p>
              </ProductDetailPageInfoDataWrapper>

              <OptionWrapper>
                <span style={{ color: "white", fontWeight: "bolder" }}>
                  ์˜ต์…˜
                </span>
                <div style={{ border: "2px solid orange" }}>
                  fdsagfagfdagfdgfda
                </div>
              </OptionWrapper>
              <AmountWrapper>
                <span style={{ color: "white", fontWeight: "bolder" }}>
                  ์ˆ˜๋Ÿ‰
                </span>
                <div style={{ border: "2px solid orange" }}>
                  fdsagfagfdagfdgfda
                </div>
              </AmountWrapper>

              <ButtonWrapper>
                <button
                  style={{
                    backgroundColor: "#7f7776",
                    color: "white",
                    width: "200px",
                    height: "60px",
                    border: "none",
                  }}
                  onClick={handleDirectClick}
                >
                  ๋ฐ”๋กœ๊ตฌ๋งค
                </button>
                <button
                  style={{
                    backgroundColor: "#c50f22",
                    color: "white",
                    width: "200px",
                    height: "60px",
                    border: "none",
                  }}
                >
                  ์žฅ๋ฐ”๊ตฌ๋‹ˆ
                </button>
              </ButtonWrapper>
            </ProductDetailPageInfoWrapper>
          </AllContentWrapper>
        </ComponentWrapper>
      </ProductDetailPageBackgroundStyle>
    </>
  );
};

export default ProductDetailPage;

์ˆ˜์ • ํ›„ ๋ชจ์Šต ๐ŸŸข

์ฝ”๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•œ๋ฐ, ์˜ค๋Š˜์€ ๋„์ €ํžˆ ํž˜์ด ๋‚˜์ง€ ์•Š๋Š”๋‹ค. handleDirectClick ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด, ๋กœ๊ทธ์ธ์ด ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด login page๋กœ ์ด๋™ํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

ํšŒ๊ณ  ๐ŸŸข

1) ์ƒ๋Œ€์ ์ธ ๋‹จ์œ„๋ฅผ ์จ์•ผ ๋ด‰๋ณ€์„ ๋ฉดํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊นจ๋‹ฌ์•˜๋‹ค. 2) 1๋ฒˆ์€ ์‚ฌ์‹ค ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, container ๋‹จ์œ„๋กœ ์ƒ๋Œ€ ๋‹จ์œ„๋ฅผ ์จ์•ผ ํ•จ์„ ๋‹ค์‹œ๊ธˆ ๊นจ๋‹ฌ์•˜๋‹ค. 3) ๋ฌธ์ œ๋Š” 2๋ฒˆ์—์„œ ๋А๋‚€ ์ ์ด ๋งž๋Š” ๊ฒƒ์ธ์ง€ ์˜๋ฌธ์ด๋‹ค. 4) ๊ทธ๋ž˜๋„ ๋Œ€๊ฐ• ๊ตฌ์กฐ๋ฅผ ์žก์•˜์œผ๋‹ˆ, ์žฅ๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ์Šฌ์Šฌ ๋งŒ๋“ค๋„๋ก ํ•˜์ž.

More to read

REST API

ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ์‚ฌ์ด

HTTP ์ƒํƒœ ์ฝ”๋“œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐฑ์—”๋“œ๋กœ ๋ณด๋ƒˆ๋˜ ์š”์ฒญ์˜ ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์˜๋ฏธํ•˜๋Š” ์ผ์ข…์˜ ์•ฝ์†์ด๋ฉฐ, API๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ•ต์‹ฌ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ƒํƒœ ์ฝ”๋“œ์™€ ๊ด€๋ จํ•˜์—ฌ, ๋ฐฑ์—”๋“œ๋Š” ์ž˜ ๋ชจ๋ฅด๋Š” ํ”„๋ก ํŠธ์—”๋“œ์˜ ์Šฌํ”ˆ ์‚ฌ์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค.์•„๋ž˜๋Š” ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์Œ์—๋„, ๋ฐฑ์—”๋“œ์—์„œ ์ƒํƒœ ์ฝ”๋“œ

JWT

ํ† ํฐ ๊ด€๋ฆฌ ๋ฐฉ์‹ ํ†บ์•„๋ณด๊ธฐ

0. ๋“ค์–ด๊ฐ€๋ฉฐ ๐ŸŽฏ ์„œ๋น„์Šค์— ์ ‘๊ทผํ•˜๋ ค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ์‚ฌ์šฉ์ž ์ธ์ฆ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์„ ํ™•์ธํ•˜๋Š” ์ž‘์—…์€ ์ธ๊ฐ€๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ธ๊ฐ€๋Š” ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ธ์ฆ์—๋Š” ๋งŽ์€ ๋ฐฉ์‹์ด ์žˆ์ง€๋งŒ, ์˜ค๋Š˜์€ ์„ธ์…˜ ์ธ์ฆ ๋ฐฉ

A2A

A2A / MCP ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜

0. ๋“ค์–ด๊ฐ€๋ฉฐ โœ๏ธ Google for Developers์—, ๋ ˆ์Šคํ† ๋ž‘ ๊ณต๊ธ‰๋ง ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ์—ฎ์€ 6๋Œ€ ํ”„๋กœํ† ์ฝœ(MCP, A2A, UCP, AP2, A2UI, AG-UI)์— ๋Œ€ํ•œ ๊ฐ€์ด๋“œ๊ฐ€ ๊ฒŒ์‹œ๋œ ์ดํ›„, MCP์™€ A2A๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•ด ๋ณด๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ