React 박신천 sprint5#119
Hidden character warning
Conversation
|
스프리트 미션 하시느라 수고 많으셨어요. |
commit 단위를 더욱 자주, 작게 해보시는건 어떠실까요?git을 다룰 때 commit은 "언제 해야 하는가"를 생각해보신 적 있으신가요?
그럼 커밋을 언제 해야 할까요?저는 다음과 같은 룰을 지키며 커밋을 하는걸 권장 드립니다:
관련하여 읽으시면 좋은 아티클을 추천드릴게요:tl;dr관련 변경 사항 커밋 자주 커밋 미완성 작업을 커밋하지 마십시오 커밋하기 전에 코드를 테스트하세요 |
커밋 타입도 한 번 고려해보세요 !tl;dr:커밋 메시지 형식 type: Subject
body
footer기본적으로 3가지 영역(제목, 본문, 꼬리말)으로 나누어졌다. 메시지 type은 아래와 같이 분류된다. 아래와 같이 소문자로 작성한다. |
There was a problem hiding this comment.
.gitignore를 작성해보시는게 어떨까요?
macos의 압축 과정에서 흔히 .DS_Store 파일이 들어가는 경우가 있습니다.
해당 파일은 프로젝트와 무관하므로 .gitignore에 다음과 같이 작성하시면 git의 추적을 무시할 수 있습니다.
.DS_Store
| }) { | ||
| const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`; | ||
| const res = await fetch( | ||
| `https://panda-market-api.vercel.app/products?${query}` |
There was a problem hiding this comment.
Base URL은 따로 정의해두는게 좋겠군요 !
| `https://panda-market-api.vercel.app/products?${query}` | |
| `${BASE_URL}/products?${query}` |
https://panda-market-api.vercel.app는 앞으로도 계속 사용 될 것이며, 변경될 수도 있기에 따로 정의해볼 수 있습니다 !
더 좋은 방법 ! base URL은 환경 변수에 저장하시는게 좋습니다!
환경 변수(Environment Variable):
process.env에 내장되며 앱이 실행될 때 적용할 수 있는 값입니다!
다음과 같이 적용할 수 있습니다:
// .env.development
REACT_APP_BASE_URL="http://localhost:3000"
// .env.production
REACT_APP_BASE_URL="http://myapi.com"
// 사용시
<a href={`${process.env.REACT_APP_BASE_URL}/myroute`}>URL</a>
왜 환경 변수에 저장해야 하나요?
개발(dev), 테스트(test), 실제 사용(prod) 등 다양한 환경에서 앱을 운영하게 되는 경우, 각 환경에 따라 다른 base URL을 사용해야 할 수 있습니다. 만약 코드 내에 하드코딩되어 있다면, 각 환경에 맞춰 앱을 배포할 때마다 코드를 변경해야 하며, 이는 매우 번거로운 작업이 됩니다. 하지만, 환경 변수를 .env.production, .env.development, .env.test와 같이 설정해두었다면, 코드에서는 단지 다음과 같이 적용하기만 하면 됩니다.
const apiUrl = `${process.env.REACT_APP_BASE_URL}/api`;
이러한 방식으로 환경 변수를 사용하면, 배포 환경에 따라 쉽게 URL을 변경할 수 있으며, 코드의 가독성과 유지보수성도 개선됩니다.
실제 코드 응용과 관련해서는 다음 한글 아티클을 참고해보세요! => 보러가기
| keyword = "", | ||
| }) { | ||
| const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`; | ||
| const res = await fetch( |
There was a problem hiding this comment.
axios를 사용해보는건 어떨까요?
현재 fetch를 그대로 사용해도 동작은 하겠으나, 반복되는 baseURL과 fetch로 받은 response에 대한 공통적인 후처리, request 보내기 전 공통적인 처리 등 또한 고려해볼 수 있을거예요.
다음 사항들을 고려해볼 수 있어요:
- 만약
get이 아닌 메써드(post,patch,delete등)일 경우는 어떻게 처리할 수 있을까요? query와body가 필요할 때는 어떻게 처리 할 수 있을까요?- 로그인 인가를 위한 토큰을 request 전에 자동으로 삽입할 수는 없을까요? (인증/인가를 자동으로 할 수 없을까요?)
- 처음 한 번에 Base URL을 지정할 수는 없을까요?
- Base URL을 사용하다가 다른 엔드포인트에 요청해야 할 때는 어떻게 할 수 있을까요?
이 모든 요구사항들을 반영한 아키텍쳐를 구상하기는 어렵습니다. 따라서 이 모든 요구사항이 잘 만족하는 http client를 사용해보시는건 어떨까요 ?
- Base URL을 사용하다가 다른 엔드포인트에 요청해야 할 때는 어떻게 할 수 있을까요?
There was a problem hiding this comment.
어떻게 세팅하면 될까? 🤔
instance를 만들어서 export를 하고 사용해보는 것 정도로 시도해보면 좋을 것 같아요. axios-instance 파일을 만들어서 instance를 생성하고 export한 후 사용해보는건 어떨까요?
다음과 같이 만들어볼 수 있어요:
const baseURL = process.env.NEXT_PUBLIC_LINKBRARY_BaseURL;
const instance = axios.create({
baseURL: baseURL,
headers: {
'Content-Type': 'application/json',
},
});
export default instance사용 방법 🚀
사용 방법은 정말 간단해요. 다음과 같이 사용할 수 있습니다:
instance.get(`/user/${userId}`)딱 보니. 마이그레이션도 정말 쉽게 할 수 있겠죠? 😊
| <Link to="/" className="head_logo"> | ||
| <img src={Logo} alt="판다마켓 로고" /> | ||
| </Link> |
There was a problem hiding this comment.
굿굿 ~ react-router-dom에서 제공하는 Link를 사용하셨군요 👍
| console.log(isTablet, "isTablet"); | ||
| const { matches: isDesktop } = window.matchMedia( | ||
| "screen and (min-width: 1024px)" | ||
| ); | ||
| console.log(isDesktop, "isDesktop"); |
There was a problem hiding this comment.
console.log들은 지워도 될 것 같군요 ! 😉
| console.log(isTablet, "isTablet"); | |
| const { matches: isDesktop } = window.matchMedia( | |
| "screen and (min-width: 1024px)" | |
| ); | |
| console.log(isDesktop, "isDesktop"); | |
| const { matches: isDesktop } = window.matchMedia( | |
| "screen and (min-width: 1024px)" | |
| ); |
| const getFilteredData = () => items; | ||
| const filteredItems = getFilteredData(); | ||
|
|
||
| const MAXPAGE = 5; |
There was a problem hiding this comment.
해당 상수도 컴포넌트 바깥으로 빼는게 좋겠어요 !
리렌더링 시 불필요한 재선언과 컴포넌트 자원을 사용하지 않는 로직을 구분할 수 있게 됩니다 😉
| const getFilteredData = () => items; | ||
| const filteredItems = getFilteredData(); |
There was a problem hiding this comment.
혹시 items와 filteredItems의 내용은 같은거 아닐까요?
| const getFilteredData = () => items; | |
| const filteredItems = getFilteredData(); |
items를 사용하면 될 것 같은데 getFilteredData`를 선언하고 호출하지 않으셔도 될 것으로 보여요 😉
|
|
||
| const MAXPAGE = 5; | ||
|
|
||
| const focusPage = (n) => document.getElementById(`page${n}`).focus(); |
| <button id="page1" onClick={() => goPage(1)}> | ||
| 1 | ||
| </button> | ||
| <button id="page2" onClick={() => goPage(2)}> | ||
| 2 | ||
| </button> | ||
| <button id="page3" onClick={() => goPage(3)}> | ||
| 3 | ||
| </button> | ||
| <button id="page4" onClick={() => goPage(4)}> | ||
| 4 | ||
| </button> | ||
| <button id="page5" onClick={() => goPage(5)}> | ||
| 5 | ||
| </button> |
There was a problem hiding this comment.
페이지네이션은 동적으로 바뀌어야 합니다 😉
현재 정적으로 5개까지만 보여지는데 현재 활성화 된 페이지에 맞는 페이지네이션이 필요합니다 ! (디자인 시안 참고)
|
크으... 신천님.. 정말 멋집니다. 함께 더욱 더욱 빠르게 성장해봅시다 ! 스프린트 미션 수행하시느라 정말 수고 많으셨습니다. |
요구사항
기본
배포 링크
중고마켓
중고마켓 반응형
베스트 상품
Desktop : 4개 보이기
Tablet : 2개 보이기
Mobile : 1개 보이기
전체 상품
Desktop : 12개 보이기
Tablet : 6개 보이기
Mobile : 4개 보이기
심화
주요 변경사항
등을 구현했습니다
스크린샷
멘토에게