저번 글(https://codelist.tistory.com/80)에서 마무리에 

 

제일 좋은 건 백엔드->프론트로 response를 전달해서 프론트에서 response를 받아 alert를 띄우는 거지만 지금의 나에겐 이 방식이 최선인 것 같다.

 

라고 했었다.

 

알고보니 axios 문제였고 해결 된 지금은 내가 원하던 대로 백엔드->프론트로 response를 전달해서 프론트에서 response를 받아 alert를 띄우는 게 가능해졌다.

 

원래는 아래처럼 작성했었다.

<script>

    methods : {
        login(){
            this.axios.post('http://olrang.shop:3000/login',  { //이 줄의 this가 문제였음
                withCredentials: true,
            id : this.id,
            password : this.password
                
            }).then((response) => { 
                this.response = response
                
            }).catch((error) => {  
                this.error=error    
            })
        },
    }
}
</script>

 

backend로 전송은 되니까 코드 자체에 문제가 없다고 생각했다.

 

받기가 안되는 건 nodejs의 문제거나 then에서 받는 코드를 잘못 작성했을 거라고만 생각했지 axios 코드 자체가 잘못됐다고 생각하지 못했다.

 

 

<script>

import axios from 'axios'

    methods : {

        login(){
            axios.post('http://olrang.shop:3000/login',  { 
                withCredentials: true,
            id : this.id,
            password : this.password
                
            }).then((response) => { 
                this.response = response
            
                
            }).catch((error) => {  
                this.error=error    
            
                
            })

        },

        

    }

}
</script>

 

위 코드로 받으니까 then부분이 잘 동작했다.

 

물론 alert도 잘 띄운다.

 

이제야 드디어 내가 원하던 방식으로 alert를 띄울 수 있게 됐다.

 

DB 연결할 때 참고한 포스팅에서 보고 8월 중순부터 this 붙여서 썼는데 처음부터 써왔던 코드도 의심해봐야하는구나.. 라고 생각했다.

 

 

DB를 사용하고 있는 만큼 생성과 삭제, 수정 기능 전부를 구현해보고 싶었다.

 

그래서 이제 수정 기능만 구현하면 되는데 마침 마이페이지-개인정보수정 기능을 넣으면 딱이겠다, 싶어서 만들기 시작했다.

 

다른 공식 페이지들을 보면 개인정보 수정하러 들어가면 폼에 기존 값이 입력되어져있다.

 

즉, 수정 페이지에 들어가면 화면에 DB값을 입력시켜 놓아야 한다는 것이다.

 

 

 


 

 

문제1  json 전송

 

DB값을 가져와 VUE에 뿌려야했는데 이 부분이 문제였다.

 

보통은 res.json/res.send로 json을 vue로 보내는 방식을 쓰는 듯한데 내가 res.json/send를 쓰면 페이지가 아래처럼 된다.

 

 

빈 화면에 값만 출력된다.

 

새로고침해도 저런 화면으로 뜨는 데 테스트를 여러 번 해보니 get 방식으로 전송하는 페이지를 새로고침할 경우 새로고침하면 그 페이지의 get 요청이 실행되어버린다.

 

그래서 처음엔 새로고침을 막을까도 생각했지만 근본적인 해결이 안되기때문에 고민하다가 도메인 연결할 때 참고했던 포스팅에서 frontend랑 backend 경로를 다르게 설정했던 게 떠올랐다.

 

frontend에서는 /login로, backend에서는 /api/login로 설정하고 frontend랑 backend랑 ip도 다르게 설정하셨던 것 같은데 처음 봤을 때는 왜 굳이 이렇게 설정하지? 라는 생각이 들었는데 구글링하다보니 이렇게 설정하시는 분이 많아서 나도 이렇게 해야하나..? 라는 생각까지 들었다.

 

그래도 난 저렇게 설정 안해도 문제 없었고 굳이? 라는 생각이 들어서 넘겼는 데 갑자기 이 기억이 생각나면서

 

데이터를 /mypage로 보내니까 json이 /mypage에 띄워져버리는 거라면 /api/mypage로 json을 보내되 출력은 /mypage에서 하면?

 

라는 생각이 들어서 해봤는데 뜻밖에도 내 가정대로 동작했다.

 

게다가 새로고침해도 멀쩡하고 /api/mypage가 눈에 보이지도 않았다.

 

