티스토리 뷰

Reference

이 프로젝트는 코딩애플 리액트 강의를 참고하여 제작되었습니다.

https://codingapple.com/course/react-basic/

 

React 리액트 기초부터 쇼핑몰 프로젝트까지!

  Next.js는 프론트엔드부터 서버까지 만들 수 있는 React기반 프레임워크입니다. 이것만 사용해도 풀스택 웹개발이 가능합니다.    Next.js 사용시 서버사이드 렌더링이 쉽기 때문에  React, Vue만 사

codingapple.com



React map function

https://lshjju.tistory.com/173



굿즈 코드 맵펑션 업그레이드 합니다.

 

굿즈 컴포넌트 맵펑션으로 업그레이드 합니다.

이미지데이터에서 원래 있던 i를 버리고 반복문의 키값을 공유하겠습니다.

i에 1을 살짝 추가하면 가능할것 같습니다.

<div className="d-flex flex-column mb-3">
  {/* 'shoes' 배열을 순회하며 각 아이템에 대해 'Goods' 컴포넌트를 렌더링합니다.
    map() 메서드는 배열의 각 요소를 순차적으로 처리합니다.
  */}
  {shoes.map((a, i) => {
    /* 'Goods' 컴포넌트의 props (속성)을 설정합니다.
      - 'shoes': 현재 순회 중인 상품 객체 (shoes[i])를 전달합니다.
      - 'i': 인덱스를 1부터 시작하도록 (i + 1) 전달합니다. 
    */
    return <Goods shoes={shoes[i]} i={i + 1}></Goods>;
  })}
</div>



 

 

맵펑션 i={i + 1} 이 부분이 꼴보기 싫습니다.

그래서 이미지에 1 플러스로 대신 하겠습니다. 

뷰를 보면 이미지 순서가 이상 합니다.

앱을 아직 수정 안해서 그런 거니까 앱으로 갑니다.

      <img
        src={
          "https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s" +
          (props.i + 1) +
          ".PNG"
        }
        width="80%"
      />



 

 

+1을 제거했습니다.

이제 이미지 데이터가 정상으로 보일 겁니다.

코어 코드에는 중요한 것만 담는 것이 좋습니다.

+1같은 부가적인 코드는 서브 코드에서 처리하는 편이 좋습니다.

마음이 편안해 졌습니다.

      <div className="d-flex flex-column mb-3">
        {shoes.map((a, i) => {
          return <Goods shoes={shoes[i]} i={i}></Goods>;
        })}
      </div>

 

 

 

 

해당 코드에서 a는 map 메서드의 첫 번째 파라미터로, 배열의 각 요소를 임시로 담는 변수입니다.
하지만 해당 코드에서는 a를 사용하지 않고, 대신 인덱스 i를 이용해 shoes[i]로 배열 요소에 접근하고 있습니다. 

이 경우 a는 사실상 불필요한 변수입니다. 즉, shoe 와 shoes[i] 는 같은 놈들입니다.

그러므로 위 코드를 이렇게 업그레이드 합니다. 사실 리액트는 해 코드를 권장 합니다.

<div className="d-flex flex-column mb-3">
  {shoes.map((shoe, i) => {
    return <Goods shoes={shoe} i={i}></Goods>;
  })}
</div>

 


test

뷰는 같습니다.

 


Completion

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
import { Link } from 'react-router-dom';
import data from './data.jsx';

function App() {
  let [shoes] = useState(data);

  return (
    <div className="App">
      <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
          <a class="navbar-brand" href="#">
            Navbar
          </a>
          <button
            class="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarNavAltMarkup"
            aria-controls="navbarNavAltMarkup"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
            <div class="navbar-nav">
              <Link to="/" class="nav-link active" aria-current="page">
                Home
              </Link>
              <Link to="/" class="nav-link active" aria-current="page">
                Detail
              </Link>
              <Link to="/" class="nav-link active" aria-current="page">
                about
              </Link>
            </div>
          </div>
        </div>
      </nav>

      <div className="main-bg"></div>

      <h1 className="my-5">Nike shop</h1>

    <div className="d-flex flex-column mb-3">
      {shoes.map((shoe, i) => {
        return <Goods shoes={shoe} i={i}></Goods>;
      })}
    </div>

      <div class="card m-5">
        <div class="card-header">Featured</div>
        <div class="card-body">
          <h5 class="card-title">Special title treatment</h5>
          <p class="card-text">
            With supporting text below as a natural lead-in to additional
            content.
          </p>
          <a href="#" class="btn btn-primary">
            Go somewhere
          </a>
        </div>
      </div>
    </div>
  );
}

