6/20 
오늘은 styled components, react swiper 라이브러리 사용법, 게시판 만드는 법을 배웠다.
styled components 는 요즘 리액트 개발 회사에서 많이 사용한다는데 배워보니 처음엔 좀 복잡했지만 쓰다보니 편하고 재밌었다. html, css, js 가 모두 접목되어 쓰고 있는 것 같았다.
react 에서 swiper 라이브러리를 사용해봤다. 강사님이 react 는 js 만큼 아직 업데이트가 되지 않아서 좀 불편하다고 하셨는데 확실히 라이브러리가 무거운건지 react 가 반응이 느려져서 이게 에러인건지 되는데 반영이 안 되는건지 좀 답답했다.
게시판 만드는 법은 많이 쓰는 공식이 있다고 하셔서 그걸 배워봤는데 로직이 복잡해서 어렵긴 했지만 이해가 어렵진 않았다. 다만 useEffect 로 api 를 가져오는 작업을 강사님과 자주 했는데도 이해가 안돼서 윤하님한테 물어봤다. 그랬더니 내가 모르는 부분까지 하나씩 다 설명해주셔서 이해가 정말 잘됐다. 특히 rse => res.json 을 해주고 또 data => setList(data) 를 해주는 부분이 걸렸었는데 json 파일로 변환해줬으면 그걸 data 매개변수로 넣고 데이터를 넣어줘야 하는 state 함수로 보내서 api 를 전달해주는 것이었다. 그리고 중간중간 reverse, slice 등 예전에 배웠던 메서드들이 나와서 좀 반가웠다.

집에 와서는 19일에 코딩앙마 react 강의를 11. json-server, rest api 까지 봐서 오늘 나머지를 다 끝내려고 했지만 12, 13, 14 까지 밖에 보지 못했다. 나머지 15, 16, 17 은 내일 꼭 마무리를 하고 17일날 받은 상세페이지 만들기 과제를 해봐야겠다.
그런데 react hook 들이 많고 쓰기가 복잡해서 강의를 두세번 보고 필기를 하며 뜯어봐야 그제야 이해가 됐다. 사실 이해가 아닌 계속 써봐야 하는데 이해가 되지 않으면 시작을 못해서 걱정이다. 
코딩앙마에서는 day 1, day 2, day 3 각 날짜를 클릭하면 그에 해당하는 단어가 나오는 식이었는데 그걸 다른 페이지로 가는 게 아닌 tab 으로 만들어줬으면 로직이 더 복잡해졌을까 라는 생각이 들었다. 물론 코딩앙마에서는 react 의 기초 기능을 모두 설명하기 위해 그렇게 만들었겠지만 tab 으로 만들어주면 데이터를 한번만 불러오면 될 것 같아 그렇게 생각해봤다. 나중에 시간이 된다면 한번 시도해보고 싶다.
 

6/21
오늘은 비즈니스 매너에 대해서 배우는 날이라 수업 때는 복습을 하거나 과제는 만들지도 못했다. 그대신 집에 와서 코딩 앙마 react 강의 마지막에 타입스크립트 영상 빼고 나머지를 모두 봤다! 이해하고, 필기를 하면서 보느라 많이 느리고 늦어지긴 했지만 이번주 스터디 모임 내에 다 봐서 다행이라는 마음이 들었다.
그리고 상세페이지 과제를 하는데 데이터 연결은 무슨, 라우터 연결부터 막혀서 오늘 교육 쉬는 시간 때도 다시 이해하느라 애를 먹었다. 집에 와서 react 강의를 모두 보고 구글링을 해보니 내가 애초에 이해를 잘못하고 있었다는 것을 알았다.
나는 app.js 에 라우팅 해준 것들이 해당 메인 페이지에만 적용되는 줄 알고 상세페이지는 어떻게 라우팅해주는지 해매고 있었는데 그냥 주소를 만들어서 이동해줄 페이지들을 전부 넣으면 되는거였다. 이렇게 쉬운 걸 오랜 시간이 걸려 해결하다니 부끄러웠다. 
이제 상세페이지 컴포넌트를 라우트해준 뒤 card 컴포넌트에 가서 상세보기 쪽에 a 태그를 link 로 변경해주고 각 데이터를 넣으면 상세보기 페이지는 완성할 것 같다. 

6/22
오늘도 비즈니스 커뮤니케이션을 배우는 날이라 교육 때는 따로 공부를 하진 못했다.
원래 오늘 스터디 모임이라 오늘까지 마무리를 하려고 했으나 어제 새벽까지 했는데 데이터 연결을 못해서 끝내지 못했다. 오늘 와서 선환님이 상세페이지를 다 했다고 하셔서 봤는데 너무 간단하게 하셔서 놀랐다. 내가 코딩 앙마로 배운 useparams 훅도 써서 id 를 뽑아냈는데 일단 선환님 것을 참고해서 id 연결까지는 마쳤다. 하지만 props 로 연결해서 각각 넣고 싶은 자리에 props.title 등 이렇게 넣었는데 아예 빈칸으로 나왔다. console 에 props 도 띄워봤는데 object 로 전체가 잘 나와서 데이터는 왜 안 나오는지 애를 먹었다. 내일 강사님께 여쭤봐야 겠다.

6/23
오늘은 todo-list 를 만들어봤다.
사실 todo-list 는 코딩앙마에서 배웠던 것이랑 아주 비슷해보였는데 강사님이 실제로 코딩한 건 너무나 어려웠다.. 특히 crud 부분이 좀 달랐는데 코딩앙마에선 함수 안에 method : delete 이런 식으로 사용했는데 강사님은 함수를 계속 사용하셨다. 코딩앙마에서 사용한 것과 강사님이 사용한 것이 무슨 차이가 있는지 모르겠어서 혼란스러웠다. 컴포넌트 중첩을 많이 이용하셔서 너무 헷갈렸지만 집에 와서 코드를 하나하나 뜯어보며 최대한 이해해보려고 노력했다.
아침에 오자마자 강사님께 상세페이지에 데이터가 왜 안 들어가는지 여쭤봤더니 각 상세페이지마다 맞는 한 더미의 데이터가 들어가야 하는데 각각 데이터 전부가 들어가 있다고 하셔서 머쓱했다. 그러고 보니 어제 console 에 props 를 띄울 때 0 부터 모든 인덱스가 있던 게 그 이유였던 것 같다. 강사님이 다시 상세페이지 컴포넌트에서 map 으로 데이터를 돌리라고 하셔서 그렇게 해보려고 했더니 다른 교육생이 선환님 것을 보여주면서 이거 하나면 추가하면 된다고 하셨다. 자세히 보니 내가 어제 const id = props.id(id-1); 이렇게 하는데 자꾸 에러가 나서 나는 prop 데이터 안에 각 id 를 뽑아오고 싶은건데 왜 안될까 머리 터지게 고민했던 것이 const data = props.data[id - 1] 이렇게만 수정하면 되는거였다. 생각해보면 props 안에 있는 것은 data 인데 냅다 {props.title} 를 해주니 당연히 경로에 오류가 날 수 밖에 없던 것이다. 그리고 id 를 뽑아온 것은 data 의 인덱스 번호를 지정해주기 위함이었던 것이다. 끝까지 안되던 코드를 이해하니 다른 코드들도 이해가 됐다. 비록 선환님의 코드를 따라친 것이 되었지만 코드가 작동되지 않아 고민했던 시간들은 나의 것이었으니 그 고민했던 시간을 토대로 다른 곳에 써먹을 수 있을 것이라 생각한다.

6/24
오늘은 useCallback, localStorage, debounce, git 기초에 대해 배웠다.
useCallback 은 업데이트 등 기능 상 영향은 없지만 메모리 낭비를 줄이기 위해 나온 훅이라고 한다. 상태값이 변할 때마다 계속 실행되면 메모리 낭비가 심하기 때문에 사용한다고 한다. 그렇게 보면 useEffect 와 유사해보이고 사용법 또한 유사해 둘의 차이가 뭔지, 각각 어떨 때 적용해줘야 하는지 헷갈렸다. 그래서 검색을 해봤는데 useEffect 는 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 훅이고, useCallback 은 특정 함수를 새로 만들지 않고 재사용하고 싶을 때 사용한다고 한다. 그러니까 정리하자면 useEffect 는 랜더링 될때마다 작업을 실행하는 것이고 useCallback 은 랜더링이 아닌 사용하고 싶을 때 사용한다는 점에서 반대의 개념이라고 할 수 있다.
local storage 는 web storage 중 하나로 object 처럼 key 와 value 쌍으로 서버가 아닌 클라이언트에 데이터를 저장하고 조회할 수 있는 저장소를 말한다. session storage 와 다르게 local storage 는 지우지 않는 이상 브라우저 자체나 탭을 닫고 다시 열어도 유지가 된다. setItem 메서드를 이용해 저장하고, getItem 메서드를 이용해 꺼낼 수 있다. 그래서 setItem 메서드로 각 key 와 value 를 지정해주고 저장한 후 getItem 메서드로 key 를 꺼내면 값이 출력된다. 객체도 저장해줄 수 있는데 이때 객체는 json 형태의 stringify(문자열)로 변환해 저장해준 뒤 json 형태의 parse(객체)로 변환해 꺼내와야 한다. 삭제는 removeItem 과 clear 로 각각 지정된 key 삭제와 전체 삭제를 수행해줄 수 있다.
debounce 는 사용자가 빈칸에 글자를 쓸 때마다 onChange 가 일어나서 함수가 호출될 때 메모리 낭비를 줄여주기 위해 사용한다. 공백 등 텀이 있을 때, 그룹화해서 한 번에 처리해준다. setTimeout 메서드를 사용해도 되지만 훨씬 복잡해지니 lodash 라이브러리를 쓰면 된다. 변수를 지정해주고 debounce( 적용할 함수, 시간 간격 ) 을 할당해주면 간단하게 처리된다.
이제 대망의 git 을 배우게 됐는데 다시 javascript 를 배울 때로 돌아간 것 같았다. 조금씩 올려봐서 어느정도 알고 있다고 생각했는데 알고 보니 나는 직접 올리는 것만 배우고 vscode 프로그램에서 터미널을 이용해 업데이트해주는 등 원격으로 사용하는 방법은 배우지 않았던 것이다. 강사님이 기초라고 여러가지를 알려주시긴 했는데 전혀 따라가지 못해서 다시 한번 복습해야 될 것 같다.

6/25
이력서 상담이 있는 날이라 하루의 절반 이상을 1분 자기소개와 이력서 자기소개를 준비하는데 보냈다. 짧은 시간 안에 최대한 많이 준비해 첨삭을 받고 싶었기 때문에 복습을 할 정신이 없었다. 그래도 상담 이후 텀이 생겨 24일 날 배운 훅과 메서드들을 복습했다. 
상담은 내가 준비를 거의 다 해왔다고 수정하는 것까지 도와주셨는데 내가 주저리주저리 써내린 것을 매니저님은 가독성 있고 깔끔하게 첨삭해주시는 것을 보고 평소에도 대단하다고 생각했지만 확실히 다르다는 느낌을 받았다. 첨삭받은 것을 수정하고 한번 더 봐주신다고 하셔서 너무 감사했다.