사실 이렇게 해결하는 게 맞는 지 모르겠지만 다른 분들이 backend에서 /api 를 덧붙이는 이유가 서버동작처리용 경로이라고 추측했기 때문에 저런 가정을 해봤다.

 

++확인해보니 주소창에 직접 /api/mypage를 칠 경우 빈 화면에 json이 그대로 보여서 완전히 해결된 상태는 아닌 것 같은데 어떻게 고쳐야 할 지 모르겠다...

 

 

 

 

문제2  접속 시 DB값 띄우기

 

 

 이건 문제 1을 해결하려다가 우연히 해결하게 됐다.

 

vue의 created()를 쓰면 화면 접속 시 DB값이 띄워져 있는 상태로 볼 수 있다.

 

화면을 그릴 때 응답을 받아서 성공하면 화면을 띄우는 방식이라 내가 원하던 대로 동작한다.

 

 

/components/mypage.vue

<script>
import axios from 'axios'

export default {
    name : "MyPage",
    data(){
        return{
            mydata:''
        }
    },
        created() {
            axios.get('http://olrang.shop:3000/api/mypage',  { 
                withCredentials: true,
                headers : {
                    "Content-Type" : "application/json"
                },
            }).then((response) => { 
                this.mydata = response.data.phone
                
            }).catch((error) => {  
                this.error=error    

            })
        },
    }

</script>

 

 

/routes/index.js

router.get('/api/mypage', (req, res) => { //마이페이지 정보 수정
  User.findOne({name : req.cookies.session},(err, users) => { 
      if(!req.cookies.session || err) {  // 쿠키 없거나 에러 났을 때
        res.redirect('/');
      } else {
        res.set('Content-Type', 'application/json');
          var mydata = {phone : users.phone};
          res.json(mydata);
      }
  })
})

 

 

app.js

app.use('/api/mypage');

 

 


 

 

사실 구현하면서 안되는 부분이 많았다. (빈 화면에 json이 뜨는 문제는 몇 달전부터 인지하고 있었고 지금은 해결되었지만 axios에서 전송만 되고 받기가 안되는 문제가 있었다.)

 

안 고쳐지는 부분이라고 생각해서 놔뒀고 더 솔직하게 말하면 모른 척했다.

 

그러나 그 부분들이 모여서 결국 이렇게 다시 맞닥뜨리게 됐을 때 너무나 복잡하고 큰 문제들로 다가와서 찰나지만 '모른 척하지 말 걸 그랬다, 손 댈 수가 없을 정도로 코드가 엉망인 것 같다, 코드를 갈아엎어야하나?' 라는 생각까지 들었다.

 

근데 해결해나가면서 든 생각은 "역시 안되는 건 안되는 이유가 있다" 였고 이젠 안 고쳐지는 게 아니라 이유가 있어서 안되는 거니 이유를 찾자 라는 생각이 들게 됐다!

 

확실히 에러들을 만날 때마다 힘들지만 해결하고 나면 또 하나 알게됐다는 성취감이 든다.

 

 

 

 

 

나는 mongodb를 사용하기 때문에 remove(구버전이라 이제 사용 X), deleteOne(), deleteMany() 등의 명령어를 사용해서 document를 삭제해야하는 데 삭제가 안됐다.

 

해결하고보니 두 가지의 문제점이 있었다.

 

 


 

 

문제점

 

