* 프로그래머스, 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 5기 강의 수강 내용을 정리하는 포스팅.
* 원활한 내용 이해를 위해 수업에서 제시된 자료 이외에, 개인적으로 조사한 자료 등을 덧붙이고 있음.
app.get('/user/:id', (req, res) => {
const userId = req.params.id;
res.send(`User ID is: ${userId}`);
});
위 코드 예시, /user 경로 뒤에 id값을 입력받는다고 할 때. 백엔드에서는 요청 데이터를 관리하는 req 인자 내부에 'param' 객체를 통해 URL 상의 쿼리 파라미터를 관리하고 있다. 클라이언트가 /user/123와 같은 요청을 보낼 때, 123이 id으로 매핑되는 것.
점 표기법을 활용하여 req 내부의 param 내부의 값을 가져와서 사용하면 된다.
app.get('/user/:userId/post/:postId', (req, res) => {
const { userId, postId } = req.params; // Extract multiple parameters
res.send(`User ID: ${userId}, Post ID: ${postId}`);
});
여러 개의 파라미터를 URL에서 가져올 수도 있다.
http://localhost:3000/user/123/post/456
라는 요청을 보낸다고 하면..
User ID: 123, Post ID: 456로 쿼리 파라미터가 매핑되어 온다.
http://localhost:3000/search?query=node&sort=desc&page=2
query의 값은 node으로 매핑
sort의 값은 desc으로 매핑
page의 값은 2으로 매핑
app.get('/search', (req, res) => {
const { query, sort, page } = req.query; // Extract query parameters
res.send(`Search Query: ${query}, Sort: ${sort}, Page: ${page}`);
});
req.params: URL 경로에 정의된 Route Parameter를 처리.
req.query: URL의 쿼리 파라미터를 처리.
쿼리 파라미터는 key값만 존재하더라도, 애초에 필수값이 아니기때문에 에러가 발생되거나 하지 않는다. undefined로만 처리되기 때문에 버그가 발생하거나 해도 알아차리기 어려울 수 있으니 주의해야 한다.
특히! 쿼리 파라미터는 URL에 노출되기 때문에 누구나 쉽게 살펴볼 수 있다! 비밀번호 등의 민감한 정보를 전달할 때는 반드시 POST 요청과 req.body를 사용하는 것이 기본 중의 기본.
실무에서는 POST 요청을 기본으로 깔고, HTTPS 사용 / 입력 데이터 검증 / 인증 및 권한 부여 / 데이터 암호화 / CSRF 방지 / CORS 설정 / 요청 제한 / 로그 및 모니터링 / API 키와 토큰 사용 / 보안 헤더 설정 / 배포 환경 보안 설정 / 정기점검 등의 방책들이 다중으로 설정된다.
const express = require('express');
const app = express();
const { callBackYoutuber } = require('./api-test-01');
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.use('/:channelName', callBackYoutuber);
app.listen(3000, () => {
console.log(`서버가 ${PORT} 포트에서 정상 동작 중입니다.`);
});
const youtuber1 = {
channelName: 'AwesomeChannel',
subscriberCount: 1500000,
videoCount: 120,
};
const youtuber2 = {
channelName: 'TechChannel',
subscriberCount: 500000,
videoCount: 80,
};
const youtuber3 = {
channelName: 'FoodChannel',
subscriberCount: 1200000,
videoCount: 220,
};
const callBackYoutuber = (req, res) => {
const channelName = req.params.channelName;
if (channelName === 'AwesomeChannel') {
res.json(youtuber1);
}
else if (channelName === 'TechChannel') {
res.json(youtuber2);
}
else if (channelName === 'FoodChannel') {
res.json(youtuber3);
}
else {
res.json('존재하지 않는 대상입니다.');
}
};
module.exports = { callBackYoutuber };
ES6에서 도입된 키-값(key-value) 쌍을 저장하는 자료형.
객체와 유사하지만 더 다양한 키를 사용할 수 있는 기능과 추가적인 메서드를 제공한다.
객체의 키는 문자열 또는 심볼만 가능하지만, Map의 키는 원시값(숫자, 문자열, 불리언)과 객체, 함수 등 모든 타입이 가능하다.
value는 일반 객체와 Map 모두 객체 타입 데이터를 담는게 가능하다.
const map = new Map();
set(key, value)
- 키와 값을 Map에 추가합니다.
get(key)
- 주어진 키에 해당하는 값을 반환합니다.
has(key)
- 주어진 키가 존재하면 true를 반환합니다.
delete(key)
- 주어진 키를 삭제합니다.
clear()
- 모든 키-값 쌍을 삭제합니다.
size
- Map에 저장된 키-값 쌍의 개수를 반환합니다.
const map = new Map();
// 값 추가
map.set('name', 'Alice');
map.set('age', 25);
// 값 읽기
console.log(map.get('name')); // Alice
console.log(map.get('age')); // 25
// 키 확인
console.log(map.has('name')); // true
console.log(map.has('gender')); // false
// 크기 확인
console.log(map.size); // 2
특징 | 객체(Object) | Map |
---|---|---|
키의 데이터 타입 | 문자열 또는 심볼만 가능 | 모든 데이터 타입 가능 (객체, 함수 등 포함) |
삽입 순서 | 보장되지 않음 | 삽입된 순서를 항상 보장 |
기본 프로토타입 키 | 존재 (toString , __proto__ 등 포함) | 없음 |
크기 확인 | Object.keys(obj).length 를 사용해야 함 | map.size 로 간단히 확인 가능 |
반복 가능 여부 | 직접 반복 구현 필요 (for...in 이나 Object.entries 사용) | 기본적으로 iterable (for...of 및 map.entries() 사용 가능) |
성능 | 대량의 데이터 추가/삭제 시 느림 | 대량의 데이터 추가/삭제 시 더 빠름 |
용도 | 단순 키-값 저장 시 사용 적합 | 다양한 키 타입 및 순서가 중요한 경우 적합 |
동일한 타입 또는 다양한 타입의 데이터를 순서대로 저장할 수 있는 선형 자료구조.
일반적으로 리스트는 배열(Array)과 연결 리스트(Linked List) 두 가지 형태로 나뉘어진다.
// 단순한 연결 리스트의 예
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
}
append(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
return;
}
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
}
const list = new LinkedList();
list.append('a');
list.append('b');
list.append('c');
console.log(list.head); // 출력: Node { data: 'a', next: Node {...} }
특징 | 배열(Array List) | 연결 리스트(Linked List) |
---|---|---|
메모리 할당 | 고정 크기 또는 연속된 메모리 공간 사용 | 동적으로 메모리 할당 |
접근 속도 | O(1), 인덱스를 통해 직접 접근 가능 | O(n), 순차적으로 접근해야 함 |
삽입/삭제 속도 | 느림(O(n)), 요소 이동 필요 | 빠름(O(1)), 포인터 변경 |
메모리 효율성 | 포인터가 없으므로 메모리 사용량 적음 | 포인터를 저장해야 하므로 메모리 사용량 많음 |
구현 복잡도 | 간단함 | 상대적으로 복잡함 |
순서 유지 | 삽입된 순서 유지 | 삽입된 순서 유지 |
적합한 경우 | 빠른 접근이 필요한 경우 | 삽입/삭제가 빈번한 경우 |