Node.js 교과서 - 기본부터 프로젝트 실습까지
Node.js 교과서 - 기본부터 프로젝트 실습까지
수강정보
(42개의 수강평)
953명의 수강생
55,000원
지식공유자 : 조현영
145회 수업 · 총 24시간 24분 수업
기간 : 평생 무제한 시청
수료증 : 발급 강의
수강 난이도 : 초급
ritmakid@hotmail.com 프로필

제로초님 HTTP 완벽가이드 추천해주신거 너무 잘 읽었습니다. ritmakid@hotmail.com 10일 전
제로초님 노드 js교과서 예전버전과 유튜브에 올려주식 새 버전 모두 너무 감사하게 잘 듣고 있습니다. 강의 중간에 소개해주셨던 HTTP 완벽가이드책을 보면서 HTTP를 한번 훓었는데 HTTP 전체 개념을 잡는데 정말 큰 도움이 된것 같습니다. 너무 좋은 책 소개해주셔서 감사드립니다. 다름이 아니라 HTTP 공부 뒤에 운영체제도 공부해보려고 하는데 혹시 추천해주실만한 책이 있는지 물어봐도 될까요?현재 알아본것은 - 운영체제 (일명 공룡책)- 그림으로 배우는 구조와 원리 운영체제- 운영체제와 정보기술의 원리 이렇게 세권이 좋다는 말은 들었습니다. HTTP 완벽가이드처럼 입문자도 쉽게 이해할수 있으면서 필수개념은 다 익힐 수 있는 책을 공부하고 싶은데 혹시 조언을 부탁드려도 되는지 여쭙고 싶습니다. 강의와 관계없는 질문이라 물어보기 죄송한데 주변에 조언을 얻을만한 곳이 없어서 이곳에 올립니다.좋은 하루 보내시기 바랍니다!

2
데구리 프로필

gif채팅방 nunjucks관련 질문입니다! 데구리 16일 전
gif채팅방 만들기에서 제로초님께서 nunjucks로 짜신 코드 복붙해서 하니까 너무 잘돌아갑니다! 근데 사진처럼 css적용하는 부분에서 문법오류가 떠서 안사라지는데 혹시 없앨 수 있는 방법이 없을까요...??

3
세로수 프로필

현영님 몽고db관련 질문입니다. 세로수 19일 전
제가 현영님 강의를 본다음 노드로 api 서버를 만들었습니다. 그런데 aws ec2에 배포하려고 이것저것 찾아보니 오토스케일링이나 확장성 문제등등 때문에 디비서버랑 was랑 분리하는게 좋다고 해서 해보려고하니 헷갈리는게 있어서 질문드립니다. 1. 하나의 서버에 was와 db서버를 같이 돌린다는 게 무슨 뜻인가요? 2. 몽구스로 쿼리작업을 할 때 따로 몽고디비 서버를 키진 않는데(몽고db를 사용할 일이 있을 때마다 mongod 명령어로 서버를 실행해야 한다고 봤습니다), /(approot)/models/index.js에 몽구스로 connect.on 하면 자동으로 몽고db가 실행되는건지 아니면 몽고 db를 설치하면 백그라운드에서 계속 켜져있는 것인지 궁금합니다. 3. 어떤상태가 몽고db서버랑 was를 분리된 상태인거고 어떻게 해야 하나요? (ec2로 예시들어주시면 더 감사드립니다!) 감사합니다. 

3
vbkj 프로필

github 코드 질문있습니다 vbkj 29일 전
강의에 나오는 링크로 접속하면 , 존재하지않는 페이지라고 떠서 repository 찾아서 restFront.js 를 찾아서 코드를 보니까 , 강의 영상에 있는 코드와 다르더라고요 ㅠㅠ 혹시 같은 코드로 올라온 것은 없을까여?

1
Baekgyu Koh 프로필

sns 만들기 강의 중 pug 코드 질문입니다. Baekgyu Koh 1달 전
1) 위에 밑줄 친 부분의 코드가 의미하는게 뭔지 잘 이해가 안가네요;; 2) 변수 follow 에는 boolean 값이 들어갈 거 같은데, user.Followings 배열에 어떤값이 들어가는지 모르겠습니다. twit.user.id는 글쓴 사람의 아이디인가요?

