본문 바로가기

JavaScript/React

React 기초 문법

하이하이 반갑습니다 피곤한 금요일입미다 특별한 근황은 없구요 그냥 삽니다. 평일에는 여기 붙잡혀서 매일 같은 하루를 보내고 주말에야 밀린 집안일 하고 좀 쉬고 하다보면 다시 평일이고,,, 먼 통학길을 오며가며 체력이 달리거나 힘들다는 생각은 안하는데 그래도 한 2주만에 와서 딱히 쓸 얘기가 없는 걸 보면 삶의 해상도가 좀 낮아지긴 했나봅니다. 무의식적으로 다른데서 자원을 아끼려는 신체의 복잡한 메커니즘이거든요 이게,,,

 

디지털 하나로 커리큘럼 상으론 지금 프론트엔드, 그 중에서도 자바스크립트를 배우고 있을 시기인데요, 이번 주 어느 순간부터 ajax 통신을 시작으로 자바(자바스크립트 아님ㅎ)와 node.js를 가르치시는 강사님을 발견했고 그냥 따로 공부 좀 했습니다. 가물가물하던 자바스크립트 ES6 문법과 기초 함수들, 이전에 다시 봐야지 하고 넘어갔던 객체와 프로토타입 등을 훑어보고 리액트 강의를 시작하기까지,,,!

 

네가 뭔데 베테랑 강사가 가르치는 거 제끼고 따로 공부를 하냐, 수업 안 들을 거면 거기 왜 갔냐라고 물으신다면 대답해드리는 게 인지상정이지요. 개인적으로 연락주시면 명쾌하게 답변 드리겠습니당. 어디 한 번 해봐,,,

 

여튼 그래서 오늘 들고 온 건 리액트 기초 문법인데요, 블로그 처음 시작하면서 Vue 강의 정리한 거 생각난다 그쵸. 안 그래도 추억 돋아서 그 때 쓴 글을 보고 왔는데요, 참 뭐랄까 '블로그에 배운 내용을 정리하는 건 정말 \'공부\'라는 것의 일부분이구나' 라는 걸 새삼 느꼈습니다. Vue 뭐 어떻게 쓰는 지 기억도 안나구요, 글 보면서 '아 맞아 대충 이런 게 있었지' 싶긴 한데 정리를 이쁘게 해놓은 것도 아니라서 그냥 관상용으로 쓴 글에 가깝습니다. 명세서 마냥 보고 뭘 할 수 있는 수준이 아니고,,,

 

배운 걸 정리하고, 실제로 써보고, 그걸 잊지 않을 간격으로 계속 머릿 속에서 건드려줘야 하는구나,,, 그 때 배운 자바스크립트는 어쨌든 계속 썼으니까 지금 어찌저찌 버티고 있지 뭐든 Vue꼴 날 수도 있겠구나 라는 생각을 하게 됩니다. 아 진짜 이번엔 리액트로 진짜 뭐 해본다ㅋㅋ 진짜임ㅋㅋ

 

자, 사설은 이 정도로 하고 이제 지짜 정리를 좀 해봅시다. 우선 환경 세팅을 할 텐데요, Node.js랑 Vscode는 깔려 있으니까 넘어가주시고 작업용 폴더를 Vscode로 열어줍시다 그리고 터미널 창에

 

npx create-react-app (프로젝트 이름)

 

을 입력하면 작업용 폴더 안에 (프로젝트 이름)으로 폴더가 하나 생성됩니다. 그 안에 뭐 별의 별 파일들이 있는데 그러면 성공. 그 많은 파일 중에서도 App.js가 메인 페이지구요, 여기서 터미널에 npm start를 입력하면 페이지를 미리 볼 수 있습미다. 앗 그 전에 (프로젝트 이름)폴더를 Vscode로 열어주셔야겠죵. 이 폴더에는 node_modules 폴더, public 폴더, src 폴더, packages.json 파일 등이 있는데 대충 설명만 덧붙이고 넘어가겠습니다.

 

 

