하이하이 반갑습니다 피곤한 금요일입미다 특별한 근황은 없구요 그냥 삽니다. 평일에는 여기 붙잡혀서 매일 같은 하루를 보내고 주말에야 밀린 집안일 하고 좀 쉬고 하다보면 다시 평일이고,,, 먼 통학길을 오며가며 체력이 달리거나 힘들다는 생각은 안하는데 그래도 한 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 형식을 사용하는 것이 있습니다.
여튼 말하고자 하는 건 리액트는 jsx라는 문법으로 돌아가기 때문에 기존에 쓰던 자바스크립트, HTML 태그와 미묘~하게 다른 점이 있을 수 있다는 것, 그리고 함수에서 반환하는 값이 컴포넌트가 된다는 것, 그 중에서도 export default로 메인 컴포넌트가 정해진다는 것입니다.
각 함수, 그러니까 각 컴포넌트에선 당연하게도 변수 선언과 할당이 가능한데요, 변수를 return()안에 들어있는 HTML 태그에 넣는 데이터 바인딩을 가장 먼저 배웠습니다. 그런데 배웠다고 하기도 민망한 게 그냥 {}로 쓰면 됨. 이게 뭔 말이냐면,,
그 다음은 state입니다. 보통 데이터는 변수에 냅다 할당하잖아요? 그런데 이걸 state라는 걸로도 저장할 수 있답니다. 왜 굳이 그러느냐, 일반 변수는 변경되면 HTML 태그에 반영이 안된다고 합니다. 반면 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 문법을 써볼 건데 그 전에 컴포넌트를 만드는 다른 방식도 첨부하고 넘어가지요
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 이름} 또아무이름 = {일반 자료}/>로 컴포넌트에서 변수를 사용할 수도 있음**
이라고 합니다. 그러니까 이걸 직접 써보면
이렇게 돼서 원래 보이던 창과 똑같은 형태가 됩니다. 참고로 City()에서도 state를 만들 수 있지만 부모 컴포넌트로 옮기는 법은 없다고 하네요. 그래서 어느 컴포넌트에서 쓰이던 간에 결국 건드려야 하는 state라면 최상위 컴포넌트, 즉 메인 컴포넌트에 만들어 주는 것이 좋다고 하네용
마지막으론 input 태그로 사용자가 입력한 문자를 state로 저장하는 것인데요. 이 또한 별 거 아닙니다. 사용자가 입력할 문자를 저장할 state를 먼저 만들어주고, input 태그에 onChange라는 이벤트 핸들러를 달고 거기서 가져온 값을 state 변경 함수의 인자로 저장해주면 끝!
후 이제 진짜 끝입니다. 리액트의 옛 문법인 class가 있긴 한데 그건 참고용으로 사진만 첨부할테니 정말 끝이지요 꽤 긴 것 같은데 끝까지 보신 분은 없으리라 믿습니다. 혹시라도 끝까지 보신 분이 있다면 제가 링크 뿌린 톡방에
"진정해 차은우"
라고 보내주세요 저희만 아는 신호임 ㅋㅅㅋ 그럼 20000.
'JavaScript > React' 카테고리의 다른 글
리액트 멸망전 2부(完) (1) | 2024.02.22 |
---|---|
리액트 멸망전 1부 (3) | 2024.02.21 |
어후 귀찮아 React -2- (3) | 2024.02.14 |