Home | Hana's DevBlog
나의 시도와 error ⚠️
data.js 파일에는 discussions 라는 배열 타입의 데이터가 있고, 이 데이터를 main.js 에 가져와서 쓰고 싶었다.
//data.js
const discussions = [{id:"",title:"",url:""},{},{},...];
...
module.exports = discussions
//main.js
const { discussions } = require('./data.js')
그런데 이렇게해서는 main.js에서 referenceError: document is not defined 에러가 계속 발생했다.
main.js에서 data.js를 통해 불러오는 변수한테 계속 레퍼런스 에러가 뜬 것이다.
당연히 data.js에 있는 데이터들이 불러와지지 않았다. (이유를 몰랐던 어제만해도 도대체 왜 안불러와지는지 몰랐지만 🥲)
오늘 무심코썼던 require() 함수와 module.exports에 대해 파헤쳐보았고 오랜만에 골똘히 생각하는 시간을 가졌던 것 같다.
Event handler?
이벤트 핸들러 event handler는 이벤트가 발생했을 때 자신은 호출을 안하고 브라우저한테 호출을 떠넘긴다(위임한다).
이벤트 핸들러 등록
이벤트 발생시 브라우저에게 이벤트 핸들러 호출을 떠넘기는 걸 이벤트 핸들러를 등록한다고 한다.
중요한 점은 이벤트 핸들러 함수를 등록할때는 함수를 호출하는 호출문이 아닌 함수 자체를 등록해야 된다. 함수 자체!!!
왜냐면 콜백 함수와 마찬가지로 함수 참조를 등록해야지 브라우저가 이벤트 핸들러를 호출할 수 있다고 한다.
만약 함수 참조가 아닌 함수 호출문 자체를 등록해버리면 함수 호출문의 평가 결과가 이벤트 핸들러로 등록된다고 한다. (모던 자바스크립트 딥다이브 758pg)
이번 react custom component 과제를 하면서 이벤트 핸들러 함수를 등록할때 함수에 parameter가 있을 때와 없을 때의 사용법이 달랐다.
모든 경우의 수를 넣어가면서 ㅋㅋㅋ 작동하는지 확인해봤는데 너무너무 헷갈렸으므로 정리하는 시간을 가져야겠다.
1. No Parameter 매개변수 X
const openModalHandler = () => {
// TODO : isOpen의 상태를 변경하는 메소드를 구현합니다.
setIsOpen(!isOpen);
};
return (
...
<ModalBtn onClick={openModalHandler}
// TODO : 클릭하면 Modal이 열린 상태(isOpen)를 boolean 타입으로 변경하는 메소드가 실행되어야 합니다. >
</ModalBtn>
)
2. parameter가 그냥 변수
const selectMenuHandler = (index) => {
// TIP: parameter로 현재 선택한 인덱스 값을 전달해야 하며, 이벤트 객체(event)는 쓰지 않습니다
// TODO : 해당 함수가 실행되면 현재 선택된 Tab Menu 가 갱신되도록 함수를 완성하세요.
setCurrentTab(index);
};
return (
...
{menuArr.map((menu, index) => (
<li onClick={() => selectMenuHandler(index)}>
</li>
))}
)
3. parameter가 이벤트 객체
const addTags = (event) => {
// TODO : tags 배열 에 새로운 태그를 추가하는 메소드를 완성하세요.
// 이 메소드는 태그 추가 외에도 아래 3 가지 기능을 수행할 수 있어야 합니다.
// - 이미 입력되어 있는 태그인지 검사하여 이미 있는 태그라면 추가하지 말기
// - 아무것도 입력하지 않은 채 Enter 키 입력시 메소드 실행하지 말기
// - 태그가 추가되면 input 창 비우기
if (tags.includes(event.target.value)) {
//이미 입력되어있는 태그이면 추가안하기
return null;
} else if (event.target.value.length === 0) {
setTags(tags); //아무런 입력 없으면, 빈 문자열이면 아무것도 하지마!
} else if (event.key === "Enter") {
setTags([...tags, event.target.value]);
event.target.value = ""; //태그 추가되면 input창 비우기
}
};
return (
...
<input onKeyUp={(event) => addTags(event)} />
)
Array.prototyple.splice()
배열에서 어떤 요소를 제거하고 싶을때 나한테 늘 처음 떠오르는 아이디어는 array.pop() 인데, pop() 메서드는 맨 마지막 요소를 제거한다.
그렇다면 특정 요소만 없애고 싶은데 그럴땐 무슨 메서드를 써야되지? filter 쓰는 것 말고.
같은 문제에 직면했을때 늘 js array remove specific element 을 구글링하는 내 자신 발견 🤣
splice()를 자유자재로 쓰지 못하고 있던 것 같아 이번 기회에 splice()를 정리하는 타임~~
splice(start, [deleteCount], [items])
첫번째 인자만 사용해서 start 부터 이후 요소까지 모두 삭제
const arr = [1, 2, 3, 4];
const result = arr.splice(1);
console.log(arr); //[1] //인덱스 1부터 모두 제거하고 변경된 원본 배열
console.log(result); //[2, 3, 4] //제거된 요소
start에 삭제를 원하는 배열 인덱스 넣고 deleteCount에는 몇 개 삭제할 건지 넣기
const arr = [1, 2, 3, 4];
const result = arr.splice(1, 1);
console.log(arr); //[1, 3, 4] //인덱스 자리 1에서 1개 제거한 이후의 배열
console.log(result); //[2] //제거된 요소
세번째 인자에 items 까지 적어주면 새로운 요소를 삽입해주어 배열 변경 가능
const arr = [1, 2, 3, 4];
const result = arr.splice(1, 1, 100);
console.log(arr); //[1, 100, 3, 4] //인덱스 1에서 1개를 제거한 다음에 새로운 요소를 넣는다.
console.log(result); //[2] //제거된 요소
- 원본 배열이 직접 변경된다. Mutable하다.
- 두번째 인자로 제거할 요소의 개수만큼 원본 배열에서 요소를 제거할 수 있다.
- 세번째 인자로 새로운 요소도 얼마든지 넣어서 원본 배열을 변경할 수 있다.
Node.js Express 프레임워크로 StatesAirlines 서버 구현하기
* 과제 목표
클라이언트 요청에 따라 항공편, 예약 데이터를 CRUD (조회, 생성, 수정, 삭제)하는 기능을 만든다.
* 구조
http://localhost:3001 로 들어가면 제대로 들어온게 맞다는 welcome! 페이지가 띄어짐
이미 주어진 과제 파일에 라우터로 설정이 되었기 때문에 웹사이트는 각 3부분으로 분기가 된다.
/airport
/flight
/book
url endpoint로 쳐서 들어가면 각각 공항 정보, 항공편 정보, 부킹 정보를 볼 수가 있는 것
공항정보를 가져오는 기능은 모두 구현이 되어있었지만, 나머지 flight와 book 에 대한 서버 기능을 만드는게 이번 과제였다.
* 어려웠던 점
query가 뭔지 감으로만 대충 알고 request, response 가 정확히 무엇인지.. express 공식문서를 봐도 개념이 잘 정리가 되지않아 과제를 하는데 매우 헤맸다. @_@
혼자 복습을 하면서 콘솔에 모두 찍어보면서 확인을 하니 이제 조금은 알 것 같다!
Airport 공항이름 자동완성
Request
GET /airport?query={query}
C가 들어있는 공항 코드 검색
console.log(req.query);
//{ query: 'c' }
console.log(req.query.query);
//c
console.log(list); //res.json()으로 보내는 데이터
[
{ name: '제주', code: 'CJU' },
{ name: '인천', code: 'ICN' },
{ name: '세부', code: 'CEB' }
]
Flight 항공편 조회
Request
GET /flight
출발시간이 oo이고 도착시간이 oo 으로 검색
출발지 oo 도착지 oo 으로 검색
console.log(req.query);
//{ departure: 'ICN', destination: 'CJU' }
Flight uuid로 항공편 조회
Request
GET /flight/{:id}
uuid값을 가진 모든 항공편 조회
/flight/af6fa55c-da65-47dd-af23-578fdba40bed
console.log(req.params);
//{ id: 'af6fa55c-da65-47dd-af23-578fdba40bed' }
console.log(req.body);
//{}
정리
query parameter
/airport? /flight? 처럼 endpoint에 물음표 이후에 나오는 값을 query string이라고 한다.
/flight?departure=ICN
보통 필터링을 해서 값을 가져오는 경우 query parameter 사용이 적합하다.
req.query
이때 uri 의 query string을 가져오려면 req.query를 사용한다.
path parameter
/flight/af6fa55c-da65-47dd-af23-578fdba40bed
id와 같이 유일한 값을 가진 데이터는 path parameter로 물음표 없이, 주소 / 이후에 바로 넣어서 사용한다.
req.params
입력된 path parameter의 값을 가져오고 싶으면 req.params를 사용한다
GET 요청을 할땐 웹 브라우저 주소창에서 직접 치면서 바로 어떤 요청이가고 어떤 응답이 오는지 데이터를 직접 눈으로 확인이 되었는데..