1
Baekgyu Koh 프로필

sns 강의 수강 중 질문있습니다. Baekgyu Koh 1달 전
게시글 업로드 구현하기 까지 수강해서 아래 사진까지 구현하였습니다.  이 상태에서 회원가입 하고 그 아이디로 로그인하면 아래같은 메시지가 뜨는데 왜 그런건가요?? router index 파일 입니다. router.get("/", async (req, res, next) => { await Post.findAll({ include: { model: User, attributes: ["id", "nick"], }, }) .then((posts) => { res.render("index", { title: "NodeBird", twits: posts, user: req.user, loginError: req.flash("loginError"), }); }) .catch((err) => { console.error(err); next(err); }); }); module.exports = router; index pug 파일입니다. extends layout block content .timeline if user div form#twit-form(action='/post' method='post' enctype='multipart/form-data') .input-group textarea#twit(name='content' maxlength=140) .img-preview img#img-preview(src='' style='display: none;' width='250' alt='미리보기') input#img-url(type='hidden' name='url') div label#img-label(for='img') 사진 업로드 input#img(type='file' accept='image/*') button#twit-btn.btn(type='submit') 짹짹 .twits form#hashtag-form(action='/post/hashtag') input(type='text' name='hashtag' placeholder='태그 검색') button.btn 검색 for twit in twits .twit input.twit-user-id(type='hidden' value=twit.user.id) input.twit-id(type='hidden' value=twit.id) .twit-author= twit.user.nick -const follow = user && user.Followings.map(f => f.id).includes(twit.user.id); if user && user.id !== twit.user.id && !follow button.twit-follow 팔로우하기 .twit-content= twit.content if twit.img .twit-img img(src=twit.img alt='섬네일') script. if (document.getElementById('img')) { document.getElementById('img').addEventListener('change', function (e) { var formData = new FormData(); console.log(this, this.files); formData.append('img', this.files[0]); var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status === 200) { var url = JSON.parse(xhr.responseText).url; document.getElementById('img-url').value = url; document.getElementById('img-preview').src = url; document.getElementById('img-preview').style.display = 'inline'; } else { console.error(xhr.responseText); } }; xhr.open('POST', '/post/img'); xhr.send(formData); }); } document.querySelectorAll('.twit-follow').forEach(function (tag) { tag.addEventListener('click', function () { var isLoggedIn = document.querySelector('#my-id'); if (isLoggedIn) { var userId = tag.parentNode.querySelector('.twit-user-id').value; var myId = isLoggedIn.value; if (userId !== myId) { if (confirm('팔로잉하시겠습니까?')) { var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status === 200) { location.reload(); } else { console.error(xhr.responseText); } }; xhr.open('POST', '/user/' + userId + '/follow'); xhr.send(); } } } }); });

1
Baekgyu Koh 프로필

파일이 github에 없는 것 같아요.. Baekgyu Koh 1달 전
안녕하세요? 강의 잘 보고 있습니다^^ 다름이 아니고 지금 sns 만들기 보고 있는데 렌더링 퍼그 파일이 github들어가서 nodejs-book/ch9에 들어가면 html파일들만 있는 것 같습니다. pug파일은 어디서 얻을 수 있나요?

2
Baekgyu Koh 프로필

