Web Front-end 공부/React
생활코딩 React 2022
Hanachoi
2023. 1. 23. 12:04
# Intro
- 복잡한 코드를 숨기고 간단하게 만들어줘서 사용할 수 있는게 React
- 리액트의 핵심적인 역할은 사용자 정의태그를 만들 수 있다는 것이다. 이 사용자 정의태그는 부품처럼 사용될 수 있다. 내 코드를 공유할수도, 남의 코드를 가져와 쓸 수도 있다.
- 리액트는 클래스 문법과 함수문법을 사용할 수 있다. 최근에는 함수를 사용하는 경향이 크다.
#소스코드 수정방법
- 리액트를 실행하기 위해서는 npm이 필요하다. 이건 node.js를 깔면 같이 딸려오는 프로그램.
- 프로그램을 설치 후, npm start를 터미널에 쳐주면 라이브 웹브라우저가 함께 오픈된다.
- 리액트 환경을 구축하고 나면 옆에 이렇게 파일들이 많이 생긴다.
- 여기서 가장 핵심적인 파일은 src/index.js -> 실질적으로 웹페이지에 구현되는 코드들을 담고 있다. 리액트 환경을 구축하고실행하면 움직이는 리액트로고를 브라우저에서 볼 수 있는데, 이 코드들은 App.js의 App 함수로부터 실행되고 있는 부분이다. index.js 파일에서는 <App /> 으로 표시되어 있다.
- index.js에서는 여러가지 전역적인 설정이 들어간다고 생각하면 된다.
- 다시 App.js파일을 보면 그 안에 App이란 함수가 존재하고 그 함수가 바로 리액트로고를 브라우저에 띄우는 역할을 한다.
- 이 파일은 App.css와 연결되어 있다. 디자인을 변경하고 싶다면 App.css를 변경해주면 된다. index.js도 index.css파일과 연결이 되어있는데, 이걸 수정하면 기본적인 css 디자인을 수정할 수 있다.
- 아래의 index.js 이미지를 보면 id값이 'root'인 태그를 골라서 rendering 하라는 코드를 볼 수 있다. 그럼 id값이 root인 저 태그는 어디에 존재하는 것일까? 이건 /public이라는 폴더 안에 있는 index.html에 있다.
- 여태까지 본 파일들은 배포용으로는 용량도 크고 적합하다고 할 수 없다. 그럼 배포를 위한 최적화는 어떻게 해줄 수 있을까?
- 터미널 개발 창에서 npm run build 라고 치면 배포판을 만들 수 있다. 그럼 build라는 폴더가 생기고 그 안에는 여러 파일들이 생기는데 그중에서 index.html파일을 열어보면, 공백조차 없는 html 파일을 볼 수 있다. 배포를 할때는 공백이 필요없기때문에 그마저도 생략한 파일이라고 볼 수 있다.
- 저 명령어를 입력하면 build라는 명령어를 서비스 할 때, serve라는 프로그램을 쓰라는 말이 나온다. serve는 웹서버인데 이 서버가 가지고 있는 옵션 중 -s를 주게되면, 사용자가 어떤 경로로 들어오건 간에 build파일에 index.html로 연결되게 된다,
- serve는 node.js로 만들어진 프로그램이기 때문에 우리가 간편하게 실행시키고 싶을때는 npx를 사용하면 된다.
- npx serve -s build 를 입력해주면 웹서버가 실행되게 된다.
#컴포넌트 만들기
- "리액트는 사용자 정의 태그를 만드는 기술이다. " -> 이게 바로 리액트의 본질이다.
- 예를들어, 지금은 기본적인 html파일의 코드가 1억개 있다고 가정해보자. 우리는 이 코드를 정리정돈 하고 싶다. 정리정돈의 핵심은 같은 역할을 하는 애들끼리 모아서 이름을 붙혀주고 이제 우리는 그 이름만 신경쓰면 되는 것이다.
- 사용자 정의 태그를 만들때는 함수를 정의하면 된다.
- 리액트에서 사용자 정의 태그를 만들때는 반드시 대문자로 시작되어야 한다.
- 사용자정의태그를 위해서 function Header를 정의해준다. return 값으로는 원래 썼던 html 태그를 넣어준다. 그리고 원래 html태그가 있던 자리에 function Header를 <Header />로 넣어주면 된다.
- 이제 <h1>태그가 적용된 모든자리의 코드를 이 function을 다룸으로써 변경이 가능해졌다.
- 이 사용자 정의태그는 컴포넌트라고 불린다. 우리는 이 기능을 통해 독립적인 부품을 만들 수 있게됬고, 복잡도를 훨씬 낮출 수 있게 되었다.
- 다른사람에게 컴포넌트를 공유하거나 다른사람 것을 가져와서 쓸 수있기 때문에 생산성은 폭발적으로 향상된다.
# props
- 리액트에서의 속성을 prop이라고 부른다. 우리가 만든 컴포넌트에 prop을 장착 할 수 있다.
- 만들었던 컴포넌트의 코드를 직접적으로 바꾸지 않고 어떤 속성값을 줬을때 이 내용이 컴포넌트에 반영되게 하고 싶다면?
- <Header title ="REACT">로 title을 정해주고 싶다고 해보자.
- 우리가 만들었던 Header()는 함수이다. 이 안에 파라미터로 props를 넣어주자. 이름은 아무거나 넣을 수는 있지만 보편적으로 props가 쓰이기 때문에 다른걸 쓸 이유는 사실 없다.
- console.log('props', props)를 찍어보면 props에는 객체가 들어오게 되는데, 이 객체의 title이 REACT로 설정되어 있는걸 볼 수 있다.
- 다시 console.log('props', props, props.title)을 찍어보면? 우리가 Header에 넣어준 타이틀 값인 REACT가 콘솔에 찍히는 걸 볼 수 있는데, 그렇다고 해서 바로 Header() 함수에 값을 넣어준다고 똑같이 나오지는 않는다. 이때는 표현식을 사용해야 됨 {props.title}로 넣어주면 REACT가 그대로 나온다.
- 여기서 Article() 함수에도 똑같이 적용하고 싶다면?
- Article 함수부분에 표현식으로 props.title 과 props.body 를 적어서 활용이 가능하다. 이렇게 만들어 놓으면 article 태그가 몇개던지 다양한 내용으로 활용이 가능하다.
- 그렇다면 우리가 만들어 둔 목록을 하드코딩하지 않고 이런식으로 변경 할 수 있을까?
- 일단 목록에 들어가는 정보를 자바스크립트 구조에 맞게 변경해서 넣어야 한다.
- 일단 topics라는 변수에 배열을 만들어준다. 목록은 각각의 제목과 본문, 각자의 아이디값을 가지고 있다. 이런 정보는 객체에 담는게 좋음.
- 이 topics를 <Nav>의 props로 전달해보자.
- topics를 중괄호{}로 감싸줘야 그냥 문자열이 아닌 내용 그 자체가 전달이 된다.
- 이제 Nav() 함수 안으로 들어와서 저 topics를 받아들이려면? 파라미터로 props를 받아주고 lis 라는 새로운 배열을 만들어준다. lis 배열안에는 담고싶은 태그를 넣어준다. 이 배열안에 있는 내용을 return 부분에 풀어 넣어주면 된다. 배열을 <ol></ol>태그 안에 가져다 넣어준다.
- topics로 전달된 값을 받아서 동적으로 {lis}안에 넣어주려면 for문을 돌려 배열안에 넣어준다.
- t.title부분으로 내용을 넣어주고, <a>태그 안에 링크를 설정해서 넣어준다. 마지막으로 우리가 동적으로 만들어주는 이 key들은 각각의 고유한 key prop이 필요하다. 이 반복문안에서만 고유하면 되기 때문에 우리가 처음에 각각 부여했던 {t.id}값을 가져와 넣어준다.
#이벤트
- 지금까지 만든 컴포넌트에는 아직 이벤트 기능이없다. 이벤트기능을 추가해보자
- 위에서 만든 <header>에 클릭했을 때 alert이 뜨는 기능을 추가하고 싶다. 여기서 함수를 넣어주어야 한다.
- 그럼 Header 태그를 어떻게 바꿔야 할까? 위에 작성한 Header()부분으로 올라가 <h1><a> 부분에서 <a>태그에 onClick을 넣어준다. 이건 html과 같은 코드처럼 보이지만 그냥 유사한 코드일뿐 전혀 html이 아니다
- 그렇기때문에 또다시 여기서 함수를 넣어준다. <a>태그가 호출되면 함수가 호출된다. 이때 페이지가 re load 되지 않게 해주려면 콜백함수에 event를 첫번째 파라미터로 넣어주고 event에 preventDefault를 걸어준다. 그리고 밑에서 호출햇던 onChangeMode를 불러준다.
- 화살표 함수로 축약도 가능하다.
- 똑같이 <nav>에서 목록들이 클릭될 때 창이 뜨게 만들고 싶다면? 똑같이 onChangeMode를 <nav>에 걸어주고 Nav()함수에서 <a>태그가 클릭될때 이벤트를 똑같이 걸어준다.
- 이때 onChangeMode를 실행할때 우리는 id 값이 필요하다. 그 아이디 값을 얻기 위해서 <a>태그에 id값을 {t.id}로 부여해준다. id 속성을 얻어내기 위해서 props.onChangeMode(event.target.id)를 넣어준다. 여기서 target은 그 이벤트를 유발시킨 태그를 가르킴.
# state
- 컴포넌트에는 입력과 출력이 존재한다. 입력은 props이고 함수를 만들어 return값을 받아내면 그 return 값이 새로운 함수가 된다.
- props 함께 컴포넌트 함수를 다시 실행해서 새로운 리턴값을 만들어 주는게 바로 state.
- prop은 컴포턴트를 사용하는 외부자를 위한 데이터고, state는 컴포넌트를 만드는 내부자를 위한 데이터라는 차이점이 있다.
- 웹브라우저에서 이 Welcome 부분이 들어오는 값에 따라서 페이지를 바꿀 수 있도록 만들어보자.
- 먼저 mode라는 지역변수를 하나 만들고 여기에 들어오는 값에 따라서 페이지가 변하도록 만들어 준다.
- 그리고 if문을 돌려 welcome일때와 read일때의 화면을 다르게 하도록 해준다.
- 하단 <Article>자리에는 {content}로 값에 따라 화면이 바뀌도록 해준다.
- 그럼 WEB 부분 말고 밑에 목록을 누를때, read로 바뀌면서 화면이 바뀌도록 만들어보자
- 여기서 유저가 목록을 클릭하게되면 우리가 아까 만들었던 지역변수 mode가 'read'로 변경되도록 <Nav>부분 onChangeMode()함수에서 mode를 'read'로 변경해준다.
- 하지만 그렇게 해주더라도 변화가 일어나지 않는다. 이유는 애초에 이 기능이 App이라는 함수안에 들어있기 때문에 이 함수가 다시 실행되지 않는 이상 이 변화는 일어나지 않는다.
- 우리가 원하는건 mode의 값이 바뀌면 이 컴포넌트 함수가 새로실행되면서 새로운 값이 만들어지고 그 리턴값이 유아이에 반영되는 것이다.
- 이때 state를 사용하면 된다.
- state를 사용하기 위해서는 import를 해줘야 함. 맨 위 상단 import 부분에 import {useState} from 'react' 를 해준다. 그리고 지역변수 mode의 값을 상태로 바꿔주는 useState를 앞에 넣어준다.
- 아래처럼 이렇게 넣어주고 console.log를 찍어보면 mode의 0번째 값은 상태의 값을 읽을 때 쓰는 데이터이고, 1번째 데이터는 그 상태의 값을 변경할때 쓰는 함수이다.
- 그렇다면 여기서 새로운 변수 const _mode = mode[0]을 통해서 상태의 값을 읽을 수 있고, const setMode = mode[1]을 통해서 mode의 1번째 원소를 통해서 모드의 값을 바꿀 수 있다는 것을 알 수 있다.
- 이 위의 있는 세줄의 코드는 한줄의 코드로 요약할 수 있다.
- 둘은 같은 문법이고 축약형이라 이렇게 한줄로 더 많이 쓴다.
- 하지만 여기까지 해도 목록들을 눌렀을 때의 변화는 없다. 이 부분의 변화를 주기 위해서 return 부분으로 다시 돌아가서 우리가 원래 mode = 'welcome' / mode = 'read'라고 변수를 변경했던 부분을 setMode()로 바꿔주면 된다.
- 변화를 주고 싶으면 setMode를 사용해야한다. 이렇게 하면 App()컴포넌트가 다시 실행되면서 useState('welcome')이 _mode의 값을 'read'로 다시 셋팅해준다.
- mode, setMode의 이름은 내 마음대로 설정할 수 있다.
- 이제 각각의 목록을 렀을때 그 선택된 글이 페이지에 뜨도록 해보고싶다. 그럼 어떻게 하면 될까?
- read일때 나오는 컨텐트가 각각의 버튼을 클릭했을때 변하도록 하면 될 것이다. 이걸 또 스테이트로 해결 가능하다.
- 새로운 스테이트를 만들어 준다. 현재 값이 아직 선택되지 않았으니까 null로 값을 넣어준다.
- 이 스테이트의 값은 <Nav>를 클릭했을 때 바뀌므로 return() 부분에 있는<Nav>의 onChangeMode에 setId(id)를 추가해준다.
- 그리고 mode가 read 일 때 반복문을 통해서 일치하는 아이디값을 찾아준다.
- 이때 각각의 topic의 [i]번째 아이디값이 서로 일치하면 타이틀은 그 토픽의 타이틀을 가져오고 바디도 그 토픽의 바디부분을 가져온다.
- 하지만 여기까지 한다고 해서 페이지가 바로 로딩되지 않는다!! 왜 그런걸까? console.log에 id값을 찍어보면 id는 string으로 형성되고 있다
- 우리가 처음에 가져왔던 setId(_id)의 값은 <Nav>태그 안에 위치한다. 그럼 이 <Nav>의 안을 들어가보면 우리가 props.onChangeMode(event.target.id)를 통해서 id 값을 알아내는데 그 아이디 값 은 <a>태그의 id={t.id}에 위치한다.
- 우리가 여기에 입력한 값은 숫자였지만, 이게 태그의 속성으로 들어가면 문자(string)으로 바뀐다. 우리는 여기에 들어오는 값을 문자에서 숫자로 convert 해주면 될것!!
# Create
- 리액트로 form을 어떻게 활용하는지 보자
- create 버튼을 만들고 그 form을 작성하면 상단 목록에 4번째로 crate 버튼이 생기고 상세페이지는 create에 관련된 내용이 뜨도록 만들어보자