React

[TIL/React] 2023/10/09

Detail page layout ๐ŸŸขProductDetailPageBackgroundStyle์— ์˜ํ•ด ์ „์ฒด์ ์ธ ๋ฐฐ๊ฒฝ์ƒ‰์ด ์ ์šฉ๋˜๊ณ  ์žˆ๋‹ค. AllContentWrapper๋Š” ์ฒซ ๋ฒˆ์งธ ์‚ฌ์ง„์—์„œ ๋…ธ๋ž€์ƒ‰ border๋กœ ํ‘œ์‹œ๋˜๋Š” ์˜์—ญ์ด๋‹ค. ํ•ด๋‹น wrapper๋Š” width๊ฐ€ 90

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

Detail page layout ๐ŸŸข

ProductDetailPageBackgroundStyle์— ์˜ํ•ด ์ „์ฒด์ ์ธ ๋ฐฐ๊ฒฝ์ƒ‰์ด ์ ์šฉ๋˜๊ณ  ์žˆ๋‹ค. AllContentWrapper๋Š” ์ฒซ ๋ฒˆ์งธ ์‚ฌ์ง„์—์„œ ๋…ธ๋ž€์ƒ‰ border๋กœ ํ‘œ์‹œ๋˜๋Š” ์˜์—ญ์ด๋‹ค. ํ•ด๋‹น wrapper๋Š” width๊ฐ€ 900px ์ดํ•˜๊ฐ€ ๋˜๋ฉด flex ๋ฐฉํ–ฅ์„ column์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ํŠน๋ณ„ํ•œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

AllContentWrapper๋Š” ์‚ฌ์‹ค์ƒ ImgWrapper์™€ InfoWrapper๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋‹ค๊ณ  ๋ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค. 'flex:1'์ด ๊ณตํ†ต์ ์œผ๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” ์ ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•˜์ž๋ฉด AllContentWrapper ์˜์—ญ์„ ๋ฐ˜๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ„๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. align-items๋ฅผ flex-start๋กœ ์ง€์ •ํ•˜์—ฌ ํ™”๋ฉด ์ƒ๋‹จ์— ์œ„์น˜ํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

๊ฐ์ข… info, ์˜ต์…˜ ๊ทธ๋ฆฌ๊ณ  ์ˆ˜๋Ÿ‰์„ ํ•ฉ์นœ ์˜์—ญ์ด ProductDetailPageInfoDataWrapper์ด๋‹ค. ํ•œ๋งˆ๋””๋กœ InfoWrapper๋ฅผ InfoDataWrapper์™€ ButtonWrapper๋กœ ๊ตฌ์„ฑ๋œ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. 'flex:1.5'์™€ 'flex:2'๋ฅผ ํ†ตํ•ด 1.5 ๋Œ€ 2์˜ ๋น„์œจ๋กœ InfoWrapper ๋‚ด๋ถ€์˜ ์˜์—ญ์„ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ProductDetailPageInfoDataWrapper๋Š” div์™€ OptionWrapper ๊ทธ๋ฆฌ๊ณ  AmountWrapper๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. InfoDataWrapper๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ ์ ˆํžˆ flex๋ฅผ ๋‚˜๋ˆ  ๊ฐ–๊ณ  ์žˆ๋‹ค.

detail page์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์นด์šดํ„ฐ์™€ ๋“œ๋กญ๋‹ค์šด์€, component -> Detail ํด๋”๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ƒํƒœ๋Š” ์•„๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์ด ์ƒ์„ธ ํŽ˜์ด์ง€์—์„œ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋ณ€๊ณก์ ์ด๋‹ค.

Counter.js

code
import React, { useState } from "react";
import styled from "styled-components";

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

const Button = styled.button`
  padding: 10px 20px;
  font-size: 1.5em;
`;

const Display = styled.div`
  padding: 10px;
  font-size: 1.5em;
  margin: 0 20px;
`;

const Counter = () => {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount((prevCount) => prevCount + 1);
  };

  const handleDecrement = () => {
    if (count > 0) {
      setCount((prevCount) => prevCount - 1);
    }
  };

  return (
    <CounterContainer>
      <Button onClick={handleDecrement}>-</Button>
      <Display>{count}</Display>
      <Button onClick={handleIncrement}>+</Button>
    </CounterContainer>
  );
};

export default Counter;

Dropdown.js

code
import React, { useState } from "react";
import styled from "styled-components";

const DropdownButton = styled.div`
  padding: 10px;
  width: 100%;
  border: 2px solid black;
  cursor: pointer;
  background-color: #f0f0f0;
  color: black;
`;