6/26
todo-list 를 복습하고 싶었는데 cbp 프로젝트 모임 준비로 하지 못했다. 이번 cbp 프로젝트에는 제타플랜 홈페이지를 맡게 되었는데 조장님의 주도로 디자인 시안과 질문할 것을 준비했다. 예시를 토대로 디자인 시안은 잘 찾을 수 있었는데 아무래도 이런 프로젝트가 처음이다보니 질문할 것을 찾기가 어려웠다. 기획서가 구체적이지 않고 디자인이 확실히 준비가 되지 않았다는 것은 두루뭉술하게 알 것 같지만 정확히 어떤 것이 필요하고 어느 부분이 부족한지 찝어내기가 어려웠다. 모임이 끝나고 집에 와선 이력서 첨삭받은 것을 토대로 수정 작업을 했다.

 

 

상세페이지 결과물

01
오른쪽으로 넘기면 코드가 있어요

 

6/13
 오늘은 react props, usestate 등 전에 배운 것들을 이용해 상품페이지를 하나 만드는 것과 react icons 플러그인, json 파일 정보들을 각각 넣어서 탭 만들기, filter 문, 콜백함수 에 대해 배웠다.
 컴포넌트가 중첩될수록 점점 어려워졌다. map 문으로 json 데이터들을 돌려 각각 맞는 데이터들을 넣어주고 filter 문으로 조건을 달아 거른 데이터만 반복하도록 만들어줬는데 map 문과 filter 문의 정확한 차이를 알 수 없어 어려웠다. 각 li 에 데이터 정보를 넣어줄 때 중괄호 밖에 미리 표시해둔 불러온 컴포넌트를 지우지 않아서 흰화면이 떴다. 그런데 얼마 전 sns 페이지를 만들 때 흰화면 에러를 아직도 해결하지 못한 것이 생각나서 돌아가 살펴봤지만 해결되지 않았다. 강사님 깃허브에 올라와 있는 코드를 복사 붙여넣기 해도 해결이 되지 않아서 결국 강사님의 sns 홈페이지 폴더를 다운로드 받아서 학습했다. 도대체 왜 되지 않았던 것일까? 강사님의 코드를 복사 붙여넣기 했는데도 되지 않았던 것은 아마 파일 이름 오타이거나 리액트 자체의 문제가 아닐까 추측해본다.
 콜백함수는 나의 논리력 부족 탓인지 잘 이해가 되지 않는다. 강사님이 다 만든 걸 보면 어떻게 작동되는지 이해가 되지만 막상 실제로 적용해보려고 하면 뇌가 굳어서 잘 움직이지 않는 것 같다. 앞으로 콜백함수를 많이 사용할 것 같은데 걱정이다.
 어제 배민 js 를 만들 때 다음 페이지로 넘어가면 이미지를 아래에서 위로 올라오게 하는 걸 afterload 메서드를 이용해서 구현하려고 했는데 이미지가 큰건지 자꾸 스크롤바가 생기는 문제가 있었다. 그래서 오늘 윤하님한테 물어봤는데 풀페이지 섹션 안에 overflow:hidden 을 주고 섹션에 width:100vw, height:100vh 를 주면 스크롤바가 생기지 않는다고 해서 그렇게 해봤더니 잘 작동이 되었다.
 그리고 header 가 마지막 섹션으로 가면 서서히 없어지도록 해주고 싶어서 display:none 을 해주고 afterload 메서드를 이용해 마지막 섹션으로 가면 display:block 을 줬는데 그냥 없어지기만 하고 서서히 없어지는 건 되지 않았다. 이것도 오늘 윤하님한테 물어봤더니 opacity:0 으로 주면 된다고 해서 opacity 와 transition 을 같이 줬더니 제대로 작동했다.
하지만 다시 다른 섹션으로 올라가면 나오지 않아서 onleave 메서드를 이용해 opacity 와 transition 을 줬는데 갑자기 섹션 1의 background 가 엄청나게 길어지면서 나머지 섹션이 가려졌다. 끝까지 해결을 하지 못하다가 방금 혹시나 싶어서 onleave 메서드 if 문 안 스타일 준 것에 끝에 세미콜론을 붙였더니 잘 작동했다. 고민을 많이 했는데 세미콜론을 붙이지 않아서 그랬다니 좀 허무했다. 앞으로 이런 실수는 안하도록 노력해야 겠다.

6/14
 배민 js 에 오른쪽 점을 누르면 이동하게 하는 걸 manubar 라고 줬는데 스크립트에 navigation 으로 주면 백그라운드 이미지로 점을 넣는 방법이 나오지 않아서 강사님과 함께 만들었던 풀페이지를 다시 봤더니 menu 와 anchor 메서드로 만들 수 있는 것 같았다. 만들었던 마크업을 복사 붙여넣기하고 내가 원하는 것에 맞도록 수정했더니 제대로 작동했다. 하지만 클릭하면 점에 동그라미 치는 것에서 또 막혀 구글링을 해봐도 답이 나오지 않아서 강사님과 만든 풀페이지를 다시 보니 class: active 를 붙여놨던 게 보였다. 그걸 개발자 검사를 켜서 봤더니 클릭될 때마다 바뀌고 active 로 작동되는 것이었다. 다시 풀페이지 active 를 구글링해보니 active 라는 class 가 풀페이지에 기본적으로 작동되도록 스크립트 설정이 되어 있었다. 그래서 active 클래스에 css를 설정했더니 잘 작동이 되었다.
 지금까지 배운 리액트 복습을 했다. state 에 대한 강의를 봤는데 리액트에는 state 라는 hook 뿐만 아니라 여러가지 hook 이 있는 걸 알 수 있었는데 오랜만에 휴식을 즐기느라 다른 hook 은 보지 못했다. 주말에 한번 봐야겠다.

6/15
 오늘은 promise, fetch 함수, async await 문법, axios 라이브러리, useEffect 에 대해 배웠다.
 아무래도 fetch 함수가 한눈에 보기가 쉬워서 제일 쉬워보인다. 하나씩 검색해보면서 다른 건 이해했는데 useEffect 는 너무 어려웠다. 강의를 봐도 강사님과 했던 코드는 이해하지 못했다. 집에 와서 다시 복습을 했는데도 response => response.data 의 response 는 무슨 뜻인지, useEffect 안의 함수를 쓴 이유가 계속 데이터를 불러들이지 않고 첫 랜더링 때만 부르고 싶어서 그런건지 잘 모르겠다. 아무래도 강사님과 자주 써보면서 익숙해져야 할 것 같다.
배민 js 를 만들 때 첫 섹션에서 새로고침될 때마다 서서히 나타나게 하는 걸 하고 싶어서 애니메이션으로 줬었는데 배민을 참고해보니 처음부터 opacity : 0 을 주고 애니메이션으로 0% 때는 opacity : 0, 100% 때는 opacity : 1 로 되어있었다. 그래서 나도 그렇게 줬는데 그게 문제였던건지 나중에 마지막 섹션에서 헤더가 없어지고 다시 다른 섹션으로 올라가면 나타나도록 하는 게 되지 않았다. onleave 에 줬다가, afterload 에 줬다가, classlist.add 로 줬다가 별 난리를 쳐봐도 되지 않아서 강사님께 여쭤봤더니 afterRender 를 주면 구조가 생성된 직후 바로 함수가 실행된다고 이 메서드를 써보라고 하셔서 애니메이션 줬던 것과 opacity : 0 을 따로 클래스로 빼서 classlist.add 를 해줬더니 첫화면에 나타나는 건 제대로 작동이 됐다. 하지만 아직도 마지막 섹션에서 없어지고 올라가면 다시 나타나는 건 구현이 되지 않았는데 윤주님의 도움으로 off 라는 클래스를 add 하면 마지막 섹션에서 없어지고, on 을 하면 다시 나타나게 되었다. 근데 z-index : -1; opacity : 0; 에 transition : all 1s 을 줬는데도 서서히 되는게 작동이 되지 않았다. 스터디 모임이 시작되어 고치지 못하고 넘어갔다.
 스터디 모임 때 다른 분들이 한걸 봤는데 지영님은 본문 섹션에 이미지가 움직이는 걸 공동 클래스로 주고 다르게 움직이는 건 다른 클래스로 줘서 간단하게 작동되도록 한 걸 봤다. 나는 작동만 되라 하는 마음으로 해서 그런지 코드가 엄청나게 길어졌는데 지영님이 한 걸 보니 나의 긴 코드가 너무나 부끄러워졌고 자극을 많이 받았다.
 그리고 배민은 다른 섹션으로 갔다가 새로고침을 하면 첫번째 섹션으로 돌아왔는데 나는 그렇게 되지 않아서 다른 분들께 물어보니 예진님이 스와이프로 하면 줄 수 있다며 알려주셨는데 나중에 스와이프로도 만들어봐야 겠다는 생각이 들었다.

6/16
라우팅이라는 걸 배웠다.
 라우팅은 한 페이지 안에서 페이지 이동을 하는 기능인데 이제 이런 기능을 배우니 진짜 한 홈페이지를 만들 수 있는 프론트엔드 개발자가 된다는 것이 실감이 났다. 라우터를 깔고 교육을 받던 중 계속 무한 로딩이 떠서 구글링을 해봤더니 버전을 낮춰야 한다고 해서 낮췄다. 그런데 아무래도 잘 되지 않아 강사님께 여쭤봤더니 낮추면 지금까지 작성한 코드와 버전이 맞지 않아 작동이 되지 않을 거라고 하셔서 다른 방법을 찾기 위해 구글링을 해봤다. 그랬더니 package.json 파일의 react-router-dom 이 곳의 버전을 임의로 변경한 후 재설치해봤더니 제대로 작동했다. 아마 버전 반영이 잘 되지 않았던 것 같다.
집에 와서 라우팅에 대해 학습했다. link 태그는 react 의 a 태그라고 하는데 예전에 a 태그를 사용하면 warning 이 떴던 이유가 이거였나 생각이 들었다. useParams, useLocation, useSearchParams, useNavigate 등 다양한 기능들도 있었는데 주말에 천천히 강의와 함께 한번 봐야겠다.

6/17
버튼 누르면 하나씩 이동하는 탭 만들기, useRef 에 대해 배웠고 상세페이지 만들기 과제를 받았다..
 오늘은 하루종일 swiper 라이브러리처럼 버튼을 누르면 하나씩 이동하는 탭을 react 로 구현하는 작업을 했는데 오전에 위로 올라가는 걸 할 땐 나름 따라갔는데 오후에 옆으로 슬라이드하듯 이동하는 건 따라가질 못했다. marginleft 를 줘서 왜 앞으로 가게 해주는건지, 부드럽게 이동시키기 위해 탭을 하나 더 추가해주는 이유가 뭔지 이해하지 못했다. 주말에 쉴 때 다시 복습을 해야할 것 같다. 

