수강이 제한됩니다.
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
게시글 좋아요 누르기 및 좋아요 취소하기 질문입니다
계속 고민하다 이렇게 질문을 남깁니다. 우선 제가 시도한 방법부터 알려드리자면 db.User.belongsToMany(db.Post, { through: 'Like'}); db.Post.belongsToMany(db.User, { through: 'Like', as: 'Liker' }); User과 Post모델 사이에 M:N관계를 정립합니다 passport.deserializeUser((id, done) => { User.findOne({ where: { id }, include: [{ model: User, attributes: ['id', 'nick'], as: 'Followers', }, { model: User, attributes: ['id', 'nick'], as: 'Followings', }, { model: User, attributes: ['id', 'nick'], as: 'Liker', }], }) .then(user => done(null, user)) .catch(err => done(err)); }); 그 다음에 세션에 로그인하면 팔로우/팔로잉 목록과 함께 좋아요 목록을 req.user에 저장합니다 res.locals.LikeIdList = req.user ? req.user.Liker.map(l => l.id) : []; page.js 에 req.user로 받은 Liker배열을 id만 따로 배열로 만들어 전역변수 LikeIdList에 넣습니다 {% if not LikeIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="like">좋아요</button> {% elif LikeIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="not-like">좋아요취소</button> {% endif %} 그 후 main.html에 이미지div밑에 좋아요와 좋아요 취소 버튼을 만들었습니다. 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('succes'); } catch (error) { console.log(error); next(error); } }) router.delete('/:id/not-like', async (req, res, next) => { try { const post = await Post.findOne({ where: { id: req.params.id } }); await post.removeLiker(req.user.id); res.send('succes'); } catch (error) { console.log(error); next(error); } }) 마지막으로 이벤트리스너를 활용하여 서버로 url을 보내고 라우터에서 처리하는 코드를 만들었습니다. 그 후 코드를 실행하고 로그인을 하고 나니 User is associated to User multiple times. To identify the correct association, you must use the 'as' keyword to specify the alias of the association you want to include. 로그인 하자마자 에러가 뜹니다. 해석해보자면 User과 User이 여러번 열결이 되니 include를 쓸 때 'as'를 써라입니다 하지만 위에 보시다시피 전 as를 확실히 썼습니다. 여기서 네트워크를 봤습니다 요청 URL: http://localhost:8001/ 요청 메서드: GET 상태 코드: 500 Internal Server Error 원격 주소: [::1]:8001 리퍼러 정책: strict-origin-when-cross-origin GET / 라우터에 에러가 발생했구나 싶어서 코드를 살펴보니 router.get('/', async (req, res, next) => { try { const posts = await Post.findAll({ include: { model: User, attributes: ['id', 'nick'], }, order: [['createdAt', 'DESC']], }); console.log(posts); res.render('main', { title: 'NodeBird', twits: posts, }); } catch (err) { console.log(err) next(err); } }); 문제가 없어 보입니다. 사실 이전까지 아무런 문제가 없는 코드라서 제 머릿속을 점점 미궁으로 빠집니다. 아마 저 include코드에서 뭔가 발생한거 같은데 제 짧은 지식으로는 아무리 봐도 문제가 없어 보입니다. 제 방식이 어디가 잘못된건지 알려주세요
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
res.render 쓰면서 url 안보이게 하는 방법 질문드립니다
선생님 안녕하세요 res.render 로 views 폴더의 파일을 웹페이지에 보여주되, url을 안보이게 만드는 방법에 대해 질문드리고 싶습니다 보안적으로 중요한 페이지는 url을 안보이게 하는 방법이 더 좋을 것 같다는 생각이 들었습니다 공식문서를 찾아보니 res.render를 post로 보내주는 방법을 찾지는 못했습니다 스택오버플로우에서는 res.render를 post로 못사용해서, res.redirect 를 쓰라고 나왔습니다 혹시 이 방법 말고 다른 방법도 있는지 질문드리고 싶습니다 일반적으로는 넌적스의 forward나 include 또는 ajax를 많이 사용하는지 질문드리고 싶습니다 항상 좋은 가르침을 주셔서 감사드립니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
static 미들웨어에 대한 질문입니다
노드버드를 만들다 궁금증이 생겨 질문합니다 저희가 static을 배울때 분명 지정된 폴더의 정적인 파일들을 브라우저에서 접근할 수 있도록 하는 기능이 있습니다 그리고 파일이 없으면 next를 호출하지만 파일이 있으면 응답으로 파일을 보내고 다음 미들웨어를 실행하지 않습니다 제 궁금증은 app.js 파일의 app.use(express.static(경로는'public')); 이 코드에서 public폴더에는 main.css가 있고 그렇다면 css를 보내고 다음 미들웨어를 실행하지 않는 것이 맞지 않나요? 네트워크로 찾아보니 로그인 전에는 views폴더의 layout.html이 실행되던데 이유가 궁금합니다. 또 로그인 이후에도 main.css가 네트워크에 있던데 왜 static 아래에 있는 미들웨어가 실행되는 것인가요? 경로가 uploads폴더인 경우도 마찬가지로 왜 요청경로에 파일이 있으면서도 왜 다음 미들웨어가 실행되는 건가요?
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
User.findAll 질문드립니다
강사님 안녕하세요이건 기본적인 질문 같아서 질문드리기가 좀 그래서..계속 찾아봤는데, 해결이 안되어서 봐주시면 감사하겠습니다의외로 간단한 문제 같은데 잘 모르겠어서요 User를 가져와서 User.create({}) 는 성공했습니다 그런데, 30행처럼 User.findAll({ attributes: ['name', 'age'], }); 이렇게 적어줘도 콘솔창에, 레코드들이 안나타나더라구요 그렇지만, 터미널을 확인해보면 확실히 select 문은 작동했습니다select문이 실행되어도 콘솔창이나, 터미널에서 레코드들을 확인할 수 없는지 질문드리고 싶습니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
시퀄라이즈 모델 생성 질문드립니다
강사님 안녕하세요항상 좋은 강의 들려주셔서 감사합니다 강의를 수강하며 코드를 따라해보니 실행도 잘되고 테이블도 잘 생성되었습니다 그런데 제가, 코드를 변형하고 싶었습니다user.js에 기본키 역할을 하는 email 컬럼(필드)을 넣고 싶었습니다 기본키로 id가 자동 생성된다고 말씀해주셨는데, 저는 email 컬럼(필드)를 만들어서 기본키 역할을 하게 만들고 싶었습니다그래서 추가했더니 에러가 생겨서 혹시 어디가 문제인지 봐주시면 정말 감사하겠습니다(스택오버플로우를 찾아봐도 아직 실력이 부족해서 원하는 해답을 찾기 어려웠습니다) 1단계. 워크 벤치에서 테이블을 다시 삭제했습니다 2단계는 user.js를 아래처럼 고쳤습니다 3단계는 comment.js를 고쳤습니다 4단계 app.js를 실행했습니다 그러자 에러가 생겼습니다 콘솔창 메시지를 그대로 복붙했습니다 C:\Program Files\nodejs\node.exe .\app.js 3001 번 포트에서 대기 중 Executing (default): CREATE TABLE IF NOT EXISTS `users` (`email` VARCHAR(30) , `name` VARCHAR(20) NOT NULL UNIQUE, `age` INTEGER UNSIGNED NOT NULL, `married` TINYINT(1) NOT NULL, `comment` TEXT, `created_at` DATETIME NOT NULL, PRIMARY KEY (`email`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; Executing (default): SHOW INDEX FROM `users` FROM `nodejs` Executing (default): CREATE TABLE IF NOT EXISTS `comments` (`id` INTEGER NOT NULL auto_increment , `comment` VARCHAR(100) NOT NULL, `created_at` DATETIME, `commenter` VARCHAR(30), PRIMARY KEY (`id`), FOREIGN KEY (`commenter`) REFERENCES `users` (`email`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; Error at Query.run (c:\실험\learn_sequelize\node_modules\sequelize\lib\dialects\mysql\query.js:52:25) at c:\실험\learn_sequelize\node_modules\sequelize\lib\sequelize.js:313:28 at processTicksAndRejections (node:internal/process/task_queues:96:5) at async MySQLQueryInterface.createTable (c:\실험\learn_sequelize\node_modules\sequelize\lib\dialects\abstract\query-interface.js:94:12) at async Function.sync (c:\실험\learn_sequelize\node_modules\sequelize\lib\model.js:937:5) at async Sequelize.sync (c:\실험\learn_sequelize\node_modules\sequelize\lib\sequelize.js:377:9) {name: 'SequelizeDatabaseError', parent: Error: Referencing column 'commenter' and refe…lumn 'email' in foreign key constraint 'comm…, original: Error: Referencing column 'commenter' and ref…umn 'email' in foreign key constraint 'comm…, sql: 'CREATE TABLE IF NOT EXISTS `comments` (`id` IN…LT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;', parameters: {…}, …} 아래는 전체 소스코드 입니다 app.js 소스코드입니다 const express = require('express'); const path = require('path') const morgan = require('morgan') const nunjucks = require('nunjucks'); const { sequelize } = require('./models') const app = express(); app.set('port', process.env.PORT || 3001); app.set('view engine', 'html'); nunjucks.configure('views', { express: app, watch: true, }); sequelize.sync({force: false}) .then(()=>{ console.log('데이터베이스 연결 성공'); }) .catch((err)=>{ console.error(err); }); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); // app.use('/', indexRouter); // app.use('/users', usersRouter); // app.use('/comments', commentsRouter); app.use((req, res, next) => { const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`); error.status = 404; next(error); }); // app.use((err, req, res, next) => { res.locals.message = err.message; res.locals.error = process.env.NODE_ENV !== 'production' ? err : {}; res.status(err.status || 500); res.render('error'); });// app.listen(app.get('port'), () => { console.log(app.get('port'), '번 포트에서 대기 중'); }); //3001번 포트 대기 중 user.js 소스코드입니다 /** * ./models/user.js */ const Sequelize = require('sequelize'); module.exports = class User extends Sequelize.Model { static init(sequelize) { return super.init({ email: { type: Sequelize.STRING(30), primaryKey: true, }, name: { type: Sequelize.STRING(20), allowNull: false, unique: true, }, age: { type: Sequelize.INTEGER.UNSIGNED, allowNull: false, }, married: { type: Sequelize.BOOLEAN, allowNull: false, }, comment: { type: Sequelize.TEXT, allowNull: true, }, created_at: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.NOW, }, }, { sequelize, timestamps: false, underscored: false, modelName: 'User', tableName: 'users', paranoid: false, charset: 'utf8', collate: 'utf8_general_ci', }); } static associate(db) { db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'email' }); } }; comment.js 소스코드입니다 /** * ./models/comment.js */ const Sequelize = require('sequelize'); module.exports = class Comment extends Sequelize.Model { static init(sequelize) { return super.init({ comment: { type: Sequelize.STRING(100), allowNull: false, }, created_at: { type: Sequelize.DATE, allowNull: true, defaultValue: Sequelize.NOW, }, }, { sequelize, timestamps: false, modelName: 'Comment', tableName: 'comments', paranoid: false, charset: 'utf8mb4', collate: 'utf8mb4_general_ci', }); } static associate(db) { db.Comment.belongsTo(db.User, { foreignKey: 'commenter', targetKey: 'email' }); } }; index.js 소스코드입니다 const Sequelize = require('sequelize'); const User = require('./user'); const Comment = require('./comment'); const env = process.env.NODE_ENV || 'development'; //환경변수 NODE_ENV 또는 'development' 로 하겠다 const config = require(__dirname + '/../config/config.json')[env]; const db = {}; const sequelize = new Sequelize(config.database, config.username, config.password, config); db.sequelize = sequelize; db.Sequelize = Sequelize; db.User = User; db.Comment = Comment; User.init(sequelize); Comment.init(sequelize); User.associate(db); Comment.associate(db); module.exports = db; 구글링을 해봐도 원인을 잘 모르겠어서 가르쳐주시면 정말 감사하겠습니다 읽어주셔서 감사합니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
지정된 경로를 찾을 수 없습니다.
cli를 치니 이런 에러가 뜹니다.. 경로를 설정해야 될것 같은데 어디서 설정해 줘야 되나요 ?? 패키지 json은 이렇게 설정 되어 있습니다.
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
혹시나 해서 올립니다.
이런 에러 뜨시는 분들, 해당 경로로 이동한 뒤 index.js파일 우클릭 -> 속성 -> 일반 -> 연결 프로그램 란에 변경 버튼 클릭 -> node.js로 바꿔주세요 스택오버 플로우 출처 남깁니다. https://stackoverflow.com/questions/70045198/windows-script-host-error-invalid-character-code800a03f6-source-microsoft
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
안녕하세요. 7장 시퀄라이즈 M:N 질문이 있습니다!
위와 같이 시퀄라이즈를 통해 관계를 설정했습니다. Post.belongsToMany(Tag, { through: "PostTag", foreignKey: "PostId" }); Tag.belongsToMany(Post, { through: "PostTag", foreignKey: "TagId" }); 여기에서 PostTag 모델도 정의했는데 이렇게 총 시퀄라이즈를 통해 N:M 관계를 정의할 때 3개의 모델을 정의하는게 맞나요? 그리고 Post.findAll({ include:[{ model:PostTag // .. 조건들 },{ model:Tag}]}); 3개의 테이블에 접근할 때 이렇게 접근하는 게 맞을까요
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
미들웨어 확장으로 아예 기능이 달라지기도 하는지 질문드리고 싶습니다
강사님 안녕하세요 다음 진도로 넘어가겠다는 말씀을 드리고 dotenv 실습 중이었는데 또 session에서 미들웨어 확장을 한번 시도하다가 아예 기능이 변하는 걸 발견해서 궁금한 점이 생겨서 질문드리고 싶습니다 아래에 session을 미들웨어 확장한 코드(빨간색)와 확장하지 않은 코드(초록색)가 있습니다 위쪽의 확장버전은 세션은 생기지만 로그인이 안되었고 아래쪽의 미확장버전은 세션도 생기고 로그인이 잘되었습니다 이유를 분석해봤습니다 session 미들웨어를 확장한 경우 87행 리다이렉션 뒤에 다시 28행으로 가서 세션을 새로 세팅했습니다 그래서 req.session.name 이 소멸되어서 로그인이 안되었습니다 반면에 session 미들웨어를 확장하지 않은 경우에는 41행의 session 미들웨어는 처음 딱 1번만 호출되고 87행 리다이렉션 다음에 90행 app.get('/') 으로 이동했습니다 그래서 req.session.name이 소멸되지 않았습니다 미들웨어 확장법을 static 가르쳐주실 때 배운 건데 session 미들웨어도 한번 확장해봤는데, 혹시 제가 잘못 확장한건지 질문드리고 싶습니다 구글링도 해봤는데, (req,res,next)=>{미들웨어(req,res,next)} 로 사용하는 것 같아서요 session 미들웨어에서 확장은 금지인지 질문드리고 싶습니다 긴 질문을 읽어주셔서 고맙습니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
express session 하나만 더 질문드리고 싶습니다
강사님 안녕하세요 항상 많은 질문을 받아주셔서 감사합니다 session 관련해서 이것만 더 질문드리고 다음 진도로 넘어가려고 하는데 가르쳐주시면 정말 감사하겠습니다 express session 미들웨어를 사용하고나서, 클라이언트에게 쿠키가 생성되는 시기에 대해 질문드리고 싶습니다 그 다음은 아이디를 입력하고 로그인 버튼을 눌렀습니다 그래서 실험을 해봤습니다 67행을 주석처리하자, 클라이언트는 세션쿠키를 받지 못했습니다 그래서 내린 결론은 req.session.name 에 값을 입력 후 res. 함수를 사용하면 클라이언트에게 쿠키가 생긴다는 결론에 도달했습니다이런 식으로 접근하는 걸 바꿔보기로 말씀드렸었는데 구글링으로 원하는 정보를 찾지 못해서 또 이렇게 접근하게 되었습니다 혹시 제가 내린 결론이 잘못된 건지 봐주시면 정말 감사하겠습니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
기 구축된 DBMS에서 ORM model을 생성할 수 있는지?
안녕하세요. 제로초님. 기 구축된 MySQL DBMS 스키마로부터 Sequelize model, 즉 js 소스 형태의 table model들을 생성하는 방법이 있습니까? 아니면, 기능 호환성을 100% 맞추기 어렵기 때문에, 사실상 수동으로 한땀 한땀 model 코딩을 해야 할까요? 이것은 아마도 legacy 시스템에서 db는 그대로 두고 프로그램 부분을 ORM 활용하는 것으로 재작업하는 프로젝트에서 요구되는 사항일 것 같습니다. 감사합니다.
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
express session 설정 질문드립니다
강사님 안녕하세요 질문드리기 전에, http 쿠키와 세션 강의를 먼저 복습했습니다 아래처럼 정리했습니다 서버측에서 클라이언트를 구분하기 위해 보내는 게 쿠키 쿠키의 중요한 정보를 클라이언트의 브라우저로 보내면 보안위험이 있고 그래서 쿠키의 중요한 정보는 서버에서 갖고, 클라이언트에게 안보내서, 브라우저에서는 중요정보는 못알아내도록 서버에서 관리하는 게 세션 예를 들면 4장의 session.js에서는 쿠키의 name 대신, 현재 시간을 보낸다 라고 복습하고 http 세션 코드도 복습했습니다 그리고나서 cookie2.js를 익스프레스 코드로 변환시킨 코드를이번에는 session을 이용한 코드로 변경해보려고 했습니다 const express = require('express'); const path = require('path'); const { nextTick, rawListeners } = require('process'); const morgan = require('morgan'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const session = require('express-session'); const { connect } = require('http2'); const app = express(); app.set('port', process.env.PORT || 3000); //'port' 라는 속성에 포트번호 3000번을 설정합니다. //서버의 포트를 3000번으로 지정합니다. app.use(morgan('dev')); //app.use(morgan('dev')); //쿠키를 객체화 시킵니다. app.use(cookieParser('zerochopassword')); //cookieparser를 사용하기 위해 //app.use('/',express.static(__dirname, 'kkk')) app.use(express.static(path.join(__dirname, 'kkk'))) app.use(express.json()); app.use(express.urlencoded({extended: true})); //post요청에 의한 req.body를 사용하기 위해서 console.log(path.join(__dirname, 'kkk')) //login 경로의 경우입니다. app.get('/login', (req, res, next) => { req.cookies // 쿠키 객체화 const expires = new Date(); expires.setMinutes(expires.getMinutes() + 5); res.cookie('name', encodeURIComponent(req.query.name),{ expires: expires, httpOnly: true, path: '/', }) // app.use(session({ // name: 'connect.sid', // resave: false, // saveUninitialized: false, // secret: 'zerochopassword', // cookie:{ // expires: expires, // httpOnly: true, // path: '/', // }, // })); // req.session.id = req.query.name; res.redirect('/'); }); app.get('/', (req,res)=>{ console.log("req.url "+req.url); if(req.cookies.name)//name이라는 쿠키가 있는 경우입니다. { //res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); res.send(`${req.cookies.name}님 안녕하세요`);//쿠키에 넣은 이름이 웹페이지에 출력됩니다 } else{ //로그인도 아니고, 쿠키도 없는 경우입니다. //next(createError(404)); try { // console.log("진입"); //res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); //익스프레스에서는 writeHead를 쓰면 안된다 에러가 생긴다 //res.send( ) 할 때 이미 자동으로 res.status().send() 이런 식으로 헤더를 설정해준다 //res.sendFile(path.join(__dirname, '/cookie2.html'));//cookie2.html 파일을 클라이언트에게 보내준다 //console.log(err.status) console.log("진입"); res.setHeader('Content-Type', 'text/html'); //익스프레스에서는 writeHead를 쓰면 에러가 생긴다 그러므로 setHeader를 써라 res.sendFile(path.join(__dirname, 'cookie2.html')); //cookie2.html 파일을 클라이언트에게 보내준다 } catch (err) { // res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' }); // res.end(err.message); next(err); //콜백함수에 err 라는 인자가 있는 app.use로 이동한다 } } }); // app.get('/:id',(req,res)=>{ // console.log("req.url "+req.url); // console.log("req.params.id "+req.params.id); // res.send(`Hello ${req.params.id}`); // }) //아래는 에러처리입니다. app.use((req,res,next)=>{ // 찾는 경로가 없으면 get을 다 지나서 use로 온다 console.log("req.url "+req.url); next(createError(404)); //찾는 경로가 없으면 404처리 }) app.use((err,req,res,next)=>{ // /favicon.ico도 여기로 간다 에러도 여기로 간다 console.log("req.url "+req.url); console.log(res.locals.message); res.locals.message = err.message; res.locals.error = req.app.get(`env`) === `development` ? err:{}; console.log(err.status) res.status(err.status ||500).send(err.message); }); app.listen(3000, () => { console.log(app.get('port'), '번 포트에서 서버 대기 중입니다!'); }); 저는 아래처럼 변경해봤습니다 공식문서도 참고했습니다 프로덕션 환경의 Express를 위한 보안 우수 사례 (expressjs.com) 그런데 로그인을 하면 세션이 안생겨서 혹시 제가 잘못 알고있는 부분을 가르쳐주시면 감사하겠습니다 + 그리고 63행과 66행에서 req.cookies.name을 req.session.id로 변경해도 에러가 해결이 안되더라구요
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
express.static 질문드리고 싶습니다
강사님 안녕하세요 현재 폴더에 kkk라는 폴더를 만들었습니다 kkk 폴더 내에도 필요한 파일들을 채웠습니다 여기서 제가 실험을 해봤습니다 kkk 폴더에서 cookie2.html을 지웠습니다 그런데 이렇게 하고 실행해봤더니 cookie2.html을 잘 불러왔습니다 혹시 제가 잘못 이해하고 있는 부분이 있는 것 같아서 질문드리고 싶습니다 가르쳐주시면 감사하겠습니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
express body-parser에 대해 질문드리고 싶습니다
강사님 안녕하세요 body-parser에 대해 질문드리고 싶습니다 소스코드는 지난번에 질문드렸던 소스코드에서 bodyParser를 이용하는 소스코드를 추가했습니다 const express = require('express'); const path = require('path'); const { nextTick, rawListeners } = require('process'); const morgan = require('morgan'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const app = express(); app.set('port', process.env.PORT || 3000); //'port' 라는 속성에 포트번호 3000번을 설정합니다. //서버의 포트를 3000번으로 지정합니다. //app.use(morgan('dev')); //쿠키를 객체화 시킵니다. app.use(cookieParser()); //cookieparser를 사용하기 위해 app.use(express.json()); app.use(express.urlencoded({extended: true})); //post요청에 의한 req.body를 사용하기 위해서 //login 경로의 경우입니다. app.get('/login', (req, res, next) => { req.cookies // 쿠키 객체화 a=req.query; b=req.params; c=req.body; console.log("req.query "+req.query); console.log("req.params "+req.params); console.log("req.body "+req.body); console.log("req.query.name "+req.query.name); console.log("req.params.name "+req.params.name); console.log("req.body.name "+req.body.name); // expires.setMinutes(expires.getMinutes() + 5); const expires = new Date(); expires.setMinutes(expires.getMinutes() + 5); res.cookie('name', encodeURIComponent(req.query.name),{ expires: expires, httpOnly: true, path: '/', }) res.redirect('/'); }); app.get('/', (req,res)=>{ console.log("req.url "+req.url); if(req.cookies.name)//name이라는 쿠키가 있는 경우입니다. { //res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); res.send(`${req.cookies.name}님 안녕하세요`);//쿠키에 넣은 이름이 웹페이지에 출력됩니다 } else{ //로그인도 아니고, 쿠키도 없는 경우입니다. //next(createError(404)); try { // console.log("진입"); //res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); //익스프레스에서는 writeHead를 쓰면 안된다 에러가 생긴다 //res.send( ) 할 때 이미 자동으로 res.status().send() 이런 식으로 헤더를 설정해준다 //res.sendFile(path.join(__dirname, '/cookie2.html'));//cookie2.html 파일을 클라이언트에게 보내준다 //console.log(err.status) console.log("진입"); res.setHeader('Content-Type', 'text/html'); //익스프레스에서는 writeHead를 쓰면 에러가 생긴다 그러므로 setHeader를 써라 res.sendFile(path.join(__dirname, 'cookie2.html')); //cookie2.html 파일을 클라이언트에게 보내준다 } catch (err) { // res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' }); // res.end(err.message); next(err); //콜백함수에 err 라는 인자가 있는 app.use로 이동한다 } } }); // app.get('/:id',(req,res)=>{ // console.log("req.url "+req.url); // console.log("req.params.id "+req.params.id); // res.send(`Hello ${req.params.id}`); // }) //아래는 에러처리입니다. app.use((req,res,next)=>{ // 찾는 경로가 없으면 get을 다 지나서 use로 온다 console.log("req.url "+req.url); next(createError(404)); //찾는 경로가 없으면 404처리 }) app.use((err,req,res,next)=>{ // /favicon.ico도 여기로 간다 에러도 여기로 간다 console.log("req.url "+req.url); console.log(res.locals.message); res.locals.message = err.message; res.locals.error = req.app.get(`env`) === `development` ? err:{}; console.log(err.status) res.status(err.status ||500).send(err.message); }); app.listen(3000, () => { console.log(app.get('port'), '번 포트에서 서버 대기 중입니다!'); }); 그런데 name 이 Hello를 잡아주는 것은 req.query.name 은 잡아줬는데 req.body.name 은 잡아주지 못했습니다 그 이유가 궁금해서, 공식문서도 찾아보고 강사님의 POST PUT DELETE 요청 보내기 강의도 다시 찾아봤습니다 [리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지 - 인프런 | 학습 페이지 (inflearn.com) 익스프레스 body-parser의 req.body 는 axios.post('경로',{ name }) 이런 식으로 axios.post의 2번째 인자만 받아주는 건가 싶었습니다 질문 드리기 전에 좀 더 충분히 찾아보기 위해서 WEB3 - Express - 9.1. 미들웨어의 사용 - body parser - YouTube생활코딩님 채널의 유튜브 강의도 참고해봤는데, axios.post('경로',{ name }) 로 보내주지 않아도 form 태그로 전송해준 속성들은 다 받아주는 것 같았습니다 혹시 req.query.name은 hello을 받아주는데 req.body.name은 hello를 못받아주고 req.body는 빈 객체가 되는 이유가 이해하기 어려워서 가르쳐주시면 감사하겠습니다
- 해결됨[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
res.send와 favicon에 대해 질문드리고 싶습니다
강사님 안녕하세요 약간 햇갈리는 부분이 있어서 질문드리고 싶습니다 http://localhost:3000/ 을 입력하면 req.url이 처음에는 /이고 마지막에는 /favicon.ico 가 되어서요 그래서 제가 63행에 저 라우터를 넣으면 req.url이 처음에는 / 일 때, cookie2.html이 웹페이지에 나온 다음에 마지막에는 /favicon.ico 때문에 웹브라우저 페이지에는 Hello favicon 으로 변경될 줄 알았습니다 그런데, 웹페이지가 안바뀌고 cookie2.html 이 그대로 유지되는 이유가 이해가 어려워서 질문드리고 싶습니다 가르쳐주시면 감사하겠습니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
req.get('host)
origin 값을 프론트나 서버에서 안넣어줘도 host는 항상 찾을수 있으니 req.get('host')하면 바로 호스트네임이 찾아지던데 굳이 origin으로 찾은 다음에 url.parse해줘서 host를 찾는 이유가 있으신가요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
노드, vs 버전
안녕하세요 현재 시점에서 LTS 최신버전은 16.15.0이고, VS는 8.10 버전인데 이것들을 다운 받아도 강연 따라가는데 오류나 문제가 발생하진 않을까요? 참고로 저는 맥북사용자이고, 이번에 본격적으로 강사님 강연 들으면서 node 열심히 공부해보려고 합니다 :) 그런데 맥북이 처음이라 예전버전 찾아서 다운받는게 아직 익숙치 않아서 이렇게 질문 남깁니다!! 감사합니다
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
web socket 프론트엔드 코드 질문
views/index.html 코드에서, WebSocket 인스턴스를 만들어 서버와 통신하는 코드에서, WebScoket을 따로 require나 import를 안했는데 new WebSocket코드를 사용할 수 있는데, 어떻게 가능한것일까요? <views/index.html> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>GIF 채팅방</title> </head> <body> <div>F12를 눌러 console 탭과 network 탭을 확인하세요.</div> <script> const webSocket = new WebSocket("ws://localhost:8005"); webSocket.onopen = function () { console.log("서버와 웹소켓 연결 성공!"); }; webSocket.onmessage = function (event) { console.log(event.data); webSocket.send("클라이언트에서 서버로 답장을 보냅니다"); }; </script> </body> </html>
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
라우터, 미들웨어 용어
app.get('/', (req, res) => {}); 이 코드에서 콜백함수 부분을 미들웨어(요청에 대한 처리, 응답을 하는 역할?)라고 부르고, get() 메서드를 라우터라고 보면 되나요?
- 미해결[리뉴얼] Node.js 교과서 - 기본부터 프로젝트 실습까지
순환참조를 쓰려면 잘 알고 써야한다고 하셨는데
실무에서 특수한 경우에 순환참조를 쓸 일이 있긴 하니까 그렇게 말씀하신 것 같은데, 그런 상황이 전혀 떠오르지가 않아요 혹시 간략한 예라던가 순환참조를 쓰는 이유 같은게 있을까요?