NextJS 기본세팅

사이드 프로젝트를 위한 프레임워크 및 필요 라이브러리 설치 과정입니다.

 

기존에는 react/ts + redux saga + node.js를 사용하여 작업을 했지만 사이드 프로젝트에서 새로운것들을 공부해보기 위해

해보지 않았던 프레임워크와 라이브러리를 이용해보기로 했습니다.

 

1. Nextjs

2. Recoil

3. TypeScript

4. styled component

5. antd

6. jest

7. firebase

 

처음 사용해보는것들은 nextjs, recoil, jest, firebase입니다.

전부다 사용해볼수 있을지 둑은둑은.......

 

next js는 서버사이드 렌더링이.... 어쩌고는 여기저기 많으니 해당 프레임워크,라이브러리 세팅 과정만 정리합니다.

 

1. npx create-next-app 프로젝트명
2. root에 tsconfig.json 파일 생성
3. npm install --save-dev typescript @types/react @types/node 
4. npm run dev 하면 빈 tsconfig.json 파일에 내용이 채워진다.
5. npm install --save styled-components	

타입스크립트를 사용 할 때 여기까지만 설치하면 styled-components를 사용할수없다.
타입을 정의해놓은것도 설치해주면 에러없이 사용 할 수 있고,
문자열 안에 스타일이 들어가기 때문에 에러 처리를 위해 별도로 babel을 설치해야한다.

6. npm install --save @types/styled-components
7. npm install --save-dev babel-plugin-styled-components

8. babel 설치 후 root에 .babelrc 파일 생성
9. {
    "presets": ["next/babel"],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true,
                "displayName": true,
                "preprocess": false
            }
        ]
    ]
}

해당내용 .babelrc파일에 생성

10. pages/_app.tsx에 글로벌 스타일 적용

const them = {
    testColor: "#ff4c01",
};

them변수를 Provider에 할당하고
하위 컴포넌트에서
const ThemeTest = styled.div`
    color: ${props => props.theme.testColor};
`; 형태로 사용한다.

 

pages/_app.tsx에 글로벌 스타일 적용

 

11. styled-components는 Next.js에서 CSS 로딩이 늦게 되어 깜빡이는 현상이 발생.
	- styled-components의 스타일은 html 렌더링 이후에 렌더되기 때문에 _document.tsx파일에 미리 적용시켜야 한다.
    - pages/_document.js 파일 생성 후 코드 삽입

 

_document.js 코드 : https://github.com/vercel/next.js/blob/master/examples/with-styled-components/pages/_document.js

 

GitHub - vercel/next.js: The React Framework

The React Framework. Contribute to vercel/next.js development by creating an account on GitHub.

github.com

 

 

12. npm i recoil // 리코일 설치

Next.js는 모든 페이지 렌더링전에 _app.js를 거치기 때문에 최상위에서 감싸주면 된다.

function MyApp({ Component, pageProps }) {
    return (
        <ThemeProvider theme={them}>
            <RecoilRoot>
                <Component {...pageProps} />
            </RecoilRoot>
        </ThemeProvider>
    );
}
13. root에 states 폴더 생성후 index.ts 생성

// states/index.ts
import { atom } from "recoil";

export const testState = atom({
    key: "testState",
    default: "바뀌기전이에옴",
});

// pages/index.tsx
import styles from "../styles/Home.module.css";
import styled from "styled-components";
import { useRecoilState } from "recoil";
import { testState } from "../states";

const ThemeTest = styled.div`
    color: ${props => props.theme.testColor};
`;
export default function Home() {
    const [test, setTest] = useRecoilState(testState);
    console.log(test);

    const handleState = () => {
        setTest("바꼇당!!!");
    };
    return (
        <div className={styles.container}>
            <button onClick={handleState}>버튼이에오</button>
            <ThemeTest>THEME PROVIDER TEST</ThemeTest>
        </div>
    );
}

recoil state 작동 확인!

14. npm i antd

// pages/_app.tsx
import "antd/dist/antd.css";

15. npm i jest @testing-library/react @types/jest babel-jest @testing-library/jest-dom @testing-library/user-event @testing-library/dom -D

** jest: a transform must export a `process` or `processasync` function 에러로 인해 jest, jest-cli,babe-jest를

