그냥 체력을 기르고 싶었습니다.

 

그래서 시작한 달리기..

 

1주차

  1. 1분 달리기 + 2분 걷기 * 4 + 1분 달리기
  2. 1분 달리기 + 2분 걷기 * 5 + 1분 달리기
  3. 1분 30초 달리기 + 2분 걷기 * 4 + 1분 30초 달리기

 


1주차 첫번째 달리기

 

내가 마지막으로 숨차게 움직여본게 언제였을까..? 라는 생각을 가지고 시작했습니다.

 

1주차의 첫 달리기는 페이스라는걸 모르고 막 달리다 마지막에 지쳐서 힘들게 겨우겨우 완주했습니다.

 

그리고 비가 와서 이틀 쉬었습니다...  (근육통도 좀 있었습니다...)

 

 

 

1주차 두번째 달리기

 

첫번째 달리기와 다르게.. 매우 할만했습니다...

 

아주 약간의 근육통이 있었습니다만.. 이건 제가 운동을 너무 안해서 그런거라 생각하고 진행했습니다.

 

페이스도 안정되었고, 케이던스라는 것에 대해 배웠습니다

 

달리는게 재밌다고 느껴집니다... (말도안댐..)

 

 

1주차 세번째 달리기

 

어.. 1분 30초 생각보다 힘들었습니다..

 

자신만만했는데.. 오우.. ㅋㅋㅋㅋㅋ

 

맞바람이 심해서인지.. 달리는 느낌이 나지않아, 저도 모르게 페이스가 올라갔고..

 

맞바람 때문에 약간 숨쉬는데 불편함도 있었습니다..

 

그런데 어찌저찌 완주는 했습니다.

 

그리고 이 글을 쓰는 지금 근육통은 없습니다

 

막 끝났을땐 다리가 약한 후들거리는 느낌이 약간 있었는데.. 

 

지금은 내일 또 뛸까 싶은 생각이 듭니다.

 

 


 

달리기 시작하려고 운동화를 사면서, 준비만 열심히 하고 결국엔 안 할까 봐 걱정했지만..

 

막상 시작하고 달리니까 잡생각도 사라지고 좋은 것 같습니다.

 

이제 1주차 이긴 하지만.. 달리는게 재밌다고 느끼고 있고 불면증도 사라졌습니다.

 

취준생 생활에 좋은 활력소가 될 것 같습니다.

생각보다 사용방법이 어렵다 느껴 간단하게 정리해보고자 합니다.

 

Multer는 파일 업로드를 처리하는 미들웨어 입니다.

특히 multipart/form-data를 처리하는데 사용하고, 파일을 디스크 또는 메모리에 저장할 수 있습니다.

 

기본개념

multer를 사용하면 클라이언트라 form-data로 업로드한 파일을 서버에서 처리하고 저장할 수 있습니다.

 

storage: 파일 저장 방식(디스크 저장 or 메모리 저장)

destination : 파일이 저장될 폴더 지정

filename : 저장될 파일명 지정 (이름 충돌 방지)

limits : 파일 크기 제한 설정 가능

fileFilter : 특정 파일만 허용 가능 ( ex : 이미지 파일만 허용)

 

const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, cb) {
      cb(null, "uploads/");
    },
    filename(req, file, cb) {
      const ext = path.extname(file.originalname); // 이미지.png => 이미지 (날짜).png    이름중복방지
      cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
		//기존 파일명 + 현재 시간(중복 방지) + 확장자 형태로 저장
    },
  }),
});

 

  1. 파일 저장위치 : uploads/ 폴더에 저장
  2. 파일 이름 처리 : 
    • path.extname(file.originalname)    -> 파일 확장자 추출
    • path.basename(file.originalname, ext)  -> 확장자를 제외한 파일 이름 추출
    • Data.now() 를 추가하여 파일 이름이 중복되지 않도록 합니다
      (여러 사람이 이용하다보면 파일 이름 중복의 가능성이 있습니다)
    • (ex : image.png  -> image62375637545.png) 의 형식으로 저장됩니다.

 


 

Multer의 활용

 

1. 파일 업로드 (single())

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="image" />
  <button type="submit">업로드</button>
</form>

 

app.post("/upload", upload.single("image"), (req, res) => {
  res.json({ file: req.file }); // 업로드된 파일 정보 응답
});

클라이언트가 image라는 이름으로 1개의 파일을 업로드하면 저장됨. (req.file 에 업로드된 파일 정보가 저장됩니다.)

