function solution(number, limit, power) {
let totalSum = 0;
for (let i = 1; i <= number; i++) {
let sum = 0;
for (let j = 1; j <= i; j++) {
if (i % j == 0) {
sum++;
}
if (sum > limit) {
sum = power;
break;
}
}
totalSum += sum;
}
return totalSum;
}
위처럼 코드를 구성해서 돌리니 시간초과가 났다..
수학공식이 필요한거 같아 구글을 뒤져보니 제곱근을 이용해 반복 수를 줄이는 방법을 찾았다.
function solution(number, limit, power) {
let totalSum = 0;
for (let i = 1; i <= number; i++)
{
let sum = 0;
for (let j = 1; j <= Math.sqrt(i); j++)
{
if (i % j == 0)
{
if (i / j == j)
{
sum += 1;
}
else
{
sum += 2;
}
}
if (sum > limit) {
sum = power;
break;
}
}
totalSum += sum;
}
return totalSum;
}
당연히 현재 미들웨어에서 응답을 보내는 경우, 즉 res.send() 나 res.json() 등의 메서드를 호출하는 경우 next()를 호출하면 안된다. 이렇게 하지 않으면 이미 요청이 종료된 상태에서 다른 미들웨어가 응답을 보내려고 해서 중복된 요청이 전달되는 문제가 발생한다.
라우터와 미들웨어 차이
라우터와 미들웨어는 서로 다른 방식처럼 보이지만 라우터는 미들웨어 기반으로 구현된 객체라서 미들웨어와 동일한 방식으로 작동된다.
라우터는 미들웨어 함수를 특정 경로에 바인딩하는 역할을 하고, 요청이 들어온 URL 경로에 따라 서로 다른 미들웨어를 실행시킬 수 있게 도와준다.
app.use(Middleware) : 모든 요청에서 미들웨어가 실행된다.
app.use('/api', Middleware) : /api로 시작하는 모든 요청에서 미들웨어를 실행한다.
app.post('/api', Middleware, (req,res)=>{}) : /api로 시작하는 POST 요청에서 미들웨어를 실행한다.
MongoDB에서 가지고 있는 각 데이터 하나하나를 문서 ( Document )라고 정의한다.
1개 이상의 Key-Value의 쌍으로 이루어져있다.
JSON 형식으로 구성되어있다.
mongoose의 컬렉션 ( Collection )
컬렉션 ( Collection )은 여러개의 문서 ( Document )를 보유할 수 있는 MongoDB의 구성요소다.
JSON 형식의 여러가지 문서 ( Document )를 보유할 수 있다.
컬렉션 ( Collection )은 고정된 구성요소가 존재하지 않고, 유연하게 구성할 수 있다.
관계형 데이터 베이스 ( RDB ) 의 Table과 동일한 역할을 한다.
mongoose의 스키마 ( Schema )
스키마 ( Schema )는 컬렉션 ( Collection )에 들어가는 문서 ( Document )가 어떤 종류의 값을 가질 것인지 정의하기 위해 사용한다.
스키마 ( Schema )는 데이터의 구조와 어떤 제약 사항을 가지는지 정의하기 위해 사용하며, 일반적으로 데이터를 모델링할 때 사용한다.
스키마 ( Schema )는 어떤 필드가 있어야 하는지, 필드는 어떤 데이터 타입을 가져야 하는지를 정의한다.
let UsersSchema = new mongoose.Schema({
name: String, // 문자열 타입
age: Number, // 숫자 타입
favorites: [String], // 문자열 배열 타입
createdAt: { type: Date, default: Date.now }, // 날짜 타입
someId: mongoose.Schema.Types.ObjectId // ObjectId 타입
});
위는 사용자 정보를 정의한 스키마 ( Schema )의 예시다
mongoose의 모델
모델 ( Model )은 데이터베이스에 데이터를 저장하고 읽어올 때 사용하는 데이터의 구조다
스키마를 바탕으로 만들어지고, JavaScript의 객체와 MongoDB 간의 상호작용을 하기 위해 사용한다.
Request의 세부 사항에는 URL, http method, 헤더( header ), 쿼리 파라미터 ( query parameter ), 바이 데이터 ( body data ) 등이 포함 된다.
Response
Response란 서버에서 클라이언트로 응답 메세지를 전송시켜주는 객체다.
Response의 세부 사항에는 상태 코드 ( status code ), 응답 데이터 ( response data ), 응답 헤더 ( response header ) 등이 포함된다.
서버 모듈
Node.js의 서버 모듈에는 대표적으로 http 모듈과 Express.js가 존재한다. ( http 모듈은 Node.js에서 기본 제공하는 http 서버 모듈이다 )
Express.js는 http 모듈을 확장해 제공한다.
Express.js는 기존 http 모듈의 메서드도 사용할 수 있지만, Express.js가 추가 제공하는 메서드나 속성들을 사용할 수 있다.
Express.js 통신 흐름
클라이언트는 특정 URL과 데이터를 담은 요청 ( Request )을 서버에 전송한다.
서버는 받은 데이터에 따라 필요한 비즈니스 로직을 수행한다.
서버는 처리된 결과를 클라이언트에게 응답 ( Response )으로 보내준다.
예제 )
app.js
// app.js
import express from 'express';
import goodsRouter from './routes/goods.js';
import newsRouter from './routes/news.js';
const app = express();
const PORT = 3000; // 서버를 열 때 사용할 포트 번호
app.get('/', (req, res) => {
res.send('Hello World!');
});
// 1. Express.js의 서버를 엽니다.
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
// localhost:3000/api -> goodsRouter
// localhost:3000/api -> newsRouter
// 2. 라우터를 등록 합니다.
// app.use 미들웨어를 사용해 /api로 접속하면 goodsRouter와 newsRouter를 연결(등록)한다
app.use('/api', [goodsRouter, newsRouter]);
1. 서버시작
app.listen을 통해 3000 포트로 웹 서버를 연다.
2. 라우터 등록
app.use 미들웨어를 사용해 /api 주소에 goodsRouter와 newRouter를 연결(등록)한다.
news.js
// routes/news.js
import express from 'express';
const router = express.Router();
// req : 클라이언트가 전달한 Path Params
// res : 서버가 클라에게 전달할 데이터 ( json 형태로 전달 )
/** 뉴스 목록 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news', (req, res) => {
// 4. 사용자의 요청에 맞는 데이터를 반환합니다.
return res // Express.js의 res 객체를 반환합니다.
.status(200) // API의 상태 코드를 200번으로 전달합니다.
.send('뉴스 목록 조회 API 입니다.'); // API의 결과값을 '뉴스 목록 조회 API 입니다.'로 전달합니다.
});
/** 뉴스 세부 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news/:newsId 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news/:newsId', (req, res) => {
// 클라이언트가 전달한 Path Params 데이터를 받아옵니다.
const params = req.params;
// Path Params 데이터 중 newsId를 추출합니다.
const newsId = params.newsId;
// 서버 콘솔에 클라이언트가 전달한 newsId를 출력합니다.
console.log('클라이언트로 부터 전달받은 뉴스 ID:', newsId);
// 4. 사용자의 요청에 맞는 데이터를 json 형태로 반환합니다.
return res.status(200).json({
data: '뉴스 세부 조회 API 입니다.',
});
});
// Express 라우터를 외부로 전달합니다.
export default router;
3. API 정의
등록된 각 라우터를 순서대로 검토하고, HTTP Method와 URL이 일치하는 함수를 실행한다.
-URL /api/news로 GET 요청이 들어오면 router.get('/new' ~ )을 실행한다.
-URL /api/news/:newsId로 GET 요청이 들어오면 router.get('/new/:newsId' ~)을 실행한다.
여기서 중요한 부분은 :newId에 해당하는 경로 변수다. 이는 req.params을 통해 들어온 변수를 읽어들일 수 있다.
위 코드에서는 req.params을 통해 들어온 변수를 params에 저장하고 params.newsId를 통해 해당 변수를 읽어오고 출력해주는 형태다