1. 형식 (출처 : https://sehwan93.github.io/oracle/2021-06-20-mongodb2/)

 

db.{COLLECTION_NAME}.remove({query},{justOne}) 방식으로 작성해야한다.

 

내가 원래 시도했던 코드는 아래였다.

 

backend/routes/index.js

var User = require('./mongodbuser');  // DB 스키마 파일 참조

User.deleteOne();

 

왜 앞에 User라고 적었냐면 기존에 사용하던 DB 생성, find, findOne 전부 앞에 User.~라고 사용했고 잘 작동했기 때문이었다.

 

그러나 저 참고한 곳에서 명령어 형식을 보고 혹시..? 라는 생각에 아래와 같이 코드를 작성했고 에러가 생겼다. (원래는 에러도 안 생기고 삭제가 안 되기만 했음)

 

router.get('/secession', (req, res) => {
  User.find({name : req.cookies.session},(err, users) => { 
      if(!req.cookies.session || err) {  // 정보/쿠키 없거나 에러 났을 때
        res.redirect('/');
      } else {
        users.deleteOne();
        res.clearCookie('session');
        res.redirect('/'); 
      }
  })
})

 

이렇게 작성했을 때 발생한 에러는 deleteOne is not a function

 

 

2. find 사용

 

에러가 생겼을 때 구글링을 했고 deleteOne이 remove보다 최신 버전인 걸 알고 있는 상태였는데 deleteAndfindeOne ? 인가 이런 함수가 최신 버전이니 이 명령어를 쓰라고 스택에 적혀있었고 해봤으나 역시나 똑같은 오류가 생겼다.

 

알고보니 버전의 문제가 아니었고 find가 아니라 findOne을 쓰니 정상동작했다.

 

 

<성공한 코드>

router.get('/secession', (req, res) => {
  User.findOne({name : req.cookies.session},(err, users) => { 
      if(!req.cookies.session || err) {  // 정보/쿠키 없거나 에러 났을 때
        res.redirect('/');
      } else {
        users.deleteOne();
        res.clearCookie('session');
        res.redirect('/'); 
      }
  })
})

 

 

 


 

 

드디어 탈퇴 기능이 구현됐다.

 

 

 

++진짜 해결!

https://codelist.tistory.com/83 

 

 

내가 alert를 띄우려고 했던 시도들은 순서대로 아래 글들을 읽어보면 볼 수 있다.

 

1. https://codelist.tistory.com/61

 

[Vue.js, Node.js] Node.js에서 보낸 response Vue에서 처리

++해결 [Node.js, Vue.js, Ajax] ::디버깅:: Vue.js alert 넣기 여는 글 먼저 내가 어떤 기능을 구현하고 싶었는 지 간단하게 설명하자면 회원가입 시 DB를 조회한 후 아이디가 이미 존재하면 이미 존재하는

codelist.tistory.com

 

2. https://codelist.tistory.com/69

 

[Node.js, Vue.js, Ajax] ::디버깅 실패:: Vue.js alert 넣기

+ 2021.10.18 해결된 줄 알고 글을 작성했으나 알고보니 안됐다. 아래 포스팅을 보면 내가 왜 착각했는 지 나와있다. [Node.js, Vue.js, Ajax] -삽질기록- Vue.js alert 넣기 원래는 패치 내용을 따로 포스팅 할

codelist.tistory.com

 

3. https://codelist.tistory.com/73

 

[Node.js, Vue.js, Ajax] -삽질기록- Vue.js alert 넣기

원래는 패치 내용을 따로 포스팅 할 계획이 없었으나 해결이 안되다보니 기록이라도 남기려 작성하게 됐다. 그 김에 앞으로 패치 관련 포스팅은 이 카테고리에서 하도록 하겠다. 내가 올랑상점

codelist.tistory.com

 

 

 

 

그리고 아래 코드로 성공 했다.

 

전에도 alert 띄우려고 아래처럼 res.send를 시도해 본 적 있는데 alert 뜨고나면 화면이 다 날라가서 하얀 상태에서 멈춰버려서 페이지 이동이 안되니까 포기했는데 이렇게 쓰면 페이지 이동까지 된다.

res.send("<script>alert('아이디/비밀번호를 입력해주세요.');location.href='/login';</script>");

 

 

그러나 테스트를 하다가 두 번째 alert 창을 띄우려고하면 Error: Can't set headers after they are sent. 라는 오류가 생긴다.

 

이 에러는 전에도 만났던 res.send를 두 번 보냈을 때 생기는 에러다.

 

에러가 생기는 것도 문제였는데 이 에러가 생기면 서버가 바로 죽어버린다.

 

배포 시 서버가 죽어버리면 안되기 때문에 try~catch문으로 감싸줬고 서버가 죽지 않고 이어서 잘 실행이 된다.

 

if(!users || err){ //id가 DB에 없으면(즉, id가 틀렸거나 회원가입이 안되어 있거나) 
      try{
        res.send("<script>alert('아이디가 틀렸습니다.');location.href='/login';</script>");
        }catch (exception) {
          res.redirect('/login');
        }

 

제일 좋은 건 백엔드->프론트로 response를 전달해서 프론트에서 response를 받아 alert를 띄우는 거지만 지금의 나에겐 이 방식이 최선인 것 같다.