* 여기서 "image"는 form애 있는 input의 name 을 의미합니다.

 

 

2. 다수의 파일 업로드( array() )

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="images" multiple />
  <button type="submit">업로드</button>
</form>

form은 위와 동일 input의 name이 image => images로 변경

app.post("/upload-multiple", upload.array("images", 5), (req, res) => {
  res.json({ files: req.files });
});

images 라는 필드 이름으로 최대 5개의 파일을 업로드 가능

 

 

3. 다수의 필드로 파일 업로드 ( fields() )

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="profile" />
  <input type="file" name="cover" />
  <button type="submit">업로드</button>
</form>
app.post(
  "/upload-fields",
  upload.fields([{ name: "profile", maxCount: 1 }, { name: "cover", maxCount: 5 }]),
  (req, res) => {
    res.json({ profile: req.files.profile, gallery: req.files.cover });
  }
);

profile 최대 업로드 : 1, cover 최대 업로드: 5

 

 

 

4. 파일 필터링 ( 이미지만 허용하는 예시)

<form action="/upload" method="POST" enctype="multipart/form-data">
    <input type="file" name="image" accept="image/*" required />
    <button type="submit">업로드</button>
  </form>
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, cb) {
      cb(null, "uploads/");
    },
    filename(req, file, cb) {
      const ext = path.extname(file.originalname);
      cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  fileFilter(req, file, cb) {
    if (!file.mimetype.startsWith("image/")) {
      return cb(new Error("이미지 파일만 업로드 가능합니다."), false);
    }
    cb(null, true);
  },
});

 

 

accept = "image/*" :  이미지 파일만 선택 가능하도록 제한

required : 파일을 선택하지 않으면 제출 불가능


 

Multer의 파일 처리과정

 

  1. 클라이언트가 form-data로 요청을 보냅니다(POST /upload)
  2. Multer가 요청을 가로채고 파일을 uploads/ 에 저장합니다 (uploads/ 는 예시)
  3. 파일 정보가 req.file 또는 req.files에 저장됩니다.
  4. 라우터에서 req.file을 이용해 응답하거나, db에 저장합니다.

'Node js' 카테고리의 다른 글

passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (1) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

1. passport.js란?

  • passport.js는 Node.js에서 인증을 처리하기 위한 미들웨어로, 다양한 인증 전략을 제공합니다.
    인증을 처리하는 데 필요한 로직을 간단하게 구현할 수 있게 도와줍니다.

