[황혜진] sprint5#64
Hidden character warning
Conversation
|
스프리트 미션 하시느라 수고 많으셨어요. |
|
굿굿 ! 템플릿 커밋 구분을 해주셨군요 ! |
| @@ -0,0 +1 @@ | |||
| REACT_APP_BASE_URL=https://panda-market-api.vercel.app No newline at end of file | |||
There was a problem hiding this comment.
훌륭합니다 ! 환경변수로 BASE_URL을 지정하셨군요 !
굿굿 ~! 환경변수는 다음과 같은 이점들이 있지요:
왜 환경 변수에 저장해야 하나요?
개발(dev), 테스트(test), 실제 사용(prod) 등 다양한 환경에서 앱을 운영하게 되는 경우, 각 환경에 따라 다른 base URL을 사용해야 할 수 있습니다. 만약 코드 내에 하드코딩되어 있다면, 각 환경에 맞춰 앱을 배포할 때마다 코드를 변경해야 하며, 이는 매우 번거로운 작업이 됩니다. 하지만, 환경 변수를 .env.production, .env.development, .env.test와 같이 설정해두었다면, 코드에서는 단지 다음과 같이 적용하기만 하면 됩니다.
const apiUrl = `${process.env.REACT_APP_BASE_URL}/api`;
이러한 방식으로 환경 변수를 사용하면, 배포 환경에 따라 쉽게 URL을 변경할 수 있으며, 코드의 가독성과 유지보수성도 개선됩니다.
실제 코드 응용과 관련해서는 다음 한글 아티클을 참고해보세요! => 보러가기
| @@ -0,0 +1 @@ | |||
| REACT_APP_BASE_URL=https://panda-market-api.vercel.app No newline at end of file | |||
There was a problem hiding this comment.
환경변수를 .gitignore에 추가해보시는건 어떨까요?
.env 파일은 보통 API 키, 데이터베이스 비밀번호, 서버 URL 등 중요한 설정값을 저장하는 파일이에요.
이런 파일을 형상관리(Git)에 포함하면 보안 문제가 발생할 수 있어요.
- 보안 문제 (API 키 & 비밀번호 노출)
예를 들어, 아래와 같은 .env 파일이 있다고 가정해볼게요.
REACT_APP_API_KEY=123456789abcdef
DATABASE_PASSWORD=my-secret-password
이 파일을 Git에 올리면 누구나 볼 수 있어요.
만약 GitHub에 올라가면, 악의적인 사용자가 API를 도용하거나, 데이터베이스에 무단 접근할 수도 있어요! 😱
- 환경별 설정값이 다를 수 있음 (개발/운영 분리)
개발할 때는 테스트 서버를 사용하지만, 실제 서비스에서는 운영 서버를 사용해야 해요.
만약.env가 Git에 포함되면, 모든 사람이 같은 설정을 쓰게 되어 개발 환경과 운영 환경을 구분할 수 없어요.
✅ 올바른 방법
.env.development → 개발용
.env.production → 운영용
실제 실행할 때 .env 파일을 개별적으로 설정
그래서 어떻게 설정할까?
# .gitignore
.env
위와 같이 추가해주시면 됩니다 !
| const queryParams = new URLSearchParams({ | ||
| page, | ||
| pageSize, | ||
| orderBy, | ||
| }); |
There was a problem hiding this comment.
오우 ! URLSearchParams를 사용하셨군요 ? 😊
| const queryParams = new URLSearchParams({ | ||
| page, | ||
| pageSize, | ||
| orderBy, | ||
| }); | ||
|
|
||
| if (keyword) { | ||
| queryParams.append("keyword", keyword); |
There was a problem hiding this comment.
다음 코드와 똑같지 않을까 예상됩니다 !
| const queryParams = new URLSearchParams({ | |
| page, | |
| pageSize, | |
| orderBy, | |
| }); | |
| if (keyword) { | |
| queryParams.append("keyword", keyword); | |
| const queryParams = new URLSearchParams({ | |
| page, | |
| pageSize, | |
| orderBy, | |
| keyword | |
| }); |
| const response = await fetch( | ||
| `https://panda-market-api.vercel.app/products?${queryParams.toString()}` | ||
| ); | ||
| if (!response.ok) { |
There was a problem hiding this comment.
BASE_URL을 정의하셨기에 다음과 같이 작성해볼 수 있어요 !
| const response = await fetch( | |
| `https://panda-market-api.vercel.app/products?${queryParams.toString()}` | |
| ); | |
| if (!response.ok) { | |
| const response = await fetch( | |
| `${BASE_URL}/products?${queryParams.toString()}` | |
| ); | |
| if (!response.ok) { |
| queryParams.append("keyword", keyword); | ||
| } | ||
|
|
||
| const response = await fetch( |
There was a problem hiding this comment.
axios를 사용해보는건 어떨까요?(제안/선택)
fetch 모듈을 잘 만든다는 것은 어렵습니다. 다음 사항들을 고려해볼 수 있어요:
- 만약
get이 아닌 메써드(post,patch,delete등)일 경우는 어떻게 처리할 수 있을까요? query와body가 필요할 때는 어떻게 처리 할 수 있을까요?- 로그인 인가를 위한 토큰을 request 전에 자동으로 삽입할 수는 없을까요? (인증/인가를 자동으로 할 수 없을까요?)
- 처음 한 번에 Base URL을 지정할 수는 없을까요?
- Base URL을 사용하다가 타 Domain에 보내야 될 때는 어떻게 할 수 있을까요?
이 모든 요구사항들을 '잘 만든다는 것'은 어려워요. 따라서 이 모든걸 만들어진fetch모듈을 사용해보고 후에fetch모듈을 만들어 보는 것도 좋은 학습 방법이 될 수 있어요.
- Base URL을 사용하다가 타 Domain에 보내야 될 때는 어떻게 할 수 있을까요?
어떻게 세팅하면 될까? 🤔
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인가에 필요한 accessToken을 localStorage가 있다면 axios의 인터셉터를 활용할 수 있습니다 !
인터셉터는 혼자 해결해보시는 것을 권장드립니다. 혹시 모르시겠으면 다음 위클리 미션에 질문해주세요. 😊
사용 방법 🚀
사용 방법은 정말 간단해요. 다음과 같이 사용할 수 있습니다:
instance.get(`/user/${userId}`)딱 보니. 마이그레이션도 정말 쉽게 할 수 있겠죠? 😊
| const imageURL = | ||
| item.images && item.images.length > 0 ? item.images[0] : placeholder; |
There was a problem hiding this comment.
다음 코드로 대체해볼 수 있을 것 같아요 ! 😊
| const imageURL = | |
| item.images && item.images.length > 0 ? item.images[0] : placeholder; | |
| const imageURL = item?.images?.[0] ?? placeholder; |
| size === "large" | ||
| ? items.slice( | ||
| 0, | ||
| window.innerWidth <= 480 ? 1 : window.innerWidth <= 768 ? 2 : 4 |
There was a problem hiding this comment.
(제안) 480, 768과 같은 숫자가 많이 보이는군요 !
| window.innerWidth <= 480 ? 1 : window.innerWidth <= 768 ? 2 : 4 | |
| window.innerWidth <= BREAKPOINTS.MOBILE ? 1 : window.innerWidth <= BREAKPOINTS.TABLET ? 2 : 4 |
앞으로도 재사용이 많을 것으로 예상되어 유지보수성과 가독성을 위해 상수로 정의해두면 어떨지 제안드려봅니다 !
|
굿굿 ! 정말 수고하셨습니다 혜진님 ㅎㅎㅎ |
요구사항
기본
###중고마켓 반응형
베스트 상품
전체 상품
심화
멘토에게