환경을 세팅한 후엔 데이터 바인딩, state, state 변경 함수, 컴포넌트 등을 쭉 배웠는데요, 그걸 하나씩 설명하기 전에 App.js 파일에 들어있는 내용을 먼저 보고 가야할 것 같습니다. 큰 틀을 잡아놓고 가보자는 얘기지요,,,

 

 

프로젝트 폴더 안에는 이렇게 되어 있는데요, App.js 파일에서 우선 App.css 파일을 import 하고 있습니다. App.css는

 

 

이런 식으로 되어 있습미다. 대충 여기서 CSS 편집하면 될 것 같군요,,, 여튼 다시 App.js 파일에 대해 얘기하자면,,, App.js 에는 App()과 같은 함수가 여럿 생기게 됩니다. 각 함수는 return의 인자로 HTML 태그를 담아 컴포넌트를 구성하구요. 그 중에서도 export default 뒤에 달린 함수가 메인 컴포넌트가 됩니다.

 

그리고 App.js에서는, App.js 뿐만 아니라 리액트에서는 jsp라는 문법을 사용하는데요, 메타가 만든 자바스크립트의 확장판이라고 생각하시면 될 것 같습니다. 자바스크립트의 기능이 모두 담겨 있고 리액트에서 사용하기 보다 수월하게 만든 무언가 라고 생각합시다. 요 App.js 파일은 HTML을 담고 있긴 하지만 결국 .html 파일이 아니잖아요? 그러니까 이후 build 과정에서 .js(진짜 js, jsx말고)로 변환되고 그게 또 다시 .html로 변환이 될텐데 그 과정에서 꼬임이 없어야 하기 때문에 기존에 쓰던 문법에서 미묘하게 다른 점이 있을 수 있습니다. 예컨대 HTML 태그의 속성으로 쓰던 class를 className으로 써야 한다거나(class는 이미 자바스크립트에서 ) style 속성을 넣을 때 따옴표가 아닌 중괄호와 object 형식을 사용하는 것이 있습니다.

 

원래 폰트 크기는 font-size로 썼는데 jsx파일 안에선 '-'기호가 따로 인식돼서 카멜표기법으로 fontSize를 쓴 모습도 보입니다.

 

여튼 말하고자 하는 건 리액트는 jsx라는 문법으로 돌아가기 때문에 기존에 쓰던 자바스크립트, HTML 태그와 미묘~하게 다른 점이 있을 수 있다는 것, 그리고 함수에서 반환하는 값이 컴포넌트가 된다는 것, 그 중에서도 export default로 메인 컴포넌트가 정해진다는 것입니다. 

 

각 함수, 그러니까 각 컴포넌트에선 당연하게도 변수 선언과 할당이 가능한데요, 변수를 return()안에 들어있는 HTML 태그에 넣는 데이터 바인딩을 가장 먼저 배웠습니다. 그런데 배웠다고 하기도 민망한 게 그냥 {}로 쓰면 됨. 이게 뭔 말이냐면,,

 

참 쉽죠,,? HTML 태그 내용물로만이 아니라 className, id와 같은 속성에도 마음껏 사용할 수 있답니다.

 

그 다음은 state입니다. 보통 데이터는 변수에 냅다 할당하잖아요? 그런데 이걸 state라는 걸로도 저장할 수 있답니다. 왜 굳이 그러느냐, 일반 변수는 변경되면 HTML 태그에 반영이 안된다고 합니다. 반면 state는 변경되면 state를 담고 있는 컴포넌트가 자동으로 재렌더링 되면서 보다 동적인 페이지를 만들 수 있기 때문이라고 합니다

 

음 일단 코드를 보면서 얘기를 하죠

 

쓰다보니 state변경함수와 이벤트 핸들러까지 갖고 오게 돼버렸군요

 

