수강이 제한됩니다.
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
에러 처리를 하면
예를 들어 404나 500에러가 났을 때 그 에러가 본질적으로는 404, 500에러가 맞지만 그 에러를 app.use()로 에러처리를 해서 res.send('어쩌구')로 처리해주면 클라이언트에 전달되는 상태코드는 기본적으로 200이 되는 것인가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
app.listen은
1. app.listen() 메서드는 뭔가 서버를 열어주는 기능을 하는 것 같은데 만약 그렇다면 제일 먼저 실행되나요 아니면 그냥 다른 코드처럼 순차적으로 실행되나요? 2. app.get(), app.post(), app.listen() 이런 메서드들은 비동기로 동작하나요?
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
넌적스 실행결과가 잘못나와서 질문드리고 싶습니다
강사님 안녕하세요 이렇게 파일과 폴더를 만들고 app.js를 실행했는데 넌적스 실행결과가 잘못나와서 질문드리고 싶습니다 넌적스 실행결과가 성공하지 못해서 혹시 그 원인을 가르쳐주시면 감사하겠습니다 아래는 app.js 코드입니다 const nunjucks = require(`nunjucks`); const express = require(`express`); const morgan = require(`morgan`); const path = require('path'); const app = express(); app.set('view engine', 'html'); nunjucks.configure('views',{ express: app, watch: true }) app.set('port', process.env.PORT || 3000); //'port' 라는 속성에 포트번호 3000번을 설정합니다. //서버의 포트를 3000번으로 지정하는 것 같습니다. // 이 속성은 아래 19행처럼 가져올 수 있습니다 //app.use(morgan('dev')); app.use(morgan('dev')) app.get('/', (req, res) => { // res.send('Hello, Express'); console.log('진입') res.sendFile(path.join(__dirname, 'views/main.html')); }); app.listen(3000, () => { console.log(app.get('port'), '번 포트에서 대기 중'); }); 아래는 main.html 파일입니다 {% include "header.html" %} <main> <h1>메인 파일</h1> <p>다른 파일을 include 할 수 있습니다</p> </main> {% include="footer.html" %} 아래는 header.html 파일입니다 <header> <a href="/">home</a> <a href="/about">About</a> </header> 아래는 footer.html 파일입니다 <footer> <div>푸터입니다.</div> </footer> 읽어주셔서 감사합니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
cookie parser 질문드립니다(소스코드 2차 수정했습니다)
강사님 안녕하세요 소스코드를 수정해서 다시 질문드리고 싶습니다(app.js 를 수정했습니다) 아래는 app.js입니다 /** * ch6.1 */ const express = require('express'); const path = require('path'); const { nextTick } = require('process'); const morgan = require('morgan'); const cookieParser = require('cookie-parser'); const app = express(); app.set('port', process.env.PORT || 3000); //'port' 라는 속성에 포트번호 3000번을 설정합니다. //서버의 포트를 3000번으로 지정하는 것 같습니다. // 이 속성은 아래 19행처럼 가져올 수 있습니다 //app.use(morgan('dev')); app.use(cookieParser()); app.get('/login', (req, res, next) => { if(req.url.startsWith('/login')){ req.cookies // 쿠키 객체화 res.cookie('name', encodeURIComponent(name2),{ expires: new Date(), httpOnly: true, path: '/', }) } else if(true) { next('route'); } else{ next(); } }, (req, res, next)=>{ console.log('실행되지 않음1') next(); },(req,res,next)=>{ console.log('실행되지 않음2') next(); }); app.get('/', (req, res) => { // res.send('Hello, Express'); console.log('실행되지 않음3') res.sendFile(path.join(__dirname, '/cookie2.html')); }); app.use((err,req,res,next)=>{ console.log(err); res.status(200).send('에러났지롱') }) app.listen(3000, () => { console.log(app.get('port'), '번 포트에서 대기 중'); }); 아래는 cookie2.html 입니다 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>쿠키&세션 이해하기</title> </head> <body> <form action="/"> <input id="name" name="name2" placeholder="이름을 입력하세요" /> <button id="login">로그인</button> </form> </body> </html> 이렇게 로그인을 해봤습니다 그런데 name2는 이렇게 cookie2.html에 있는데, 혹시 어디가 문제인지 도와주시면 감사하겠습니다 도저히 모르겠습니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
next('route') 질문드립니다
강사님 안녕하세요 next('route') 는 다음 라우트 함수 next( ) 는 같은 라우트 내에서 다음 콜백함수 로 이해가 되었습니다 그런데, 16행 다음 18행이 실행되어서 혹시 그 이유를 가르쳐주시면 감사하겠습니다 읽어주셔서 감사합니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
bcrypt의 compare메서드의 리턴값이 계속 false로 나오는데요, 어떻게 하면 true를 반환할까요
안녕하세요, 제로초님! bcrypt의 compare 함수의 return 값이 계속 false가 나와서, 혹시 제시해주실 힌트가 있으실지 글을 남겨봅니다 이와 관련해 구글링에서 제시한 방법들을 적용해봤는데도, 계속적으로 false가 리턴됩니다ㅠ… : 1. password 타입의 length를 늘리기(데이터가 짤려서 출력될 수 있다고 하여,,) : 2. password 타입을 string 타입으로 변환? 후 디비에 저장하기 : 3. pre 미들웨어를 사용할 경우, pre()특성상 반복적?으로 pwd를 해싱하기 때문에 isModified()/ .isNew() 일 경우를 추가하기 : 4. compare()함수의 인자를 작성시, 인자의 순서 체크 - 첫번째인자는 유저가 입력한것, 두번째는 hashed되어 디비에 저장된 패스워드로 입력하기 위와 같이 해결방법을 찾았는데요,,, 1,2번은 이미 mongoose에서 해결해주는 부분이라 패스하고,,, 3,4번은 적용을 했는데도 ㅠ comprare함수의 리턴값이 false로 나옵니다,,, compare함수의 리턴값이 false여도... false를 true라고;;; 조건식을 변경하면;;;; 입력한 값에 해당하는, json객체가 출력되어 문제는 없지만,,,, (아래 authController.js파일, !passwordMatch를 passwordMatch로 변경하면 원하는 로직대로 나오지만 ㅠ ) (폼에 입력한 값에 해당한, json객체가 나와서 문제는 없는데..) false를 true라고 가정하고;; 코드를 변경하면 원하는 결과를 얻게 되는데,,, 작성된 코드가 ,,,이건 아닌거 같아서요 ㅠ 왜 계속,,,false를 반환할까요,,;; bcrypt말고 다른 라이브러리를 사용해야할까요?? 감사합니다, p.s) 추가 질문입니다. 1. issModified(‘password’) || isNew()User.js 내용 중 UserSchema.pre('save', async function () {…} 부분에서, isModified(‘password’) || isNew() 이하 블록이 실행되는 조건은, password가 변경되거나 처음 입력될 경우 실행되는 건지요, 제가 잘 이해하고 코드를 작성했는지 궁금합니다 2. 에러 핸들링 bycript 공식홈페이지나 관련 코드를 구글링을 해보면, 코드를 콜백방식으로 작성한걸 심심치 않게 볼수 있는데요, 저는 async-await로 작성해서, 이걸어떻게 에러 핸들링 코드를 작성해야할까요? try..catch로도 충분할까요? -------------------------------------------------------------------------------------------------------------------------- User.js import bcrypt from 'bcrypt'; import mongoose from 'mongoose'; const UserSchema = new mongoose.Schema( { …중략… password: { type: String, required: true, min: 6, }, …중략… }, { timestamps: true } ); UserSchema.pre('save', async function () { try { const salt = await bcrypt.genSalt(10); if (this.isModified('password') || this.isNew()) { this.password = await bcrypt.hash(this.password, salt); } } catch (err) { console.log(err); } }); const User = mongoose.model('User', UserSchema); export default User; authController.js export const login = async (req, res) => { try { const { body: { email, password }, } = req; const user = await User.findOne({ email: email }); if (!user) { // user가 ! 없는것이 맞다(true)면 = user가 없다면 return res.status(404).json({ error: 'user is not found' }); } else { const passwordMatch = await bcrypt.compare(password, user.password); //부정문을 먼저 시작하는 조건식 // passwordMatch가 false로 나와 계속 { error: 'Invalid Password' }를 출력 // !passwordMatch에서 !을 제거하면 원하는 결과 도출 if (!passwordMatch) { // match되는 password가 !없다는게 맞다(true)면 = return res.status(400).json({ error: 'Invalid Password' }); } return res.status(200).json(user); } } catch (err) { return res.status(401).json(err); } };
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
package.json 외에 여러 *.config.* 파일을 특정(내/외) 폴더에서 관리하도록 경로 설정이 가능할까요?
안녕하세요 강사님. package 의 경로 와 설정파일들 간의 관계에 대해 궁금한것이 있어 질문하게 되었습니다. 아래 이미지를 보시면 이해되시겠지만, 이런 방법이 가능할지 모르겠습니다. 인터넷에 아무리 찾아봐도 잘 찾아지지가 않는데요, 질문입니다. node.js 는 package.json 가 위치한 경로를 root 로 기준잡는 것으로 알고 있습니다. 그래서 ... 위에 이미지와 같이 프로젝트 루트 NODE_PATH 를 기준으로 package.json 은 이동하지 않고, 다른 잡다한 설정파일들을 내부 폴더로 이동시켜 "인식" 하도록 하는것이 가능한지요? 또는 package.json 위치 기준으로 외부 경로( ../../) 에서도 가능할까요? 쭉... 찾아보고 있는데 자료가 없는것 같아 질문하게 되었습니다. 위 두가지 방법이 안된다면 가능한 방법이 있을까요? 읽어주셔서 감사해요!
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
mockReturnValue 질문
db 에러가 발생하면 next(error) 호출부분 질문드립니다. User.findOne부분을 mocking해서 reject를 반환하게 해서 에러처리하는 부분을 테스트하는것으로 이해를 하고 있습니다. user 컨트롤러에서 findOne이 reject를 반환하니, User.findOne({where: {id : req.user.id}}); 이 controller 코드에서 req.user.id가 필요없다고 생각하여 req 객체를 빈 객체로 만들고 테스트를 진행하니, req.user가 undefined라는 에러가 나오며 테스트가 실패하였습니다. 이 부분을 혹시 User.findOne 부분을 mocking 하더라도 findOne 함수 실행을 끝까지 하고 reject를 반환한다고 이해해도 되는것일까요? test("db 에러 발생하면 next(error)호출", async () => { const error = "error for test"; User.findOne.mockReturnValue(Promise.reject(error)); await addFollowing(req, res, next); // req = {}로 넣어도 되지 않을까? expect(next).toBeCalledWith(error); }); ////////////////////////////// exports.addFollowing = async (req, res, next) => { try { //질문대상인 User.findOne const user = await User.findOne({ where: { id: req.user.id } }); // req.user가 :id 사람을 팔로잉 한다. if (user) { await user.addFollowing(parseInt(req.params.id, 10)); res.send("success"); } else { res.status(404).send("no user"); } } catch (error) { console.error(error); next(error); } };
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
Post controller test 질문입니다.
exports.createPost = async (req, res, next) => { try { const post = await Post.create({ content: req.body.content, img: req.body.url, UserId: req.user.id, }); /////////////////// const hashtags = req.body.content.match(/#[^\s#]*/g); if (hashtags) { const result = await Promise.all( hashtags.map((tag) => { return Hashtag.findOrCreate({ where: { title: tag.slice(1).toLowerCase() }, }); }) ); ///////////// await post.addHashtags(result.map((r) => r[0])); } res.redirect("/"); } catch (error) { console.error(error); next(error); } }; 위 코드는 제가 post 라우터 unit test를 하기위해서 post를 생성하는 미들웨어를 controller로 분리한 코드입니다. 저기서 슬래시로 감싸진 부분을 어떻게 테스트를 해야할지 모르겠어서 질문드립니다. 또한 jest.mock("../models/post"); jest.mock("../models/hashtag"); const Post = require("../models/post"); const Hashtag = require("../models/hashtag"); 로 모델을 mocking하고 시작하였는데 User.hasMany called with something that's not a subclass of Sequelize.Model 라는 테스트 에러가 나와서, 왜 user model에 대한 부분이 에러로 나오는지 이해가 가지 않아서 질문드립니다. 여기 저기를 주석 처리한 결과 위 4줄의 코드가 에러의 원인인 것 같아 질문드립니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
sequelize로 데이터베이스 생성후 sql에서 수정시 충돌
예를 들어 sequelize로 timestamp를 생성하지 않고 sql에서 timestamp를 생성하면 sequelize를 사용시에 충돌이 일어나지 않나요 ? sequelize에서 지정하지 않은 컬럼이 더 생겨나는데
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
스트림 방식에서 read와 write 사용법 차이
제로초님 안녕하세요. 혼자서 코드를 실습해보다가 스트림 방식으로 createReadStream을 사용할 때와 createWriteStream을 사용법의 차이가 궁금해서 질문 드립니다! 혼자서 수업 코드를 작성해볼 때는 createReadStream처럼 createWriteStream도 writeStream.on('write', () => {}) 같은 이벤트 리스너 형식으로 코드를 작성해야한다고 생각했는데, 수업에서는 writeStream.write()로 작성하시더라구요! 왜 이렇게 사용 방식이 다른지 궁금합니다. 수업 중에 전자 같이 작성한 코드를 이벤트 리스너라고 하셨는데, 왜 read에는 이벤트 리스너 형식으로 작성하고 write에는 메서드로 작성하는 건가요? 그냥 외워야 하는 문법인건지 알고 싶습니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
req.file.location 질문입니다.
안녕하세요 node.js 수강중인 수강생입니다. 익스프레스로 SNS 서버만들기 강의중에 궁금한점이 있어서요 이미지 업로드후 미리보기를 구현할때 console.log(req.file); const originalUrl = req.file.location; const url = originalUrl.replace(/\/original\//, '/thumb/') res.json({ url, originalUrl: req.file.location }); 이렇게 적어주셨는데요 로그를 봐도 location 이란 속성이 없어서 error 가 나오는데 혹시 제가 빠트린게 있을까요? 아래 log 에는 location 소성이 없어서 undefinded 를 반환하고 있습니다. 일단은 res.json({url : `/img/${req.file.filename}` , originalUrl : `/img/${req.file.filename}` }); 이렇게 별도로 originalUrl 을 처리하고 있긴한데 location 속성이 안되서 여쭈어봅니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
외부 APP과의 연동 데이터 파싱시 Socket.io를 이용하면 될까요 ?
회원가입 로그인 등을 외부 앱에서 ( 유니티 ) 통신하여 받아오기 위해서는 socket으로 json 데이터를 받아서 string으로 해석하여 사용하면 될까요 ?? 아니면 더 나은 방법이 존재하는지 궁금합니다 !
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
REST API 서버 만들기 경로 문제입니다!
안녕하세요! 강의를 수강중인 학생입니다!강의를 보면서 서버를 작성해보다가 에러가 발생했습니다. 에러메시지를 보고 경로 문제인것을 확인했습니다. 그런데 같은 폴더 안에서 해당 파일을 readFile()로 불러왔는데 이름도 경로도 모두 맞는데 어떤 부분때문에 읽지를 못하는 걸까요?ㅠ 코드를 깃에서 받아서 그대로 실행했는데 파일을 읽어오지 못합니다ㅠ! 단순한 문제인것 같은데 번거롭게 해드려서 죄송합니다 ㅠㅠ 확인해주시면 감사하겠습니다!
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
회원가입 form data 궁금 사항이 생겨서 질문 드립니다
현재 제로초님이 짜신 코드를 따라 치면서 구성을 해보았는데 회원가입을 하는 경우에 네트워크 join에 form data로 password가 그대로 노출되는데 그렇게 회원가입을 진행해도 되나요 ? form data던 어느한 항목이던 찍히는 데이터는 무조건 hash화가 되어 있어야 되지 않나 궁금증이 생겨 질문드립니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
if / else를 전부 삼항 연산자로 대채해도 무방할까요?
제목 그대로 입니다. 제가 삼항연산자에 대해 알기 전까지는 조건이 참 혹은 거짓일 경우 if / else를 주로 써왔는데 삼항연산자는 최소 코드1줄로 이를 구현이 가능하니 즐겨쓰게 되었습니다. 그런데 이를 남용해도 될까요? is / else 만 쓴다던지 삼항연산자만 쓴다던지 그것은 개인의 코드 스타일인걸까요? 조현영님의 생각이 궁금합니다.
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
내보내는 객체의 콤마, 불러와서 변수를 사용하는 방식에 대해 질문 드립니다!
제로초님 안녕하세요. 강의를 듣고 코드를 실습해보다가 두 가지가 궁금해서 질문 드립니다. 1. 코드를 export로 내보내실 때 객체의 마지막 값까지 콤마를 작성하셨는데 저는 작성하지 않아도 실행이 되더라구요. 혹시 다른 문법적인 이유가 있으신건가요? 코드 예시 : module.exports = { odd, even, }; * 여기서 even 뒤 콤마를 질문드렸습니다! 2. 강의를 듣고 혼자 실습을 해보다가 변수를 조금 다르게 불러와서 사용했는데도 결과가 똑같이 나왔습니다. 저는 모듈에서 불러온 값을 바로 사용했는데, 제로초님께서는 변수에 담아서 사용하셨더라구요! 혹시 변수에 담아서 사용하는 것과 바로 사용하는 것의 차이가 있을까요? (제가 고민해봤을 때는 바로 사용하는 방식은 값을 한 번만 사용할 때 편할 것 같고, 변수에 담는 방식은 값을 자주 그리고 많이 사용하는 경우에 유용할 것 같은데 제초로님 의견이 궁금합니다!) 제로초님 코드 : const value = require('경로'); const odd = value.odd; const even = value.even; 제 코드 : const value = require('경로'); if ~ { console.log(value.odd); }
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
제로초님 프론트 담당이 따로 있다면 데이터 처리를 어떻게 해줘야 하나요 ?
저희가 현재는 로그아웃 로그인등 return문을 써서 조건에 해당하면 다른 url로 이동시키거나 에러처리 미들웨어로 보내는 형식으로 사용했었는데 프론트가 따로 있다고 해도 그런식으로 처리가 되나요 ? 아니면 서버쪽에서 프론트단으로 데이터를 넘겨주어야 되나요 ?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
nodebird ppt 파일을 혹시 어디서 받아 볼 수 있을까요?
안녕하세요 제가 강의를 중간에 멈추고 다시 중반부 부터 강의를 듣고 있습니다. nodebird 강의를 듣고 있는데 혹시 강의중에 제공되는 ppt 파일을 어디서 다운 받을 수 있을까요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
redis에 개념에 대해 질문있습니다.
로그인 후 쿠키에 세션ID가 저장되고 그 세션ID를 통해 redis에 접근해서 로그인 된 userId를 받아오는것으로 이해했는데요 제가 이해하고 있는 방식이 맞는건가요? 또 이게 맞다면 userId만 저장되어있을땐 userId로 다시 DB에 접근해서 유저정보를 가져와야할꺼 같은데 userId와 닉네임, 이름같은 화면에 필요한 정보를 redis에 같이 저장하는 방식은 문제가 있는걸까요?