레이아웃은 퍼플스토어 웹페이지를 참고하여 웹뷰로 제작하였습니다.
├─common
├─components
├─pages
├─public
│ ├─data
│ └─image
├─redux
│ ├─actions
│ ├─reducers
│ └─store
└─styles
SSR은 클라이언트가 접속했을 때 브라우저에서 js 코드를 다운받아 해석할때까지 기다리지 않고, 서버에 보여질 HTML을 미리 준비해 응답해주는 방식이다.
장점: 렌더링 속도 향상. SEO
CSR은 js파일을 브라우저에서 해석해 렌더링하는 방식이다.
장점: 부드러운 UX. 필요한 데이터만 요청해서 서버 부하가 줄어든다.
Unhandled Runtime Error
Error: Invalid src prop (http://) on next/image, hostname "assets.example.com" is not configured unter images in your next.config.js
// next.config.js
module.exports = {
images: {
domains: ['assets.example.com'],
},
}
// .babelrc
{
"presets": ["next/babel"], // 하나의 목적을 위한 여러개의 플러그인 집합
"plugins": ["styled-components"] // babel-plugin-styled-components 추가하여 서버와 클라이언트 결괏값 일치.
}
액션 -> ( 미들웨어 ) -> 리듀서 -> 스토어 -> 뷰(리액트) -> 액션
리덕스 특징
- 같은 상탯값을 다수의 컴포넌트에서 필요로 할 때 사용하기 좋다.
- 상탯값은 불변객체이며, 하나의 객체(스토어)에 저장한다.
Next.js는 유저가 요청할때마다 redux store를 새로 생성한다.
Next.js가 제공하는 getInitialProps, getServerSideProps등에서 리덕스 스토어에 접근하려면 serverside일때 redux store와 client side일때 redux store를 합쳐 주어야 한다.
👉 redux store를 wrapper로 감싸주고 최상위 컴포넌트를 wrapper.withRedux로 감싸준다.
const configureStore = () => {
const store = createStore(reducer);
return store;
};
const wrapper = createWrapper(configureStore);
const MyApp = () => {
// ...
}
export default wrapper.withRedux(MyApp);
api 서버에서 데이터을 요구할때 http Authorization 헤더에 user id 와 , password 을 base64 로 인코딩한 문자열을 추가하여 인증하는 형식
headers: {
"Content-Type": CONTENTTYPE,
Authorization: Basic base64
}
8비트 이진 데이터(예를 들어 실행 파일이나, ZIP 파일 등)를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 문자열로 바꾸는 인코딩 방식
const infiniteScroll = () => {
const scrollHeight = document.documentElement.scrollHeight;
const scrollTop = document.documentElement.scrollTop;
const clinetHeight = document.documentElement.clientHeight;
if (scrollTop + clinetHeight > scrollHeight - 100 && products.next !== null)
setPage(page => page + 1);
};
useEventListener("scroll", infiniteScroll, []);
dep가 변화하면, ms후에 callback 함수를 실행한다.
export const useDebounce = (callback, ms, deps = []) => {
useEffect(() => {
const id = setTimeout(callback, ms);
return () => clearTimeout(id);
}, deps);
};
설정한 시간(delay)에 한번씩 이벤트를 발생시킨다.
export const useEventListener = (type, listener, deps = []) => {
return useEffect(() => {
window.addEventListener(type, listener);
return () => window.removeEventListener(type, listener);
}, deps);
};
export const useScroll = (type, deps = []) => {
useEffect(() => {
document.body.style.overflow = type;
}, deps);
};
리액트에 있는 모든 컴포넌트는 reference element를 가지고 있어서 어떤 component에 ref={변수명}을 넣어주면, 해당 component를 참조하게 된다.
(주의) component가 렌더링 되지 않은 상태에서 current에 접근하면 undefined가 나타난다.
변수가 업데이트 된다고 해서 컴포넌트가 리렌더링이 되지 않는다.
속성을 서서히 변화시키는 속성
transition: property timing-function duration delay | initial | inherit
직선형 그라데이션을 설정할 수 있는 속성
const Graph = styled.div`
position: relative;
width: ${props => props.price}%;
height: 100%;
margin-bottom: 0.3rem;
border-radius: 0.4375rem;
background-image: linear-gradient(
to right,
rgb(242 242 242),
rgb(127 131 135)
);
transition: 0.5s;
`;
미디어 쿼리와 함께 사용하며 뷰포트의 크기에 따라 길이를 가변적으로 핸들링 할 수 있다.
em은 단위가 적용된 요소의 글자 크기에 비례한다.
rem은 html 태그(최상위 요소)의 글자 크기에 비례한다. (=root em)
브라우저 기본 설정 기준에서 16px을 가지고 시작하는데 62.5%를 곱해주면 10px로 맞추고 rem을 10배수로 쓸 수 있다.