저번시간에 state 를 deepcopy 하면서 새로운 배열을 복사하는 방법까지 배웠다.
이번시간에는 나머지 문법강의인 Component부터 신문법과 구문법의 차이까지 배워보자.
코딩애플 React 강의는 크게 세가지 파트로 나뉘어져있다.
part 1: 블로그 제작 & 기초문법
part 2: 쇼핑몰 프로젝트
part 3: 실무에 필요한 부가내용
이번시간까지하면 part 1을 마무리하게 되는데, 이전에스파르타코딩클럽 웹개발을 수강하며 자바스크립트를 배웠던 기억을 되살려 문법을 공부하는데 react의 기본문법이 javascript다 보니까 일부 배웠던 내용들이 나와서 기분이 좋았다.
아직은 부족하지만, 꾸준히 공부하다보면 언젠간 빛을 발하지 않을까
우리는 지금까지
<div className="modal">
<h2>제목</h2>
<p>12월 1일</p>
<p>상세내용</p>
</div>
HTML을 만들어서 같은 코드를 여러줄을 작성해서 사용했다.
하지만, " Component문법을 사용하게 되면 긴 HTML을 한 단어로 깔끔하게 넣을 수 있다. "
function App(){
return(
<div>
<Modal></Modal>
</div>
)}
function Modal(){
return(
<div className="modal">
<h2>제목</h2>
<p>12월 1일</p>
<p>상세내용</p>
</div>
)
}
이렇게 사용하면 원하는 HTML을 <Modal></Modal>이라는 한 단어로 줄일 수 있다.
주의할점은
- Component Naming할때 첫글자는 보통 영어대문자로 시작한다.
- return() 내부에 있는건 태그하나로 묶어야한다. (
<div></div>)- 의미없는 태그로 묶어줄때는
fragment:< > </>를 사용하자.Component의 위치는function App(){}과 나란히 만든다.
그렇다면, 모든 HTML을 Component로 치환하기는 힘들텐데 어떤 HTML들을 Component로 만들까?
기준은 따로 없으나 관습적으로 다음과 같이 사용한다.
- 사이트에 반복해서 출현하는
HTML- 내용이 변경되는 빈도가 높은
HTML- 다른 페이지를 만들고 싶으면 해당 페이지의
HTML내용들을 하나의 컴포넌트로 만드는게 좋다.(필수는 아님)- 다른 팀원들과 협업할때 웹페이지를
Component단위로 나눠서 작업을 분배하기도 한다.
Component를 많이 사용하게 되면 단점도 있기마련인데,
제일 큰 단점은 " 상위 state를 사용하고 싶을때 props 문법을 사용해야한다. "
클릭하면 보여주는 간단한 UI는 삼항연산자를 사용하면 되는데,
기존 쌩 javascript에서는 다음과 같은 코드를 작성했었다.
function openClose() {
// id 값 post-box의 display 값이 block 이면
if ($('#post-box').css('display') == 'block') {
// post-box를 가리고
$('#post-box').hide();
} else {
// 아니면 post-box를 보여주기
$('#post-box').show();
}
}
하지만, react에서는 현재 상태를 state에 저장하고 if문을 사용해서 state에 따라 모달창을 보여준다. 다음은 삼항연산자를 사용한 예시이다.
조건식
? 참일때 실행 할 코드
: 거짓일때 실행 할 코드
react에서 클릭할때 보이는 UI 만드는법은 다음과 같다.
- UI가 보이는 / 보이지 않는 상태정보를
state에 저장한다. (보통 true / false 형으로 사용함.)state가true일때만 UI를 보여준다고 가정함<열기버튼>을 누르면state가true로 바뀌도록 기능개발한다.
function App(){
let [UI보이기, UI보이기함수] = useState(false);
return(
{
modal === true
? <Modal />
: null
}
<button onClick={() => { UI보이기함수(true)} }>열기</button>
)
이렇게 설정하면 state가 true로 바뀌게 된다.
이전시간에 state를 변경하려면 복사본을 만들어서 수정하라고 했었다.
하지만, 복사본을 생성하는것은 reference 자료형(array, object)들만 하면 된다.
문자, 숫자, boolean들은 할 필요가 없다.
위에서 알려준 내용은 버튼을 한번 누르게 되면
state가 true상태가 되는데, 한번 더 누르면 state가 변경되는 문제였다.
간단하게 !modal을 붙이면 되는 문제였다.
function App(){
let [modal, modal함수] = useState(false);
return(
<div>
<button onClick={() => {modal함수(!modal)}}>열고닫는버튼</button>
{
modal === true
? <Modal />
: null
}
</div>
)
}
실행결과


map은 중괄호 안에서 사용하는 반복문이고, array에 붙일 수 있는 일종의 내장함수이다.
array안에 자료형이 있다고 가정해보자.
그러면, array안의 모든 자료에 똑같은 작업을 하나씩 시켜주고 싶을 때가 있을것이다.
그럴때, map이라는 내장 함수를 사용하면 된다.
let array = [2, 3, 4];
array.map(function(){
});
위처럼 사용하면되고, map 안의 코드가 array 자료의 갯수만큼 실행된다.
array는 3개의 자료를 갖고있으니 3번 실행되겠다.
만약, array내부의 자료에 10씩 곱해주고 싶다고 하면
let array = [2, 3, 4];
let newArray = array.map(function(n){
return n * 10
})
console.log(newArray)
👉🏽 [20, 30, 40]
여기서 n 파라미터는 array 안에 있는 모든 자료를 하나씩 출력해주는 역할이다. n에 어떤 식을 사용하든 상관없다.
그리고, map 함수는 원본 자료형을 변형시키지 않아서 보통 새로운 변수에 담아서 사용한다.
그렇다면, 지금까지 사용했던 HTML코드를 map함수로 간단하게 표현해보자.
function App(){
let [글제목, 글제목함수] = useState(['커피 맛집 추천', '동탄 맛집 추천', '리그오브레전드' ]);
return(
{
글제목.map(function(글){
<div className="list">
<h2> {글} </h2>
<p> 12월 1일 발행 </p>
<hr />
</div>
)}
이렇게 작성하면 HTML을 하드코딩하지 않아도 글제목 배열안에 값만큼 만들어진다.

일반 for문을 쓰고싶다면 다음과 같이 사용할 수 있다.
function App(){
function 반복된UI(){
let array = [];
for (let i = 0; i < 3; i++){
array.push(<div>안녕</div>)
}
return array
}
return (
<div>
{반복된UI}
</div>
)
}
map함수를 사용하고나서 console 창을 띄워보면 다음과 같은 warning이 보인다.

이는 key={ 파라미터 }를 적지 않아서 생기는 에러이다.
react는 반복문을 작성한 HTML요소에는 꼭 key={ 파라미터 }를 적으라고 권장한다.
let [글제목, 글제목변경] = useState(['배추도사 무도사', '아이폰 XS', '김치찌개']);
{
글제목.map(function (글) {
return (
<div className="list" key={글}>
<h3>{글}</h3>
<p> 12월 2일 발행 </p>
<hr/>
</div>
)})}

앞서 Component를 사용할때 가장 큰 단점은 상위 state를 사용하고 싶을때 props 문법을 사용해야한다고 작성했다.
코딩을 깔끔하게 하고 싶다면 여러 난관을 극복해야한다.😃😃
그렇다면, props를 배워보자.
props란 자식 Component가 부모 Component를 사용하고 싶을때 사용하는 문법이다. 다음과 같은 과정을 밟으면 사용가능하다.
- <자식 Component 전송할 이름 = {state명}>
- function안에 동일한 파라미터 생성
코드로 설명하자면
function App(){
let [글제목, 글제목함수] = useState(['커피 맛집 추천', '동탄 맛집 추천', '리그오브레전드' ]);
return(
<div>
<Modal 글제목 = {글제목} ><Modal>
</div>)
}
function Modal(props){
return(
<div className="modal">
<h2> {props.글제목[0]} </h2>
<p> 12월 1일 발행 </p>
<p> 상세내용 </p>
</div>
)
}
[ 참고1 ] props는
<Modal 글제목 = {글제목} 좋아요 = {좋아요}></Modal>처럼 변수를 무한정으로 전송할 수 있다.
[ 참고2 ]props.글제목이런식으로 원하는 것만 꺼내쓰면된다.
[ 참고3 ] 글제목 = { 변수명 } 글제목 = "동탄맛집" 처럼 일반 텍스트는 " 따옴표 "를 작성하여 사용해도 된다.
내가 이해하는데 시간이 조금 걸렸던 예제이다.
강의를 듣다가 중간에 멈추고 30분정도 고민했던 예제이기도 하다.
function App(){
let [글제목, 글제목함수] = useState(['커피 맛집 추천', '동탄 맛집 추천', '리그오브레전드' ])
let [누른제목, 방금누른제목] = useState(0);
}
return(
{
글제목.map(function(글, i){
<div className = "list" key={i}>
<h3 onClick={() => {방금누른제목(i)}}>{글} <span> 👍🏽 </span> </h3>
<p> 12월 1일 발행 </p>
<p> 상세내용 </p>
<hr/>
</div>
)}
<Modal 글제목 = {글제목} 누른제목 = {누른제목}>
)
function Modal(props){
return(
<div className="Modal">
<h3>{props.글제목[props.누른제목]}</h3>
<p>12월 1일 발행</p>
<hr/>
</div>
)
}
처음에 글제목 state를 정의한 내용을 map 함수에 {글}이라는 파라미터로 넣었다.
글제목은 3개 값이 들어있으니까 총 3개의 <div>가 생길 것이다.
Modal 창 구현은 아들 Component에서 props문법을 사용하면 된다.
<Modal 글제목 = {글제목} 누른제목 = {누른제목}></Modal>을 통해 자식 Component에 전달할 수 있다.
Modal에서 <h3>{props.글제목[props.누른제목]}</h3> 을 사용하고 위에서 방금누른제목(i)를 사용함으로써 누른제목이 몇번째인지 알 수 있다.
map 반복문을 쓸 때 i라는 파라미터를 뒤에 추가해주는데, 이는 반복문이 돌면서
0, 1, 2, 3... 하나씩 증가하는 정수를 뜻한다. 이를 enumerate라고 부른다.
다른 제목을 누를때마다 Modal창의 제목도 변경되는 모습


결론적으로 state는 UI의 현재상태를 보관하는 저장소 역할을 한다.라고 생각하면 기억을 쉽게 할 수 있다.
자바스크립트와 다른점이 있다면 <input></input>처럼
코드가 끝날때에도 </input>을 선언해줘야 한다는 점이다.
input에 저장 할 데이터도 마찬가지로 state에 저장한다.
빈 state는 다음과 같이 선언한다.
let [입력값, 입력값변경] = useState('');
useState에 초기값을 보통 ' '으로 선언하는데
무엇을 담을지 모르겠다면 [ array ]나, ' 빈 문자열 '을 선언해주도록 하자.
input의 입력값을 알고 싶을때는 onChange 함수를 사용하자.
onChange는 input에 무언가를 입력할때마다 특정 함수를 동작시킬때 주로 사용한다.
먼저, 입력한 값을 console.log에 찍어보자
function App(){
let [입력값, 입력값변경] = useState('');
return(
<div>
<input onChange={(e) => {console.log(e.target.value)}}></input>
</div>
)
}
여기서 e.target은 쌩 javascript 문법으로 지금 이벤트가 동작하고 있는 HTML요소이고, .value는 input에 입력한 값을 의미한다.

이렇게 <input></input>에 작성한 내용이 나온다.
<textarea>, select 에도 사용가능하다.
쌩 javascript 에서는
let keyword = $(`#post-url`).val()
jQuery를 이용해서 입력값을 찾았는데 이는 react와는 다르다. (😁 좋다. 😁)
그럼, console.log말고 state에 저장해보자.
아까선언했던 입력값에 저장하면 되겠다.
function App(){
let [입력값, 입력값변경] = useState('');
return(
<input onChange={(e) => {입력값변경(e.target.value)}}></input>
<hr/>
{입력값}
)
}
입력값함수 안에 e.target.value를 담았다.
이제 input에 뭔가를 입력 할 때 마다 입력값의 state가 e.target.value로 바뀔것이다

내가 여기서 고민했던 방향은 다음과 같았다.
map반복문을 돌리고 있기 때문에 같은HTML을 어떻게 생성하지? 보다는글제목이라는 변수에 어떻게입력값을 넣어주지? 라고 생각했다.- 원본
state는 되도록 수정하지 말라고 하셨다.
결론적으로 " 방향이 달랐다."
게시물이 1개 이상 작성하게 되면 5개, 6개 새로 추가되는것이 아니고
항상 4개인 게시물인 결과가 나왔다. 😂 😂
function App(){
let [글제목, 글제목변경] = useState(['배추도사 무도사', '아이폰 XS', '김치찌개']);
let [입력값, 입력값함수] = useState('');
return(
{
return(
글제목.map(function(글){
<div className="list" key={글}>
<h3>{글}</h3>
<p>12월 2일 발행</p>
<hr/>
))}
<input onChange={(e) => {입력값함수(e.target.value)} }></input>
<button onClick={() => {글제목변경([입력값, '배추도사 무도사', '아이폰 XS', '김치찌개']);}}>게시물 추가</button>
)}
개발자는 구글링을 잘해야한다는데, 괜히 나온말이 아닌 것 같다.
" 배열에 원소추가하는법 "을 검색하면 금방 풀 수 있던 내용이었다.
배열에 원소를 추가하는 방법
- unshift(): 맨 앞에 원소를 추가하는 메소드
- push(): 맨 뒤에 원소를 추가하는 메소드
- shift(): 맨 앞에 원소를 제거하는 메소드
- pop(): 맨 뒤에 원소를 제거하는 메소드
간단한 test를 해보자.
let array = [1, 2, 3];
let newArray = [...array];
// unshift()
newArray.unshift(0);
console.log(newArray);
👉🏽 [0, 1, 2, 3]
// push()
newArray.push(4);
console.log(newArray);
👉🏽 [1, 2, 3, 4]
// shift()
newArray.shift();
console.log(newArray);
👉🏽 [2, 3]
// pop()
newArray.pop();
console.log(newArray);
👉🏽 [1, 2]
마찬가지로 react로 돌아가보면
let [글제목, 글제목변경] = useState(['배추도사 무도사', '아이폰 XS', '김치찌개']);
let [입력값, 입력값함수] = useState('');
{글제목}이라는 배열 맨 앞에 {입력값}이 추가되면 된다.
그러므로 unshift()를 사용하면 된다!
function App(){
let [글제목, 글제목변경] = useState(['배추도사 무도사', '아이폰 XS', '김치찌개']);
let [입력값, 입력값함수] = useState('');
return(
<input onChange={(e) => {입력값함수(e.target.value)} }></input>
<button onClick={() => {
let 뉴글제목 = [...글제목];
뉴글제목.unshift(입력값);
글제목변경(뉴글제목);
}}></button>
)}
unshift()를 사용하면 맨 앞에 글을 추가하고,

push()를 사용하면 맨 뒤에 글을 추가 할 수 있다.
결론적으로 글제목이라는 state의 상태를 직접 건들지 않고 해결 할 수 있다.
지금까지 배웠던 Component, 함수만들기, state 상태변경등의 방법들은
모두 react의 신문법이었다.
그러나, 개발자일을 하다보면 구문법도 마주 할 수 있다.
구문법의 틀을 알아보자.
setState만 변경하려면 구문법을 사용하는것이 편하다.
딱 필요한 부분만 수정하고 나머지는 건들지 않기 때문이다.
하지만, 신문법은 state deep copy -> 수정 -> paste 작업을 거쳐야한다.
예전문법은 다음과 같다
class: 변수 / 함수를 보관하는 덩어리extends: 우측 성질을 물려받아 만든다React.Component: 컴포넌트 성질을 갖고있는 문장constructor: 새로운 변수를 넣는 공간super:extends React.Component의 변수들을 그대로 물려받아 쓴다.extends해서class를 만들면Component를 계속 만들 수 있다.
class Profile extends React.Component {
constructor(){
super();
this.state = { name: 'AN', age: 25}
}
changeName = () => {
this.setState({name: 'yeong'})
}
render(){
return(
<h3>저는 { this. state. name } 입니다.</h3>
<button onClick={() => {this.setState({name: 'Woo'})}}> 버튼 </button>
<button onClick={() => {this.changeName}> 버튼 </button>
)
}
}
javascript에서 () => {} (arrow function)과 그냥 function(){}은 거의 비슷하게 쓰이는데,
arrow function을 사용하면 안에 있는 this값을 재정의하지 않고,
바깥에 있던 this의 값을 그대로 갖고와서 사용 한다.
그러나, function(){}을 사용하면 this 값이 새롭게 변한다.
결론적으로 arrow function은 내부의 this키워드 값을 변화시키고 싶지 않을 때 사용한다.
지금까지 React의 핵심문법에 대해서 배워봤다.
part.1를 공부하는데 거의 7일 정도 소요됐던것 같다.
건물을 지을때 기초가 중요하듯이 프로젝트를 진행하기전에도 기초가 중요하다.
처음 react의 아이콘을 마주했을때는 보이지 않는 벽이 느껴졌는데 기초문법과 블로그제작의 기초를 배우니 어느정도 허물어진것 같다.
벌써 강의의 1/3을 들었다는게 믿기지 않는다.
남은 part.2 쇼핑몰 프로젝트 와 part.3 실무에 필요한 부가내용을 배우고 나만의 블로그를 제작하고 싶다.
얼른 배워서 내 홈페이지에 react 기능을 추가하고 싶다.
남은 강의도 아자아자! 🤩 🤩
잘 보고 갑니다.