6/19
코딩애플 react 강의를 보며 지금까지 강사님과 함께 배운 것 이해하고 복습, 17일자 탭 만들기 이해 및 복습

 

 

배달의 민족 클론코딩 결과물

01234567

1. max-width, min-width

max-width : 최대값, 이 이하라는 소리 그 값보다 브라우저가 작으면 꽉 채워지고 커지면 그 값까지만 표시,

min-width : 최소값, 이 이상이라는 소리 !다시!

 

2. viewport 492p

! 했을 때 나오는 기본 태그 : viewport 를 넣어주고 width=devic  e-width 를 해주면 디바이스 넓이에 맞게 조절해줌

유저 스퀘어블의 경우 노를 해도 디바이스 자체에서 풀어버림

<meta http-equiv="X-UA-Compatible" content="IE=edge"> 모바일은 익스 안쓰기 때문에 안해도 상관 x

content="IE=edge" : 최신 버전으로 고정 호완성을 위해

 

3. 모바일 코딩

배수라는 것을 생각해야 함 , 디바이스(기기화면)와 해상도는 차이가 있음 ,

제일 작은 사이즈 기준에서 배수로

배수하지 않으면 이미지나 글자가 깨져보임

피그마 xd 백터 비트맵이 아님 이미지 일배수 적용하고 이배수삼배수해도 안깨짐

psd하면 두배수 삼배수하니까 이미지 잘라서 받으면 됨

크게 잘라서 밀도를 높여서 보여지게 넣어준다

가장 작은 사이즈 기준으로 이배수 삼배수해서 나머지 비율 맞춰주기

재플린 들어가서 봤을 때 그 이미지를 공간에 넣어주려면 하이 위드 반으로 계산

재플린으로 작업하면 320으로 하기

 

 

4. 모바일 코딩 블루보틀

모바일 코딩할 때 리셋 설정으로 :

- a{display: block;} 공간 설정, 사이즈 꼭 해주기

- text-size-adjust: none  모바일 폰트 크기 조절, 오토면 화면 크기에 따라 달라짐, 요즘은 벤더프리픽스할 필요 없음

- overflow-x: hidden; 가로 사이즈 넘어갈 경우가 있어서 해줌

 

a span 은 인라인에 인라인 div 쓰나 상관은 없음

header height 값은 px 써도 되지만 유동적으로 하려면 미디어쿼리(em,rem) 써서 조절 

header 에 패딩 주지 않은 이유는 h1에 넓게 주고 싶어서

반응 공간을 만들기 위해서 .header h1{height: 70px; width: 150px;} 이렇게 설정

디자인 나올 때 나누기 힘드니까 되도록 짝수로

공간의 사이즈는 그대로 맞추고 이미지는 반으로 해서 밀도 높게

이미지는 두배로 작업됐지만 만들 때는 2분의 1, %말고 절대값으로 줘야 함 영역의 퍼센트라고 하면 영역을 크게 잡으면 실제 이미지의 2분의 1로 안나옴

이미지에 이미지 삽입: 바텀에서 몇 픽셀로 잡으면 화면이 커져도 조절이 안됨 / 따라서 계산해줘야 함 / 360 기준으로 vw 계산해서 넣어주면 됨 위드 하이 바텀

em, rem 으로 넣으려면 미디어쿼리로 기준점 바꿔줘야 함 @media screen {htm l{font-size: ; }}

노토산스 400 500 700 구글폰트 다운로드

px to vw : 사이트 이용하면 편히 계산 가능

calc(50% - 9px) = 절반 위치에서 -9px 간격을 내준다는 뜻?

 

4. 03.html 파일 필기

여백이라서 이미지를 올릴 수 없음 따라서 패딩 값을 줘야 함

이미지를 백퍼로 하고 넓이 높이 나누기 해야 함

548/606x70

배경 이미지의 높이/ 배경이미지의 넓이 x width  지정된 %

 

5. 미디어쿼리 512p

max-width:1200px 이하에서는 ~