POST, PUT 을 요청하려니까 문제가 생겼다.
POST는 실제로 데이터를 요청해서 req.body 내용을 저장해야되는데 도대체 이걸 어디서 요청을 보내고 어떻게 확인한다는 거지?
웹 브라우저 주소창에서 할 수 있는건 GET 요청밖에 할수가 없었다. 아무리 주소창에 백날 POST 요청 uri를 쳐도 아무일도 일어나지 않았다..
정답은 Postman 활용이었다. 불과 몇주 전에 기본 실습해보고 그냥 그런앤가보다 했는데 이럴때 쓰는 거였다!
POSTMAN은 API 테스트 도구로 HTTP 요청을 쉽게 눈으로 볼수 있게 도와주는 그런 아이다.
POST 요청

여기서 주의할 점은, 실제로 post 요청하는 데이터를 body에 json 형식으로 손수 넣어준다!
[POST] /book
let booking = [];
...
create: (req, res) => {
// TODO:
const bookData = req.body;
booking.push(bookData);
return res.status(201).json(bookData);
},
console.log(bookData);
//{ flight_uuid: 'KE1909', name: '에밀리', phone: '010-1111-2222' }
PUT 요청

마찬가지로 put 요청하는 데이터를 body에 제이슨 형식으로 넣는다.
[PUT] /flight/:id
요청된 id 값과 동일한 uuid값을 가진 객체를 찾아서 그 객체의 데이터를, 요청된 body의 데이터로 수정한다.
즉, id값을 uri에 넣고, body에 수정할 내용을 넣은 다음에 put 요청을 날리면 이제 그 데이터는 body에서 요청하는 데이터에 맞게 덮어쓰기가 된다.
console.log(updatedFlight); //uuid 찝어서 req.body로 보내는 데이터
// {
// uuid: 'af6fa55c-da65-47dd-af23-578fdba99bed',
// departure: 'ICN',
// destination: 'CJU',
// departure_times: '2021-12-02T11:00:00',
// arrival_times: '2021-12-04T15:00:00'
// }
JSON.stringify() 원리를 재귀함수로 직접 만들어보다가 헷갈리는 문자열 표현 방법 정리
JSON.stringify 메서드는 객체를 JSON 포맷의 문자열로 변환한다.
일단, 들어오는 요소가 모두 문자열로 변환되어야하고 최종 객체 또한 문자열이 되어야하는 것이 포인트이다.
인자의 타입이 boolean, number 이거나, 인자자체가 null일 경우에는 한겹 ‘’ 씌운 문자열을 감싸준다.
인자가 문자열일경우에는, 문자열 자체에 또 한겹 씌운 ‘””’ 문자열을 반환한다.
그리고 배열과 객체의 경우, 각 요소 또한 문자열로 변환되어야 하기때문에 요소의 타입을 확인하면서 문자열로 변환시켜주는 게 필요한데, 이때 재귀함수를 사용한다.

