49,500원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
시퀄라이즈 실습 강의 : CREATE 가 아니라 SELECT가 출력됩니다.
-C:\Users\ysm65\learn-sequelize>npm start> learn-seuqellize@0.0.1 start> nodemon app[nodemon] 3.0.1[nodemon] to restart at any time, enter rs[nodemon] watching path(s): .[nodemon] watching extensions: js,mjs,cjs,json[nodemon] starting node app.js3001 번 포트에서 대기중Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'users' AND TABLE_SCHEMA = 'nodejs'Executing (default): SHOW INDEX FROM users FROM nodejsExecuting (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'comments' AND TABLE_SCHEMA = 'nodejs'Executing (default): SHOW INDEX FROM comments FROM nodejs데이터베이스 연결 성공 --개정 3판 7장 내용 실습 중 마지막에 브라우저 창에 띄우는 것 까지 확인을 했지만 이름을 클릭 시 comment 내용이 뜨지 않아 하나씩 확인하면서 오류를 찾고 있습니다. 그 과정에서 3판 교과서 344page에서 소개된 내용과 다른 점을 찾았고 강사님과 다르게 CREATED가 아니라 SELECTED 로 뜨는 게 문제의 원인이지 않을까 생각하고 있습니다. 코드의 오타는 확인한 상황인데, 다른 원인이 어떤 게 있는지 고민을 하다가 이렇게 질문 글을 남깁니다. 어떻게 해결을 하는 게 좋을 지 조언을 구하기 위해서 질문을 남깁니다.
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
req.session 질문
16:19의 3번에서 세션 객체를 찾아서 req.session으로 만든다고 했었는데 이전에 처음에 로그인 했을 때 req.session으로 등록된 세션 객체(13:40의 6번)는 사라진 건가요?
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
강의 9.3 에서 passport.authenticate('local')이 호출되면 그 이후 passport.use( new LocalStrategy() ) 로 어떻게 흐름이 넘어가는지 모르겠습니다.
강의 9.3 에서 route/auth.js 파일에서 passport.authenticate('local')부분이 호출되는 것 까지는 이해가 됩니다. 근데 왜 authenticate에서 passport/localStrategy.js(전략코드) 가 실행이 되는건지 모르겠습니다. 'local'이라는 매개변수가 있다고 해도 localStrategy.js를 실행하라는 뜻은 아닐것인데 말이죠. 로그인 구현 흐름 자체는 이해가 되나 이쪽 부분이 어떤 논리로 이어지는건지를 모르겠습니다.
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
error처리 질문드립니다
error처리 질문드립니다.현재 라우터에는 /about1234는 없습니다. http://localhost:5000/about12344 여기입력해서 들어가면 강의처럼 err로 가서 asdasd가 나와야하는걸로 이해하고있습니다. 이렇게 나옵니다.asdasd가 나와야하는거 같은데 뭐가 잘못된건지 잘모르겠습니다.
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
multer를 사용해서 이미지 업로드할때 db(mysql)에 질문있습니다
uuid를 통해서 file의 원본이름을 변경해서 mysql의 image컬럼에 아래처럼 저장하고있습니다. \images\042c8bb1-e0fd-4005-85e9-68d7c587c02d.png홈페이지를 접속하면(로그인 안되면 로그인 페이지로 이동) 로그인했을때만(jwt 토큰을 발행해서 cookie에 보내주고) 홈페이지를 접속가능하게 하였습니다.홈페이지로 이동하면 이미지들을 볼수있도록 했습니다. 근데 이미지주소 복사하면 로그아웃해도 해당이미지가 나옵니다.제가 하고자는건 로그인했을때만 이미지보여주고 해당 이미지주소입력하면(로그인 안됐을때) 이미지가 안보이도록 하고싶은데 어떻게 해야할까요?db에 image컬럼에 원본이름만 저장하고 다른폴더에 이미지를 저장하고 db 인덱싱을통해서 이미지를 가져와서 이미지를 보여주도록 할려면 어떻게 해야할까요?(db인덱싱을통해(원본이름) 다른폴더에있는 해당이미지 가져오도록 하려면 어떻게해야할지 잘 모르겠습니다). 하나의 게시글에 다중이미지를 업로드하면 다중이미지를 보여주게 할려면 어떻게해야할까요? 현재는 db에 넣으면 num에(ai를통해서) 예를 들어 3장을 업로드하면 num이 1,2,3으로 생성되어서 이미지 경로도 각각 저장되고 홈페이지에서 하나하나씩 보입니다. 그럼 db에 저장을 어떻게해야하나요?사진을보면 밀리미터까지 똑같이 저장이 되는데 하나의 구분에 다중이미지의 주소를 넣을려면 어떻게해야할지요?... 이렇게해놔도 여기로 들어오지도 않고 바로 이미지주소로 검색하면 바로 이미지가 나옵니다.초보자라서 자세히 설명해주시면 감사하겠습니다.
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
POST처리후 페이지 이동
강의에서 설명하신 코드로 이것저것 해보다가 궁금한점이 생겼습니다!form태그에 사용자명 입력후 submit하면, POST요청이기 때문에 위의 코드가 실행되는데, 모든 작업처리 후에 어째서 다시 'localhost:8080/' 의 경로로 이동한 것인지 궁금합니다!!! 위처럼 작성하신 restFront.js 파일에도 따로 이동명령을 내린 것이 없는데, 어디서 설정할 수 있는 건가요?? POST요청 처리 후에 다른 경로로 이동하려면 어떻게 해야하는 것인지 알려주시면 감사하겠습니다!!
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
ejs, cjs 둘 중 무엇으로 코딩해야하나요?
ejs와 cjs 둘 중 express 프레임워크를 사용해서 프로그래밍을 하려면 어떤 방식을 추천하시나요?
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
노드버드 7장 오류 질문드립니다
app.jsconst express = require("express"); const cookieParser = require("cookie-parser"); const morgan = require("morgan"); const path = require("path"); const session = require("express-session"); const nunjucks = require("nunjucks"); const dotenv = require("dotenv"); const { sequelize } = require("./models"); dotenv.config(); const pageRouter = require("./routes/page"); const app = express(); app.set("port", process.env.PORT || 8001); app.set("view engine", "html"); nunjucks.configure("views", { express: app, watch: true, }); //force:true로 할 시 서버 재시작시 모든 데이터베이스 날리고 다시 시작, true는 개발용 sequelize .sync() .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(cookieParser(process.env.COOKIE_SECRET)); app.use( session({ resave: false, saveUninitialized: false, secret: process.env.COOKIE_SECRET, cookie: { httpOnly: true, secure: false, }, }) ); app.use("/", pageRouter); app.use((req, res, next) => { const error = new Error(`${req.method} ${req.url} no exist router.`); 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"), "waiting at the empty port."); }); index.js const Sequelize = require("sequelize"); const fs = require("fs"); const path = require("path"); const env = process.env.NODE_ENV || "development"; const config = require("../config/config.json")[env]; //설정 불러오기 const db = {}; const sequelize = new Sequelize( //불러온 설정을 시퀄라이즈와 연결하는 부분 config.database, config.username, config.password, config ); const basename = path.basename(__filename); //index.js fs.readdirSync(__dirname) .filter((file) => { return ( file.indexOf(".") !== 0 && // .으로 시작하는 파일은 숨김 파일이라는 의미 그래서 제외 file !== basename && //현재 파일인 index.js는 제외 file.slice(-3) === ".js" //마무리로 확장자가 .js인 파일만 불러오기 ); }) .forEach((file) => { const model = require(path.join(__dirname, file)); console.log(file, model.name); db[model.name] = model; //model.name은 model파일에서 class의 이름과 동일함 model.initiate(sequelize); }); Object.keys(db).forEach((modelName) => { //위에서 initiate할 때 같이 associate까지 하면 되지 않냐라고 할 수 있지만 associate는 모든 파일을 initiate해주고 해야함 console.log(db.modelName); if (db[modelName].associate) { db[modelName].associate(db); } }); module.exports = db; //시퀄라이즈와 그의 모델들은 자주 사용하니까 서로 묵어서 exports 해줌 언제어디서든 쓸 수 있게 .sync() ^TypeError: Cannot read properties of undefined (reading 'sync') at Object.<anonymous> (C:\Users\zzan9\OneDrive - dgu.ac.kr\nodejs\nodebirdSNS2\app.js:22:6) at Module._compile (node:internal/modules/cjs/loader:1267:14) at Module._extensions..js (node:internal/modules/cjs/loader:1321:10) at Module.load (node:internal/modules/cjs/loader:1125:32) at Module._load (node:internal/modules/cjs/loader:965:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) at node:internal/main/run_main_module:23:47Node.js v20.1.0 이런 오류가 뜨는데 왜 뜨는지 모르겠습니다.. 검색해도 답이 나오지 않길래 질문드립니다
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
sequelize 대신 mongoose를 사용하는 이유
12장 프로젝트는 sequelize로도 구현이 가능할 텐데, seqeulize 대신 mongoose를 사용하신 이유가 궁금합니다. mongoose를 사용하는 것이 더 좋은 성능을 보이나요?
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
부하테스트중 errors.ETIMEDOUT:
안녕하세요 json부하테스트중에 에러표시나서 방화벽들어가서 mysql포트 확인하고 3306설정했는데 안되서 포트80도해보고 했는데 에러표시만뜹니다https://binshuuuu.tistory.com/m/214제가 따라한 설정입니다
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
선생님 premium 해결했습니다
선생님 콘솔로그 쳐서 premium위치 찾아서req.user.Domains[5].type === 'premium' 했는데 true 나와서 해결했습니다 감사합니다 앞으로 콘솔로그 쳐서 하는 습관가져야겠습니다 정말 감사합니다 ^_^!!!
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
7.5 시퀄라이즈
안녕하세요 선생님 시퀄라이즈 강의를 듣는데 raw쿼리를 쓰는게 가능하더군요. spring + ibatis 로 주로 개발해와서 raw 쿼리가 익숙한데 실무에서는 시퀄라이즈 vs raw 쿼리 중에 어떤걸 많이 사용하는 편인가요..?
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
Premium 문의…!
선생님 어제 코드 감사합니다 아쉽게도 많이 배워야할것같아서 ㅠㅜ 혹시 제가 빠트린 코드가 있을까요 ? 아니면 다른부분 확인할 사항이 있을까요? 작성한 코드 올려드립니다nodebird-api -> middlewares-> index.jsconst jwt = require("jsonwebtoken"); //토큰을 검사하는 미들웨어 const rateLimit = require("express-rate-limit"); const User = require("../models/user"); const { Domain } = require("../models/"); const cors = require("cors"); exports.isLoggedIn = (req, res, next) => { if (req.isAuthenticated()) { next(); } else { res.status(403).send("로그인 필요"); } }; exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { // 패스포트 통해서 로그인 안했으면 next(); } else { const message = encodeURIComponent("로그인한 상태입니다."); res.redirect(`/?error=${message}`); //localhost:8001? error=메시지 } }; //토근검사 exports.verifyToken = (req, res, next) => { try { res.locals.decoded = jwt.verify( req.headers.authorization, process.env.JWT_SECRET ); return next(); } catch (error) { if (error.name === "TokenExpiredError") { return res.status(419).json({ code: 419, message: "토큰이 만료되었습니다.", }); } return res.status(401).json({ code: 401, message: "유효하지 않은 토큰입니다.", }); } }; const limiter = rateLimit({ widowMs: 60 * 1000, max: (req, res) => { if (req.user?.Domains[0]?.type === "premium") { return 10; } return 1; }, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: `1분에 ${ req.user?.Domains[0]?.type === "premium" ? "열" : "한" } 번만 요청 할 수 있습니다...`, }); }, }); exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id }, include: { model: Domain }, }); } req.user = user; limiter(req, res, next); }; exports.deprecated = (req, res) => { res.status(410).json({ code: 410, message: "새로운 버전이 나왔습니다. 새로운 버전을 사용하세요", }); }; exports.corsWhenDomainMatches = async (req, res, next) => { const domain = await Domain.findOne({ where: { host: new URL(req.get("origin")).host }, }); if (domain) { cors({ origin: true, Credential: true, })(req, res, next); //미들웨어 확장패턴 } else { next(); } }; nodebird-api -> routes -> v2.jsconst express = require("express"); const { verifyToken, apiLimiter, corsWhenDomainMatches, } = require("../middlewares"); const { createToken, tokenTest, getMyPosts, getPostsByHashtag, } = require("../controllers/v2"); const cors = require("cors"); const router = express.Router(); router.use(corsWhenDomainMatches); router.use( cors({ origin: true, credentials: true, //쿠키요청 }) ); router.post("/token", apiLimiter, createToken); router.get("/test", verifyToken, apiLimiter, tokenTest); router.get("/posts/my", verifyToken, apiLimiter, getMyPosts); // GET /v2/posts/hashtag/:title router.get("/posts/hashtag/:title", verifyToken, apiLimiter, getPostsByHashtag); module.exports = router;
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
10.6 재질문…!
exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ widowMs: 60 * 1000, max: user?.type === "premium" ? 10 : 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청 할 수 있습니다...", }); }, })(req, res, next); }; Api 프리미엄고객만 1분에 열번만요청할수있게 미들웨어 확장패턴으로만들었습니다 그런데 localhost:4000/myposts 접속해서 10 번이상새로고침해도 api가 제한이 안되고 제가작성한 게시글 목록만 뜹니다
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
10.6 사용량 제한 질문
nodebird-api 미들웨어 index.js 타입이 any로 떠서 프리미엄이 체크가 안되고 계속 제가 작성한 게시글정보만 뜹니다 사용량제한 어떻게 하나요? ㅠㅠ const jwt = require("jsonwebtoken"); const rateLimit = require("express-rate-limit"); const User = require("../models/user"); exports.isLoggedIn = (req, res, next) => { if (req.isAuthenticated()) { next(); } else { res.status(403).send("로그인 필요"); } }; exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { next(); } else { const message = encodeURIComponent("로그인한 상태입니다."); res.redirect(`/?error=${message}`); } }; exports.verifyToken = (req, res, next) => { try { res.locals.decoded = jwt.verify( req.headers.authorization, process.env.JWT_SECRET ); return next(); } catch (error) { if (error.name === "TokenExpiredError") { return res.status(419).json({ code: 419, message: "토큰이 만료되었습니다.", }); } return res.status(401).json({ code: 401, message: "유효하지 않은 토큰입니다.", }); } }; exports.apiLimiter = rateLimit({ windowMs: 60 * 1000, // 1분 max: 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, // 기본값 429 message: "1분에 한 번만 요청할 수 있습니다.", }); }, }); exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ widowMs: 60 * 1000, max: user?.type === "premium" ? 10 : 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청 할 수 있습니다...", }); }, })(req, res, next); }; exports.deprecated = (req, res) => { res.status(410).json({ code: 410, message: "새로운 버전이 나왔습니다. 새로운 버전을 사용하세요", }); };
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
10.6 사용량 제한 구현하기파트 질문
nodebird-api 미들웨어 index.js코드 const jwt = require("jsonwebtoken"); const rateLimit = require("express-rate-limit"); const User = require("../models/user"); exports.isLoggedIn = (req, res, next) => { if (req.isAuthenticated()) { next(); } else { res.status(403).send("로그인 필요"); } }; exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { next(); } else { const message = encodeURIComponent("로그인한 상태입니다."); res.redirect(`/?error=${message}`); } }; exports.verifyToken = (req, res, next) => { try { res.locals.decoded = jwt.verify( req.headers.authorization, process.env.JWT_SECRET ); return next(); } catch (error) { if (error.name === "TokenExpiredError") { return res.status(419).json({ code: 419, message: "토큰이 만료되었습니다.", }); } return res.status(401).json({ code: 401, message: "유효하지 않은 토큰입니다.", }); } }; exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ windowMs: 60 * 1000, max: user?.type === "premium" ? 1000 : 10, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청할 수 있습니다.", }); }, }); }; exports.deprecated = (req, res) => { res.status(410).json({ code: 410, message: "새로운 버전이 나왔습니다. 새로운 버전을 사용하세요", }); }; nodebird-api routes v2.js 코드 const express = require("express"); const { verifyToken, apiLimiter } = require("../middlewares"); const { createToken, tokenTest, getMyPosts, getPostsByHashtag, } = require("../controllers/v2"); const router = express.Router(); router.post("/token", apiLimiter, createToken); router.get("/test", verifyToken, apiLimiter, tokenTest); router.get("/posts/my", verifyToken, apiLimiter, getMyPosts); router.get("/posts/hashtag/:title", verifyToken, apiLimiter, getPostsByHashtag); module.exports = router; 프리미엄으로 클라이언트 비밀키 발급하고 프리미엄만 사용량제한 구현했는데 터미널에 GET/search/%EA%B3%A0%EC%96%91%EC%9D%B4 - - ms - - 이렇게 나오고 사이트로딩만 뜹니다 ㅜㅜ
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
화살표 함수 자동완성이 궁금합니다
안녕하세요 선생님강의를 보다보니 그림판에서 텍스트로 코딩을 하시는데 화살표함수 작성시 뒤에 구문이 자동으로 입력이 되던데 그림판에 어떤 플러그인을 설치하셨길래 이런 기능이 되는건지 궁금합니다.
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
[8.2] 몽고디비 설치 중 ECONNREFUSED 127.0.0.1:27017 오류 발생
안녕하세요, Mac (M2 pro) mongoDB 설치 중 오류가 발생하여 질문 드립니다.brew install 통해서 mongodb-community, mongosh 설치하였고, 관리자 계정 생성 및 인증 설정까지는 문제 없었다가생성한 관리자 계정으로 접속하려 하니 오류가 발생했습니다.$ mongosh admin -u [이름] -p [비밀번호] Current Mongosh Log ID: 649446c2b1a5e49aba3e9a36 Connecting to: mongodb://<credentials>@127.0.0.1:27017/admin?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.1 MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017설치에 오류가 있나 싶어서 uninstall 후 재설치를 했을 때는 mongosh 만 입력해도 아래와 같은 오류 메세지가 발생했습니다.$ mongosh Current Mongosh Log ID: 64944aeec3f1dc59c1744436 Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.1 MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017 5버전으로도 설치해봤는데도.. 동일하게 오류가 자꾸 발생하네요ㅠ 이유를 모르겠습니다....
- 해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
강의자료 ppt는 어디서 받을 수 있나요?
안녕하세요 11강에서 강의자료 ppt 파일을 올려주신다고 했는데 어디서 다운로드 받을수 있나요?
- 미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
9장 추가 과제 관련 질문
안녕하세요. 9장강의를 듣고 추가 과제를 시도해보던 중 궁금증이 생겨 질문드립니다.스스로 해보기 -> 팔로잉 끊기에서 destory와 라우터를 사용하라고 안내해주셨는데 user자체를 삭제하는 것이 아닌 중간테이블(follow)에서 해당 로우만 삭제하는 방법이 따로 있나요? if (user) { const a = await user.destroy({ where: { Followings: { followerId: req.params.id } }, });위와 같이 방법을 여러가지로 시도해보았지만 계속해서 유저 삭제(탈퇴)가 되는 상황이라 도움주시면 감사하겠습니다..!