본문 바로가기
노드

노드 7장, 9장

by ㅎㅁ0517 2022. 3. 3.

express에 use를 차례로 연결시킬 때 순서대로 실행되기 때문에 순서에 유의해야 함. 마지막에 이런 코드를 두면 무조건 에러가 나는 게 아닌가 궁금했었는데 indexRouter 등 앞에 쓰여진 라우터들이 먼저 실행되서 종료되기에 여기까지 오지 않아서 에러가 나지 않음. 특히 아래 err 변수가 하나 더 있는 라우터에는 next(error)를 줘야 저 라우터로 가게 됨.

app.use((req, res, next) => {
    const error= new Error(`${req.method} ${req.url} 라우터가 없습니다`);
    error.status= 404;
    next(err);
});

app.use((err, req, res, next) => {
    console.log('aasdf');
    res.locals.message= err.message;
    res.locals.error= process.env.NODE_ENV !== 'production'? err : {};
    res.status(err.status || 500);
    res.render('error');
});

db를 정의할 때 1:N 관계에서는 1.hasMany(N) N.belongsTo(1) 로 표기하고 뒤의 인자로 foreignkey를 지정함. hasmany에선 sourcekey, belongsTo에서는 targetkey도 지정해야 함. 따로 지정안하면 알아서 모델명+기본키 (UserId)처럼 만들어서 연결해줌. 1:1 에서는 hasOne과 belongsTo를 사용하는데 이때 belongsTo를 사용하는 모델에 참조키가 생기니 유의해야 함. N:M은 belongsToMany를 쓰고 through로 새로 만들 테이블 이름을 지정해줄 수 있음. 이때 만들어진 테이블은 모델 파일로 만들어 놓지 않으니 꺼내 쓸 때 db.sequelize.models.테이블명 해서 꺼내 쓰면 됨. 실제 테이블 명은 앞자리가 소문자에 s가 붙는 듯.

 