useState()의 인자로 저장할 데이터를 넣어주시구요(정수부터 object까지 다 들어감), 그걸 destructuring 문법을 사용해서 변수에 저장해줍니다. 변수를 보니 useState()는 길이가 2인 array를 반환하는 것 같은데 그 중 첫번째 요소는 저장한 데이터, 두번째는 데이터를 변경할 수 있게 해주는 함수입니다. 

 

이렇게 저장한 state는 일반 변수를 사용하듯 {} 이 안에 넣어서 쓸 수 있구요, 방점은 이 값을 변경하는 곳에 찍힙니다. state로 저장한 데이터는 꼭 state 변경함수를 사용해서 변경해줘야하는데요, stat 변경함수의 이름은 state를 저장할 때 사용한 변수(두번째)가 되구요, 인자로 변경할 값을 전달해주면 끝입니다.

 

위 코드에선 onClick이라는 이벤트 핸들러에 딸려서 setb()가 실행됐는데요, 위와 같은 형식으로 쓰입니다. 중괄호 안에 arrow function으로 쓰인 익명함수가 들어가고 그 안에서 콜백함수로 setb()를 쓴 모습. 

 

state 변경 함수에는 state를 변경할 값을 전달해주는 걸로 끝인데요(아직까진,,), 참 인자로 콜백함수 받고 뭐 길게 늘어지는 코드들 생각하면 선녀다 그쵸,,,?? 그런데 state가 원시자료형이 아닌 array나 object라면 조오금 이야기가 달라지는데요. 이것도 코드로 먼저 보시죠.

 

 

새로운 state인 c를 만들었습니다! 이건 array네요~ 그 중에서도 첫번째 요소인 'seoul'이 화면에 나타나고 있습니다. 근데 버튼을 누르면 newyork으로 화면의 글자를 바꾸려고 합니다. 그럼 c를 냅다 바꾸면 되겠지요? 라고 하겠습니까? array나 object 형태의 state는 웬만하면 그 원본을 건드리지 않는 게 좋다고 합니다. 왜인지는 잘 모르는데 왠지 납득이 가지요. 원본 훼손은 언제나 큰 문제를 야기할 수 있을 것 같군요.

 

그렇다면 화면 상에 나타나는 글자를 바꿀 땐 복사본을 만들고 복사본의 요소를 바꿔주기로 합시다. 복사본을 만드는 건 ES6에서 배웠지요 spread operator를 사용해봅니다. 

 

이번엔 컴포넌트를 만들어봅시다. 지금까진 프로젝트가 생성될 때 주어지는 App() 함수에서만 코드를 적었는데요, App()말고 다른 컴포넌트를 만드는 겁니다. 컴포넌트를 만드는 데에는 쓰리 스텝이 있습니다.

 

1. function을 만들고(대신 함수 첫글자가 대문자여야됨. 다른 함수 밖에 만들어야됨. App() 안에 만들면 안 됨.)

2. 이 함수의 return()의 인자로 HTML 태그를 만들어주고

3. 메인 컴포넌트나 다른 곳에서 <함수이름></함수이름> 이렇게 갖다 쓰거나 <함수이름/>으로 갖다 쓰면 됨.

 

각 스텝을 코드로 보자면

 

 

대충 이렇습니다. function App(){} 외부에 function Modal(){}을 만들었구요 그 안의 return()의 인자로 HTML 태그를 전달해주었습니다. 그리고 메인 컴포넌트인 App()의 return()에 인자로 추가했구용. 저러면 '모달창입니다'가 두 번 보이겠습니다.

 

컴포넌트는 반복적인 HTML을 축약하거나, 큰 페이지들 혹은 자주 변경되는 부분을 만들 때 많이 쓴다고 합니다. 단점이라고 하면 다른 함수의 state를 갖다 쓰기 영 곤란하다는 건데요, 지금 저 상태에서 App()에 들어있는 state들을 Modal()에서 쓰려고 하면 에러가 납니다. 이제 이걸 가능하게 해주는 props 문법을 써볼 건데 그 전에 컴포넌트를 만드는 다른 방식도 첨부하고 넘어가지요

 

