https://www.youtube.com/watch?v=Tt_tKhhhJqY
description: |-
1. 이건 꼭 알아야 한다^1
[? 질문] 브라우저에서만 돌던 자바스크립트를 내 컴퓨터/서버(백엔드)에서 실행하려면 무엇이 필요한가^2
[= 답] 브라우저의 인터프리터 없이도 자바스크립트를 실행할 수 있게 해주는 런타임인 Node.js를 설치해야 한다.^9
[? 질문] Node.js 백엔드에서 “필요한 기능을 빠르게 구현”하는 핵심 메커니즘은 무엇인가^22
[= 답] npm(Node Package Manager) 으로 이미 만들어진 모듈(패키지) 을 설치해 가져다 쓰는 방식이며, package.json/package-lock.json으로 의존성을 관리한다.^24
[? 질문] Express로 API 서버를 만들 때 요청이 들어오면 내부에서 어떤 흐름으로 처리되는가^83
[= 답] 서버가 listen(포트)로 요청을 “항상 듣고” 있다가, 요청의 HTTP method(GET/POST 등) 와 라우팅(path) 에 매칭되는 핸들러(app.get('/path', callback))를 실행하고, res.send() 또는 res.json()으로 응답을 돌려준다.^84
[? 질문] 프론트엔드(HTML/브라우저)에서 백엔드 API를 호출할 때 자주 막히는 문제(CORS)는 왜 생기고 어떻게 해결하는가[^134]
[= 답] 보안 정책 때문에 “다른 출처(origin)에서 온 요청”이 기본적으로 차단될 수 있고, 서버에서 cors 미들웨어를 설치해 app.use(cors())로 허용 정책을 설정하면 된다.[^141]
2. 큰 그림^1
이 콘텐츠는 “Node.js로 백엔드 개발을 시작하는 사람”을 대상으로, Node.js 설치 → npm으로 모듈 설치/관리 → Express로 서버 실행 → 라우팅/요청 파라미터 처리 → JSON API 만들기 → CORS 해결 → 프론트엔드(fetch)와 연결까지 한 번에 실습하는 흐름으로 구성되어 있다.^1 또한 “코딩은 전부 직접 작성하는 것이 아니라, 검증된 모듈을 가져와 조합하는 것”이라는 관점으로 백엔드 개발 접근법을 설명한다.^27
- Node.js 런타임을 설치하면 브라우저 없이도 로컬/서버에서 자바스크립트를 실행할 수 있고, 이를 기반으로 백엔드 서버를 만들 수 있다.^46
- npm 모듈 생태계(패키지 수/활용성)가 크기 때문에 필요한 기능을 빠르게 조립할 수 있으며, 설치/삭제/전역설치(-g) 같은 관리 개념이 중요하다.^41
- Express로 서버를 띄우고
GET, 라우팅,req/res,params/query를 이용해 API(JSON 응답) 를 구성한 뒤, CORS까지 해결해 프론트엔드에서 호출 가능하게 만든다.[^121]
3. 하나씩 살펴보기^1
3.1 오늘 목차와 “왜 Node.js인가” (브라우저 JS vs 백엔드 JS)^1
강의는 “오늘 배울 목차”를 먼저 언급한 뒤, 다양한 백엔드 프레임워크 중 Node.js를 선택해 학습하겠다고 밝힌다.^1 이어서 Node.js가 무엇인지 설명하기 위해, 기존에 파이썬 실습에서 했던 방식(컴퓨터에 파이썬 설치 → 코드 작성 → 실행)과 자바스크립트 학습 방식의 차이를 비교한다.^5
- 파이썬은 내 컴퓨터에 설치하고 로컬에서 실행했다.^5
- 반면 지금까지의 자바스크립트는 “설치 과정이 없었던 이유”가 있는데, 자바스크립트는 브라우저에서 실행되기 때문이라고 설명한다.^7
- 브라우저에는 자바스크립트를 해석/실행하는 인터프리터(엔진)가 있어서, 내 컴퓨터 OS에 “자바스크립트를 따로 설치”하지 않아도 브라우저가 실행을 담당해 왔다.^8
여기서 목표는 “내 컴퓨터 혹은 서버에서 돌아가는 백엔드”이므로, 브라우저 없이도 자바스크립트를 실행할 환경이 필요해진다.^9 그 역할을 하는 것이 Node.js이며, Node.js를 설치하면 브라우저가 없어도 설치된 컴퓨터에서 자바스크립트를 실행할 수 있다고 정리한다.^10
Node.js의 “수요/점유율/생태계”를 근거로 든다^11
화자는 Node.js가 “얼마나 좋은가”를 간단히 소개하며, 채용/시장 수요와 생태계를 근거로 든다.^11
- indeed.com 등의 잡 트렌드 자료를 언급하며 Node.js 관련 직무 그래프가 가파르게 증가하는 모습을 보여주고, “배워두면 써먹을 때가 많다”는 결론으로 이어간다.^12
- 전 세계적으로 Node.js를 사용하는 곳이 많다고 언급한다.^13
- “모듈 카운트” 개념을 소개하면서, Node.js는 npm을 통해 쓸 수 있는 모듈이 다른 언어 대비 “압도적으로 많다”고 말한다.^17
특히 “처음부터 모든 코드를 짜지 않는다”는 개발 관점을 비유로 풀어낸다.^15
- 모듈은 “미리 짜여진 코드” 또는 기능 단위이며, 쇼핑몰에서 재료를 담듯이 필요한 것을 가져다 쓰는 것이라고 설명한다.^15
- Node.js는 재료(모듈) 종류가 많아 “부대찌개를 쉽게 맛있게 끓일 수 있다”는 비유로, 풍부한 생태계가 생산성을 높인다고 표현한다.^17
또한 Stack Overflow 2022 조사에서 웹 프레임워크 사용 비율 1위가 Node.js라는 점을 언급하며, 오늘은 점유율 1위 기술을 배우겠다고 말한다.^18
그리고 “기술은 많이 사용하는 것을 배우는 게 유리”하며, 실무/취업/코드 재사용(인터넷/타인이 만든 코드 활용) 관점에서도 널리 쓰이는 기술을 선택하는 것이 합리적이라고 덧붙인다.^19
[!IMPORTANT] “직접 다 짜는 코딩” 오해 교정^26 화자는 “코드를 다 짜야 한다”는 오해가 있지만 그렇지 않으며, 필요한 도구/기능은 패키지 매니저로 찾아 설치해 쓰는 것이 일반적이라고 강조한다.^26
3.2 Node.js 설치(LTS)와 첫 실행: node index.js^20
화자는 Node.js 설치를 진행한다.^20 설치 링크를 제공할 것이며, 다운로드 시 LTS(Long Term Support) 로 “안정적 버전”을 설치하길 권장한다.^21 윈도우에서는 MSI 설치 파일을 받아 Next를 눌러 설치를 진행하면 된다고 안내한다.^22
설치 과정 중 “Python과 Visual Studio Build Tools”가 특정 모듈에서 필요할 수 있다는 체크 옵션이 있으며, 체크해도 나쁠 것은 없지만 오늘 실습에 꼭 필요하진 않을 것이라고 설명한다.^23 맥북도 설치 가능하며 진행이 비슷할 것이라고 언급한다.^24
작업 폴더/파일 준비와 한글 경로 주의^25
Visual Studio Code에서 폴더를 열고 실습을 진행한다.^25 여기서 실무 팁으로, 한글 폴더 경로에서 작업하면 한글 때문에 오류가 나는 경우가 있어 작업 폴더는 영어 이름을 추천한다고 말한다.^26 이후 index.js 파일을 새로 만든다.^27
Hello World 실행^28
브라우저 콘솔에서 실행하던 자바스크립트와 달리, 이제는 Node.js 설치로 로컬에서 실행할 수 있으므로 console.log('hello world')를 작성한다.^28
터미널을 열고(폴더 위치가 week4 같은 현재 프로젝트 폴더인지 확인) node index.js로 실행한다.^30 파이썬에서 python 파일.py로 실행하는 것과 같은 방식이라고 연결해 설명한다.^31 실행 결과 터미널에 hello world가 출력되며 Node 설치가 정상임을 확인한다.^32
에러가 나면: 에러 메시지 그대로 구글링^33
화자는 개발 중 에러는 흔하며, 에러 메시지를 구글에 붙여 넣으면 “90% 이상 답이 나온다”고 조언한다.^33
다만 검색 시 개인 파일명/특정 경로 등 공통적이지 않은 요소는 제거하고 핵심 에러 메시지로 검색하라고 안내한다.^34 예시로 권한 문제/cmd로 해결하는 글이 나오는 상황을 보여준다.^35
3.3 npm 소개: “필요한 기능은 설치해서 쓴다”^36
다음 주제로 npm을 다룬다.^36 npm 사이트를 보여주며 “Build amazing things”라는 문구와 함께, npm은 Node Package Manager의 약자라고 설명한다.^37
여기서 다시 한 번 “모든 코드를 직접 짜는 것은 말도 안 된다”는 개발 방식의 전제를 강조한다.^38 npm은 필요한 도구를 검색해 다운받아 쓰는 곳이며, 오늘은 웹 프레임워크인 express 모듈을 사용할 것이라고 예고한다.^39
npm에는 모듈이 매우 많고(화자가 언급한 시점 기준 40만 이상), 웬만한 기능은 직접 개발하지 않고 모듈을 설치해 쓰면 된다고 말한다.^40 심지어 “짝수/홀수 판별” 같은 사소한 기능까지도 모듈로 올라와 있을 정도로 다양하다는 유머성 사례를 든다.^41
npm 설치는 setup.exe가 아니라 npm install^42
윈도우 프로그램이 setup.exe로 설치되듯, Node 생태계에서는 터미널에서 npm install 모듈명을 입력하면 자동으로 다운로드/설치된다고 비교한다.^42
즉, 설치 경험을 GUI 대신 커맨드로 하는 것뿐이며, 역할은 “시스템/프로젝트에 기능을 설치”하는 동일한 개념이라고 정리한다.^43
3.4 figlet 모듈 실습: npm init → 설치 → require로 사용^44
화자는 가벼운 실습용 모듈로 FIGLET을 선택한다.^44 FIGLET은 텍스트를 ASCII art 형태로 출력해주는 모듈이며, 댓글/커뮤니티에서 텍스트로 그림처럼 표현하는 예시를 들어 설명한다.^45
모듈마다 사용법은 “공식 문서 따라가기”^46
모듈 사용법은 각각 다르고 npm 페이지(공식 문서)에 사용법이 적혀 있으니 그대로 따라가겠다고 한다.^46
npm init으로 프로젝트 메타데이터/의존성 관리 시작^47
설치 전에 npm init을 권한다.^47 의미는 “npm을 이용해 패키지를 다운받기 위한 프로젝트 초기화”이며, initialize의 약자라고 풀어준다.^48
패키지 이름/버전/설명 등 질문이 나오면 “쭉 엔터”로 넘어가도 된다고 안내한다.^49 실행 후 package.json이 생성된다.^50
package.json의 역할은:
- 이 프로젝트 이름/버전/설명/메인 파일 등 정보를 담고^51
- npm으로 설치한 모듈(의존성)이 기록되어 관리가 쉬워진다는 것이라고 설명한다.^52
package.json없이도 설치는 가능하지만 관리를 깔끔하게 하려고 쓰는 것이라고 덧붙인다.^52
npm install figlet과 옵션 --save, -g 설명^53
FIGLET 설치 명령은 npm install figlet이며 npm i figlet처럼 줄여 쓸 수도 있다고 말한다.^53
추가로 옵션을 설명한다.^54
--save: 예전에는package.json에 기록하려면 필요했지만 요즘은 기본(default)으로 기록되므로 생략 가능하다고 설명한다.^55-g(global): 프로젝트 폴더에만 설치하는 것이 아니라 컴퓨터 전체에서 사용하도록 전역 설치하는 옵션이다.^56 다만 전역은 충돌 가능성이 있어 “웬만하면 프로젝트 단위 설치가 좋다”고 답한다.^58
실제 실습에서는 전역이 아닌 프로젝트 로컬 설치로 진행한다.^57 설치가 끝나면 “added 1 package” 메시지가 나오고, package-lock.json과 node_modules 폴더가 생성된다.^59
package.json vs package-lock.json vs node_modules^60
화자는 세 구성요소를 비교해 설명한다.
package.json:dependencies에figlet과 버전 범위 같은 “대략적 명시”가 들어간다.^60package-lock.json: 설치된 버전/출처 등 “정확하고 구체적인 정보”가 기록된다.^61node_modules: 실제로 설치된 모듈 소스코드가 들어가는 폴더이며, 내부에 복잡한 JS 파일들이 있지만 우리는 직접 작성하지 않고 가져다 쓰는 것이라고 강조한다.^62
require('figlet')로 모듈 로드하고 실행^63
사용 예제는 공식 문서의 “simple usage”를 그대로 복사해 index.js에 넣는다.^63
코드에서 require는 “요구하다/가져오다”라는 의미로, figlet 모듈을 불러와 변수에 담아 사용할 수 있게 하는 과정이라고 풀이한다.^64
실행(node index.js)하면 hello world가 ASCII art로 출력된다.^65 텍스트를 “조코딩”으로 바꾸면 출력도 바뀌는 것을 보여준다.^66 이를 통해 “상상하는 거의 모든 기능이 모듈로 존재”하며, 문서대로 설치/사용하면 된다고 정리한다.^67
3.5 모듈 삭제: npm uninstall figlet과 “모듈 없으면 require 실패”^68
Express로 넘어가기 전에, 설치한 모듈을 지우는 방법도 보여준다.^68
npm uninstall figlet을 실행하면 node_modules에서 사라지고 package.json의 의존성에서도 제거된다.^69
그리고 index.js에 require('figlet')가 남아 있는 상태에서 실행하면 module not found 오류가 난다.^70 이는 모듈을 요구(require)했는데 설치되어 있지 않기 때문이라고 설명한다.^71 즉 “안 쓰는 모듈은 지우되, 코드도 함께 정리해야 한다”는 점을 실습으로 확인한다.^71
3.6 Express 설치와 Hello World 서버 띄우기^72
이제 본격적으로 Express를 소개한다.^72 Express는 Node.js로 “웹 프레임워크(백엔드 서버)를 만들도록 돕는 모듈”이라고 정의한다.^73
프론트엔드에서 클릭 등 이벤트가 발생하면 백엔드로 요청이 가고, 백엔드가 처리(계산, DB 조회 등) 후 응답을 돌려주는 구조를 다시 상기시키며, 그 역할을 담당하는 것이 웹 프레임워크라고 설명한다.^74
Express 설치는 npm에서 검색 후 npm install express를 실행한다.^75 설치가 끝나면 package.json에 express가 추가되어 설치 확인이 가능하다.^76
Express 예제 코드 실행과 localhost:3000^77
Express도 예제 코드가 있고 이를 붙여 넣어 실행해본다.^77
node index.js로 실행하면 터미널이 “가만히 있는 상태”가 되는데, 이는 서버가 실행되어 요청을 대기하고 있기 때문이라고 설명한다.^78
브라우저에서 localhost:3000으로 들어가면 “Hello World”가 뜬다.^79
서버를 끄려면 Ctrl + C를 사용하며, 서버를 끄고 나면 같은 주소로 접속해도 연결이 안 된다는 것을 보여준다.^80 이를 통해 “서버 프로세스가 떠 있을 때만 포트를 listen하며 응답한다”는 감각을 주려고 한다.^81
3.7 Express 핵심 코드 해부: listen, 포트, localhost, app.get, 라우팅, 콜백, req/res^82
화자는 Express 공식 홈페이지 예제와 거의 동일한 코드 기준으로 각 요소 의미를 하나씩 해설한다.^82
3.7.1 app.listen(port, callback)과 포트(Port) 개념^83
app.listen의 인자는 포트 번호이며, “그 포트로 들어오는 요청을 듣고(listen) 대기한다”는 의미라고 한다.^83
포트는 “입구” 비유로 설명한다.^84
또한 “기본 규격처럼 정해진 포트”가 있다고 말하며, 예시로:
- HTTP는 80번 포트^88
- HTTPS는 443번 포트^89
를 언급한다. 사용자는 보통
naver.com처럼 포트를 입력하지 않지만 내부적으로는 80 또는 443으로 접속하고 있다는 점을 설명한다.^90
또한 한 서버에서 포트마다 다른 프로그램을 실행할 수도 있어, 3000에는 Node 서버를 띄우고 다른 포트에는 다른 서비스를 띄울 수 있다고 한다.^92
listen의 두 번째 인자 콜백에서 console.log(...)는 “기능적으로 필수는 아니고, 실행 메시지를 찍기 위한 용도”라서 생략해도 된다고 덧붙인다.^93
3.7.2 localhost 의미^94
localhost:3000에서 localhost는 “내 컴퓨터(로컬 머신)의 IP”를 가리키는 별칭이며, 로컬 접속 시 IP를 직접 쓰지 않고 localhost로 사용한다고 설명한다.^94
3.7.3 app.get(method, path, callback)에서 HTTP method(GET/POST)^95
app.get(...)은 HTTP method 중 GET 요청을 처리하겠다는 뜻이다.^96
HTTP method는 요청 목적/종류를 나타내는 수단이며, 대표적으로 GET과 POST가 있다고 설명한다.^97
- GET: 주소창으로 데이터를 넘기는 방식으로 이해하면 편하다.^98
- POST: 주소창이 아니라 요청 “바디(body)”에 정보를 담아 보내는 방식으로 이해하면 된다.^98
(다른 method도 있지만, 이 둘만 이해하면 확장하기 쉽다고 말한다.)^99
따라서 app.get은 “GET 방식으로 들어온 요청은 여기로 와라”라고 매핑하는 것이다.^100
3.7.4 라우팅(Routing): /, /about, /board처럼 경로에 따라 동작 분기^101
라우팅은 같은 서버/포트 내에서도 “경로(path)”에 따라 다른 페이지/기능을 제공하는 구조다.^101
유튜브 예시로 youtube.com/feed/explore, 채널별로 달라지는 URL처럼, 경로가 바뀌면 화면/처리가 달라진다고 설명한다.^102
3.7.5 콜백 함수(Callback)와 setTimeout 예시^104
app.get('/path', (req, res) => {...})의 세 번째 인자는 콜백 함수이며, “앞선 작업이 끝난 다음 실행될 함수”로 설명한다.^104
콜백을 더 깊게 다루면 비동기 개념까지 필요해 복잡해지므로, 여기서는 “함수 안에 함수를 넣어 나중에 실행 순서를 조정한다” 정도로 이해하라고 안내한다.^105
이를 설명하기 위해 setTimeout(callback, ms) 예시를 든다.^106
- 첫 번째 인자: 실행할 함수(콜백)^107
- 두 번째 인자: 밀리초(ms) 시간^107
setTimeout(() => console.log('1초 지난'), 1000)을 실행하면 1초 후 출력되고, 5000으로 바꾸면 5초 후 출력된다고 시연한다.^108
즉 “5초 기다린 다음 콜백 실행”처럼 실행 순서를 지정하는 용도임을 강조한다.^109
3.7.6 req와 res: 요청/응답 객체^110
서버는 요청을 받아 응답하는 구조이며, Express에서는 req(request), res(response)로 이를 다룬다고 설명한다.^110
req: 요청 정보가 담김^111res: 응답에 대한 제어(무엇을 보낼지)가 담김^111res.send('hello world')는 “응답에 hello world 문자열을 담아 보내겠다”는 뜻이라고 풀어준다.^112
3.7.7 전체 동작 흐름을 한 번에 연결^113
화자는 왜 localhost:3000에서 Hello World가 떴는지 흐름을 조합해 설명한다.^113
- 서버가
listen(3000)으로 3000번 포트를 계속 듣고 있다.^114 - 사용자가 브라우저 주소창으로 접속하면 이는 GET 요청이다.^115
- 경로가
/(root)이므로app.get('/', ...)핸들러가 매칭된다.^116 - 콜백이 실행되며
res.send('Hello World')로 응답을 반환한다.^117 - 브라우저는 그 응답을 화면에 표시한다.^117
화자는 “서버는 눈에 안 보이는 부분이라 생소하지만, 이 그림(요청↔응답)만 기억하면 끝”이라고 말한다.^118 또한 listen은 “서버가 켜져 있다”는 의미로 계속 유지되는 상태이고, get은 “경로에 따라 처리”를 분기하는 역할이라고 정리한다.^120
3.8 라우팅 확장 실습: /dog, /cat 만들기 + 텍스트/HTML 응답[^121]
간단한 API 예제로 /dog와 /cat 라우팅을 추가한다.[^121] 목표는 다음과 같다.
/dog로 들어가면 JSON{ sound: "dog" }형태(최종 목표)로 응답[^122]/cat로 들어가면{ sound: "야옹" }같은 응답[^123]
먼저 root(/) 외에 핸들러를 복사해 app.get을 여러 개 만들고, 라우팅을 각각 /dog, /cat으로 분리한다.[^124]
그리고 우선 JSON이 아닌 텍스트로:
/dog→ “강아지”/cat→ “고양이” 를res.send()로 응답하도록 만든다.[^125]
서버를 실행(node index.js)하고:
localhost:3000/는 Hello World[^126]localhost:3000/dog는 강아지[^127]localhost:3000/cat는 고양이[^128] 로 잘 분기되는 것을 확인한다.
res.send()는 문자열로 HTML도 보낼 수 있다[^129]
“GET으로 HTML 파일을 보낼 수 있냐”는 질문에 가능하다고 답하면서, 문자열로 <h1>강아지</h1>를 보내면 브라우저가 HTML로 렌더링해 굵은 큰 글씨로 보이는 것을 시연한다.[^129]
또한 <a href="..."> 링크를 문자열로 보내면 클릭 가능한 링크가 되고, 링크를 누르면 조코딩 유튜브로 이동하는 것까지 보여준다.[^130]
결론적으로 send를 통해 “뭐든지 다 보낼 수 있다”고 정리한다.[^131]
axios vs express 역할 질문에 답변[^132]
“axios로 통신하는 것과 무슨 차이인가” 질문에 대해, express는 요청을 받아 응답을 돌려주는 서버 측 역할, axios는 요청을 보내는 클라이언트 측 라이브러리라고 구분한다.[^132]
“axios로 요청해서 express로 응답한다”는 댓글의 정리를 확인해주며, 브라우저 주소창으로 요청하는 행위가 axios와 같은 “요청자 역할”이라는 관점도 덧붙인다.[^133]
3.9 JSON 응답 만들기: res.send({sound: ...}) vs res.json(...)[^121]
이제 목표대로 JSON 데이터를 응답하는 방식으로 변경한다.[^121]
JSON은 JavaScript Object Notation이며, 결국 자바스크립트 오브젝트 형태(중괄호 {})라고 설명한다.[^121]
예: /dog 핸들러에서
res.send({ sound: "멍멍" })처럼 오브젝트를 보내면 브라우저/클라이언트는 JSON 형태로 받게 된다.[^121]
또한 더 명시적으로는 res.json(...)을 써도 되며, send로도 동일하게 동작하지만 JSON 응답임을 드러내고 싶을 때 json을 사용할 수 있다고 말한다.[^121]
결과적으로 /dog는 sound: 멍멍, /cat은 sound: 야옹 같은 API 형태로 동작함을 확인한다.[^121]
화자는 이 형태를 “API 문서” 관점으로도 설명한다: “GET 방식으로 특정 URL 요청을 보내면 response로 어떤 JSON이 날아온다”가 API 문서의 기본 구조이며, 지금 그 문서대로 구현한 것이라고 말한다.[^121]
URL에 한글 라우팅이 깨지는 문제(인코딩)[^121]
라우팅에 한글을 직접 넣으면 에러가 나며, URL은 한글이 들어가면 안 되고 인코딩이 필요하다고 언급한다.[^121]
인터넷에서 한글이 %.. 같은 이상한 문자열로 보이는 것을 본 적이 있을 텐데, 그것이 한글을 URL 인코딩한 형태라고 설명한다.[^121] 따라서 한글 경로를 쓰려면 인코딩 변환 사이트 등을 통해 변환한 값을 사용해야 한다고 안내한다.[^121]
3.10 “변수로 라우팅 받기”: params와 query 두 가지 방식[^121]
화자는 “변수로 줄 수 없냐”는 질문을 받아, Express에서 GET 요청으로 값을 받는 대표 방법 두 가지를 소개한다.[^121]
- params(parameter): 경로(path) 일부를 변수로 받는 방식[^121]
- query:
?key=value&...형태로 받는 방식[^121]
3.10.1 params: /user/:id에서 req.params로 받기[^121]
실생활 예시로 유튜브 채널 URL을 든다.[^121]
.../user/침착맨채널ID, .../user/우아쿠시처럼 앞부분은 같고 뒤의 ID만 다른데, 모든 유튜버에 대해 라우팅을 일일이 만들면 말이 안 되므로 “변수로 받는 방식”이 필요하다는 논리다.[^121]
Express에서 params는 콜론(:)을 사용한다:
- 라우트:
/user/:id(여기서id는 변수명,name등으로 자유롭게 지정 가능)[^121] - 요청 예:
/user/jocoding처럼 실제 값이 들어온다.[^121]
서버에서 확인:
req.params를q변수에 담아console.log(q)로 찍으면{ id: '조코딩' }처럼 들어오는 것을 확인한다.[^121]q.id로 특정 값만 뽑아 사용할 수 있다.[^121]
그리고 응답으로 res.send("user id : " + q.id)처럼 보내면, 주소창에 넣었던 값이 화면에 출력되는 것을 시연한다.[^121]
3.10.2 query: ?q=조코딩&name=조&age=20에서 req.query로 받기[^121]
query는 구글 검색 URL 예시로 설명한다.[^121]
검색하면 URL 뒤에 ?q=... 같은 형태가 붙는데, 이는 key-value 구조로 값이 전달되는 방식이라는 것이다.[^121]
Express에서:
req.query를q로 받아console.log(q)하면{ q: '조코딩', name: '조', age: '20' }처럼 들어온다.[^121]q.q,q.name,q.age로 각각 접근할 수 있다.[^121]- 이를 응답에 넣어 화면에 표시할 수도 있다.[^121]
정리하면:
- params:
/sound/:name처럼 경로 변수[^121] - query:
/sound?name=dog처럼 물음표 뒤 key-value[^121] 두 방식으로 GET 요청에서 값을 받을 수 있다고 마무리한다.[^121]
3.11 POST 방식은 body로 받는다(예고 수준)[^121]
POST는 주소창이 아니라 body에 값이 담기며, axios/fetch 등으로 POST 요청을 보낼 때 body에 JSON이 실린다고 설명한다.[^121]
params는 POST에서도 동일하게 쓸 수 있고, body는 req.body를 찍어 보면 같은 방식으로 다룰 수 있다고 말하지만, 여기서는 자세한 시연은 뒤에서 하겠다며 넘어간다.[^121]
또한 “유튜브 서버 역할”을 다시 연결한다: id(파라미터) 값이 서버로 전달되고, 서버는 그 값에 맞는 채널 페이지/데이터를 응답하는 구조라는 것이다.[^121]
3.12 동물소리 API 서버 완성: /sound/:name + 조건 분기(if/else)[^121]
이제 앞선 /dog, /cat처럼 라우팅을 일일이 만드는 대신, 요구사항을 바꿔 동물 이름(name)을 변수로 받아 하나의 라우트로 처리하는 API를 만든다.[^121]
목표:
GET /sound/:name에서name이dog면{sound: '멍멍'}cat이면{sound: '야옹'}pig이면{sound: '꿀꿀'}- 그 외면
{sound: '알 수 없음'}[^121]
params 값을 받는 코드 구성(구조분해 할당 포함)[^121]
name은 parameter로 받으므로 req.params에서 꺼낸다.[^121]
화자는 두 방식 중 더 간편한 방식(많이 쓰는 스킬)로 구조분해 할당을 소개한다:
const { name } = req.params;형태로 쓰면
req.params가{ name: 'dog' }같은 오브젝트이므로, 그 안의name값이 바로 변수name에 담긴다고 설명한다.[^121]- 이를
console.log(name)으로 찍어/sound/dog요청 시dog가 출력되는 것을 보여준다.[^121]
if/else if/else로 응답 분기[^121]
name 값에 따라 응답을 달리하려고 자바스크립트 조건문을 사용한다.[^121]
if (name === 'dog') res.json({ sound: '멍멍' })else if (name === 'cat') res.json({ sound: '야옹' })else if (name === 'pig') res.json({ sound: '꿀꿀' })else res.json({ sound: '알 수 없음' })[^121]
서버 재시작 후:
/sound/cat→ 야옹/sound/dog→ 멍멍/sound/pig→ 꿀꿀/sound/jocoding→ 알 수 없음
이 정상 동작을 확인한다.[^121]
화자는 여기까지 이해하면 백엔드의 핵심(“요청에서 변수 받기 → 서버에서 처리 → JSON으로 응답”)을 이해한 것이라고 강조한다.[^121] 그리고 “동물 소리 API 서버를 완성했다”고 선언하며, 요청에 따라 다른 JSON을 돌려주는 API 서버를 만든 상태라고 정리한다.[^121]
3.13 CORS 이슈: 왜 생기고, cors 모듈로 어떻게 푸는가[^121]
API 서버를 만들고 나면 프론트엔드에서 호출할 때 CORS 문제가 자주 발생한다고 말한다.[^121]
CORS는 보안상 “이상한 출처에서 요청이 오는 것”을 막기 위해 브라우저가 기본적으로 차단하는 정책이며, CORS 설정이 없으면 HTML 파일에서 보낸 요청이 차단될 수 있다는 것이다.[^121] 그래서 “다른 곳(다른 서버/HTML)에서 요청해도 응답이 잘 들어오도록” 설정을 해줘야 한다고 설명한다.[^121]
3.13.1 cors 모듈 설치와 의존성 기록 확인[^121]
해결은 모듈 설치라고 안내한다.[^121]
- npm에서
cors(Node middleware)를 찾아 설치한다.[^121] - 설치 후
package.jsondependencies에cors가 추가되고,package-lock.json에도 기록이 추가되는 것을 보여준다.[^121] 이를 통해 “어떤 모듈을 설치했고 무엇을 쓰는지”를 두 파일로 확인할 수 있다고 다시 강조한다.[^121]
3.13.2 코드 적용: app.use(cors())[^121]
사용법은 간단히:
const cors = require('cors');app.use(cors());를 추가하면 기본적으로 모든 요청을 허용한다고 설명한다.[^121]
또한 조건을 넣어 “어디는 허용/어디는 거절” 정책도 가능하지만, 비워두면 전체 허용이라고 말한다.[^121]
이 설정은 “브라우저에서 다른 출처로부터 오는 요청 차단을 풀어주는 서버 측 설정”이라서, 서버 자체를 브라우저로 들어가 테스트할 때는 눈에 띄는 변화가 없을 수 있다고 덧붙인다.[^121]
3.14 프론트엔드 HTML에서 fetch로 API 호출 연결(입력→요청→응답 표시)[^121]
CORS 해결이 왜 필요한지 보여주기 위해, 프로젝트에 index.html을 만들고 프론트엔드에서 직접 API를 호출한다.[^121]
3.14.1 HTML 구성: input + 버튼 + onclick[^121]
빠르게 HTML을 만들며, 버튼을 만들고 클릭 시 getSound() 함수를 호출하도록 onclick을 단다.[^121]
getSound()는 fetch로 API를 호출하는데, fetch 문법은 외우지 말고 “무조건 복사해서 써야 한다”, 외우는 것은 시간 낭비라고 강하게 조언한다.[^121]
3.14.2 템플릿 리터럴(백틱)로 URL에 변수 삽입[^121]
fetch URL에 사용자가 입력한 name을 넣기 위해 문자열을 단순 따옴표로 쓰면 변수를 끼워 넣기 어렵고, 키보드 1 왼쪽의 **백틱()** 을 사용한 템플릿 리터럴로 ${변수}를 삽입할 수 있다고 설명한다.[^121] 즉 input의 value를 읽어 name변수에 넣고,fetch(`http://localhost:3000/sound/${name}`)`처럼 구성한다.[^121]
3.14.3 응답 처리: JSON 받고 화면에 표시[^121]
fetch로 응답을 받은 뒤 콘솔에 찍어 확인하고, 추가로 특정 DOM에 결과를 넣어 화면에 표시하도록 만든다.[^121]
처음에는 object가 들어오는 것을 확인한 뒤, 실제로는 {sound: '멍멍'} 같은 구조이므로 화면에는 data.sound를 넣어야 한다고 수정한다.[^121]
그 결과:
- dog → 멍멍
- pig → 꿀꿀
- cat → 야옹
- 기타 → 알 수 없음
이 화면에서 바뀌는 것을 확인한다.[^121]
3.14.4 CORS 오류 재현과 해결 확인[^121]
CORS 설정을 제거하면 fetch 요청이 “CORS policy 위반”으로 막히는 오류가 콘솔에 나타난다고 보여준다.[^121]
에러 메시지의 핵심은 “요청 대상은 localhost 서버인데, 요청을 보낸 쪽은 다른 파일/출처에서 왔다”는 점이라고 설명한다.[^121]
다시 app.use(cors())를 적용하고 강력 새로고침(캐시 비우기) 후 요청하면 정상적으로 응답이 들어오는 것을 확인한다.[^121]
3.15 포트 충돌과 포트 변경(3000 → 8080 등)[^121]
따라 하다가 “포트 충돌로 안 된다”는 질문에, 3000은 임의로 정한 값이라 다른 포트로 바꾸면 된다고 답한다.[^121]
예시로 8080, 1234 등 아무 번호를 써도 되고, listen 포트를 바꾸면 접속 URL도 localhost:8080처럼 바뀐다고 안내한다.[^121] 실제로 8080으로 변경 후 localhost:8080에서 Hello World가 뜨는 것을 확인한다.[^121]
3.16 마무리 확장 아이디어: 다른 API 결합, 응답에 이미지 URL 추가[^121]
마지막으로 화자는 API는 “정말 만들기 나름”이라며 확장 아이디어를 제시한다.[^121]
예를 들어 숙제 사례로 “고양이 사진 API”를 결합해, cat 버튼을 누르면 고양이 사진이 랜덤으로 바뀌어 나오는 데모를 소개한다.[^121]
이를 자신의 동물소리 API에 결합하려면, 응답 JSON에 sound뿐 아니라 image 같은 두 번째 키로 이미지 URL을 포함시킬 수 있다고 말한다.[^121]
프론트엔드는 그 URL을 받아 화면에 이미지를 표시할 수도 있으며, 원하는 기능을 추가해 자신만의 백엔드 API를 만들 수 있다고 격려하며 마무리한다.[^121]
4. 핵심 통찰^1
- Node.js의 본질은 “브라우저 밖에서 자바스크립트를 실행”하게 해주는 런타임이며, 백엔드/서버 실행을 가능케 한다.^9
- npm 생태계를 활용하면 기능을 직접 구현하기보다 모듈을 설치해 조합하는 방식으로 개발 속도를 크게 높일 수 있다.^38
npm init으로 프로젝트 단위 관리 기반을 만들고package.json/package-lock.json으로 설치 이력을 남기는 습관이 중요하다.^51
- Express 서버의 핵심 모델은 “listen으로 대기 → method/path 라우팅 → 콜백 실행 → res로 응답”이다.^117
- 라우팅을 하드코딩(
/dog,/cat)하는 것에서 벗어나 params(/sound/:name)를 사용하면, 하나의 라우트로 무한한 경우의 수를 처리할 수 있다.[^121] - 프론트엔드에서 API 호출까지 연결하려면 CORS를 반드시 이해해야 하며, 서버에서 cors 미들웨어로 정책을 설정하는 것이 실무적으로 자주 쓰인다.[^141]
- 개발 중 오류는 흔하며, 에러 메시지 핵심만 추려 그대로 검색하는 습관이 문제 해결의 기본기다.^33
실행 관점 시사점(콘텐츠가 제시한 흐름을 그대로 체크리스트화):
node -v로 설치 확인 후node index.js로 실행 루틴 익히기.^31npm init→npm i express cors→app.use(cors())→app.get('/sound/:name', ...)→res.json(...)순으로 최소 API 서버 골격 만들기.[^121]- 라우팅 테스트는 브라우저 주소창(GET)으로 먼저 하고, 그 다음
fetch로 프론트 연동 및 CORS 점검하기.[^121] - 포트 충돌 시 포트 번호 변경으로 회피 가능하다는 점 기억하기.[^121]
5. 헷갈리는 용어 정리^1
Node.js: 브라우저 없이도 컴퓨터/서버에서 자바스크립트를 실행하게 해주는 런타임(환경).^10
npm: Node Package Manager. 필요한 모듈을 검색/설치/삭제하는 패키지 관리 도구.^37
모듈(패키지): 미리 만들어진 기능 단위 코드. 필요한 기능을 직접 구현하지 않고 가져다 쓸 수 있게 해준다.^15
package.json: 프로젝트 메타데이터와 의존성(dependencies)을 “대략적으로” 기록/관리하는 파일.^51
package-lock.json: 설치된 패키지의 정확한 버전/출처 등 “구체적인” 설치 상태를 고정/기록하는 파일.^61
node_modules: 설치된 모듈 실제 코드가 저장되는 폴더.^62
Express: Node.js에서 웹 서버/라우팅/미들웨어 등을 쉽게 만들게 해주는 웹 프레임워크(모듈).^73
포트(Port): 서버/프로그램으로 들어오는 “입구 번호”. 같은 IP라도 포트로 서비스가 구분된다.^85
HTTP method(GET/POST): 요청의 종류/목적을 나타내는 방식. GET은 주소창 기반, POST는 body 기반으로 설명.^98
라우팅(Routing): URL 경로(/, /dog, /sound/:name)에 따라 다른 처리/응답을 하도록 분기하는 것.^103
콜백 함수(Callback): 어떤 작업이 끝난 다음 실행할 함수를 인자로 넘기는 방식(예: setTimeout).^104
req/res: Express에서 요청(request)과 응답(response)을 다루는 객체 약칭.^110
params: URL 경로의 변수(예: /user/:id). req.params로 접근.[^121]
query: URL 물음표 뒤 key-value(예: ?q=...&age=20). req.query로 접근.[^121]
CORS: 다른 출처에서 오는 브라우저 요청이 보안 정책으로 차단되는 이슈. 서버에서 cors 설정으로 허용 가능.[^121]
참고(콘텐츠 정보)^1
- 제목: 한시간만에 Node.js 백엔드 기초 끝내기 (ft. API 구축)^1
- 채널: 조코딩 JoCoding^1
- 길이: 60분 36초^1
- 링크: https://www.youtube.com/watch?v=Tt_tKhhhJqY^1
[^121]: @[31:06] "간단한 이제 api를 만들어 보겠습니다" (이후 API/params/query/CORS/fetch/포트/확장까지 이어지는 전체 실습 구간의 시작점) [^122]: @[31:22] "json data... sound... dog" [^123]: @[31:32] "cat... sound... 야옹" [^124]: @[31:46] "복사해서 늘려... format document" [^125]: @[32:12] "dog routing... cat routing... 강아지/고양이" [^126]: @[32:50] "root... hello world" [^127]: @[32:59] "slash dog... 강아지" [^128]: @[33:17] "cat... 고양이" [^129]: @[33:42] "h1 태그... html 문법... 전달" [^130]: @[34:14] "a 태그 링크... 조코딩 유튜브" [^131]: @[34:27] "샌드를 통해서 뭐든지 다 보낼 수" [^132]: @[34:31] "엑시오스로 통신... 차이... 요청을 쏠 때" [^133]: @[35:09] "엑시오스로 요청해서 express로 응답" [^134]: @[50:21] "CORS라는 이슈... 문제가" [^141]: @[52:08] "require로 불러온 다음에 use CORS만 하면"