여기서 나를 정말 고통받게 만든건 …
테스트파일에서 돌려보면 분명!! 숫자, 불리언, 문자열일 경우엔 따옴표가 감싸진게 눈에 보이게 나타나있다.
객체는 문자열 “9”로 변환되어야 합니다
객체는 문자열 “null”로 변환되어야 합니다
객체는 문자열 “true”로 변환되어야 합니다
객체는 문자열 “false”로 변환되어야 합니다
객체는 문자열 ““Hello world”“로 변환되어야 합니다
그런데, 숫자와 문자열을 포함하고있는 배열의 경우
[8, "hi"]
내가 예상했을때는 분명, ‘[‘8’,’“hi”’]’ 의 형태로 나타나야할 것 같은데,
결과값은 ‘[8,”hi”]’ 이렇게 배열의 요소에는 string 겹이 안겹쳐져있는 상태?로 나와야 한다는게 아닌가…?
이게 도저히 이해할 수 가 없었다. 재귀를 거치면 당연히 8은 숫자요소니까 얘도 string형태로 변환되고, “hi”는 문자열이니까 당연히 double로 된 문자열 ‘“hi”‘이어야 되는것 같은데…

그런데 콘솔에 찍어보니 결국 8, “hi” 모두 문자열의 형태였다.
즉 내가 예상하는대로 실제 값은 문자열 타입으로 변환된 값이지만, 표현되는건 문자열이 벗겨진 상태로 표현되는 것 같다.