뭘 쓰든 자기 마음이겠지용 근데 아래처럼 const로 선언해서 만들면 수정 방지 할 수 있다고 합닌다

 

props 배우기 전에 동적인 UI 만드는 법 짚고 갑시다. 이전 강의들에서도 빠지지 않고 나온 내용인데요 그럼에도 또 써봅시다. 동적인 UI를 만드는 데에도 쓰리 스텝이 있다고 했습니다.

 

1. HTML과 CSS로 미리 UI 디자인을 해놓고

2. UI의 현재 상태(ex.보이는 지 안 보이는 지)를 state로 저장하고

=> let [modal, setModal] = useState(false);

3. state에 따라 UI가 어떻게 보일 지 작성

 

하면 됩니다. 그럼 어떤 버튼을 누름으로써 아까 만든 모달 컴포넌트를 보였다가 안 보였다가 하게 만들어 보도록 할까요. 첫 번째 스텝은 완성이 되었군요. modal이라는 state를 만들어서 false일 때는 안보이게, true일 때는 보이게 해봅시다. 그렇다면 조건문이나 뭐 여튼 제어문이 필요할 것 같은데,,,

 

우리는 지금까지 return()의 인자로 HTML 태그만 썼다 그쵸? 근데 이 안에 중괄호를 열어서 자바스크립트 문법을 사용할 수 있다고 합니다. 근데 또 어이없는 게 if나 for문은 사용 못한다고 함ㅋㅋ 되는 게 있고 안되는 게 있고 지 멋대로임ㅋㅋ 그리고 되는 게 뭔지 안되는 게 뭔지 모름ㅋㅋ 여튼 조건문을 못쓰면 세번째 스텝 못하는 거 아님? 이라고 할 수 있는데 삼항연산자라는 게 있다고 합니다. 대충

{조건식 ? 참일 때 실행할 코드 : 거짓일 때 실행할 코드}

이런 식으로 쓰는 거라고 하는데

지금까지 말한 걸 코드로 써볼까용

 

 

우선 state 변경 함수를 보면,,,modal이라는 state를 바까줍니다. 근데 modal은 boolean형으로 true 아니면 false란 말이죠. 그걸 스위치처럼 바꾸려면 'modal이 true면 false로 바까주고 false면 true로 바까조'라고 쓸 수도 있겠지만 간편하게 논리 부정 연산자를 써버리는 모습입니다. 저 부분은 강의에서 나온 건데 좀 간지난다고 생각했어요

 

그리고 앞서 말한 삼항연산자가 보이는데요, {조건식 ? 참일 때 실행할 코드 : 거짓일 때 실행할 코드} 에 따르면 modal이 true면<Modal></Modal>이라는 태그가 저 자리에 남고 false라면 아무것도 남지 않게 됩니다. 그 결과

 

 

이렇게 생긴 화면이 생깁니다 ta da- 이전에 쓴 코드도 실제로 동작하고 있지용

 

다음은 반복되는 HTML 태그 혹은 컴포넌트를 반복문을 통해 간편하게 처리하는 법인데요, for문을 밴 당한 상태에서 어떻게 할 수 있을까요 바로 array.map() 함수입니다. array.map() 함수는 보는 것 처럼 배열 뒤에 붙는 함수고 인자로 콜백함수를 전달해서 배열의 각 요소 별로 콜백함수를 실행해주는 함수입니다. 설명하기 참 어렵다 그쵸? 그냥 코드로 보는 게 낫겠다 그쵸? 그리고 사실 이거 전에 ES6 해서 그렇게 자세한 설명도 필요없다 그쵸? 그럼 실제로 쓰인 코드를 보는 게 낫겠다 그쵸?

 

 

