• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 Node.js, Express 게시판 유저간 채팅기능 만들기 2에서 ObjectId 적용 시 발생하는 에러

유저간 채팅기능 만들기 2에서 ObjectId 적용 시 발생하는 에러

4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 글쓴이
  • #56138

    정윤식
    참가자
    선생님 안녕하세요 선생님의 강의를 듣고 있는 한 학생입니다. 
    우선 질문하기에 앞서 좋은 강의를 남겨주셔서 따라가기에 많은 도움이 되고 있어 감사하다는 점 말씀드립니다.
    이렇게 글을 쓰게 된 이유는 다름이 아니라 채팅기능 만들기 2 강의에서 chatroom을 post할 때 자꾸 발생하게 되는 에러 때문인데요
    (아래는 server.js에 있는 해당코드)
    
    (server.js 상단) 
    const {ObjectId} = require('mongodb'); 
    
    (server.js 하단)
    app.post('/chatroom', 로그인했니, function(요청, 응답){
        
        var 저장할거 = {
            title : '무슨무슨채팅방',
            member : [ObjectId(요청.body.target), 요청.user._id],
            date: new Date()
        }
        db.collection('chatroom').insertOne(저장할거).then(function(결과){
            응답.send('저장완료')
        })
    })
    에서 요청.body.target을 ObjectId로 감쌀 경우
    
     Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
        at new ObjectID (C:\Users\user\Desktop\todoapp\node_modules\bson\lib\bson\objectid.js:59:11)
        at ObjectID (C:\Users\user\Desktop\todoapp\node_modules\bson\lib\bson\objectid.js:40:43)
        at C:\Users\user\Desktop\todoapp\server.js:228:19
        at Layer.handle [as handle_request] (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\layer.js:95:5)
        at next (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\route.js:144:13)
        at 로그인했니 (C:\Users\user\Desktop\todoapp\server.js:218:9)
        at Layer.handle [as handle_request] (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\layer.js:95:5)
        at next (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\route.js:144:13)
        at Route.dispatch (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\route.js:114:3)
        at Layer.handle [as handle_request] (C:\Users\user\Desktop\todoapp\node_modules\express\lib\router\layer.js:95:5)
    와 같은 에러가 뜹니다. 그래서 ObjectId를 인식을 못하는 것 같아 감싸지 않고 실행할 경우, db에서의 화면은
    
    
    _id: ObjectId('뭐시기')
    title: "무슨무슨채팅방"
    member: Array
       0: ""
       1: ObjectId('뭐시기')
    date: 블라블라~
    
    이렇게 0이 블랭크 처리가 되구요... 뭐가 문제인지 다른 수강생들의 qna도 참고했지만 도저히 이유를 모르겠어서 이렇게 글을 남깁니다.
    
    require('mongodb')을 할 시 .이 세개가 생기는데 커서를 대면 
    
    
    모듈 'mongodb'에 대한 선언 파일을 찾을 수 없습니다. 'c:/Users/user/Desktop/todoapp/node_modules/mongodb/index.js'에는 암시적으로 'any' 형식이 포함됩니다.
    해당 항목이 있는 경우 'npm i --save-dev @types/mongodb'을(를) 시도하거나, 'declare module 'mongodb';'을(를) 포함하는 새 선언(.d.ts) 파일 추가ts(7016)
    
    이라는 문구가 뜨는데 실행은 또 되어서 무시하고 했었는데 이 부분이 문제인가 싶기도 하네요. 
    
    아래에 server.js 와 list.ejs 코드 남기겠습니다.
    
    server.js
    
    const express = require('express')
    const app = express()
    app.use(express.urlencoded({ extended: true }));
    const MongoClient = require('mongodb').MongoClient;
    const methodOverride = require('method-override')
    const {ObjectId} = require('mongodb');
    app.use(methodOverride('_method'))
    app.set('view engene', 'ejs');
    app.use('/public', express.static('public'));
    require('dotenv').config()
    var db;
    MongoClient.connect(process.env.DB_URL,{ useUnifiedTopology: true }, function(에러, client){
            if (에러) return console.log(에러) 
            db = client.db('todoapp');
        });
       
            app.listen(process.env.PORT, function(){
                console.log('listening on 8080')
            });
    app.get('/pet', function(요청, 응답) { 
        응답.send('펫용품 사시오')
    })
    app.get('/', function(요청, 응답) { 
        응답.render('index.ejs')
      });
    app.get('/index', function(req, res){
        res.render('index.ejs')
    });
    app.get('/write', function(req, res){
        res.render('write.ejs')
    });
    app.get('/list', function(요청, 응답){
        db.collection('post').find().toArray(function(에러, 결과){
            console.log(결과);
            응답.render('list.ejs', { posts : 결과 });
        });
    });
    app.get('/search', function(요청, 응답) {
        var 검색조건 = [
            {
              $search: {
                index: 'todoSearch',
                text: {
                  query: 요청.query.value,
                  path: '제목'
                }
              }
            }
          ] 
        db.collection('post').aggregate(검색조건).toArray(function(에러, 결과) {
            console.log(결과)
            응답.render('search.ejs', {posts : 결과});
        });
    });
    
    
    app.get('/detail/:id', function(요청, 응답){
        db.collection('post').findOne({_id : parseInt(요청.params.id)}, function(에러, 결과){
            console.log(결과)
            응답.render('detail.ejs', { data : 결과 });
        })
    })
    app.get('/edit/:id', function(요청, 응답){
        db.collection('post').findOne({_id : parseInt(요청.params.id)}, function(에러, 결과){
            console.log(결과)
            응답.render('edit.ejs', { post: 결과 })
        })
        
    })
    app.put('/edit', function(요청, 응답){
        db.collection('post').updateOne({ _id : parseInt(요청.body.id) },{ $set: { 제목: 요청.body.title, 날짜: 요청.body.date} }, function(에러, 결과){
            console.log('수정완료')
            응답.redirect('/list')
        })
    })
    const passport = require('passport');
    const LocalStrategy = require('passport-local').Strategy;
    const session = require('express-session');
    app.use(session({secret : '비밀코드', resave : true, saveUninitialized: false}));
    app.use(passport.initialize());
    app.use(passport.session());
    passport.use(new LocalStrategy({
        usernameField: 'id',
        passwordField: 'pw',
        session: true,
        passReqToCallback: false,
      }, function (입력한아이디, 입력한비번, done) {
        db.collection('login').findOne({ id: 입력한아이디 }, function (에러, 결과) {
          if (에러) return done(에러)
      
          if (!결과) return done(null, false, { message: '존재하지않는 아이디요' })
          if (입력한비번 == 결과.pw) {
            return done(null, 결과)
          } else {
            console.log('비번틀림')
            return done(null, false, { message: '비번틀렸어요' })
          }
        })
      }));
      passport.serializeUser(function (user, done) {
        done(null, user.id)
      });
      
      passport.deserializeUser(function (아이디, done) {
        db.collection('login').findOne({id : 아이디}, function(에러, 결과){
            done(null, 결과) 
        })
      });
      app.post('/register', function(요청,응답){
        db.collection('login').insertOne( { id : 요청.body.id, pw : 요청.body.pw }, function(에러, 결과){
            응답.redirect('/')
        })
      })
      app.post('/add', function(요청, 응답){
        console.log(요청.user._id)
        응답.send('전송완료');
        db.collection('counter').findOne ({name : '게시물갯수'}, function(에러, 결과){
            var 총게시물갯수 = 결과.totalPost;
            var post = { _id : 총게시물갯수 + 1, name : 요청.user._id, 제목: 요청.body.title, 날짜: 요청.body.date}
            db.collection('post').insertOne(post, function(에러, 결과){
                db.collection('counter').updateOne({name:'게시물갯수'},{ $inc : {totalPost:1} },function(에러, 결과){
                    if(에러){return console.log(에러)}
                })
            });
        });
    });
    app.delete('/delete', function(요청, 응답){
        요청.body._id = parseInt(요청.body._id);
        
        db.collection('post').deleteOne({_id : 요청.body._id, name: 요청.user._id }, function(에러, 결과){
            console.log('삭제완료');
            console.log('에러',에러)
            응답.status(200).send({ message : '성공했습니다' });
        })
    });
    
    
    app.use('/shop', require('./routes/shop.js'));
    app.use('/board/sub', require('./routes/board.js'));
    let multer = require('multer');
    var storage = multer.diskStorage({
        destination : function(req, file, cb){
            cb(null, './public/image')
          },
          filename : function(req, file, cb){
            cb(null, file.originalname )
          }
        
    });
    var path = require('path');
    var upload = multer({
        storage : storage,
        fileFilter: function (req, file, callback) {
            var ext = path.extname(file.originalname);
            if(ext !== '.png' && ext !== '.jpg' && ext !== '.jpeg') {
                return callback(new Error('PNG, JPG만 업로드하세요'))
            }
            callback(null, true)
        },
        limits:{
            fileSize: 1024 * 1024
        }
    });
    app.get('/upload', function(요청,응답){
        응답.render('upload.ejs')
    });
    app.post('/upload', upload.single('profile'), function(요청, 응답){
        응답.send('업로드완료')
    });
    app.get('/image/:imageName', function(요청,응답){
        응답.sendFile( __dirname + '/public/image/' + 요청.params.imageName)
    })
    app.get('/login', function(요청, 응답){
        응답.render('login.ejs')
    });
    app.post('/login', passport.authenticate('local', {
        failureRedirect : '/fail'
    }), function(요청, 응답){
        응답.redirect('/')
    });
    app.get('/mypage', 로그인했니, function(요청, 응답){
        console.log(요청.user);
        응답.render('mypage.ejs', {사용자 : 요청.user})
    });
    function 로그인했니(요청, 응답, next){
        if (요청.user){
            next()
        } else {
            응답.send('로그인안하셨는데요?')
        }
    }
    app.post('/chatroom', 로그인했니, function(요청, 응답){
        
        var 저장할거 = {
            title : '무슨무슨채팅방',
            member : [ObjectId(요청.body.target), 요청.user._id],
            date: new Date()
        }
        db.collection('chatroom').insertOne(저장할거).then(function(결과){
            응답.send('저장완료')
        })
    })
    app.get('/chat', 로그인했니, function(요청, 응답){
        db.collection('chatroom').find({ member : 요청.user._id }).toArray().then((결과)=>{
          console.log(결과);
          응답.render('chat.ejs', {data : 결과})
        })
      
      }); 
    
    
    list.ejs
    
    
    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="/public/main.css">
        <title>Hello, world!</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
      </head>
      <body>
        <%- include('nav.html') %>
        
        <h4 class="m1-2 my-3 text-center">서버에서 가져온 할일 리스트</h4>
        
        <div class="container input-group mb-2">
          <input class="form-control" id="search-input">
          <button class="input-group-append btn btn-danger"
          id="search">검색</button>
            
          
        </div>
         <div class = 'container'>
          <ul class="list-group">
            <% for (var i = 0; i < posts.length ; i++){ %>
            <li class="list-group-item">
              <p>글번호 : <%= posts[i]._id %></p>
              <h4>할일 제목 : <%= posts[i].제목 %></h4>
              <p>할일 마감날짜 : <%= posts[i].날짜 %></p>
              <button class="btn btn-danger delete" data-id="<%= posts[i]._id %>">삭제</button>
              <button class="btn btn-secondary chat"data-id="<%= posts[i].name %>">채팅</button>
            
            <% } %>
          
        </div>
    
    
          <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
          <script>
            
            $('.delete').click(function(e){
              var 글번호 = e.target.dataset.id;
              var 지금누른거 = $(this);
              
              $.ajax({
              method : 'DELETE',
              url : '/delete',
              data : {_id : 글번호},
            }).done(function(결과){
              console.log('성공했어염')
              지금누른거.parent('li').fadeOut();
            }).fail(funcion(function(xhr, textStatus, errorThrown){
              console.log(xhr, textStatus, errorThrown);
            }));
          })
          $('#search').click(function(){
            var 입력한값 = $('#search-input').val()
            window.location.replace('/search?value=' + 입력한값);
          });
          
          $('.chat').click(function(e){
            var 상대방아이디 = e.target.dataset.id;
            $.post('/chatroom', {target : 상대방아이디}).then(()=>{
              console.log('성공')
           
            })
          });
          
         
          </script>
    
    
         
        
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>
      </body>
    </html>
    
    
    
    
     
    #56146

    정윤식
    참가자
    아 그리고 mongodb 버전은 3.6.4 입니다.
    #56165

    codingapple
    키 마스터
    버튼에 data-id 왼쪽에 띄어쓰기 해봅시다
    그리고 data-id="" 안에 데이터도 잘 들어있나 크롬개발자도구에서 확인해봅시다
    #56192

    정윤식
    참가자
     
     
     
     
    강사님 덕에 드디어 해결했습니다! 애플님 말씀대로 띄어쓰기 하고나서 혹시나 싶어서 db에 등록되어있던 아이디정보랑 게시물 싹 다 새로 등록했더니
    언제 그랬냐는듯 잘 작동됩니다. 감사합니다. 몸 건강히 지내십시오~
     
     
4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관, 개인정보처리방침
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