마치, 그냥 문자열 “choco” 이 있을때, choco라는 값 자체는 ‘choco’이지만, 콘솔에 찍어보면 그냥 choco 로 나오는 것 처럼 실제로는 배열, 객체 안의 모든 요소가 string 의 형태인 것이다.

문자열”” 을 감싸고 있는 ‘””’ 문자열 형태도 콘솔에 찍어보았는데, 실제 가지고있는 값은 ‘””’ 두겹 문자열일지라도 콘솔에는 한겹 “” 으로만 보여진다.

마찬가지로 실제로 JSON.stringify() 메서드를 사용해서 object를 serialize화 시켰을때도, 이 변수의 실제 값은 문자열로 변환된 ‘{}’ 객체인 것이고, 표현은 그냥 {} 객체로 된다는 것
배열, 객체의 요소가 숫자형이나 true, false의 boolean 값 일때는 string ‘’ 이 아예 없는 썡(?)값으로 보여지고, 문자형일때는 “” 한겹만 씌어진 문자형으로 보여서 너무 헷갈렸다.
그런데 알고보니 모든 요소는 이미 다 string 타입으로 변환이 된것이었고, 눈에 보이는 표현 방식이 콘솔에 찍히는 것처럼 문자열 “” 따옴표가 벗겨져서 나타난다는 것이 오늘의 레슨이다.
(다른 테스트케이스와 표현 형식?을 맞추려면 문자열 “9”로 변환되어야 합니다가 아닌 문자열 9로 변환되어야 합니다. 이렇게 실제로 보여지는 값 자체를 보여줘야 되는 듯…)
어쨌든 중요한건 JSON.stringify() 메서드는 객체를 싹 다 문자열 형태로 만든다는 것. 요소도 다 하나하나 찾아서 모든 요소를 하나도 빠짐없이 모두 다 문자형으로 만든다는게 여기서 알아야될 포인트이다.
두 달 전부터 깃허브 블로그 만들기를 시도했는데 그동안 온갖 갖가지 모든 에러와 싸우고 드디어… 오늘 깃헙블로그 설치를 완료했다.
근데 무슨 이미지 넣는것도 코드로 넣어야…??? 롸??
가장 힘들었던 부분은 ruby/jekyll 설치할때 에러 해결과 jekyll 테마적용..? 맥북 M1은 ruby가 시스템에 자동적으로 설정?되어있어서 이걸 또 다 바꿔줘야 된다는걸 알았을리가 🥲
그래도 내 손으로 직접 이렇게 다 설치를 하고 깃에 푸쉬까지 해서 url로도 잘 보이는걸 보니 아주 뿌듯하다.
근데 내가 2개월동안 낑낑거리면서 만들었긴한데 막상 포스트하고 레이아웃 바꾸는 것도 잘 모르겠고 마크다운도 익숙해지려면 좀 시간이 필요할 것 같다. 😓
그래도 힘들게 만들었으니 그 과정에서 공부가 된것 같기도하고… 과정을 남겨봐야겠다.
1. 깃허브에서 블로그로 사용할 레파지토리 생성
나는 먼저 로컬 내 컴터에 GithubBlog 파일을 만들고 거기에 내 username.github.io 형식에 맞춘 폴더를 또 하나 생성했다. 그리고나서 깃허브로 커밋 후 푸쉬를 했다.

