css는 디자인 적인 부분이니 차치하고, 핵심 기능 역할을 수행하는 js를 위주로 살피자.
일단 들어가기 앞서, create-react-app으로 자동 생성된 이 리액트는 확장자명 js 파일을 사용한다.
하지만 조금만 구글링을해서 git 등에서 다른 사람들의 리액트 프로젝트를 보면 js(자바스크립트) 확장자 대신 jsx(자바스크립트 확장, eXtension)를 사용하는 경우를 심심치 않게 볼 수있다.
그래서 js대신 jsx를 쓰는 리액트 프로젝트는 무엇인가에 대해 궁금함을 가질 수도 있다고 생각한다.
여기 그 궁금증을 해결해 줄 오랜 친구 스택 오버 플로우를 살펴보자.
링크 :
JS vs JSX
jsx는 js와 확장자로서의 차이점은 없으나
jsx가 표준 자바스크립트 문법이 아니므로 호환성 등을 고려해야 하는 논쟁이 있을 수 있고, 그냥 취향차이 에 가깝다.
다만, jsx는 표현식을 포함할 수 있는 강력한 객체를 제공함으써, 확실히 렌더링시 사용자의 편의를 줄 수 있다.
요약하면,
1. js와 jsx의 확장자역할의 차이는 없고,
2. jsx는 js에 비해 강력한 객체를 확장해 지원하지만,
3. 논쟁이 있을 수 있고, 취향차이에 가깝다는 것이다.
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
자 본론으로 돌아와서 App.js를 보자. html문법에 해당하는 return이하를 날리고 js 구조만을 생각해 보도록 하자.
import logo from './logo.svg';
import './App.css';
function App() {
return ( //...중략...
);
export default App;
}
얼마 안되니 순차적으로 살펴보겠다.
import logo from './logo.svg';
App.js 파일이 위치한 폴더와 같은 폴더에 있는 logo.svg 파일을
logo라는 이름으로 이 App.js파일에 import해 사용하겠다.
import './App.css';
App.js 파일이 위치한 폴더와 같은 폴더에 있는 App.css 파일을 사용하겠다.
function App() { return ( //...중략... ) };
return 부 안쪽을 리턴하는 함수 App을 정의하겠다.
export default App;
함수 App을 default export 형태로 내보내겠다.
여기서 가장 마지막 export default App에 집중해 보도록 하겠다.
java스크립트에서 export, 즉 내보내는 방법은 2가지가 있다.
1. default export
하나는 지금 이 default export다.
export default class User {...} 의 형태로 export하고
import User from ... 의 형태로 import한다.
여기서 default의 특장점은
한 js 파일에서 default export가 유일하다는 예시를 들면
import logo from './logo.svg';
import './App.css';
function App() {
return ( //...중략...
);
}
function Test() {
return ( //...중략...
);
}
export default App;
export default Test;
이러면 export default Test에 빨간줄이 그어지는 것을 확인 할 수 있다.
import 받는 측에서 수정 가능하다는 예시를 들면
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Bpp from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Bpp />
</React.StrictMode>
);
실제로 App.js의 함수명은 App이지만 여기서는 Bpp로 명명해서 사용 가능한 것을 볼 수 있다.
2. named export
named export는 말그대로 이름이 있는 export이다.
해당 클래스, 컴포넌트, 펑션을 해당 이름 그대로 외부에 가져다 쓰겠다. 는 의미이다.
export class User {...} 형태로 export 하고
import {User} from ... 형태로 import 한다.
상기된 App.js파일은 default export 형태로 작성되어 았으며
이렇게 class가 아닌 함수형 컴포넌트에서도 적용가능함을 인지하고,
named export 형태로 바꾼다면
import logo from './logo.svg';
import './App.css';
export function App() { //여기에 export를 달아주어
return ( //...중략...
);
}
export function Bpp() { //여기에 export를 달아주어
return ( //...중략...
);
}
//여기서 export를 지우고
default 와는 달리 여러개의 함수를 export 할 수 있다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { App, Bpp } from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
<Bpp />
</React.StrictMode>
);
이처럼 중괄호를 사용하여 App.js의 export function App에 접근 가능하다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import App from './App';
import =>
const root = ReactDOM.createRoot(document.getElementById('root'));
document.getElementById('root')가 저번 public 폴더의 index.html의 id="root"엘리먼트를 찾고 해당 엘리먼트를 루트라고 한다.
이 위치
root.render(<React.StrictMode><App />
</React.StrictMode>)
이번엔 index.js를 살피도록하자.
이것은 root에서 임포트한 App.js를 실행한다.
특히, React.StrictMode는 자바스크립트의 엄격모드와 같이 이하의 자식 컴포넌트에서 문법에 맞지않거나 맞지않을 우려가 있거나 지원 종료된 함수의 호출 등을 검사하는 기능을 수행한다.(빼도 된다)
reportWebVitals는 앱의 퍼포먼스 시간을 제공하는데 실행 플로우 이해상 그다지 중요하지는 않아 생략한다.
프로젝트를 git에서 작업할 때, git에 push시 푸쉬하지 않는 영역을 지정한다.
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
git에 푸쉬할 때
/node_modules 폴더를 제외한다, /.pnp를 제외한다....
이런 의미다.
여기엔 git에 올리기 민감한 정보, private_key, DB접근 url id pw 등등을 답은 .env 파일을 포함할 수 있으며
node npm 사용자로써 의식해야 하는 것은
/node_modules를 제하고 푸쉬하므로 git에서 clone 받아 실행할 때, node_modules는 포함되어 있지 않기 때문에 npm i를 수행해서 필요한 디펜던시 모듈들을 설치 하고, npm start를 해야한다.
{
"name": "project_name",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
dependencies를 위주로 보면 된다.
프로젝트를 진행 하다 보면 npm i [모듈명] 으로 외부 모듈을 가져다 쓰는 경우가 있을 텐데 해당 모듈들은 전부 이 dependencies에 명시된다. clone 받은 뒤에 비어있는 node_modules를 채우는 것도 이 파일을 중심으로 해결된다.
lock은 의존성 트리를 포함해서 저장하는데 여기는 크게 건드릴 게 없다. 알고만 있자.