const env= process.env.NODE_ENV || 'development';
const config = require('../config/config')[env]; //config 폴더에 config.json 파일을 참고하되
// test, production 중 development 부분을 참고함. db 이름, 사용자 등 정보가 적혀 있음
   .post(async (req, res, next) => {
        try { //axios.post('/users', {name, age, married}); 처럼 주면 req.body 로 사용 가능
            console.log('routes/user post호출됨'); 
            const user= await User.create({
                name: req.body.name, 
                age: req.body.age,
                married: req.body.married,
            }); //생략
    
router.get('/:id/comments', async (req, res, next) => { //:id 로 변수로 표현가능. 이 변수는 req.params.id로 조회할 수 있음.

html 때 createElement하고 이 요소를 appendChild 해버리면 이 요소는 다시 쓸 수 없음. 다시 만들지 않으면 에러남. 

 

빈 문자열은 false임

 

const age= e.target.age.value; // -> target은 이벤트가 발생한 대상 객체를 가리킵니다.

req로 이제 요청의 데이터를 확인하면 응답의 res를 주는데 주로 get에서는 res.render로 화면을 띄우고 get이 아니면 res.json으로 데이터를 주는 것 같음.

 

const morgan= require('morgan'); //로그로 상세하게 출력해줌
app.use(morgan('dev'));

const nunjucks= require('nunjucks');
nunjucks.configure('views', {
    express: app, //express an express app that nunjucks should install to 
    watch: true, //watch (default: false) reload templates when they are changed
});

const dotenv= require('dotenv');
dotenv.config(); //이걸 해야 process.env로 쓸 수 있음 안하면 undefied

const pageRouter= require('./routes/page'); //각각 다 분리해놔야 좋은 코드임^^
const authRouter= require('./routes/auth');
const postRouter= require('./routes/post');
const userRouter= require('./routes/user');

const { sequelize }= require('./models'); // 이렇게 따로 지정하는 게 없으면 index.js를 알아서 지정함

const passport= require('passport');
const passportConfig= require('./passport')
passportConfig();

const app= express();

app.set('port', process.env.PORT || 8001); //이렇게 app.set으로 저장해놓으면 app.get('port')로 찾을 수 있음
app.set('view engine', 'html');

sequelize.sync({force:false}).then(()=>{console.log('연결 성공');}).catch((err)=>{console.error(err);});
//sync({ force: true }) - This creates the table, dropping it first if it already existed

app.use(express.static(path.join(__dirname, 'public'))); //public 폴더 안의 파일을 전역 파일처럼 localhost:3000/파일이름 해서 접근 가능
app.use('/img', express.static(path.join(__dirname, 'uploads'))); //localhost:3000/img/파일이름
 

location.href=> href 는 location 객체에 속해있는 프로퍼티로 현재 접속중인 페이지 정보를 갖고 있음. 또한 값을 변경할 수 있는 프로퍼티이기 때문에 다른 페이지로 이동하는데도 사용됨. 새로고침 잘 안 될 때 location.reload(true) 주면 잘 됨

 

 document.getElementById('post-image').addEventListener('change', function(e) { 
                const formData= new FormData(); //Don't forget the enctype="multipart/form-data" in your form.
                console.log(this, this.files);
                formData.append('img', this.files[0]);  //upload.single('img'),  It is important that you use the name field value from the form in your upload function.
                axios.post('/post/img', formData)
                    .then((res) => {
                        document.getElementById('post-image-preview').src= res.data.url; //post하면 res.json({url:'--'})로 데이터 넣어주니 그걸 갖다 씀
                        document.getElementById('post-image-url').value= res.data.url;
                        document.getElementById('post-image-preview').style.display= 'inline';
                    }).catch((err)=>{ console.error(err); });
            });
            
    router.post('/img', isLogin, upload.single('img'), (req, res)=>{ 
    console.log('/img 잘 도착하고 됨', req.file);
    //. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
    res.json({url: `/img/${req.file.filename}`});
    //document.getElementById('post-image-preview').src= res.data.url; 에서 씀
    //static으로 img로 하면 uploads 폴더로 연결해줌
});
 const ext= path.extname(file.originalname); //확장자만 줌 asdf.html이면 '.html'
 
 cb(null, path.basename(file.originalname, ext)+Date.now()+ext);
 //originalname: Name of the file on the user’s computer
 //path.basename(path, extension) -> 주어진 path에서 file name만 리턴해 줌.
 //단 extension이 주어지고 file name이 extension으로 끝난다면 이를 제외하고 리턴해 줌
 //즉 'C:\user\folder1\asdf.html', '.html'이 주어지면 -> asdf 
 //여기에 현재 날짜를 붙여 중복되지 않도록 만들어주고 다시 확장자를 붙여줌

//https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions
        //https://heropy.blog/2018/10/28/regexp/
        //g 모든 문자열에서 검사, [^ ] <- 이 아닌 문자열, \s는 공백 의미, +는 1회 이상 반복 가능
        const hashtags= req.body.post_text.match(/#[^\s#]+/g);
 
{% if post.dataValues.good %}
      <h3 id="post-good" style="cursor:pointer">♥</h3>
{% else %}
      <h3 id="post-good" style="cursor:pointer">♡</h3>
      
await Promise.all(
            posts.map(async(list,idx)=>{
                const result= await UserPost.findOne({
                    where:{
                        UserId:req.user.id,
                        PostId:list.id,
                    }
                }); //idx는 index, datavalue는 디비에 컬럼이 아닌 다른 속성을 넣고 싶을 때 쓰면 됨
                if(result) posts[idx]['dataValues'].good=true;
                else posts[idx]['dataValues'].good=false;
            })
        );
//http://www.passportjs.org/packages/passport-local/ 참고
module.exports= () => { //참고할 폼 네임 필드
    passport.use(new LocalStrategy({usernameField: 'email', passwordField: 'password'}, async (email, password, done) => {
        try {
            const exUser= await User.findOne({ where: {email: email}});
            //라우터에서 passport.authenticate('local', (authError, user, info)때 사용, ${info.message}
            if(exUser) {
                const result= await bcrypt.compare(password, exUser.password);
                if(result) {
                    done(null, exUser);
                } else {
                    done(null, false, {message: '비밀번호가 일치하지 않습니다.'});
                } //뒤에 인자들을 생략 가능, undefined로 전달됨 다만 앞에껄 생략하고 뒤에꺼만 줄 수는 없음

모든 요청 전에 passport serializeUser, deserializeUser 가 실행됨. 앞에 이런 식으로 res.locals.user= req.user; 넣어두면  html 파일에서 변수로 쓸 수 있음.

'노드' 카테고리의 다른 글

노드 10장  (0) 2022.03.03
노드 8장  (0) 2022.03.03
js 6장  (0) 2022.01.24
js 4,5장  (0) 2022.01.19
js 3장  (0) 2022.01.17

댓글