function Goods(props) {
  return (
    <div className="p-2">
      <img
        src={
          'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s' +
          (props.i + 1) +
          '.PNG'
        }
        width="80%"
      />
      <h4 className="my-3">{props.shoes.title}</h4>
      <p>{props.shoes.price}</p>
    </div>
  );
}

export default App;

 



홈/디테일 페이지 분리하고 네브유알엘 세팅 합니다.


페이지 콘트롤 하기 위해 Routes, Route, Outlet을 임포트 합니다.

import { Routes, Route, Link, Outlet } from "react-router-dom";

 

 

 

메인비쥬얼과 굿즈를 페이지로 따로 분리 하겠습니다. 

그러기 위해 일단 그 부분을 태그 하나로 묶고 주석처리 합니다.

      {/* <>
      <div className="main-bg"></div>

      <h1 className="my-5">E-commerce project</h1>

      <div className="d-flex flex-column mb-3">
        {shoes.map((shoe, i) => {
          return <Goods shoes={shoe} i={i}></Goods>;
        })}
      </div>
      </> */}

 

 

 

 

페이지 분리하려면 라우츠를 사용해야 합니다.

자리는 네브아래가 적절할것 같습니다.

네브 아래 라우츠를 만듭니다.

뭐든 하기전에 일단 테스트 해보고 만드는게 국룰입니다.

간단한 텍스트로 라우트를 만듭니다.

      <Routes>
        <Route path="/" element={<div>It is main</div>} />
        <Route path="/detail" element={<div>It is detail</div>} />
      </Routes>

 

 

 

 

유알엘 테스트 합니다.

아직 네브에 적용하지 않았으니 유알엘로 체크해 봅니다.

http://localhost:3000/

It is main

http://localhost:3000/detail/

It is detail

뷰 잘 되는지 체크 합니다.

 

 

 

테스트 통과했다면 이제 네브 링크 수정 해야 합니다.

네브 수정합니다.

            <div class="navbar-nav">
              <Link to="/" class="nav-link active" aria-current="page">
                Home
              </Link>
              <Link to="/detail" class="nav-link active" aria-current="page">
                Detail
              </Link>
            </div>

 

네브 탭 잘 작동하는지 테스트 합니다.

 

 

 

하다 보니까 햄버거 토글 맛이 간것 같습니다.

이 코드를 삭제하면 아마 잘 될 수도...

import 'bootstrap/dist/js/bootstrap.bundle.min.js';

 

 

 

메인에서 히어로와 굿즈만 렌더링 합니다.

히어로는 우리가 익히 알고 있는 메인비쥬얼 영역을 지칭합니다.

유아이디자이너들이 부르는 현장 용어입니다.

가출하고 노숙하던 아이들을 따뜻한 라우트 안으로 옮겨 줍니다.

신중하고 자애로운 마음으로. 

옮긴 뒤 노숙의 흔적은 깨끗하게 정리하는 센스.

신기하게도 뭔가 세상이 좀 더 밝아진 느낌이 듭니다.

      <Routes>
        <Route
          path="/"
          element={
            <>
              <div className="main-bg"></div>

              <h1 className="my-5">E-commerce project</h1>

              <div className="d-flex flex-column mb-3">
                {shoes.map((shoe, i) => {
                  return <Goods shoes={shoe} i={i}></Goods>;
                })}
              </div>
            </>
          }
        />
        <Route path="/detail" element={<div>It is a detail</div>} />
      </Routes>

test

네브로 뷰 체크 합니다.

뷰는 같습니다.

http://localhost:3000/

http://localhost:3000/detail/

 

 


Completion

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Routes, Route, Link, Outlet } from 'react-router-dom';
import data from './data.jsx';

function App() {
  let [shoes] = useState(data);

  return (
    <div className="App">
      <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
          <a class="navbar-brand" href="#">
            Navbar
          </a>
          <button
            class="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarNavAltMarkup"
            aria-controls="navbarNavAltMarkup"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
            <div class="navbar-nav">
              <Link to="/" class="nav-link active" aria-current="page">
                Home
              </Link>
              <Link to="/detail" class="nav-link active" aria-current="page">
                Detail
              </Link>
            </div>
          </div>
        </div>
      </nav>

      <Routes>
        <Route
          path="/"
          element={
            <>
              <div className="main-bg"></div>

              <h1 className="my-5">Nike shop</h1>

              <div className="d-flex flex-column mb-3">
                {shoes.map((shoe, i) => {
                  return <Goods shoes={shoe} i={i}></Goods>;
                })}
              </div>
            </>
          }
        />
        <Route path="/detail" element={<div>It is detail</div>} />
      </Routes>

      <div class="card m-5">
        <div class="card-header">Featured</div>
        <div class="card-body">
          <h5 class="card-title">Special title treatment</h5>
          <p class="card-text">
            With supporting text below as a natural lead-in to additional
            content.
          </p>
          <a href="#" class="btn btn-primary">
            Go somewhere
          </a>
        </div>
      </div>
    </div>
  );
}

