컴포넌트(사용자 정의태그)를 사용하여 가독성 및 재사용성 향상
환경 설치/설정을 하지 않고 웹 브라우저에서 바로 웹 개발을 할 수 있도록 해주는 온라인 개발환경
순수 자바스크립트는 아니다. js라는 확장자를 사용하고 있지만 실제 확장자는 jsx를 사용하고 있으며 스크립트안에 태그를 직접 사용할 수 있다.
function App(){
return(
<div className="App">
<h2>Hello, ReactJS!</h2>
</div>
)
}
-> vue와 마찬가지로 최상위 엘리먼트는 항상 1개여야 한다.
리액트 프로젝트 개발 시 목표에 따라 필요한 여러 가지 개발 환경 및 도구를 모아 한 번에 제공하는 도구
vue에서는 npm install -g @vue/cli > vue create . 혹은 vite 하면 뷰에서 사용 가능한 도구를 설치할 수 있었다.
이것처럼 리액트에도 툴 체인이라는 도구가 있다.
Next.js(풀스택 개발에 유용한 프레임워크)
Remix(중첩 라우팅을 활용하는 기술을 제공한다.)
Gatsby(cms 백엔드 개발에 유용한 기술 제공)
등이 있다.
윈도우 운영체제 설치방법
1. npm install -g create-react-app
맥 운영체제 설치방법
2. sudo install -g create-react-app
설치 확인
3. create-react-app -V
npm == 프로그램 설치
npx == 해당 프로그램을 한 번만 설치 후 자동 삭제
=> 컴퓨터 공간 낭비를 방지할 수 있다.
=> 설치할 때 마다 새로 다운로드 받기 때문에 항상 최신 상태를 유지할 수 있다.
프로젝트 폴더의 경로에 한글이 포함되어 있으면 프로젝트 실행이 되지 않는 경우가 있으므로 주의해야 한다.
개발에 필요한 디렉토리 생성
-> 디렉토리 이름은 react사용 불가
터미널 또는 cmd에서 디렉토리 이동
-> cd
프로젝트 생성 명령 입력
-> create-react-app [프로젝트명]
-> create-react-app . (현재 디렉토리에 설치)
npm start
-> vue와 다르게 자동으로 실행이 된다. (vue는 ctrl을 함께 눌러야 실행이 되었다.)
app.js
app.vue와 같은 역할
index.js
main.js와 같은 역할
index.css
-> reset.css 처럼 사용해도 된다.
build
-> npm run build 하면 dist가 아닌, build라는 파일이 생성된다.
-> serve build 하면 미리보기 할 수 있다. (serve -s build)
-> 빌드하기 전, npm start 했을 때와 빌드 후 serve build를 비교해보았을 때 용량의 차이가 크다. 배포하기 위해서는 build는 필수!
class vs fuction
기존에는 컴포넌트를 생성할 때 class방식을 사용했지만 함수방식을 사용하도록 많이 변경되었는데, class 방식이 함수방식에서 작동하지 않는 경우도 있기 때문에 함수방식에서도 사용할 수 있도록 hook을 이용한다.
사용자 정의 hook은 이름이 use로 시작한다.
그 중 가장 많이 사용하게 될 hook의 이름에는 use state, use effect 가 있다.
const 변수명 = useState(초기값, 변경될 값) << 두 개를 인자를 가지도록 되어있음
출력할 때 사용되고, 값을 바꿀 때 사용된다는 의미.
(사용 예시)
import './App.css';
import React, {useState} from "react"
function App(){
const _number = useState(0)
const number = _number[0]
const setNumber = _number[1]
let num=0
return(
<div>
<h2>{number}</h2>
<button
onClick={
()=> {
//num=num+1
//console.log(num)
//콘솔의 값은 변경되지만 브라우저의 값은 변경되지 않음
setNumber(number+1)
}
}
>ADD</button>
</div>
)
}
export default App;
(같은 내용 다른 코드)
비정형 배열: 배열은 배열인데, 불규칙적인 형식의 배열 형태
따라서 useState는 첫 번째 인자 담을 변수, 두 번째 인자 담을 변수가 필요하기 때문에 변수를 배열로 담으면 된다.
import './App.css';
import React, {useState} from "react"
function App(){
// const _number = useState(0)
// const number = _number[0]
// const setNumber = _number[1]
const [number,setNumber] = useState(1)
let num=0
return(
<div>
<h2>{number}</h2>
<button
onClick={
()=> {
//num=num+1
//console.log(num)
//콘솔의 값은 변경되지만 브라우저의 값은 변경되지 않음
setNumber(number+1)
}
}
>ADD</button>
</div>
)
}
export default App;
[컴포넌트의 변화 예시, hook 사용 x]
class 방식 컴포넌트
(형식)
import React, {Component} from 'react';
class NAME extends Component {
render(){
return(
)
}
}
(실제 예시)
import React, {Component} from 'react';
class App extends Component {
render(){
return(
<div className="App">
Class Type Component!
</div>
)
}
}
함수 방식 컴포넌트
(형식)
function NAME(){
return(
)
}
<생성 예시>
function App() {
return (
<div className="app">
<header>
<h1>WEB</h1>
<p>Wold Wide Web!</p>
</header>
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JAVASCRIPT</a></li>
</ul>
</nav>
<article>
<h2>HTML</h2>
<p>HTML is....</p>
</article>
</div>
);
}
기존 app.js에서 컴포넌트를 생성하는 방법
규칙 1. 컴포넌트 이름은 첫 글자가 항상 대문자여야 한다.
-> 예를 들어 내가 만든 컴포넌트의 이름이 < header > 라면 기존 html element와 겹치기 때문에 인식할 수 없다. < Header > 처럼 첫글자를 대문자로 설정하여 사용자 이름을 정의해야 한다.
규칙 2. 최상위 엘리먼트 1개 고정, 함수를 생성하여 App에 태그를 불러온다.
function Subject(){
return(
<header>
<h1>WEB</h1>
<p>Wold Wide Web!</p>
</header>
)
}
function Nav (){
return(
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JAVASCRIPT</a></li>
</ul>
</nav>
)
}
function Component(){
return(
<article>
<h2>HTML</h2>
<p>HTML is....</p>
</article>
)
}
function App() {
return (
<div className="app">
<Subject />
<Nav></Nav>
<Component></Component>
</div>
);
}
이렇게 새로운 함수를 생성하고 내용을 return() 안에 담은 뒤 App 안에 태그로 불러온다.
App.js 의 내용을 index.html로 연결시켜주고 있는 파일은 index.js이다.
1. src 폴더 안에 components 폴더 생성 후 안에 js 파일 생성하기