이런 식으로 써주려고 하는데 엇, 빨간 밑줄이 뜨네요 인터프리터 언어 주제에 건방지군요. 왜 그런걸까 보니, 모든 return()의 인자로 들어가는 HTML 태그는 병렬로 입력할 수 없다고 하네요 뭔 말이냐면

 

 

이렇게 div 태그로 감싸주면 병렬이 아닌 하나의 태그가 돼서 에러가 없어진다는 소리입니다. 여튼 그게 중요한 게 아니죠. 저렇게 써두면 .map() 함수가 총 3개의 div 태그를 반복해주고, 인자 a와 i 역시 HTML에 잘 바인딩 되게 됩니다. 저 결과물로는 

 

 

이렇게 잘 나옵니다 아무래도 i는 인덱스 값이여서 0부터 시작하는군요. 자 그럼 지금 저 부분을 컴포넌트로 만들어볼까요? 컴포넌트는 어떻게? function 컴포넌트() 만들고, return()에 HTML 태그 넣고, 쓴다. 그럼

 

 

어허,, 또 빨간 밑줄이 뜨네요 왤까요?? 바로 저기 저 c 라는 state는 City에서 선언된 적 없고 메인 컴포넌트인 App()에 있는 state이기 때문이지요. 구조상 App()이 부모 컴포넌트, City()가 자식 컴포넌트라고 불리구요, 부모 컴포넌트에 있는 state를 자식 컴포넌트에서 쓰려면 props라는 문법을 사용해야 합니다. props 오랜만이네요 Vue.js에서도 한창 배웠던 것 같은데 말이죠. 사용법은 매우 쉽습니다. 

 

1. <자식컴포넌트 아무이름 = {state 이름}/>

2. 자식 컴포넌트 생성 함수의 매개변수로 props를 넣고 함수 안에서 props.위에서쓴아무이름 으로 변수 사용

**<자식컴포넌트 아무이름 = {state 이름} 또아무이름 = {일반 자료}/>로 컴포넌트에서 변수를 사용할 수도 있음**

 

이라고 합니다. 그러니까 이걸 직접 써보면

 

아무이름이라고 했지만 보통 원래 state이름 따라 갑니다

 

 

이렇게 돼서 원래 보이던 창과 똑같은 형태가 됩니다. 참고로 City()에서도 state를 만들 수 있지만 부모 컴포넌트로 옮기는 법은 없다고 하네요. 그래서 어느 컴포넌트에서 쓰이던 간에 결국 건드려야 하는 state라면 최상위 컴포넌트, 즉 메인 컴포넌트에 만들어 주는 것이 좋다고 하네용

 

마지막으론 input 태그로 사용자가 입력한 문자를 state로 저장하는 것인데요. 이 또한 별 거 아닙니다. 사용자가 입력할 문자를 저장할 state를 먼저 만들어주고, input 태그에 onChange라는 이벤트 핸들러를 달고 거기서 가져온 값을 state 변경 함수의 인자로 저장해주면 끝! 

 

state를 미리 만들어두고,

 

input 태그에서 e.target.value로 입력된 값을 가져와 버리기.

 

 

후 이제 진짜 끝입니다. 리액트의 옛 문법인 class가 있긴 한데 그건 참고용으로 사진만 첨부할테니 정말 끝이지요 꽤 긴 것 같은데 끝까지 보신 분은 없으리라 믿습니다. 혹시라도 끝까지 보신 분이 있다면 제가 링크 뿌린 톡방에 

"진정해 차은우"

라고 보내주세요 저희만 아는 신호임 ㅋㅅㅋ 그럼 20000.

'JavaScript > React' 카테고리의 다른 글

리액트 멸망전 2부(完)  (1) 2024.02.22
리액트 멸망전 1부  (3) 2024.02.21
어후 귀찮아 React -2-  (3) 2024.02.14