2. passport의 흐름

  1. passport.use로 전략 등록하기
    • 인증 전략의 개념 
      • 인증 전략은 사용자가 시스템에 접근하기 위한 인증방법을 정의하는 것 입니다.
        예를들어, 로컬 로그인, 카카오 로그인, 구글 로그인 등이 전략으로 제공됩니다.
    • passport.use 사용법
      • passport.use() 메서드는 인증 전략을 등록하는 함수입니다.
        등록된 전략은 이후 passport.authenticate()로 호출해 사용합니다.
    • 예시
      passport.use(
        new LocalStrategy(
          {
            usernameField: 'email', // 로그인 시 사용할 필드
            passwordField: 'password',
          },
          async (email, password, done) => {
            const user = await User.findOne({ where: { email } });
      	  //유져가 있고, password 와 user.password가 같다면
            if (user && bcrypt.compareSync(password, user.password)) {
              return done(null, user);
            } else {
              return done(null, false, { message: 'Invalid credentials' });
            }
          }
        )
      );

      인자값에 대해 정리를 해보자면,
      1. passport.use(strategy(option, callback));
       - strategy : 사용하고자 하는 인증 전략 (ex : LocalStrategy)
       - option : 전략에 필요한 옵션 설정 (ex : usernameField, passwordFiend, passReqToCallback)
       - callback : 인증을 처리하는 함수, 이 함수에서 done을 호출하여 인증결과를 반환합니다.

      2. callback(username, password, done);  , done(error, user|false, options?)
       - error : 인증 중에 발생한 에러 (에러가 발생하지않으면 null 또는 undefined
       - user : 인증 성공시 인증된 사용자 객체 (없으면 false)
       - options : 인증 실패 시 추가적인 정보 (ex {message : "Invalid credentials"})
  2. passport.authenticate로 인증 요청하기
    • 인증 요청의 과정
      • 사용자가 로그인 폼 형식에 맞춰 제출하면 passport.authenticate가 호출되고, 해당 전략에 맞는 인증 과정이 시작됩니다.
    • passport.authenticate 와 전략 선택
      • passport.authenticate("local")에서 "local"은 등록된 전략의 이름입니다.
      • local 전략이 사용되며 그에 맞는 인증 로직이 실행됩니다.
      • local 의 경우 passport-local 의 LocalStrategy를  kakao의 경우 passport-kakao 입니다.
        passport.authenticate("local") 은  passport.use( new LocalStrategy()) 을 실행
        passport.authenticate("kakao") 은  passport.use( new KakaoStrategy()) 을 실행

      • 저는 여기서 의문이 생겼습니다. authenticate에서 "local"은 어떻게 passport.use( new LocalStrategy())를 찾고 실행하는가 였습니다.
        passport.use("kakao", new KakaoStrategy(...)) , passport.use("local", new LocalStrategy (...)) 처럼
        "kakao"  "local 을 명시적으로 붙이지 않아도, 내부적으로 passport가 전략의 생성자를 보고 자동으로 매칭해주기 떄문이라고 합니다.
  3. serializeUser 로 세션에 사용자 정보 저장하기
    • 세션 관리의 필요성
      • 로그인한 사용자의 정보를 세션에 저장하여, 사용자가 로그인을 유지하고 인증된 상태를 지속적으로 사용할 수 있도록 합니다.
    • serializeUser의 역할과 사용법
      • serializeUser 는 로그인 한 사용자 정보를 세션에 저장할 떄 사용합니다. 
      • 보통 사용자 id만 저장하며, 이 정보는 deserializeUser 에서 사용합니다.
      • passport.serializeUser((user, done) => {
          done(null, user.id); // 사용자 정보를 세션에 저장
        });
        passport.use 에서의 callback이 가지고 있는 done과 흡사합니다.
        passport.use는 인증 시도 및 실패 처리가 이뤄지는 반면  serializeUser 에서는 인증이 성공한 후에 세션에 저장하는 과정이므로 실패 관련 정보가 없습니다.
        그렇기 때문에  user | false , option 이 없습니다.
  4. deserializeUser 를 이용해서 세션에서 사용자 정보 조회하기
    • 세션을 통한 인증 유지
      • 세션에 저장된 사용자 정보를 기반으로 인증된 상태를 유지합니다. 세션이 만료되거나 사용자가 로그아웃할때  까지 세션 정보를 참조합니다.
    • deserializeUser의 역할과 사용법
      • deserializeUser는 serializeUser를 통해 저장된 사용자 ID를 조회하여 실제 사용자 정보를 데이터베이스에서 가져옵니다. 로그인 후 매 요청시마다 호출되어 사용자 정보를 불러옵니다.
      • passport.deserializeUser((id, done) => {
            User.findOne({ where: { id } })
              .then((user) => done(null, user))
              .catch((err) => done(err));
          });


3. 결론

  • passport.js를 사용하면 전략을 등록하고 인증을 처리한 후, 세션을 이용해 인증된 사용자를 관리할 수 있습니다.
    • 세션을 통해 인증을 유지하며 serializeUser , deserializeUser를 사용하여 사용자정보를 효율적으로 관리합니다.
  • 전략 등록부터 인증까지의 전체 흐름
    • 전략 등록(passport.use)  -> 인증 요청(passport.authenticate) -> 세션 저장(serializeUser) -> 세션 조회 (deserializeUser) -> 인증유지

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (1) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

1. mongoDB

mongoDB는 NoSQL 데이터베이스이고, 그  구조와 사용법이 JSON 형식과 유사하게 설계되어있습니다.

 

2.mongoDB와 JavaScript의 관계

 

1. JSON 과 BSON : mongoDB는 데이터를 JSON과 비슷한 BSON 형식으로 저장합니다.

자바스크립트 개발자에게는 친숙하게 느낄 수 있습니다.

 

2. JavaScript 기반 쿼리 : mongoDb의 셸에서 쿼리는 JavaScript 구문을 기반으로 작성합니다.

JavaScript 를 사용하는 것처럼 데이터를 조회하고, 조작할 수 있습니다.

 

3. Node.js와의 호환성 : mongoDB는 Node.js와 잘 어울리는 라이브러리(mongoose, mogodb)나 패키지를 제공하여 JavaScript로 쉽게 다룰 수 있습니다.

 

3. mongoDB의 NoSQL 에 대해

 

NoSQL의 특징

  • 관계형 데이터베이스(RDBMS)처럼 고정된 테이블 구조가 없습니다.
  • 데이터를 도큐먼트(document)로 저장하며, 각 도큐먼트는 키-값 쌍으로 구성됩니다.
  • 스키마가 유연하여 서로 다른 구조의 데이터를 한 걸렉션에 저장할 수 있습니다.
  • 수평확장(sharding)에 유리하며 대규모 데이터를 처리하기 적합합니다.

 

MySQL 과 NoSQL(몽고디비) 비교

MySQL NoSQL(몽고디비)
규칙에 맞는 데이터 입력
JOIN 지원
안정성, 일관성
용어(테이블, 로우, 칼럼)
자유로운 데이터 입력
JOIN 미지원 (aggregate로 비슷하게 가능)
확장성, 가용성
용어(컬렉션, 도큐먼트, 필드)

 

비정형 데이터에는 mongoDB가 사용하기 좋다

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
3. express 미들웨어 정리하기  (1) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

express의 미들웨어는 요청과 응답 사이에 위치한 함수로, 주로 요청을 처리하거나. 응답을 수정하는 작업을 합니다.

각 미들웨어는 요청을 처리하고, next()를 호출하여 다음 미들웨어로 넘길지, 응답을 보낼지 결정할 수 있습니다.

 

  • 미들웨어는 app.use()로 설정합니다.
  • 요청이 들어오면 순차적으로 실행되며, 각각의 미들웨어가 요청을 수정하거나 처리합니다.

1. morgan("dev")

app.use(morgan("dev"));

기능

- morgan은 HTTP 요청에 대한 로깅을 처리하는 미들웨어입니다.

dev는 로깅 형식중 하나로, 개발환경에서 요청 URL, HTTP상태 코드, 응답시간을 콘솔에 출력합니다.

 

사용하는 이유

 - 요청과 상태를 쉽게 추적하기위해 사용되며, 요청이 서버에 들어올 때마다 콘솔에 로그가 찍혀 확인할 수 있습니다.

 morgan은 단순히 요청을 로그로 보여주며 next()를 호출하지 않아도 다음 미들웨어로 넘어갑니다.

 

 

2. express.static()

기능

 - 정적 파일 제공,

 - 이 미들웨어는 정적파일(HTML, CSS, 이미지, JavaScript 파일)을 제공하는 미들웨어입니다.

 - 서버에서 제공할 파일들이 특정 폴더에 있을 때, 해당 파일들을 URL 경로에 맞게 자동으로 제공해줍니다.

app.use(express.static(path.join(__dirname, "public")));

( __dirname : 현재 파일의 디렉토리를 의미)

path.join을 통해 디렉토리 안의 public 폴더를 지정하며, 폴더안의 파일을 클라이언트(브라우저)에게 제공할 수 있게 합니다.

 

3. express.json()

app.use(express.json());

 

기능

 - json 데이터를 파싱하는 미들웨어입니다.

클라이언트에서 JSON 형식으로 데이터를 전송하면, JavaScript 객체로 변환하여 req.body에 저장합니다.

 

요청 본문에 JSON 데이터가 있으면 파싱하고, next()를 호출하여 다음 미들웨어로 넘어갑니다.

(직접호출 하지 않아도 자동으로. 호출됨)

 

4. express.urlencoded({extended: boolean})

app.use(express.urlencoded({ extended: false }));

 

기능

 - URL 인코딩 된 폼 데이터를 파싱하는 미들웨어입니다.

false 옵션은 querystring 라이브러리를 사용하여 데이터를 처리합니다.  중첩된 객체나 복잡한 구조는 처리하지 않으며, 일반적인 폼 데이터는 파싱합니다.

(직접호출 하지 않아도 자동으로. 호출됨)

 

HTML 폼을 통해 전송된 데이터를 처리하기 위해 사용하며 사용자가 제출한 폼 데이터를 req.body에서 확인할 수 있습니다.

 


 

express 에서는 미들웨어가 위에서 아래로 순차적으로 실행됩니다. 각 미들웨어가 요청을 처리하거나, 요청을 수정하거나, 응답을 보내며, 그 후  next()가 호출되면 다음 미들웨어로 넘어갑니다. 
단, 정적 파일을 제공하거나 응답을 완료한 미들웨어는 더 이상 다음 미들웨어로 넘어가지 않습니다.

그렇기에 미들웨어의 순서는 매우 중요합니다.

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

문제 설명
과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.

한 상자에 사과를 m개씩 담아 포장합니다.
상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.
과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)