@media screen and (max-width:1200px) {

            body{background-color: red;}

            .txt-box > .txt{font-size: 24px; color: #fff;}

 

맥스는 큰값부터 작은값 순으로 적어야 함 아니면 큰값이 작은값을 다 먹어버림

민은 작은값부터 큰값 순으로 적어야함 아니면 작은값이 큰값을 다 먹어버림

 

그리고 상위 값을 상속받음 적은대로 순서대로 덮어씀 값이 설정되지 않으면 가까운 상위 미디어쿼리의 값을 받는다는 뜻

아무리 밑에 적었어도 경로가 있는 게 우선순위에 있기 때문에 그거 맞춰줘야 함

{ 속성 : value !important } 이렇게 해주면 무조건 먼저 최상위로, 그런데 나머지 값이 다 무시됨

다른 이름으로 저장하기: 컨트롤 시프트 s

 

1. 이솝 페이지 메인 만들기

캐러셀(carousel) 회전목마? : 스크립트로 짜는 사람 거의 없음 99퍼 플러그인 씀

스와이프 슬라이더: 리액트 제이커? 많이 쓰는 플러그인, 자동으로 넘어가는 화면

플러그인 고유의 구조가 있음

이런 건 리액트 배울 때 제대로 배울거임

풀페이지도 플러그인도 많이 씀

플러그인 구조 갔다 쓰고 스타일 만들어야 함

naver modoo! : 무료로 모바일 웹페이지 만들어줌

 

center center / cover 축약하려면 / 꼭 붙이기

.header-bottom #allMenuBtn:hover ~ .allmenu-area{display: block;}

=> 형제 요소 뒤에 있는 걸 오버했을 때 나타나게 하고 싶으면 이렇게, 하지만 형제 요소는 앞에 있는 건 못 부르고 다음에 있는 것만 부를 수 있음

<div class="right"></div> 빈태그 넣어서 여백 만들어주기

z : 위에 쌓인다는 뜻

 

2. 태그

z-index 346p 나중에 마크업 된 것을 위로 올리기 위해 씀(상단 고정), 기본값 오토, 단계 올라가면 12345~20만 이렇게 속성값, 포지션 값이 있어야 쓸 수 있음

섹션 안에 섹션 해도 됨

섹션 안에 h 태그 있기만 하면 에러 안뜸 하지만 그 섹션에 대한 제목은 아니기 때문에 시맨틱적으로 하려면 h 태그 따로 잡고 제목 만들고 안보이게 처리 그리고 안에 있던 h 는 단계를 작게

마크업 수정이 있을 수 있으니 태그로 부르는 것보다 클래스 부여해주는 게 나음

border spacing 359p

 

3. vertical-align ex2.html 파일 필기

- 인라인 요소, 텍스트의 경우 기본적인 베이스 라인(기본적인 선) 위에 배치, 아래를 디센더 위에를 뭔센더라고 부름, 베이스라인이 조금씩 틀림 그래서 검색창 아래가 조금 비어 있는 것(디센더 공간), 아무리 사이즈를 잘 맞춰도 애초에 디센터 공간이 있기 때문에 맞추기 힘듬 이 공간을 맞추는 태그가 버티컬 얼라인임 그래서 공간, 즉 블록에 위치를 주는 게 아니라 인라인 요소에 직접 위치를 잡아주는 것

탑 미들 바텀에 맞는데 인라인 요소끼리 상하단임 사이즈가 똑같으면 ??????? 뭔소린지?????

img,input,button{vertical-align: middle;} 리셋에 이렇게 넣기도 함

 

!!백퍼센트와 오토라는 값은 틀림, 넓이값을 안 적으면 오토, 근데 오토는 자기가 속한 공간의 오토, 백퍼는 넓이값의 백퍼센트, 그래서 마진 쓰면 밀려나감!!

 

4. 반응형 웹페이지 490p

모바일 웹 분리해서 사이트를 만듦, 도메인 두개.

절대 단위 말고 상대 단위.

절대값 : 단위는 px 

상대값 : 단위는 % em rem vw v vh vmin vmax 

calc 칼큘레이션 : 연산 함수가 돼서 연산이 됨 공간이 아무리 길어져도 콘텐츠의 너비는 유지되도록 할 때 쓰는 것 단위는 +-*/  0으로 값을 하면 에러 떠서 안됨 기호를 기준으로 앞뒤에 띄어쓰기 할 것 width: calc(50% - 25px) 전체 넓이 50%에서 -25px / 임의로 지정 넓이 퍼센트 맞추고 그 다음에 계산 / 1280(전체 넓이) 기준으로 221픽셀(콘텐츠)이면 221/1280*100 하면 됨 501p / 임의로 지정한다고 하지만 실무에서는 그렇게 하면 안됨 / 상위요소에서 하위요소로 계산 / 보통 글꼴에 많이 쓰고 패딩이나 마진도 사용

 

단위 504p

- em : equl to m 약자 / 폰트 사이즈 20 이면 20이 기준 사이즈가 되는 것 / 1em =16 / 상위 요소의 폰트 사이즈를 기준함

- rem : equl to root m 약자 / 가장 최상위 요소를 기준함 / html 태그 기준으로

- vw : 뷰포트위드 의 약자 / 화면 기준으로 무조건 계산해주는 것 /

-vh : 뷰포트하이

-vmin : 화면에서 위드, 하이 중 작은 걸 기준 /

-vmax : vmin 의 반대

3. 컴포넌트, jsx ~ 4. 첫 컴포넌트 만들기

jsx = javascript xml

 

내부 css style 은 객체로 작성해야 함 => <h1 style={{color: 'red'}} 그리고 숫자는 그냥 기입해도 되지만 문자는 '' 안에 문자열로 'red'

 

return 밖에 변수 지정해주고 내부에 {변수이름} 입력해주면 해당 값이 출력되어 나타남

하지만 객체는 안됨

만약 객체로 지정해주고 {변수이름.} 이렇게 입력해주면 해당 값이 출력되어 나타남

 

컴포넌트 리턴문 안에는 꼭 하나의 태그만 가능한데 <div> </div> 가 아닌 <> </> 빈 태그도 가능

 

rsc 도 가능하지만 내보냄과 동시에 만들어 줄 수 있음

export default function hello ( ) { return ( ) }

 

 

5. css 작성법

index.css 는 전체 프로젝트에 영향을 미치는 스타일로 되어 있고 app.css 는 웹 컴포넌트에 한정된 내용들이 있음

만약 app.css .box 라는 네임에 스타일을 지정하고 컴포넌트.css .box 라는 네임에 스타일을 지정하면 전페이지에 영향을 미치게 됨

 

module.css

보통은 컴포넌트 이름으로 파일 이름을 지정 컴포넌트이름.module.css

import 'css 파일 경로'; 이렇게 해주는 게 아니라

import styles from 'css 파일 경로'; 이렇게 해줌

그러면 styles 라는 객체가 생성된 것이고

css 를 넣고 싶은 해당 컴포넌트 안의 요소에 가서 classname = {styles.box} 해주면 적용 가능

그리고 app.js 도 따로 module.css 를 만들고 import 해서 classname = {styles.box} 해주면 같은 이름을 적었더라도 서로 중복될 걱정이 없음

 

 

6. 리액트에서 이벤트 처리하기

두가지 방법이 있음

 

미리 함수를 만들어 놓고 전달해주기

- 리턴문 밖에 function showname () { console.log('mike'); }

- 리턴문 안에 <button onclick={ showname }> </button>

=> console mike 라는 게 클릭할 때마다 뜸

 

onclick 내부에 직접 함수를 작성해주기

- 리턴문 안에 onclick = { ( ) => { console.log(30); } }

=> console 30 이 클릭할 때마다 뜸

 

이 두가지 방법은 상황에 따라 맞게 사용하면 되고

장점은 매개변수를 전달하기 편하다 라는 것

 

!&! 만약 매개변수를 전달해주고 싶다면

- 리턴문 밖에 function showage(age) { console.log(age); }

- 리턴문 안에 onclick = { ( ) => { console.log(10); } }

=> 10 을 매개변수로 받아 console 10 이 뜸

 

미리 함수를 만들어 놓고 전달하는 방법으로 input 태그 이벤트 처리로 값을 받아오기

- 리턴문 밖에 showtext(e) { console.log(e.target.value); }

- 리턴문 안에 <input type='text' onchange={showtext} />

=> showtext (e) 이벤트 객체를 받고, target input 태그, value input 의 밸류로 작성한 값이 된다. 따라서 텍스트박스 안에 작성한 값이 onchange 될 때마다 콘솔에 그대로 찍힘

 

!&! onclick 내부에 직접 함수를 작성해주는 방법으로 하고 싶다면

- 리턴문 안에 <input type='text' onchange={ (e) => { console.log(e.target.value) } } />

=> 동일하게 적용 가능

 

!&! showtext 함수를 살리고 싶다면

- 리턴문 밖에 showtext(txt) { console.log(txt); }

- 리턴문 밖에 <input type='text' onchange={ e => { const txt=e.target.value; showtext(txt); } } />

=> txt e.target.value 라고 지정, showtext 를 호출하는 방법으로 동일하게 적용 가능

 

 

7. usestate

state 는 컴포넌트가 가지고 있는 속성값으로 속성값이 변하면 리액트는 자동으로 ui 를 업데이트 시켜준다. 화면을 다시 그려주는 작업은 신경 쓰지 않아도 되어 편리함.

 

js 에서 적용 시켜준 것처럼 한다면

- 리턴문 밖에 function changename() { name = name === 'mike' ? 'jane' : 'mike'; console.log(name); }

- 리턴문 안에

<h2>{name}</h2>

<button onclick={changename}> change </button>

=> 해주면 이름은 바뀌지만 h2 에 업데이트가 되지 않음

 

그래서 js로 추가해준다면

- 리턴문 밖에 console.log(name); 다음에 document.getelementbyid('name').innerText = name;

- 리턴문 안에 <h2 id='name'>{name}</h2>

=> id name 인 안의 텍스트를 name 으로 바꿔주고 이렇게 업데이트 작업이 작동됨

 

맨 상단에서 지정해준 let name = 'mike'; 는 단순히 변수일 뿐 컴포넌트가 관리하고 있는 상대값이 아님 그래서 바뀌어도 리액트는 그걸 인지하지 못하고 ui 를 업데이트 해주지 않음

 

그래서 usestate 를 씀

- const [name, setname] = usestate('mike');

- function changename() { const newname = name === 'mike' ? 'jane' : 'mike'; setname(newname);

 

!OR!

- function changename() { setname( name === 'mike' ? 'jane' : 'mike'); }

 

!OR!

- <button onclick={ () => { setname( name === 'mike' ? 'jane' : 'mike'); } }> change </button>

 

이 컴포넌트를 여러 개 만들더라도 각각 관리됨

 

8. props

props 값을 컴포넌트에서 억지로 변경하려고 하면 에러가 남

불러들인 컴포넌트에 <Hello name={30} /> 넣어주고 해당 컴포넌트 파일에 가서 function Hello (props) { } 해주고 리턴문 안에 넣어주고 싶은 곳에 {props.name} 하면 해당 값이 어플에 출력됨

 또는 구조분해할당으로 function Hello ( {name} ) { } 하고 리턴문 안에 넣어주고 싶은 곳에 {name} 하면 해당 값이 출력됨

 그리고 한 컴포넌트가 가지고 있는 state props 로 넘길 수도 있음 하위 컴포넌트에 가서 값을 넣어주고 바로 위에 있는 것처럼 넣어주고 다시 상위로 돌아와 하위 컴포넌트를 불러준 뒤 그 곳에 <Hello name={30} /> 이런 식으로 값을 전달해주면 그 상위 컴포넌트에서는 state 지만 하위 컴포넌트 입장에서는 props 가 되는 것, 이렇게 하면 하위 컴포넌트에도 state 값이 적용되어 해당되는 값들도 같이 바뀜

 따라서 일일이 값을 바꿔주지 않고 간단하게 props 를 적용해 바꿔줄 수 있음

 

 

9. 더미 데이터 구현, map 반복문

더미 데이터를 가져오고 그 더미 데이터만큼 컨텐츠를 만들어주고 싶다면 map 반복문 사용

 

map 반복문

- map 은 배열을 받아서 또 다른 배열을 반환해주는 것, 이때 반환되는 배열의 요소는 jsx(중괄호) 로 작성해주면 됨

- return ( <ul classname = 'list_day'> { dummy.days.map( day => ( <li> day {day.day} </li> ) ) } </ul> )

- 이때 키가 필요하다는 에러가 뜸 키는 반복되는 요소에 고유한 값을 넣어줘야 함

- <li key = { day.id }> day {day.day} </li>

 

- 이제 각 day 에 해당하는 데이터들을 표의 형태로 하위 컴포넌트로 만들기

- 특정 날짜를 클릭해서 들어갔을 때 단어들이 나오게

- return ( <table> <tbody> { dummy.words.map(word => { <tr key={word.id}> <td> { word.eng } </td> <td> { word.eng } </td> </tr> ) ) } </tbody> </table> )

 

- 이때 문제 1 : 모든 단어가 다 나와버림

- 그래서 여기서 filter 를 써서 day 1일 때로 고정 : const day = 1; const wordlist = dummy.words.filter( word => (word.day === day ) ) console.log(wordlist)

 => dummy 데이터 안의 word 들을 filter 로 걸러서 단어의 날짜가 day(1) 일 때만 출력

- 그리고 { wordlist.words.map(word => ~ 으로 수정해주면 day 1 의 단어들만 출력됨

- 여기서 const day = 1; 에 숫자를 2로 바꿔주면 day 2 단어가 출력되고 3이면 day 3 이 출력됨

- 문제 2 : 원래 특정 날짜를 클릭해서 들어갔을 때 각 day 의 단어들이 나오게 해야함 그건 라우팅으로

 

 

9-1. 번외 : react 에서 key 가 중요한 이유? 그냥 index 를 쓰면 안되는 이유?

- key 값에 index 를 넣어주면 당장은 에러가 뜨지 않음, 순서가 고정되어 있는 경우 큰 문제가 되지 않음, 순서가 일정하지 않을 때는 각 요소의 고유한 값으로 키를 사용해야 순서를 배정받을 수 있음

- 왜 이런 것일까? 그 이유는 react 는 형태가 바뀌면 이전 상태의 트리와 이후 상태의 트리를 비교함, 이때 키가 같다면 동일한 요소로 판단하고 업데이트를 해줌

- 반면 index 를 넣어주면 변경될 때 단순히 앞에 하나를 추가한 것 뿐이라도 모든 요소가 같이 변경됨, 왜냐 키도 함께 달라지기 때문에 react 는 단순히 앞에 하나 추가하고 뒤로 밀면된다는 걸 모름, 키와 값이 모두 다르니까 모두 바뀌었다고 생각하는 것, 그래서 제일 위에 추가했는데도 불구하고 요소에서는 가장 아래쪽에 추가됨,

- 고유한 값인 id 로 넣어주면 요소에서 가장 위쪽에 추가되고 나머지는 변화가 없는 것을 볼 수 있음, 키를 통해서 이전에 요소와 변경된 이후의 요소가 동일한 요소라는 걸 알고 있기 때문에 나머지 요소들은 변화가 없다는 걸 react 에 알려주는 것

- 이렇게하면 react 트리 업데이트 시 효율성이 상당히 증가하게 됨

- 정리해보면 배열의 순서나 내용이 변경되지 않는다면 아무 key 나 사용해도 됨(다르기만 하다면. 동일한 키는 에러. 따라서 index 를 사용해도 무방.) 하지만 순서나 내용이 변화되는 상황이라면 요소를 특정할 수 있는 고유한 key를 사용함 그렇지 않으면 매번 랜더가 발생하고 효율이 크게 떨어짐

 

 

10. 라우터 구현 react-router-dom

npm install react-router-dom 으로 먼저 라우터 설치

 

app.js 로 와서 import { browserrouter, route, switch } from 'react-router-dom';

return 바로 다음에 <browserrouter> 로 감싸주고 <header /> 는 모든 페이지에 나와야 하니 그 다음 부분을 <switch> 로 감싸 줌

그러면 <switch> 내부는 url 에 따라 각각 다른 페이지들을 보여줄 것

<switch> 의 외부는 모든 페이지들에 공통으로 노출

만약 <footer /> 가 필요하면 <switch> 밖에 작성해주면 됨

 

그 다음 <switch> 안에 <route> 를 사용해줄 것임

<route path='/'> path 는 주소를 적어주면 되는데 / 는 첫화면을 의미

첫화면은 <route path='/'> <daylist /> </route> 를 보여주고

다음은 <route path='/day'> <day /> </route> 를 보여줄 것임

 

근데 / 로 들어가도 daylist 가 보이고 /day 로 들어가도 <daylist /> 만 보임

<switch> route 들을 감싸놓으면 일치하는 첫번째 결과를 보여줌

그래서 /day 로 들어가도 / 가 포함되어 있기 때문에 <daylist /> 을 보여줌

그래서 이런 경우는 <route exact path='/'> 라고 해줘야 함

그러면 정확하게 주소에 / 가 일치할 때만 <daylist /> 이 부분이 랜더링 됨

다시 /day 로 하면 day 에 해당하는 컨텐츠만 나옴

 

링크 연결해주기 :

html 에서는 a 태그로 링크를 연결해주지만 react 에서는 link 태그를 이용

<link to='/day'> day {day.day} </link>

import { link } from 'react-router-dom'; 해줘야 함

그리고 요소 검사해보면 a 태그로 랜더링된 걸 확인해볼 수 있음

클릭도 해보면 /day 로 잘 이동함

 

day 1 을 누르면 1 에 해당하는 단어가 나오도록 :

먼저 daylist 컴포넌트로 가서 <link to={ `/day/${day.day}` }> day {day.day} </link> 로 변경해서 day 1 버튼을 누르면 주소에 /day/1 로 뜨도록 설정

그런데 동일한 날짜의 단어만 나오고 있음

 

url 에 있는 값을 day 로 사용하려면?

이렇게 다이내믹한 url 을 처리할 때는 : 으로 처리하면 됨

app.js 로 가서 <route path='/day/:day'> 로 수정해주면 됨

day 1 로 들어왔을 때 :day 라는 변수로 1이라는 값을 얻을 수 있음

만약 :id id 의 값으로 1이라는 값을 얻을 수 있는 것임

 

day 컴포넌트로 가서 이렇게 url 에 포함된 값을 얻을 때는 useparams 훅을 사용

import { useparams } from 'react-router-dom'; 먼저 해주고

const a = useparams(); console.log(a); 를 해보면 console day : '2' 라는 값이 나오는 걸 볼 수 있음 경로를 /day/80 으로 바꿔보면 console day : '80' 이라고 나옴 문자열이나 이상한 값을 넣어도 그대로 출력이 됨

그래서 다시 const day = 3; 으로 정해놨던 변수는 지우고 const day = useparams().day; 라고 작성하거나 const { day } = useparams(); 라고 해주면 특정날짜로 연결되어 이동하게 됨

 

하지만 단어들이 나오지 않음

방금 console 에도 뜨듯이 들어오는 값은 숫자가 아닌 문자, 하지만 json day 에는 숫자가 들어오고 있음

따라서 문자와 숫자를 비교하고 있으니 아무것도 들어오지 않는 것

그래서 word => (word.day === number(day) ) 로 수정해주면 문자 값이 들어와도 숫자로

변경시켜주고 있음

 

여기서 일치하는 라우터가 없는 주소를 치면 / 로 정해진 것 외에는 아무것도 나오지 않음

주소를 잘못 친 경우 잘못된 경로라고 표시해주고 싶으면

다른 컴포넌트 파일을 만들어주고 그 안에 잘못된 경로임을 알려주는 문구과 홈으로 돌아가는 링크도 추가해줌

app.js 로 돌아가 route 들 맨 마지막에 path 를 적지 않고 <route> <위에서 만든 컴포넌트 파일 /> </route> 해주면

앞에 있는 route 들이 모두 만족하지 않으면 <위에서 만든 컴포넌트 파일 /> 이 페이지가 보이게 됨

만약 위에 적어놓으면 모든 페이지가 다 <위에서 만든 컴포넌트 파일 /> 이쪽으로 가니까 주의 해야함

 

 

11. json-server, rest api

영어 뜻 보기, 삭제 버튼, 체크박스

day 컴포넌트로 가서 체크박스 하나 만들고 <td> <input type='checkbox' /> </td>

하단에 뜻 보기, 삭제 버튼 만들고 <td> <button> 뜻 보기 </button> <button> 삭제 </button> </td>

 

 state 때 말했듯이 컴포넌트 별로 state 를 가지고 있는데 버튼 눌렀을 때 뜻이 나타났다 없어졌다 하는 건 한 단어에만 해당하는 것이기 때문에 따로 컴포넌트를 제작해주는 것이 좋음

 

word 컴포넌트를 따로 만들고 단어를 의미하는 부분을 때서 리턴문 안에 넣기

그리고 원래 있었던 자리에는 word 컴포넌트를 불러서 반복

word, key 값 잊지 말기, word 컴포넌트에는 키값 지워주기

 

버튼을 구현하기 위해서는 state 가 필요함

const [isshow,  setisshow] = uststate(flase);

<td> {isshow && word.kor} </td>

=> 초기값을 flase 로 설정해 isshow 일 때만 뜻이 보이도록

 

function toggleshow( ) { setisshow(!isshow); }

<button onclick={toggleshow}> { isshow ? '숨기기' : '보기'} ~

=> 버튼을 클릭하면 뜻이 보이도록 isshow true 일 때 버튼이 눌리고 보이도록

=> 그리고 isshow true 면 숨기기, isshow false 면 보기 로 누를 때마다 바뀌도록

 

체크 하면 외운 것으로 dim 처리:

dummy 데이터에 isdone : false 로 되어 있는데

isdone false 면 아직 못 외운거니까 체크를 해제, true 면 외웠다는 뜻으로 체킹되도록

- <input> 안에 checked = {word.isdone} 해주고

- 미리 맞는 css 준비해준 뒤 <tr> classname = {word.isdone ? 'off' : ''}

=> isdone ture 면 외웠으니까 off style 적용, 아니면 빈 문자열

 

근데 이렇게 하면 한번 체킹되고 다시 클릭하면 바뀌지 않음

요소 검사의 에러를 보면 어떤 액션을 취해도 checked 가 항상 word.isdone , false 로 고정이 되어 있기 때문에 읽기전용이랑 다를 바가 없다고 뜸

그래서 onchange 로 반응형으로 적용

- const [isdone, setisdone] = usestate(word.isdone);

- function toggledone() { setisdone( !isdone ); } 로직은 똑같고 반대값으로 바꿔줌

- <input> 안에 onchange={toggledone} 을 넣어줌

- state 를 사용할 때 isdone 으로 했으니, word isdone 은 바꿔준 적이 없으니 tr classname word.isdone 이 아닌 isdone 으로 변경, checked 에도 isdone 으로 변경

=> usestate 를 이용해 변화가 일어날 때마다 dim checked onchange isdone true 로 변화가 있을 때 input 이 계속 변화하도록 적용

 

사용자 액션에 따라서 데이터를 읽고 쓰고 업데이트하고 삭제하는 방법 :

DB 를 구축하고 api 를 만들어야 됨 json 서버를 이용해서 rest full api? 를 만들기

api 만드는 게 제일 귀찮음 백엔드 찾아보고 db 설치하려면 힘드니까 json 서버를 씀

json 서버는 빠르고 쉽게 rest api 를 구축해줌 공공 목적이나 프로토타입, 작은 프로젝트에

쓸 수 있음

terminal 에서 npm install -g json-server 설치

json-server --watch ./src/db/data.json --port 3001

=> 중간의 경로는 json 파일의 경로, --port 는 해당 파일 주소 localhost:3001 의 숫자

=> 터미널에 나온 주소로 들어가면 해당 주소에 들어가 있는 json 파일 데이터들이 나와 있음

 

rest api ?

url 주소와 메서드로 crud 를 요청하는 것

Create : post 메서드

Read : get 메서드

Update : put 메서드

Delete : delete 메서드

- 터미널에 나온 주소로 들어가서 /2 를 주소 끝에 붙여주고 그 데이터들 중 해당하는 데이터가 나옴 -> get 메서드로 읽은 것

- delete 메서드로 호출하면 2번이 지워짐

- 다른 내용들을 작성해서 put 으로 호출하면 수정됨

- 다시 돌아가서 이 주소로 post 를 날리면 새로운 단어가 하나 생성됨

- 물론 적절한 내용을 담아 보내줘야 함 각각 맞는 경로들을 담아서 보내주면 새로운 단어들을 생성할 수 있음

- 만약 words 다음에 물음표를 하고 day=1 을 해주면 해당하는 날의 단어들만 모두 갖고 올 수 있음

- url 와 메서드만 보더라도 어떤 요청인지 유추 가능한 장점이 있음

- 각 메서드를 이용해 만들고 가져오고 수정하고 지워볼 것임, 물론 그 모든 것들은 json 파일에 다 저장될 것임

 

 

12. useeffect, fetch api 호출

api 를 가져왔으니 더미로 작업했던 부분들을 하나씩 바꿔줌

- const [days, setdays] = usestate([])

=> 처음에는 빈배열로 만들고 api 에서 list 로 가져와서 바꿔주는 방식으로 하겠음 그럼 데이터가 바뀌면 자동으로 랜더링 될 것임

- return ( <ul classname = 'list_day'> { dummy.days.map( day => ( <li> day {day.day} </li> ) ) } </ul> )

=> dummy.days.map 부분에 dummy 를 없앰

 

api 를 호출하기 전 useeffect 를 알아볼 것임

- 어떤 상태값이 바뀌었을 때 동작하는 함수를 작성할 수 있음

- useeffect( ( ) => { console.log('change'); } )

- 첫번째 매개변수로 함수를 넣음, 이 함수가 호출된 타이밍은 랜더링 결과가 실제 돔에 반영된 직후임 그러니까 div 등 요소가 그려지고 나서 호출됨, 그리고 컴포넌트가 사라지기 직전에도 마지막으로 호출됨

 클릭할 때마다 state 가 변경시키기:

- const [count, setcount] = usestate(0);

 => count 라는 state 값을 만들고 초기값은 0 으로 부여

- onclick 함수를 만들어서 count 1씩 증가되도록

 => function onclick () { setcount(count + 1 }, <button onclick={onclick}>{count}</button>

이렇게 useeffect 는 상태값이 변경되어서 상태값이 다시 랜더링된 다음에 호출됨

랜더링이 끝나고 어떤 작업을 해주고 싶다면, api 호출 작업, useeffect 첫번째 함수로 전달해주면 됨

 

그런데 이렇게만 해주면 매번 변경이 이러날 때마다 불필요하게 함수가 호출될 수 있음

원하지 않는 상황에서도 호출될 수 있다는 뜻

다른 state 를 작성했을 때 console.log('change'); 도 콘솔에 나타나게 됨

만약 무거운 작업을 하는 경우라면 문제가 됨 불필요한 실행을 하게 되는 것이기 때문에

 

그래서 이럴 때는 두번째 매개변수로 배열을 전달함

useeffect( ( ) => { console.log('change'); }, [ count ] )

=> count 가 변경되었을 때만 실행됨 , 이것을 의존성 배열 이라고 함

 

api 의 경우 랜더링되고 최초에 한번만 호출해주면 됨

그럴 때는 빈배열을 입력하면 됨

api 비동기 통신을 위해서 fetch 를 이용할 것임

useeffect( ( ) => { fetch(~localhost:3001/days)  }, [ ] )

=> fetch(api 경로) 이렇게 하면 promise 가 반환됨

fetch(api 경로) .then ( res => { return res.json() } )

=> 여기서 api 경로가 json 데이터가 아니라면 .json 이렇게 메서드 사용해줌 이렇게 하면 json 으로 변환되고 promise 를 반환

fetch(api 경로) .then ( res => { return res.json() } ) .then ( data => { setdays( data ); } )

=> json 으로 변환한 것을 setdays data 라는 매개변수로 넣어 전달

 

이제 dummy 로 사용되던 데이터들을 다 교체해줄 것임

day 컴포넌트로 가서

useeffect( ( ) => { fetch( `~localhost:3001/words?day=${day}` ) .then ( res => { return res.json() } ) .then ( data => { setdays( data ); } )  }, [ ] )

위에서 useparams 훅으로 주소창에 문자열이 들어옴, <route path='/day/:day'> 로 해줬기 때문에 따라서 ${day} 해주면 day 에 해당하는 1,2,3 ${day} 여기에도 들어옴

 

그런데 이렇게 하면 [ ] 이쪽에 day 가 의존성 배열이 없다 라는 에러가 뜸

그 이유는 주소를 ${day} 같이 백틱으로 특정값을 사용하면 [ ] 입력하라는 뜻

의존성 배열이 비어있기 때문에 day 가 변경되어도 새로운 정보를 가져올 수 없게 됨

그래서 [day] 해주면 day 값이 최신 값으로 보장 받을 수 있게 됨

 

그런데 daylist day 컴포넌트에서 쓴 useeffect 로 가져온 데이터가 주소 빼고는 똑같이 작성됨

그래서 이렇게 동일한 로직은 사용자가 직접 훅을 만들어서 사용할 수 있음 custom 훅이라고 함

 

 

13. custom hooks

- 다른 폴더를 하나 만들고, usefetch 라고 원하는 이름의 컴포넌트를 만들어준 뒤

- const [ words, setwords ] = usestate([]);

useeffect( ( ) => { fetch( `~localhost:3001/words?day=${day}` ) .then ( res => { return res.json() } ) .then ( data => { setdays( data ); } )  }, [ ] )

- day 컴포넌트의 위 코드를 그대로 가져와 usefetch () { } 의 중괄호 안에 넣어줌

- 훅들 import 해주고

- day daylist 에 주소만 다르니까 usefetch ( url ) { } 이라고 매개변수를 지정해준 뒤

- fetch( `~localhost:3001/words?day=${day}` ) -> fetch(url) 해줌

=> 주소를 받아서 fetch 를 해준 것

- 의존성 배열에도 달라지는 주소값을 업데이트 해줄거니까 url 넣어주고

- const [ words, setwords ] = usestate([]); 이 부분을 다른 컴포넌트에서도 사용할 수 있게 data, setdata 로 변경 / setdays( data ) setdata 로 같이 변경

- 결국 우리가 필요한 건 data 니까 return data; 를 해줌

이렇게 하면 나만의 커스텀 훅이 완성!

위에 것 설명 : data 라는 상태값이 있고 url , api 를 넘겨받아서 fetch 하고 응답하는 데이터를 setdata 해주는 것 그리고 마지막으로 그 최종 data 를 넘겨줌

 

그러면 daylist 컴포넌트에 가서

usefetch( '~localhost:3001/days' ) 해주면 이 컴포넌트가 랜더링되고

usefetch 컴포넌트에 해줬던 useeffect 가 실행이 되는 것

그리고 usefetch ( url ) '~localhost:3001/days' 이 값을 넘겨주는 것

거기에 const days = usefetch( '~localhost:3001/days' ); 해주면 days daylists 에서 days.map 으로 반복해서 넣어주고 있었기 때문에 각 데이터가 알아서 들어감

 

따라서 api data 로 받아오는 부분은 const days = usefetch( '~localhost:3001/days' ); 이 한줄로 처리할 수 있음

 

day 컴포넌트도 마찬가지로

const words = usefetch( `~localhost:3001/words?day=${day}` );

=> 주소를 전달해주기만 하면 됨

 

이렇게 비슷한 작업들을 하나의 커스텀 훅으로 만들어서 여기저기에 쓸 수 있음

반복x 코드도 간결해짐

수정해야 될 경우, 만들어뒀던 usefetch 컴포넌트로 가서 수정만 해주면 됨

 

 

14. put(수정), delete(삭제)

put 메서드로 update 해주기:

- 다 외웠다는 뜻으로 체크박스를 체크해주면 그 단어를 dim 처리 하도록 업데이트 해줘야 함

- 지금은 체크하고 새로고침해주면 다시 원 상태로 돌아옴

- word 컴포넌트에 toggledone 함수에 setisdone(!isdone) 해준 것을 지우고 그 안에 작성해줄 것임

- 사용법은 get 할 때와 비슷

- fetch( `~localhost:3001/words/${word.id}` ) => 단어의 id 로 넣어줌

- fetch( `~localhost:3001/words/${word.id}` ), { } -> 그리고 객체 안에 옵션을 넣어줄 것임

- { method : 'PUT', headers : { 'Content-Type' : 'application/json' },  }

=> Content-Type(https://jw910911.tistory.com/117) 은 보내는 리소스의 타입을 의미함 api 연동시에 보내는 자원을 명시하기 위해 보통 사용함 평범한 문자열부터 html, 이미지 등 여러가지가 있음 우리는 json 형태로 보낼 것이기 때문에 json 이라고 한 것임

- headers 다음에, body 를 입력해줄 것임 단순히 정보를 가져오는 get 과는 달리, put 은 수정해줘야 하기 때문에 수정을 위한 정보들을 실어서 보내줘야 함 그것을 body 에 입력

- body : { ...word, isdone : !isdone } => ...word 이전 데이터에 isdone 을 바꿔서 입력해주면 됨

- 이걸 json 의 문자열로 변환하기 위해서 body : JSON.stringify( ) 로 감싸줌

- .then( res => { if(res.ok) { setisdone(!isdone) } => then 하고 응답을 받아서 만약 응답이 ok 면 스테이트를 바꿔주도록

이렇게 하면 반영이 됨

 

단어 삭제 버튼을 누르면 삭제를 물어보고 확인을 누르면 삭제하는 것:

- word 컴포넌트에서 del 이라는 함수를 만들고 삭제 버튼에 onclick 으로 넣어줌

- 함수 안에 if( window.confirm( '삭제하시겠습니까? ) ) { fetch ( `~localhost:3001/words/${word.id}` ), { method : 'DELETE'  }

=> 만약 창에 '삭제~' 가 뜨면 url 로 주소를 넘겨주고, 메서드 옵션은 delete

- 이렇게만 하면 삭제가 바로 안되고 새로고침을 해야 삭제됨 삭제된 이후에 이 단어리스트를 다시 그려주지 않았기 때문임

- 그래서 삭제 요청을 하고 ok 응답을 받으면 컴포넌트를 다시 랜더링 해주도록 설정

- 이때 null 을 리턴해주면 아무것도 표현하지 않음

- const [word, setword] = usestate(w); 해주고 이름이 겹치면 안되니까 function Word( {word: w} ) 로 수정 / word: w -> 새로운 이름을 할당해준 것 prop 로 넘어온 word w 라는 변수명으로 사용하겠다 라는 뜻

- .then( res => { if ( res.ok ) { setword ( { id: 0 } ); } } ); => 삭제를 하면 word id 0 으로 바꿔줌

- 그리고 함수 밖에 if ( word.id === 0 ) { return null; } => word 의 아이디가 0 이면 리턴으로 null 해서 아무것도 표현하지 않게 함

- 새로고침해도 안 보이고 json 파일에도 확인해보면 완전히 삭제된 것을 볼 수 있음

 

이제 다음에는 post 로 단어와 day 추가해줄 것

 

 

15. post(생성), usehistory

단어 추가를 위해 createword 컴포넌트 생성,

app.js route 로 컴포넌트 연결해주고,

header 에도 단어 추가 버튼에 link to route 주소 연결,

단어 등록 폼을 하나 만듦 - label eng input computer, label kor input 컴퓨터, day 추가 select option

 

day 추가 하는 부분 에는 하드 코딩으로 넣었는데 실제 daylist 를 받아서 넣어주면 됨

저번에 만들어 둔 데이터 custom 훅이 있으니까 그걸 활용

const days = useFetch( '~localhost:3001/days' );

데이터 불러주고 map 을 이용해 넣어주면 됨

{ days.map ( day => { <option key = {day.id} value={day.day}> {day.day} </option> } ) }

그러면 1,2,3 셀렉트 박스가 주르륵 나옴

 

그리고 저장 버튼을 누르면 새로고침이 되는데 이건 form 태그로 감싸져 있어서 그럼

function onSubmit (e) { e.preventDefault( ); } 함수를 만들어주고

<form onSubmit={onSubmit}> 이라고 수정해주면 버튼을 눌러도 새로고침 되지 않음

preventDefault 로 기본 기능을 막아준 것

 

저장 버튼을 눌렀을 때 단어와 뜻에 대한 정보를 찍어보기 :

input 창에 적힌 값들을 얻기 위해 useRef 라는 훅을 사용

useRef 라는 훅은 돔에 접근하게 해줌 예를 들어 스크롤 위치를 확인하거나 포커스를 줄 때 사용할 수 있음

const engRef = useRef (null);

const korRef = useRef (null);

const dayRef = useRef (null);

=> 각 초기값이 null 인 세개의 ref 객체를 만듦

input, select ref 를 연결 -> ref={ engRef } / ref={ korRef } / ref={ dayRef }

이렇게 연결해주면 돔 요소가 생성된 후 접근할 수 있음

 

이 저장버튼을 클릭하는 숫자는 당연히 랜더링 결과가 돔에 반영된 이후 임

그래서 console.log( engRef.current.value ); console.log( korRef.current.value ); console.log( dayRef.current.value ); 이렇게 찍어주고 아무 거나 적은 뒤 저장을 누르고 콘솔을 보면 그 값이 제대로 나오는 걸 볼 수 있음

이렇게 current 속성을 이용하면 해당 요소에 접근할 수 있고 value input 에 입력한 값을 얻을 수 있음

 

이제 post 를 이용해서 단어 생성 :

필요한 정보는 day, eng(영어), kor(), isdone

day, eng, kor 는 이 form 으로 입력을 받고 isdone 은 초기값 false 로 고정해서 저장

word 컴포넌트에서 put 했던 코드를 가져와서 사용할 것

fetch 에 들어가는 주소는 words/ 까지만 해주고,

메서드는 POST,

body 는 중괄호 안을 day, eng, kor, isdone : false 로 수정

이 값들은 current.value 했던 값들을 찍어주면 됨

day : dayRef.current.value, eng : engRef.current.value, kor : korRef.current.value

그리고 if ( res.ok ) 쪽으로 가서 생성되면 alert('생성이 완료되었습니다') 을 하나 띄워줄 것임

 

이제 생성이 될 때마다 직접 가보는 방법 말고 생성이 완료되면 day 컴포넌트로 보내주도록 :

console.log( engRef.current.value ); console.log( korRef.current.value ); console.log( dayRef.current.value ); -> 이 부분은 지워주고

useHistory 를 사용할 것임 useHistory react-router 에서 지원하는 기능

history 객체는 페이지를 이동한 내역을 정보로 가지고 있는 객체

alert 밑에 history.push( `/day/${ dayRef.current.value }` )

useHistory 로 생성한 history 에 주소를 push 해주면 해당 페이지로 이동함

link to 처럼 a 태그를 사용하지 않고 페이지를 전환시킬 때 유용하게 사용할 수 있음

그니까 history.push 와 이벤트를 이용하여 저장 버튼을 클릭하면 저장할 때 선택한 day 의 페이지로 이동하는 주소의 path로 이동

 

날짜를 생성하는 작업 :

createday 라는 컴포넌트를 만들고 link to 로 연결해주기

현재 일수 : 10 -> 현재 몇 일까지 있는지 표시해줄 것임

day 추가 라는 button 도 생성

const days = useFetch( '~localhost:3001/days' ); 불러오고

현재 일수 : { days.length } -> 현재 일수를 데이터의 인덱스 길이만큼으로 표시하도록 수정

 

버튼을 누르면 day 가 추가되도록 수정할 것임

단어 추가와 똑같은 로직이니까 가져오면 됨 fetch 해줬던 것 가져오기

day 추가 버튼에는 onclick 하면 {addDay} 호출 추가

함수 addDay 에 가져온 fetch 넣어주고

fetch url words 가 아닌 days 로 하고 필요한 정보는 day 하나 이고 id 는 자동으로 만들어 주기

body 에는 day 하나만 있으면 됨

현재 3일까지 있으니까 4일을 추가하면 되고 4일까지 있으면 5일 추가하면 됨

결론적으로 현재 날짜에 +1 을 해주면 됨

=> day : days. length + 1

완료가 되면 첫번째 페이지로 가도록 history.push(`/`) 로 수정, const history = useHistory(); 추가

 

16. 마치며

단어 페이지나, day 선택이 네트워크 연결이 느려서 안 뜨면 로딩이 뜨도록 설정

단어 추가에 저장 버튼을 눌렀는데 네트워크 연결이 느려서 창이 안 뜨고 저장버튼을 계속 누를 수 있게 되면 state 와 로딩 함수를 추가해서 단어 추가 과정이 안 뜨도록

 

여기에다가 day를 잘못 만들 수도 있으니 삭제하는 기능도 필요해보이고, day 1 단어에서 다른 day 단어 페이지로 가려면 header 의 로고를 클릭해야 하는데 슬라이더 처럼 양 쪽에 화살표를 설치해서 다른 페이지로 갈 수 있게 하는 기능도 필요해보임 -> 과제.. 할 수 있을까..?

 

 

 

 

 

출처 : 코딩앙마 React JS 유튜브 강의

 

 

 

 

 

6/7
오늘은 풀페이지, 비구조화 할당, 모듈, 리액트를 배웠다. 
 풀페이지는 script 로 어렵게 구현했던 슬라이드를 플러그인을 통해 쉽게 구현할 수 있어서 재밌었다. 다만 아직 확실히 구조를 잡는 방법이 어려워서 계속 만들어보며 연습하는 게 중요할 것 같다. 또 콜백처리가 익숙하지 않아 배민을 만들면서 같이 사용해봐야 할 것 같다.
 비구조화 할당은 리액트를 쓸 때 많이 사용한다고 해서 최대한 이해하려고 노력했다. 아마 리액트를 하는 중간중간 다시 봐야겠지만 대충 좌변에는 변수, 우변에는 해당 변수에 넣는 값이라고 이해했다. 코드가 좀 더 간단해지고 초기값 지정이 가능하기 때문에 많이 쓰는 것 같다.
 모듈이란 걸 사용했는데 외부 스크립트를 단순하게 파일로 불러들이는 것이 아니라 import, export 를 사용해서 다른 파일에서도 사용할 수 있도록 변수 등을 재사용하도록 하는 것 같았다. 간단하게 사용해봤지만 아마 실제로 사용하면 많이 어려울 것 같았다.
 오늘 처음 리액트를 했는데 리액트 화면을 브라우저에 나타나게 하는 부분부터 작동이 되지 않아 강사님부터 여러 사람의 도움을 받았지만 해결하지 못했다. 아마 npm 파일에 문제가 있는 것 같은데 node.js 프로그램을 몇 번이나 삭제하고 재설치해도 작동이 전혀 되지 않았다. 나중에는 해결하려고 구글링을 하면서 여러 개를 만지다보니 MODULE_NOT_FOUND 라는 문구가 계속 뜨면서 create-react-app 조차 되지 않았다. 교육 때 리액트 기초를 가르쳐주셨는데 아예 볼 수가 없으니 아예 따라가지 못해서 처음으로 무기력함을 느꼈다. 이렇게 작은 거 하나조차 못 견뎌하는데 과연 개발자가 나에게 정녕 맞는건지 궁극적인 의문이 들었다.
 집에 와서는 배민 마크업을 했다. 강사님과 만들었던 걸 보면서 마크업을 했는데 배민이 좀 복잡한 부분이 있어서 강사님과 했던 것을 대부분 복사 붙여넣기 했는데도 슬라이드 부분이 화면에 나오지 않아 조원의 도움을 받아서 마크업을 수정했다. 

6/8
오늘은 deep copy, shadow copy 와 map 반복문, react component 에 대해 배웠다. 
 드디어 리액트 npm 문제를 해결했다. 다른 교육생과 문제를 풀어보려고 했을 때 컴퓨터에 저장되어 있는 npm 파일을 보고 혹시 node.js 프로그램을 삭제해도 컴퓨터에 잔류되어 있는 npm 파일에 문제가 있는 것이 아닐까 라는 생각이 들었다. 그래서 node.js 프로그램을 삭제한 뒤 node, npm 을 검색해 나온 파일 중 관계 없는 삭제하면 안될 것 같은 파일은 제외하고 전부 삭제했다. 그 뒤 다시 node.js 프로그램을 설치하고 리액트 파일을 만든 뒤 해당 파일 내에서 npm start 를 했더니 아무 문제없이 실행이 됐다.

 이틀동안 해결되지 않아서 강사님, 교육생 모두 같이 고민해주시고 고생해서 얻은 결과라 그런지 성취감을 깊이 느꼈다. 아직도 에러가 나오면 치가 떨릴 정도로 싫긴 하지만 이젠 두렵지 않다. 어떻게든 해결될 것이라 믿기 때문이다. 비록 해결하느라 교육도 제대로 듣지 못하긴 했지만 이정도로 끝나길 다행이라는 생각이 들었다. 
 집에 와서는 배민 첫번째 슬라이드 css 를 만들고 오늘 제대로 듣지 못했던 리액트의 기초 강의를 들었다. 

6/9
json placeholder 를 만드는 방법, for/in 문 aos 라이브러리에 대해 배웠다.

 placeholder 는 간단하게 데이터베이스를 만드는 것인데 동일한 구조의 컨텐츠에 각각 해당하는 데이터를 집어넣을 때 쓰인다고 한다.

 for/in 문은 객체 타입의 데이터를 다룰 때 객체 안의 프로퍼티 이름, 값을 각각 따로 뽑아볼 수 있어 스크립트 처리할 때 유용해보였다.

 aos 라이브러리는 요소가 뷰포트에 나타날 때 효과를 주는 간단한 라이브러리인데 확실히 활용도가 높아보였다.
 리액트에 대해 배울 때 map 으로 중복되는 요소 각각에 해당 데이터를 넣는 작업을 했었다. 그런데 화살표 함수의 소괄호 안에 들어있는 movie 가 무엇을 뜻하는지 궁금해서 강사님께 여쭤봤다. movieList.map 을 돌릴 때 movieList 가 json 파일을 통해 가져온 데이터로 지정되어 있었는데 movie 는 각 데이터 덩이를 뜻하고 표현식 안의 {movie.title} 는 그 덩이들 안의 title 이라는 프로퍼티 이름의 값을 불러들이는 것이다. 
 스크립트 기초만 다지다가 처음으로 보충 수업 때 강사님과 했던 arrow 스크립트를 안보고 따라해봤다. 비록 하다가 너무 진행되지 않는 건 조금씩 보고 했지만 내가 생각한대로 코드를 치고 그대로 잘 작동이 되니 너무 재밌었다. 강사님과 했던 스크립트를 외우듯이 해설을 따로 적어놓고 어떤 부분이 바뀌어야 하는지 대충 생각하고 적은 다음 혼자 변수 설정부터 끝까지 해봤다. 맨바탕에 처음부터 끝까지 클론코딩하기엔 아직 부족하지만 계속 이런 식으로 연습하다보면 익숙해져서 스터디 과제인 배민도 할 수 있을 것 같은 자신감이 들었다.


6/10
props 구조분해할당, state 에 대해 배웠다. 
 props 는 리액트 기초강의에서 봤던 것인데 다시 배우니 색다른 느낌이 들었다. props 구조분해할당은 컴포넌트에서 Porps를 조회하는 코드를 더 짧게 구현하는 방법이라고 한다. 객체 안의 값을 효율성있게 가져올 수 있는 방법 같았다. app.js 에 컴포넌트 한 개에 각 이름과 값을 지정하고 불러들이면 해당 값이 출력된다. 
 state 를 사용해서 클릭 이벤트를 생성하는 걸 배웠다. state 는 초기값을 설정하고 그에 대한 변수와 변수에 대한 함수를 지정해주는 리액트 문법이다. 계속 강사님과 연습을 했는데도 어려워서 기초 강의를 들어봐야겠다. 

6/11
강의로 state 문법 이해, 배민 css 마무리
 배민 css 를 만들면서 배경이 확대됐다가 원래 상태로 돌아오는 걸 하고 싶었는데 transform 을 주고 transition 을 적용했는데 커졌다가 다시 돌아오는 건 되지 않아서 배민은 어떻게 했는지 참고했더니 애니메이션을 주고 있었다. 그래서 애니메이션으로 transform 을 주고 각 속성값을 적용하자 제대로 작동했다.

6/12
배민 js, 코딩 알려주는 누나 js 강의 보기

5/30
탭을 구현하는 것과 해당 배경색도 바뀌도록 구현하는 응용탭, 모달, 아코디언 등을 배웠다. 뜯어서 보면 이해가 가지만 변수를 지정하고 함수를 만들어 자동으로 돌아가도록 하는 게 어려웠다. 그러니 막상 만들려고 하면 변수만 지정하고 그 뒤에 식은 하나도 만들지 못했다. 그래서 변수부터 돌아가서 다시 공부했다. 책과 필기, 이제까지 했던 실습 파일들을 다시 살펴보면서 이해했다. 나는 이해했다고 생각하고 넘어갔던 것들이 사실은 아무것도 이해를 못했던 것 같다.

5/31
어려운 것부터 이해하려고 애썼던 것을 모른다고 인정하니 마음이 편안해졌다. 그래서 그런지 오히려 오늘 했던 슬라이드, 버튼이 이해가 잘 됐다. 따로 문서에 적으면서 하니까 강사님 말씀도 놓치고 불편한 점이 많았는데 주석을 넣으며 필기하니 강사님 말씀을 더 빨리 필기할 수 있어 더 편했다. 또 연산자를 다시 공부하니 조건식들이 눈에 들어오면서 함수를 이해할 수 있었다. 연산자를 끝내고 제어구문을 공부하기 시작했다. 조건문까지 공부했다. if/else 문은 많이 써봐서 공부가 수월했다.

6/1
오늘 쉬면서 복습을 거의 끝내고 강사님이 과제로 내주신 sushi 를 하려 했으나 반복문을 공부하느라 시간을 전부 보내버렸다. 특히 while 문을 이해하는데 애를 먹었었는데 간단한 식은 괜찮았지만 책의 예제에 있던 증감연산자가 내가 생각한대로 적용이 되지 않았다. 결국 console 에 출력된 값은 아직 증감이 적용되지 않아 내 값이랑 다를 수 밖에 없었던 것이다. 그걸 하루 온종일 공부해서 목표로 잡은 sushi 는 하지 못했지만 늦게라도 기초를 이해하고 넘어가서 다행이라는 생각이 들었다.

6/2
window 객체의 주요 프로퍼티와 주요 메서드에 대해 배웠다. xy 위치값을 잡고 스크롤로 이동을 하는 방법을 배워 각 목록을 누르면 거기에 맞는 각 본문으로 이동하는 페이지를 계속해서 만들었다. 비슷한 메서드들이 많고 살짝씩 달라서 어디에 뭘 적용해야 해야 좋을지 구분하기 어려웠다. getBoundingClientRect 는 브라우저 안쪽 상단부터 요소까지의 거리로 getBoundingClientRect().top + scrollY 를 하면 절대값이 나온다는 것을 다른 교육생 덕분에 이해하게 되었다. 

6/3
오늘은 IntersectionObserver, 어제 배운 html 의 위치를 잡는 메서드를 이용해 계속해서 스크립트를 만드는 연습, swiperjs 플러그인을 활용한 슬라이더 만드는 방법을 배웠다. IntersectionObserver 는 뷰포트에 어느 정도 컨텐츠가 들어오면 어떤 효과를 보이게 하고 싶을 때 사용하는데 교차나 관찰 같은 말들이 잘 이해가 되지 않았다. 하지만 몇번 강사님과 함께 연습을 해보니 scroll 보다 쉽게 할 수 있을 것 같았다. swiper.js 는 많이 연습하며 써봐야 익숙해질 것 같다.

6/5
코딩 알려주는 누나 자바스크립트 영상을 봤다.

5/23
 오늘 js 는 변수와 함수에 대해 배우고 css는 grid 부모 요소에 적용하는 속성에 대해 배웠다. 변수까지는 이해가 잘 됐는데 함수는 이해하기 어려웠다. 특히 매개변수에 for 문을 이용했던 것이 잘 작동은 되지만 어떤 구조로 작동되는지 어떻게 작용하는지 이해가 되지 않았다. 그리고 grid 는 간단하고 쉽지만 속성의 종류가 많아서 외울 필요가 있을 것 같다.
 집에 와서 삼성전기 마크업과 오늘 배운 js 부분 이해와 grid 속성 외우기를 했다. 삼성전기는 마크업이 복잡해서 여러번 뜯어고치는 과정을 반복했다. 전에는 간단해서 머리 속으로 레이아웃을 잡았는데 앞으로 계속 마크업이 복잡한 페이지를 만들테니 조원분이 알려준 그림을 활용하는 방법을 써야겠다는 생각이 들었다.

5/24
 오늘 js 는 객체를 생성하는 방법에 대해 배우고 css grid 자식 요소에 적용하는 속성에 대해 배웠다. 다양한 방법에 대해 배웠는데 prototype 부터 막히기 시작해서 점점 이해가 어려웠다. 
 스터디 모임에서는 각자 과제 중 어려웠던 점을 묻고 답하는 시간을 가졌는데 nature 페이지 구현 중 모바일 반응형에 속성이 잘 먹지 않았던 것이 경로 우선순위를 지키지 않아서 반영이 되지 않았던 것이었다. 그리고 transition 이 작동하는 원리에 대해 궁금했는데 조원의 도움으로 이해가 가능했다. 반응형 웹페이지에 모바일 반응형을 할 때 메뉴 부분에 호버가 되면 바탕색이 전체로 적용되지 않았는데 넓이를 px 로 주고 마진을 줘서 전체에 적용이 되지 않았던 거였다.

5/25
오늘은 클래스, 입력출력 메서드, 전역 객체, 숫자 객체, 문자 객체, date 객체에 대해 배우고 grid 나머지에 대해 배웠다. js 는 각 객체의 속성들에 대한 이해를 하고 외웠다. grid 속성에 대한 양이 많아서 외우고, 다른 교육생이 연습하던 '몬드리안' 의 그림으로 연습했다. 

5/26
오늘은 배열, 돔트리, foreach, 이벤트 처리기에 대해 배웠다. 배열 만드는 것도 물론 어려웠지만 돔트리부터 노드나 element 가 태그인지? 등 새로운 단어가 우수수 나오니 정신이 없고 힘들었다. 다른 부분 배울 때보다 이해력이 많이 떨어져서 어려움을 겪은 것 같아 기분이 좋지 않았다. 쉬는 시간마다 연산자부터 기본 메서드들까지 다시 살펴봤다. 이벤트 처리기는 처음엔 재밌었는데 페이지 구현을 시작하니 점점 복잡해졌다. css 와 연결해 js 를 구현하는 부분에서 잘 연결이 되지 않아 답답했다. 또한 작은 오타 실수를 해도 값이 나오지 않으니 유의해서 코드를 작성해야 할 것 같다.

5/27
오늘은 계속해서 이벤트에 대해 배웠다. 이벤트 부분이 잘 이해가 되지 않는데 계속 진도를 나가고 홈페이지를 계속 구현하는 작업을 해서 좀처럼 따라가지 못했다. 연산자가 지나간지가 언젠데 계속해서 기초만 붙잡고 있는 내 모습이 답답하기도 했다. 역시나 강사님과 만든 걸 보면 이해가 되는데 막상 페이지를 만들라고 하면 복사 붙여넣기만 반복하고 있어서 자습 시간 중 계속 기초 강의를 알아보고 수강했다.

5/29
삼성전기 상단 css 를 만들었다.

5/16
저번 주에 배운  padding  으로 높이 잡는 게 이해가 잘 되지 않아서 조원들에게 물어봐서 도움을 받았다. 앞으로 flex 부분을 많이 이용할 것 같아 속성값을 입력해보며 다시 연습했다. 블루 보틀 페이지를 다시 만들어보며 복습했다. 

5/17
오늘 처음으로 js 를 배웠는데 완전 새로운 미지를 배우는 것 같았다. 메모리, 콘솔, 변수 등등 모르는 것 투성이었다. 그래도 일단 머리 속에 꾸역꾸역 잘 집어넣긴 한 것 같다. 카카오톡 chat 부분을 다 하지 못해 집에서 마무리를 했다. chat 은 reset 적용한 거 말곤 html, css 전부 만들어 봤는데 flex 덕분에 쉽게 할 수 있었다. 다만, 하단 부분이 처음부터 일렬로 잘 맞지 않아 각 요소들의 위치를 잡기가 너무 어려웠다. 겨우겨우 padding 과 magin, position 을 이용해 맞춰서 엉성하게 나마 맞출 수 있었다. 매번 쓰던 것만 쓰다보니 새로운 페이지를 만들 땐 새로 배운 것들을 적용하기가 너무 어렵다. 

5/18
오늘은 css 반, js 반 정도를 배웠는데 역시나 js 를 배울 때는 너무 정신이 없었다. 처음보는 것 투성이라 강사님의 설명이 더욱 빠르게 느껴지고 두루뭉술해서 이해하기 보단 머리 속에 집어넣기 바빴다. 집에 도착하고 스터디 과제로 nature 페이지를 만들어 봤다.

5/19
오늘은 js 의 다양한 연산자에 대해 배우고 nature 페이지를 강사님과 함께 만들어 보는 시간을 가졌다. 연산자는 들으면 이해는 갔지만 막상 써보려고 하니 잘 되지 않았다. 집에 와서 외우고 직접 써보면서 익히는 공부를 했다. 그리고 강사님이 교육 중간에 내준 미디어쿼리를 이용한 페이지 구현과 sns 페이지 과제를 하루에 다 만들었다. 빠른 속도는 아니지만 그래도 이전보다는 빨라진 것 같아 뿌듯했다. 

5/20
오늘은 js 의 제어문에 대해 배워봤다. 제어문에는 조건문, 반복문, 점프문이 있고 조건문에는 if/else문,  switch문, 반복문에는 while문, do/while문, for문, for/in문, 점프문에는 라벨문, break문, continue문이 있었다. 아직 배우지 않은 구문도 있지만 추후에 배울 것 같다. 완성된 걸 보면 이해는 가는데 강사님이 직접 만들어보라고 할 때 손도 대지 못했다. 쉬는 시간마다 책을 보면서 이해를 해봤지만 부족해서 유튜브에 관련 기초강의를 들었다. 그리고 오후에는 scss 라는 전처리기기를 이용하여 css를 보다 쉽게 작성할 수 있도록 배워봤는데 막상 해보니 잘 되지 않아서 원초적으로 하나씩 작성하는 게 더 쉬웠다. 좀 더 익숙해지도록 연습이 필요할 것 같아 sns 페이지 css를 scss를 이용해 다시 만들어봤다.

5/22
3주차에 배운 것을 복습해보고 정리하여 기록했다.

 이번 주에는 지마켓과 이솝페이지를 따라해보면서 중간중간 CSS에 대해 학습했다. 수요일에  교육을 끝내고 만나서 회의할 때는 전 날 진행한 지마켓 상단과 하단은 다 끝낸 상태여야 했고 이솝도 상단과 하단을 다 끝냈어야 했다. 하지만 모든 조원이 아직 완성하지 못해서 이번주에는 그것을 완성해보는 것을 목표로 정했다. 완성한 후 각자 어떻게 만들었는지 비교해보고 해설하는 시간을 가져보고 싶었는데 아무래도 하루 학습량이 많다보니 각자 복습하는 것도 빠듯해서 보류하기로 했다. 

 요즘 진도가 아주 빠르게 나가기 때문에 그날 배운 것을 복습하더라도 새로운 것을 배우다보면 이전에 배운 것을 잊어버려 자괴감이 들 때도 있다. 또 빠르게 배우는 것도 좋지만 기초 뼈대가 탄탄하지 않으면 건물이 무너지는 것처럼 그날 배운 내용을 충분히 이해하지 못하고 새로운 것으로 넘어가면 결국 떨어져 나갈 것 같다는 불안감이 있다. 그래서 예습을 하는 것보다 복습이 낫다고 판단되어 수업 중 어렵거나 이해가 잘 되지 않았던 점은 유튜브에 CSS에 관한 기초강의를 찾아보고 보충했다.
 이번에 지마켓의 상단과 하단을 만들 때 background 에 img를 transform 을 써서 위치를 잡는 것, calc 함수가 작동되는 원리, background img 가 화면 크기에 따라 움직이지 않고 크기를 유지할 수 있는 방법 등이 구글링을 해도 잘 이해가 되지 않아서 조원들에게 도움을 구했고 이해하는데 많은 도움을 받았다. 이해가 되었다고 생각하여 빈 화면에다 이해가 되지 않는 부분을 직접 다시 입력해보고 실행해보는 시간을 가졌다. 그럼에도 지마켓 상단과 하단을 다시 만들어봤을 때 생각대로 잘 만들어지지 않아서 오랜 시간이 걸렸다. 

+ Recent posts