2. 내용 붙여넣기(js 파일 안에) 및 내보내기
function Subject(){
return(
<header>
<h1>WEB</h1>
<p>Wold Wide Web!</p>
</header>
)
}
export default Subject
=> 내보내야 할 함수가 1개라면 export default를 사용한다.
3. 불러오기
import Subject from './components/Subject';
function App() {
return (
<div className="app">
<Subject />
<Nav></Nav>
<Component></Component>
</div>
);
}
export default App;
-> 다른 함수들도 마찬가지로 export default 후 import 해서 app.js 로 불러오기 한다.
//App.js
import Subject from './components/Subject';
function App() {
return (
<div className="app">
<Subject title="WEB"></Subject>
<Nav></Nav>
<Component></Component>
</div>
);
}
//Subject.js
function Subject(props){
return(
<header>
<h1>{props.title}</h1>
<p>Wold Wide Web!</p>
</header>
)
}
export default Subject
Spa 방식의 특징!
불필요한 부분은 수정되지 않고 수정되는 부분만 변환되어서 보여진다.
가상의 DOM을 생성하여 달라지는 부분만 보여지는 것이다.
=> console 창에 같은 데이터가 2번씩 보이는 이유이다.
function Subject({title,content}){
return(
<header>
<h1>{title}</h1>
<p>{content}</p>
</header>
)
}
export default Subject
function Nav ( props ){
//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const content_list = []
for(let i=0; i<props.data_list.length; i++){
let data = props.data_list[i]
content_list.push(
<li key={data.id}>
<a href={data.id + ".html"}>
{data.title}
</a>
</li>
)
}
return(
<nav>
<ul>
{content_list}
</ul>
</nav>
)
}
export default Nav
//app.js
function App() {
//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const data_list = [
{id:1, title: "HTML", content: "HTML is..."},
{id:2, title: "CSS", content: "CSS is..."},
{id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
]
return (
<div className="app">
<Subject title="WEB" content="World Wide Web!"></Subject>
<Nav data_list={data_list}></Nav>
<Component articleTitle="HTML"></Component>
</div>
);
}
export default App;
사용자 정의 이벤트를 만들어야 한다.
//app.js
function App() {
//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const data_list = [
{id:1, title: "HTML", content: "HTML is..."},
{id:2, title: "CSS", content: "CSS is..."},
{id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
]
return (
<div className="app">
<Subject
title="WEB"
content="World Wide Web!"
onTestEvent={
(msg) => alert(msg)
}
></Subject>
<Nav data_list={data_list}></Nav>
<Component articleTitle="HTML"></Component>
</div>
);
}
export default App;
//subject.js
function Subject(props){
return(
<header>
<h1>
<a
href="#"
onClick={
(e)=>{
e.preventDefault();
props.onTestEvent('nct wish!')
}
}>
{props.title}
</a>
</h1>
<p>{props.content}</p>
</header>
)
}
export default Subject