예를 들어, k = 3, m = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.

(최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8
사과의 최대 점수 k, 한 상자에 들어가는 사과의 수 m, 사과들의 점수 score가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ k ≤ 9
3 ≤ m ≤ 10
7 ≤ score의 길이 ≤ 1,000,000
1 ≤ score[i] ≤ k
이익이 발생하지 않는 경우에는 0을 return 해주세요.

 


 

 

function solution(k, m, score) {
    var answer = 0;
    let arr = score.sort((a, b) => b - a); // 내림차순 정렬
    let box = [];
   
    arr.forEach((item,i) =>{
        box.push(arr[i])  
        
        // 박스에 사과가 m개 담겼다면 점수계산
        if(box.length === m){
            answer += Math.min(...box) * box.length;
            box=[];
        }
    })
    
    return answer;
}

중간에 발생한 문제점

처음에는 splice로 꺼내는 작업을 했더니 forEach가 멈춰버리는 일이 생겼습니다.
알아보니 forEach는 처음에 시작할때 배열의 길이와 요소를 고정된 상태로 순회한다는걸 몰랐습니다.

 

 


혹시 문제가 남은 사과까지 계산한다면..?

 

문제에서는 남은 사과는 계산하지 않습니다.

 

혹시라도 남은 사과를 계산을 했었다면

 

for문이나 while문으로짜고 splice로 잘라서 넣고 남은 arr.length가 m보다 작다면 arr의 요소를 더해서 계산하면 될 듯 싶습니다.

 

 

 

function solution(k, m, score) {
    let answer = 0;
    let arr = score.sort((a, b) => b - a);  

    // 상자 단위로 처리 (m개씩 꺼내서 상자 구성)
    while (arr.length >= m) {
        let box = arr.splice(0, m);  // m개씩 꺼내서 상자에 담기
        answer += Math.min(...box) * m;  // 최소 점수 * m (상자의 가격)
    }

    // 남은 사과가 있으면 마지막 상자에 대해 처리
    if (arr.length > 0) {
        let box = arr.splice(0, arr.length);  // 남은 사과들
        answer += Math.min(...box) * arr.length;  // 남은 사과들 가격 계산
    }

    return answer;
}

'개발공부 > 알고리즘' 카테고리의 다른 글

[Algorithm] 2차원 배열 최대합 구하기  (0) 2023.04.30
[Algorithm] 점수계산하기  (0) 2023.04.27
[Algorithm] 가위바위보  (0) 2023.04.27
[Algotithm] 큰 수 출력하기  (0) 2023.04.26
[Algorithm] 보이는 학생  (0) 2023.04.26

1. 이벤트기반

Node.js는이벤트를 기반으로 동작합니다.

이벤트가 발생했을 때 반응하도록 처리합니다.


2. 흐름

1. 콜백 함수 생성 : 이벤트가 발생했을 때 실행될 콜백 함수를 정의합니다.

2. 이벤트리스너 등록 : 특정 이벤트가 발생시 콜백함수가 실행되도록 이벤트 리스너를 등록합니다.

3. 이벤트 발생 : 이벤트가 발생하면 등록된 이벤트 리스너가 반응하며 지정된 콜백 함수를 실행합니다.

 

 


3. 블로킹과 논블로킹 I/O

Node.js는 기본적으로 비동기적이고 논 블로킹 방식으로 동작하며, 동기적이고 블로킹 방식으로도 동작할 수 있습니다.

  • 비동기(Asynchronous) : 다른 작업의 완료를 기다리지 않고 즉시 작업을 시작합니다.
  • 논블로킹(Non-blocking) : 작업을 실행할 때, 그 작업이 끝날때 까지 대기하지않고 계속해서 실행됩니다.
  • 동기(Synchronous) : 작업이 순차적으로 실행되며, 하나의 작업이 완료되어야 다음 작업을 시작합니다.
  • 블로킹(Blocking) : 작업을 실행할 때, 그 작업이 끝날 떄까지 다른 작업을 멈추거나 대기합니다.

Node.js의 비동기적, 논블로킹에 대해

Node.js는 기본적으로 비동기적이고 논블로킹 방식으로 설계되었습니다. 이것은 I/O 작업을 수행할 때 다른 작업들이 대기하지 않고 계속 실행될 수 있도록 합니다.

 

 

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (1) 2025.01.24
1. Node.js 란?  (0) 2025.01.07

1. Node.js란 크롬 V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다. (공식 홈페이지)

서버 애플리케이션을 개발할 수 있게 해주는 플랫폼으로, 자바스크립트를 사용하여 서버를 구축할 수 있게 해줍니다.

 

2. Node.js는 내장된 HTTP 서버 라이브러리를 포함하고 있어, Apache와 같은 별도의 웹 서버 소프트웨어 없이도 웹 서버를 구축할 수 있습니다.  따라서 Node.js는 서버 측 애플리케이션을 개발하는 데 사용되는 런타임 환경이며, 서버로서의 역할을 수행합니다.

질문) 노드는 서버가 아닌가?
 - Node.js는 서버 자체가 아니라, 서버를 구축할 수 있는 런타임 환경입니다.  Node.js는 JavaScript사용하여 서버를 개발할 수 있는 플랫폼을 제공합니다. 서버라고 불리는 이유는 Node.js를 이용해 운영되는 서버 애플리케이션입니다.

 