const DropdownList = styled.div`
  display: ${({ isOpen }) => (isOpen ? "block" : "none")};
`;

const DropdownItem = styled.div`
  padding: 10px;
  width: 200px;
  border: 2px solid black;
  cursor: pointer;
  &:hover {
    background-color: #f0f0f0;
  }
`;

const Dropdown = () => {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedOption, setSelectedOption] = useState(null);

  const options = ["Option 1", "Option 2", "Option 3"];

  const handleOptionClick = (option) => {
    setSelectedOption(option);
    setIsOpen(false);
  };

  return (
    <>
      <DropdownButton onClick={() => setIsOpen(!isOpen)}>
        {selectedOption || "Select an option"}
      </DropdownButton>
      <DropdownList isOpen={isOpen}>
        {options.map((option) => (
          <DropdownItem key={option} onClick={() => handleOptionClick(option)}>
            {option}
          </DropdownItem>
        ))}
      </DropdownList>
    </>
  );
};

export default Dropdown;

ํ˜„์žฌ ๐ŸŸข

๊ตฌ๋ฆฌ๋‹ค. ํ•˜์ง€๋งŒ ์ฒ˜์Œ๋ณด๋‹จ ๊ดœ์ฐฎ์•„์กŒ๋‹ค. ๋‚ด์ผ ๋” ์ˆ˜์ •ํ•˜๊ธฐ๋กœ

More to read

Amazon VPC

Amazon VPC Architecture ์ดํ•ดํ•˜๊ธฐ

์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐํšํ•˜๋ฉฐ, ๊ฐœ๋ฐœ์—์„œ ๋ฌด์—‡์„ ๊ฐ€์žฅ ๋จผ์ € ๊ณ ๋ฏผํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‹ค์‹œ ๋Œ์•„๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.ํ•œ๋•Œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ๋ชจ๋“  ์„ค๊ณ„์˜ ์ถœ๋ฐœ์ ์ด๋ผ๊ณ  ๋ฏฟ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ ์ €๊ฐ€ ๋ฌด์—‡์„ ๋ณด๊ณ , ์–ด๋–ค ํ๋ฆ„์—์„œ ๋จธ๋ฌด๋ฅด๊ณ  ์ดํƒˆํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์ดํ•ด ์—†์ด ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ ๋‹ค๋Š” ๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ

'์›์‚ฌ์ดํŠธ'

ํ”„๋ก ํŠธ์—”๋“œ ๊ด€์ ์œผ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ดํ•ดํ•˜๊ธฐ

์˜ค๋žœ๋งŒ์— ๋ฐฉ๋ฒ•๋ก ์— ๊ด€ํ•œ ๊ธ€์„ ์“ฐ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ตœ๊ทผ ์ƒํ™ฉ์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค. SSAFY์—์„œ๋Š” ํ•˜๋ฃจ์— ์—„์ฒญ๋‚œ ์–‘์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ๋“ค์„ ๊ณผ์ œ๋กœ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ, '๊ตฌํ˜„๋ ฅ'์ด ๋งค์šฐ ๋–จ์–ด์ง„๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์™„์ „ํžˆ ์–ด๋ ค์šด ๋ฌธ์ œ๋ผ๋ฉด '์•„์‰ฌ์›€'์ด๋ผ๋Š” ๊ฐ์ •์กฐ์ฐจ ๋А๋ผ์ง€

Subnet

VPC ์„ค๊ณ„์˜ ์‹œ์ž‘: IP์™€ Subnet

๋ฐ˜๋ณต๋˜๋Š” ๋ฃจํ‹ด ์†์—์„œ ์–ป์€ ์•ˆ์ •๊ฐ์„ ๋ฐœํŒ ์‚ผ์•„, ์ด์ œ๋Š” ๊ธฐ์ˆ ์  ์ŠคํŽ™ํŠธ๋Ÿผ์„ ๋„“ํžˆ๊ธฐ ์œ„ํ•œ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์— ์ฐฉ์ˆ˜ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋Š” ๋‹จ์ˆœํ•œ ํฌํŠธํด๋ฆฌ์˜ค ๊ตฌ์ถ•์„ ๋„˜์–ด, ์‹ค์ œ ์„œ๋น„์Šค ์ˆ˜์ค€์˜ ๋ธ”๋กœ๊ทธ ์‹œ์Šคํ…œ ๊ตฌํ˜„๊ณผ ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ ์ ์šฉ ๋“ฑ ์‹ค๋ฌด์— ๊ฐ€๊นŒ์šด ์—ญ๋Ÿ‰์„ ํ•œ ๋‹จ๊ณ„