CLI 만들기 수업 관련 질문있습니다. Baekgyu Koh 1달 전
어제는 강의 따라하면서 실행했더니 되었는데 오늘 다시 파일을 만들어서 sudo npm i -g를 실행해보면 아래 메시지가 뜹니다. 폴더랑 파일 지우고 새로 만들어봐도 동일하네여.. 아래와 같은 오류가 발생하는 이유와 해결 방법이 있는지요? ------------- Last login: Tue Aug 25 11:28:45 on console bgkoh86@baegbal-iuiui-MacBookPro node-cli % sudo npm i -g  Password: npm ERR! code EEXIST npm ERR! path /usr/local/bin/cli npm ERR! Refusing to delete /usr/local/bin/cli: ../lib/node_modules/cli/template.js symlink target is not controlled by npm /usr/local/lib/node_modules/cli npm ERR! File exists: /usr/local/bin/cli npm ERR! Remove the existing file and try again, or run npm npm ERR! with --force to overwrite files recklessly. npm ERR! A complete log of this run can be found in: npm ERR!     /Users/bgkoh86/.npm/_logs/2020-08-25T02_46_26_515Z-debug.log bgkoh86@baegbal-iuiui-MacBookPro node-cli % 

1
Baekgyu Koh 프로필

노드 html 응답 관련 질문있습니다. Baekgyu Koh 1달 전
안녕하세요 강의 잘 듣고 있습니다. 혼자 예시 코드 보고 작성하면서 공부중인데요 아래처럼 코드를 작성하고 인터넷 주소창에 localhost:3002 를 입력하면 화면이 안뜨다가 노드 프로그램으로 들어가서 저장을 한번 더 눌러줘야 화면에 html이 렌더링 되는데 html 파일에서 css 링크 파일을 지우고 하니까 바로 렌더링 되는데 왜그런지 궁금합니다.--------- const http = require("http"); const fs = require("fs").promises; const port = 3002; http .createServer(async (req, res) => { try { if (req.method === "GET") { // GET Requests if (req.url === "/") { console.log(req.url); const data = await fs.readFile("./restFront.html"); res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); return res.end(data); } } } catch (err) { console.log(err); } }) .listen(port, () => { console.log(`${port}번 포트에서 대기중입니다.`); });

1
박정인 프로필

스스로해보기 좋아요, 좋아요 취소 부분 구현 박정인 1달 전
안녕하세요~  강의를 듣다보니 시간의 흐름에 따라 바뀐 부분들이 많아서 이번에 나온 개정판 책을 사서 강의와 함께 보면서 개정판 책에 나오는 코드를 기준으로 실습을 하고 있는데 스스로해보기 부분의 좋아요, 좋아요 취소 부분에서 막혔습니다. main.html에서 좋아요, 좋아요 취소 if 조건 값 설정을 어떻게 해야하는지 궁금합니다. 좋아요 버튼클릭하면 db에 저장까지는 되는데 좋아요 취소로 버튼이 바뀌지 않고 삭제도 되지 않습니다. {% for twit in twits %} <div class="twit"> <input type="hidden" value="{{twit.User.id}}" class="twit-user-id"> <input type="hidden" value="{{twit.id}}" class="twit-id"> <div class="twit-author">{{twit.User.nick}}</div> {% if not followerIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="twit-follow">팔로우하기</button> {% endif %} {% if followerIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="twit-unfollow">팔로우끊기</button> {% endif %} <div class="twit-content">{{twit.content}}</div> {% if twit.img %} <div class="twit-img"><img src="{{twit.img}}" alt="섬네일"></div> {% endif %} {% if user and not liker %} <button class="like">좋아요</button> {% endif %} {% if user and liker %} <button class="unlike">좋아요 취소</button> {% endif %} </div> {% endfor %} document.querySelectorAll('.like').forEach(function(tag) { tag.addEventListener('click', function() { const twitId = tag.parentNode.querySelector('.twit-id').value; axios.post(`/post/${twitId}/like`) .then(() => { location.reload(); }) .catch((err) => { console.error(err); }); }); }); document.querySelectorAll('.unlike').forEach(function(tag) { tag.addEventListener('click', function() { const twitId = tag.parentNode.querySelector('.twit-id').value; axios.post(`/post/${twitId}/unlike`) .then(() => { location.reload(); }) .catch((err) => { console.error(err); }); }); }); router.post('/:id/like', async (req, res, next) => { try { const post = await Post.findOne({ where: { id: req.params.id } }); await post.addLiker(req.user.id); res.send('OK'); } catch (error) { console.error(error); next(error); } }); router.post('/:id/unlike', async (req, res, next) => { try { const post = await Post.findOne({ where: { id: req.params.id } }); await post.removeLiker(req.user.id); res.send('OK'); } catch (error) { console.error(error); next(error); } });

7
김기리 프로필

jwt 관련 질문 김기리 1달 전
안녕하세요 제로초님.책을 보면서 jwt를 연습중입니다. 요청 헤더에 저장된 토큰을(req.headers.authorization) 사용합니다. 라고 책에 적혀있는데요req.headers.authorization 확인 시 값이 나오질 않네요.=> 왜 그런가요?? 어떤식으로 수정을 하면 될까요? req.cookies를 이용하여 쿠키값을 확인 후 토큰을 검증 후 로그인 기능을 구현해도 상관없을까요?해당 코드입니다. const express = require('express'); const jwt = require('jsonwebtoken'); const { user } = require('./models'); var cookies = require("cookie-parser"); const app = express(); app.use(cookies()); app.get('/login', async (req, res, next) => { let token = jwt.sign({ email: "cho@naver.com" }, 'qlalfaldi', { expiresIn: '2m' }) let userOne = await user.findOne({ where: { email: "cho@naver.com" } }); if(userOne.dataValues.pwd === '1234') { res.cookie("authorization",token); res.json({ token: token }) res.end(); } }) app.get('/api', (req, res) => { console.log(req.headers.authorization); // undefined console.log('here', req.cookies); res.end(); })

3
유기쁨 프로필

이미지 업로드 관련 질문 유기쁨 2달 전
안녕하세요. multer를 이용한 이미지 업로드 강의 중에 post 라우터 코드 부분에서 destination을 'uploads/'로 설정하셨는데 이렇게 했을 경우, 이미지를 제대로 불러오지 못하더라구요. 그래서 저는 public에 img 폴더를 만들고 'public/img/'로 경로를 설정하니 문제가 해결되었는데 혹시 강의 코드가 잘못된 것인지 확인차 질문드립니다. 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) + new Date().valueOf() + ext);         }     }),     limit: { fileSize: 5 * 1024 * 1024}, }); router.post('/img', isLoggedIn, upload.single('img'), (req, res) => {     console.log(req.file);     res.json({ url: `/img/${req.file.filename}` }); });

2
유기쁨 프로필

sequelilze 강의 질문 유기쁨 2달 전
안녕하세요. 제로초님 강의 잘 듣고 있습니다. 강의 내용과는 관련없지만 궁금한 점이 생겨 질문드려요. sequelize 강의 중에 sequelize.html에 있는 form 태그 아래의 input 태그에 접근할때 <form id="user-form"> <div><input id="username" type="text" placeholder="이름"></div> <div><input id="age" type="number" placeholder="나이"></div> <div><input id="married" type="checkbox"><label for="married">결혼 여부</label></div> <button type="submit">등록</button> </form> document.getElementById('user-form').addEventListener('submit', async (e) => { e.preventDefault(); const name = e.target.username.value; const age = e.target.age.value; const married = e.target.married.checked; 자바스크립트에서  위 코드처럼 id명을 사용해서 자식 엘리먼트에 접근하신 코드를 보았는데 보통 e.target.children 같은 식으로 접근하는 방법만 보다가 처음 보는 방식이라 공부하려고 하는데 어떤 키워드로 검색해야할지 모르겠어서 질문드려요. 답변주시면 감사하겠습니다~

1
김기리 프로필

mysql 설정관련 문의입니다. 김기리 2달 전
sequelize db:create  입력 시 Access denied for user 'root'@'localhost' (using password: YES)라는 에러가 계속 뜨는데 해경방법이 궁금합니다.

3
김학준 프로필

질문입니다~!. 김학준 3달 전
  // store: new RedisStore({   //   host: process.env.REDIS_HOST,   //   port: process.env.REDIS_PORT,   //   pass: process.env.REDIS_PASSWORD,   //   logErrors: true,   // }), 위부분을 포함시켜 실행시키면 서버가 응답하지 않습니다 어떤부분을 실수했을까요 ?

2
지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스