import './App.css';
import Subject from './components/Subject';
import Nav from './components/Nav';
import Component from './components/Component'
function App() {
//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const data_list = [
{id:1, title: "HTML", content: "HTML is..."},
{id:2, title: "CSS", content: "CSS is..."},
{id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
]
let selected = 0;
return (
<div className="app">
<Subject
title="WEB"
content="World Wide Web!"
onTestEvent={
(msg) => alert(msg)
}
></Subject>
<Nav
data_list={data_list}
onChangeSubject={
(get_id) => {
//console.log(get_id)
selected = (get_id-1) //실행되지 않음
console.log("sc : ", selected)
//return selected //실행되지 않음
//변수값이 바뀌더라도 브라우저가 새로고침 되지 않음
}
}
></Nav>
<Component
title={data_list[selected].title}
content={data_list[selected].content}>
</Component>
</div>
);
}
export default App;
function Component(props){
return(
<article>
<h2>{props.title}</h2>
<p>{props.content}</p>
</article>
)
}
export default Component
값이 바뀌면 브라우저의 상태도 변경해주는 변수가 필요한데 이런 경우를 react에서는 state 라고 부른다. => userState (hook) 목차에 설명.
import './App.css';
import React, {useState} from "react";
function Menu( props ){
let menu_list=[]
for(let i=0; i<props.menus.length;i++)
menu_list.push(
<li key={props.menus[i].id}>
<a
href="#"
onClick={
(e) => {
e.preventDefault();
props.onChangeMenu(props.menus[i].id)
}
}
>
{props.menus[i].title}
</a>
</li>
)
return <ul>{menu_list}</ul>;
}
function Item(props){
return(
<div>
<h3>{props.title}</h3>
<p>{props.content}</p>
</div>
)
}
function App(){
//let menu = 0;
const [menu, setMenu] = useState(1)
const menus= [
{id: 1, title:"WISH", content:"Riku"},
{id: 2, title:"HANDS UP", content:"MaeDa"},
{id: 3, title:"SONG BIRDS", content:"MaeDa Riku"},
{id: 4, title:"SAIL AWAY", content:"Kuri"},
{id: 5, title:"NASA", content:"Neko Riku"},
]
return(
<div>
<Menu
menus={menus}
onChangeMenu={
//console.log(menu_id)
(menu_id)=>{
//menu = menu_id
setMenu(menu_id)
console.log("Call Menu Comp : " + menu_id)
}
}
></Menu>
<hr />
<Item
title={menus[menu-1].title}
content={menus[menu-1].content}
></Item>
</div>
)
}
export default App;