리뷰 피드백 반영하기1. ts, webpack, react 세팅2. data-table 구현2.1 [feat] data, column을 가지는 기본 Table 구현2.2 [feat] sort 기능 구현2.3 [feat] searchFilter 구현3. 이슈 및 질문4. 소감 및 아쉬운 점참고링크
리뷰 확인 및 반영리뷰 피드백 반영하기
1. ts, webpack, react 세팅
- npm init -y
- react 설치
npm i react react-dom
- typescript 설치
- tsconfig 설정
- gitbook
- tsconfig.json 컴파일 옵션 정리
npm i -D typescript @types/react @types/react-dom
내 설정
{ "compilerOptions": { "target": "es5", // 컴파일 된 결과물이 어느 버전의 ECMAScript를 따를 것인지 "strict": true, "module": "esnext", // 프로그램에서 사용할 모듈 시스템. import/export 코드가 어떤 방식의 코드로 컴파일 될지 결정 "esModuleInterop": true, // es module 사용시 컴파일 단계에서 헬퍼 함수를 사용 여부 "allowJs": true, // js files를 허용 여부 "sourceMap": true, // map 파일 생성 여부 "skipLibCheck": true, // 사용하는 라이브러리의 타입 검사를 skip 여부 "forceConsistentCasingInFileNames": true, // 파일명에 대소문자 구분하지 않아도 되는 기능 사용 여부 "moduleResolution": "node", // 모듈 해석 방법 "isolatedModules": true, // 각 파일을 분리된 모듈로 트랜스파일링 할 지 여부 "noEmit": true, // 컴파일러의 js 파일 등 출력 결과물 여부 "jsx": "react-jsx", // jsx 코드를 어떻게 컴파일 기준 "baseUrl": "./", // 비상대적 import 모듈 해석시 기준이 되는 경로 "paths": { "@/*": ["src/*"] } }, "include": ["src"] }
- webpack 설치
- webpack
- 기본 webpack 라이브러리
- loader 및 플러그인
- 단순히 비교하면 번들이 생성 되기 전(빌드 전)에 쓰이냐, 후에 쓰이냐로 구분할 수 있다
- loader는 webpack으로 빌드를 진행하기 전/진행 중에 개별 파일들(빌드 과정에 포함되는 각 파일들)에게 적용하기 위해 사용된다
- plugin은 번들이 생성 된 후 결과 파일에 적용하기 위해 사용된다. 번들된 js 난독화, 압축, 복사, 특정 텍스트 추출, 별칭 등 부가 작업 등등 후처리를 한다.
- ts-loader는 타입스크립트 컴파일 단계를 웹팩안으로 통합하여 진행하도록 함
- fork-ts-checker-webpack-plugin은 타입스크립트 타입 검사를 별도로 실행하는 웹팩 플러그인입니다. 웹팩을 실행하면 먼저 컴파일과 번들링만 빨리 실행하고 타입 체크는 좀 늦게 따로 실행할 수 있습니다.
- webpack.config.js 설정
npm i -D webpack webpack-cli webpack-dev-server
npm i -D ts-loader css-loader style-loader file-loader html-webpack-plugin
fork-ts-checker-webpack-plugin
❓ loader와 plugin은 무슨 차이일까?
❓ ts-loader, fork-ts-checker-webpack-plugin (링크)
code
require("dotenv").config(); // ❓ const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); const isProd = process.env.NODE_ENV === "production"; // ❓ const PORT = process.env.PORT || 3001; module.exports = { mode: isProd ? "production" : "development", devtool: isProd ? "hidden-source-map" : "source-map", entry: "./src/index.tsx", output: { filename: "[name].js", path: path.resolve(__dirname, "public"), publicPath: "/", clean: true, }, resolve: { extensions: [".js", ".jsx", ".ts", ".tsx"], alias: { "@": path.resolve(__dirname, "src"), }, }, module: { rules: [ { test: /\.(ts|tsx)$/, loader: "ts-loader", options: { transpileOnly: isProd ? false : true, }, }, { test: /\.css?$/, use: ["style-loader", "css-loader"], }, { test: /\.(webp|jpg|png|jpeg)$/, loader: "file-loader", options: { name: "[name].[ext]?[hash]", }, }, ], }, plugins: [ new ForkTsCheckerWebpackPlugin(), new HtmlWebpackPlugin({ template: path.resolve(__dirname, "public", "index.html"), }), ], devServer: { port: PORT, historyApiFallback: true, }, };
- emotion & storybook설치
npm i @emotion/styled @emotion/react
npx sb init --builder webpack5
2. data-table 구현
2.1 [feat] data, column을 가지는 기본 Table 구현
- data와 columns를 props로 받아, Table형식으로 나타내는 기본 컴포넌트 구현
- content가 길어질 경우 ellipsis 처리
- data가 배열일 경우, map으로 풀서주는 처리
- Header와 Content의 간격을 맞추는 작업
- flex 속성으로 각 요소에
flex-grow:1
,flex-basis:0
을 주어, 절대적으로 n등분 하는 넓이를 가지도록 함 - ellipsis 지정을 위한 속성 적용
flex-wrap: nowrap;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

2.2 [feat] sort 기능 구현
…
2.3 [feat] searchFilter 구현
- keyword를 useState로 관리하고, keyword변화에 따라 useEffect를 통해, filteredData를 tData로 setState해주는 방안 시도
- tData자체가 계속 변하기 때문에, keyword를 지워도 이전에 tData로 돌아갈 수 없는 이슈 발생
- setState로 update해주는 것이 아니라, 렌더링 시 바로 filter를 적용하여, filter 할 것이 없으면 바로 tData를 보여주게 함으로 해결
3. 이슈 및 질문
이슈1. 이전 data 참조 오류- 리렌더링 되는데 이유 찾기 어렵다
Tab click
⇒App setState(”SORT”) → <DataTable
data
={movies2} />
⇒- data를 prop으로 받아서, DataTable내에서 tData로 초기값만 받으며 사용하는데, 이 패턴이 잘 못된 것 같다는 생각도..
- 코드실행 순서는
rendering
⇒effect hook 실행
이기 때문에, 이전의 tData를 통해 렌더링이 먼저 되는 것이 당연하다.- 단 나는 tData가 update 되기 전 data이므로 불필요한 리렌더링 및 이 과정에서 error 발생한다.
- useEffect로 props로 받아온 data를 설정할 때, 첫 리렌더링을 막는 방법 ⇒
해결 포커스 아니였음
문제

- 세부구현 함수의 위치
- 세부구현 함수 필요하다고 생각 for DX(가독성). 동의하시는지?
- 함수명만으로도 주요 로직에 대한 이해가 가능할 정도라면 함수화 (나의 기준)
- 재사용성 있다면 util에 두겠지만, 해당 컴포넌트에서만 쓰일 경우, 어디에 두어야 할지
- 어느정도로 쪼개는게 좋을 지
4. 소감 및 아쉬운 점
- DX에 대한 고민 조금 더 할 수 있지 않았나
- 다양한 data 타입에 대한 처리 ( Date타입이라던가, 현재는 string | number | string[])
- UX 관련
- 이 컴포넌트 언제/왜 사용할까에 대한 고민에 맞는 기능 추가
- expendable 기능
- editable 기능
과제 안내 ⇒ Link
이 과제는 실제 프론트엔드 신입 채용 과제임으로 각별히 외부 유출에 주의해 주시기 바라며, 특히 블로그 포스팅에 유의해 주시기 바랍니다.
💡 과제 안내
- 과제 기간: 6월 28일(화) ~ 7월 3일(일) 오후 23시 59분
- 리뷰 기간: 7월 4일(월) ~ 7월 9일(토)
- 내용: 포맷팅 가능한 input 컴포넌트 작성하기와 확정 가능한 DataTable 컴포넌트 구현 둘 중 하나를 선택해서 과제를 완성해 주세요. 예시로든 라이브러리 코드는 가급적 참고하지 않고 구현하는 것을 추천합니다.
- 2가지 과제 중 택 1 진행, 시간이 된다면 2가지 다 구현해보셔도 됩니다.
포맷팅 가능한 input 컴포넌트 작성하기
자신이 가장 잘 쓸 수 있는 웹 프레임워크, 라이브러리를 통해 포멧팅 가능한 input 컴포넌트를 구현합니다. 휴대폰 번호, 날짜, 시간, 숫자 등을 포함해 최대한 많은 기능을 사용할 수 있도록 작성해 보세요.
ex) 날짜의 경우 20191225라고 입력하면 2019-12-25으로 입력과 동시에 포맷팅
ex) 숫자의 경우 123456789라고 입력하면 123,456,789으로 입력과 동시에 포맷팅
라이브러리 예
확장 가능한 DataTable 컴포넌트 구현
자신이 가장 잘 쓸 수 있는 웹 프레임워크, 라이브러리를 통해 rowspan, colspan, floating header, sort, search, group, selectable, expandable, custom styling 등 확장 가능한 테이블 컴포넌트를 설계, 구현해 보세요. 최대한 많은 기능이 있을 수록 좋습니다.
라이브러리 예