26.6.3 버전으로 다운그레이드 하였음. **

16 npm install --save-dev jest babel-jest @testing-library/react @testing-library/jest-dom identity-obj-proxy react-test-renderer @babel/preset-env @babel/preset-typescript ts-node jest-cli @testing-library/dom jest-dom 

17 root/ babel.config.js

module.exports = {
    presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript", "next/babel"],
};


18 root/ jest.config.js

export default {
    testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/"],
    setupFilesAfterEnv: ["<rootDir>/setupTests.js"],
    moduleNameMapper: {
        "\\.(css|less|scss|sass)$": "identity-obj-proxy",
        "^@/components/(.*)$": "<rootDir>/components/$1",
    },
    transform: {
        "^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
        "/^.+.(css|less|scss|sass)$/": "identity-obj-proxy",
    },
};

19 root/ setupTests.js
import "@testing-library/jest-dom";

20 root/package.json / scripts에 추가
 "test": "jest"
 
21 root/helpers/sum.ts

export default (a: number, b: number) => {
    return a + b;
};

22 root/tests/sum.test.ts

23 npm test

다른 값을 넣었을 때 !
정상 값을 넣었을 때

Jest로 recoil, TypeScript등을 테스트 할 때는 추가적으로 라이브러리나 방법이 조금 다른것 같다.

그건 프로젝트 진행하면서 찾아가야겠다..

 

24 npm install firebase react-firebase-hooks react-firebaseui

firebase에서도 hooks가 있더라 !! 공식문서도 잘정리되어있는것 같고 쓰기 편할듯해서 설치

25 root/.env.local
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_DATABASE_URL=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGIN_SENDER_ID=
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
 
26 root/utils/initFirebase.js
import firebase from "firebase/app";
// 필요한것들을 더 추가해서 쓰면된다
import "firebase/auth";
import "firebase/firestore";

var firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGIN_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

// 이 부분은 에러처리를 위함이라고 한다
if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
}

export default firebase;

27 pages/index.tsx // 기존코드에서 추가

import firebase from "../utils/initFirebase";
import { useCollection } from "react-firebase-hooks/firestore";


export default function Home() {
    const [value, loading, error] = useCollection(firebase.firestore().collection("mymy"), {
        snapshotListenOptions: { includeMetadataChanges: true },
    });
    
      return (
        <div className={styles.container}>
            {/* <button onClick={readData}>버튼이에오</button> */}
            {loading && <div>로딩중이다</div>}
            <Link href='/sample'>
                <a>샘플페이지 이동</a>
            </Link>

            {value?.docs.map(e => console.log(e.data()))}
            <Button>개미 버튼</Button>
            <ThemeTest>THEME PROVIDER TEST</ThemeTest>
        </div>
    );
    }

document 데이터 가져오기
firebase console -> firstore database에서 규칙을 true로 수정해줘야한다.

 

컬렉션에서 데이터를 가져오기까지만 세팅하였고 인증등은 프로젝트 시작하면서 그때 사용해보려고 한다.

firebasehooks 공식문서에 잘나와있다 !

https://github.com/csfrequency/react-firebase-hooks/tree/ef58420b1c74ea5b5d2cec42fe24370f45b76950/firestore#usecollection

 

GitHub - CSFrequency/react-firebase-hooks: React Hooks for Firebase.

React Hooks for Firebase. Contribute to CSFrequency/react-firebase-hooks development by creating an account on GitHub.

github.com

 

역시 개발은 세팅이 9할이다 !!

이곳저곳 떠돌며 참고하며 한거라 틀린 부분이 많이 있을것 같지만.. 작동은된다..

 

Next js는 리액트와 크게 다를것 같지 않았고, recoil은 조금만 해보면 saga보다 편하게 할 수 있지 않을까 생각이 든다.

firebase는 처음에 데이터 가져오기까지 많은 시간이 걸렸는데, 알고보니 환경변수에 오타가 있었다

후..................................................................분명 복붙했는데 .................................... merge...............

 

hooks와 ui 라이브러리를 이용하면 내가 생각했던것 보다 쉬울지도 모를거라는 착각에 빠져들고있따.

 

보자보자 어디보자 jest 아 넌 담에보자

너무어렵ㅂ따 꼽표다