정리하자면
1. Node.js === 자바스크립트 런타임

2. 자바스크립트를 서버에서 실행할 수 있게 해주는 런타임 환경이며 서버 애플리캐이션을 개발할 수 있는 플랫폼을 제공

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (1) 2025.01.24
2. 노드의 특성  (0) 2025.01.07

제스트(Jest)는 자바스크립트 테스트 프레임워크로, 주로 리액트 애플리케이션의 테스트에 사용됩니다. 

 

Meta에서 개발하였으며, 단위 테스트(unit testing) 및 통합 테스트(integration testing)를 쉽게 작성할 수 있도록 설계되었습니다

 

특징

 

  • 스냅샷 테스트: 컴포넌트의 UI가 예상대로 렌더링되는지 확인하기 위해 스냅샷을 찍어 비교하는 기능을 제공합니다.
  • 모듈화: 다양한 모듈을 쉽게 모킹(mocking)하여 테스트할 수 있어, 실제 의존성을 제거하고 독립적으로 테스트할 수 있습니다.
  • 빠른 실행: 변경된 파일만 테스트하여 실행 속도를 높이는 "빠른 테스트" 기능을 제공합니다.
  • 비동기 테스트: 비동기 코드를 간편하게 테스트할 수 있는 API를 제공하여, Promises와 async/await을 쉽게 사용할 수 있습니다.

 