function Goods(props) {
  return (
    <div className="p-2">
      <img
        src={
          'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s' +
          (props.i + 1) +
          '.PNG'
        }
        width="80%"
      />
      <h4 className="my-3">{props.shoes.title}</h4>
      <p>{props.shoes.price}</p>
    </div>
  );
}

export default App;


라우츠 디렉토리에 페이지 만듭니다.


코드 살짝 정리 하겠습니다.

맨 아래 이 코드 삭제합니다.

export default App;


펑션앱 헤드를 이렇게 수정 합니다.

이것은 개발자의 선택사항입니다.

상황에 따라 효율적인 방향을 선택하면 됩니다.

export default function App()

 

 

 

routes/Detail.jsx

페이지를 만들것입니다.

일반적으로 리액트에서 페이지 만들때는 src/routes 디렉토리 만드는 루틴이 있습니다.

법은 아니고 뭔가 그냥 사회적 합의 같은 그런 느낌입니다.

디테일 뷰 유아이 만들겠습니다.

정해진 방법은 없으니 대략 이렇게 만들어도 문제 없습니다.
내부에 Detail.js 파일 빌딩 합니다.

라우츠 파일네임 첫글자를 대문자로 하는 것은 팀 내부의 룰에 맞춰서 해도 됩니다.

필자는 컴포넌트 네임과 일치시키기 위해 이렇게 했습니다.

체크 해보니 소문자로 해도 에러는 안나는것 같습니다.

라우츠 파일네임 대문자 소문자는 아직 사회적 합의가 안된것 같습니다.

export default function Detail() {
  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img
            src="https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s1.PNG"
            width="100%"
          />
        </div>
        <div className="col-md-6">
          <h4 className="pt-5">title</h4>
          <p>content</p>
          <p>price</p>
          <button className="btn btn-danger">order</button>
        </div>
      </div>
    </div>
  );
}

 


App.jsx

당연히 파일 임포트 합니다.

import Detail from "./routes/Detail";


디테일 컴포넌트가 준비 되었습니다.

그러므로 라우츠 내부 디테일 라우트 엘레멘트를 변경 합니다.

<Route path="/detail" element={<Detail />} />

 


test

네브로 디테일 페이지 체크 합니다.


Completion

 

routes/Detail.jsx

다음과 같습니다.

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Routes, Route, Link, Outlet } from 'react-router-dom';
import data from './data.jsx';
import Detail from './routes/Detail';

export default function App() {
  let [shoes] = useState(data);

  return (
    <div className="App">
      <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
          <a class="navbar-brand" href="#">
            Navbar
          </a>
          <button
            class="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarNavAltMarkup"
            aria-controls="navbarNavAltMarkup"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
            <div class="navbar-nav">
              <Link to="/" class="nav-link active" aria-current="page">
                Home
              </Link>
              <Link to="/detail" class="nav-link active" aria-current="page">
                Detail
              </Link>
            </div>
          </div>
        </div>
      </nav>

      <Routes>
        <Route
          path="/"
          element={
            <>
              <div className="main-bg"></div>

              <h1 className="my-5">Nike shop</h1>

              <div className="d-flex flex-column mb-3">
                {shoes.map((shoe, i) => {
                  return <Goods shoes={shoe} i={i}></Goods>;
                })}
              </div>
            </>
          }
        />
        <Route path="/detail" element={<Detail />} />
      </Routes>

      <div class="card m-5">
        <div class="card-header">Featured</div>
        <div class="card-body">
          <h5 class="card-title">Special title treatment</h5>
          <p class="card-text">
            With supporting text below as a natural lead-in to additional
            content.
          </p>
          <a href="#" class="btn btn-primary">
            Go somewhere
          </a>
        </div>
      </div>
    </div>
  );
}

function Goods(props) {
  return (
    <div className="p-2">
      <img
        src={
          'https://raw.githubusercontent.com/lshjju/cdn/refs/heads/main/ca-shop/s' +
          (props.i + 1) +
          '.PNG'
        }
        width="80%"
      />
      <h4 className="my-3">{props.shoes.title}</h4>
      <p>{props.shoes.price}</p>
    </div>
  );
}

 

 

 

참고사이트 : ca03

 

ca03

Reference이 프로젝트는 코딩애플 리액트 강의를 참고하여 제작되었습니다.https://codingapple.com/course/react-basic/ React 리액트 기초부터 쇼핑몰 프로젝트까지! Next.js는 프론트엔드부터 서버까지 만들 수

lshjju.tistory.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함