2. 맥 운영체제의 패키지 매니저인 homebrew 설치
brew는 패키지 매니저로 터미널 환경에서 여러 프로그램을 설치하고 삭제, 검색 등 관리해주는 프로그램이다.
난 부투캠프에서 리눅스 기초를 배울때 깔아뒀으므로 이건 스킵
3. brew에서 rbenv 설치
루비 버전을 관리해주는 프로그램인 rbenv를 설치
시행착오
처음엔 루비매니저 rvm으로 설치를 진행해서 Ruby는 깔았지만 계속 jekyll 설치에 오류남

결국 rvm을 모두 삭제하고 homebrew환경에서 rbenv로 설치하였다.
다른 프로그램처럼 루비도 계속 새로운 버전으로 업데이트가 되는데, 어떤 버전은 어떤 기능이 되고 어떤 버전은 안되는게 있고해서 이런 개발?프로그램을 설치할땐 버전끼리의 충돌을 피하는게 좋으니 보통 버전매니저 프로그램을 같이 설치하는 것같다. 그치만 난 아직까진 이걸 뭘 이렇게 많이 깔아야되는지 와닿진 않음
4. Ruby 를 rbenv가 관리하는 Ruby로 설치
맥 M1환경에서 자동으로 깔려있는 sytem Ruby가 있는데 얘 말고 rbenv로 관리되는 Ruby 를 설치해야된다.
나는 가장 최신버전인 3.1.2 버전을 설치했다.
그런데 여기서 중요했던건, 루비를 설치하고 터미널에 rbenv versions 을 쳐서 버전을 확인해보면 두개의 버전이 나오는데 rbenv가 관리하는 애로 글로벌 버젼을 변경해야 기본 루비가 변경된다.
system \* 3.1.2 (set by /Users/hana/.rbenv/version)
5. Jekyll 설치
루비는 gem을 사용해서 라이브러리를 설치한다고 한다.
gem install 명령어를 통해 jekyll 과 bundler를 설치한다.
6. Jekyll 테마를 내 로컬 폴더로 다운
여기서도 테마 적용이 안되서 꽤나 헤맸는데 알고보니 받아온 테마 폴더 압축풀고 그대로 내 username.github.io 에 넣는게 아니라 그 폴더에 있는 내용물을 다 그대로 username.github.io에 넣어줘야하는 것 이었다…
7. 로컬에 있는 내용을 Github에 커밋하고 푸쉬하기
이제 테마까지 모두 적용된 걸 git에 올려주는 일이 남았다. 그래야 서버에 뜨는것!
git add.
git commit -m "커밋메시지"
git push origin main
설레는 마음으로 커밋 푸쉬를 했는데 또 오류 …^^

error: failed to push some refs to ‘git주소’
Updates were rejected because the remote contains work that you do not have >locally.
오류메시지를 자세히 보니 내가 업로드하려는 원격 파일에 내가 로컬에 가지고 있지 않은 파일이 포함되어있다고 했다.
내가 이블로그 저블로그 참고하다가 만들면서 파일을 삭제했다가 지지고 볶아서 그래서 원격이 갖고있는 파일과 로컬이 갖고있는 파일이 달랐었던 것 같다.
힌트대로 git pull origin main으로 원격파일을 pull 해와서 원격에 있는 파일이랑 로컬에 있는 파일을 같게 만들어주고!
다시 푸쉬하니 드디어… 브라우저에 내 블로그 주소를 입력하니깐 테마가 잘 적용된 블로그가 떴다. 🎊
8. bundle exec jekyll serve 을 통해 아직 서버에 띄우기 전에 블로그 미리 보기
터미널에서 내 블로그가 있는 디렉토리에서 bundle exec jekyll serve 를 하면 localhost 주소가 뜨면서 거기서 블로그 미리 보기를 할 수 있다는데, 나는 이 명령어를 치니 또 에러였다. 후우…
cannot load such file – webrick

찾아보니 webrick만 추가해주면 된다고해서 추가해주었더니
이젠 아주 잘 된다..!!
너무나도 오랜 시간동안 붙들고 힘들게 만들었지만 그래도 이 수많은 에러를 뿌셔내고 깃허브 블로그 만든 내 자신한테 장하다고 해야겠다..!
🎃
참고 블로그
https://zeddios.tistory.com/1222
https://choijaegwon.github.io/githubblog/GithubBlog1/
https://hyeonjiwon.github.io/blog/markdown_img/
You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit.