그만 알아보고 정리해야겠다.

 

정의 : 고수준 모듈이 저수준 모듈에 의존해서는 안된다. 둘 다 추상화된 인터페이스에 의존해야한다.

예시 : 리엑트에서 특정 API 서비스에 직접 의존하지 않도록, 추상화된 서비스에 의존하게 설계할 수 있습니다.

 

DIP 위반 예시

function UserProfile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch('/api/user/1')
      .then((res) => res.json())
      .then((data) => setUser(data));
  }, []);

  return (
    <div>
      <h1>{user?.name}</h1>
      <p>{user?.email}</p>
    </div>
  );
}

UserProfile 컴포넌트는 특정 API 호출방식에 의존하고 있습니다.

만약 API가 바뀐다면 이 컴포넌트도 수정을 해야합니다.

이는 DIP를 위반한 사례로 상위 컴포넌트(UserProfile)가 하위 구현(API fetch)에 의존하고 있기 때문입니다.

 


DIP 적용

// UserProfile은 오로지 UI를 렌더링하는 역할만 담당
function UserProfile({ user }) {
  return (
    <div>
      <h1>{user?.name}</h1>
      <p>{user?.email}</p>
    </div>
  );
}

UserProfile 컴포넌트는 

 

function App() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const fetchUserFromAPI = async () => {
      const response = await fetch('/api/user/1');
      const data = await response.json();
      setUser(data);
    };

    fetchUserFromAPI();
  }, []);

  return <UserProfile user={user} />;
}

 

UserProfile은 더이상 구체적인 데이터 처리나 API호출 방식에 의존하지않고 상위 컴포넌트가 제공하는 데이터(Props)를 받아 UI만 랜더링하게 됩니다. (이제보니 이렇게 만들면 ISP도 적용되는 것 같습니다)

 

+ Recent posts