여는 글


 

서브 페이지에서 새로 고침하면 404 뜨는 건 개발 초기에 vue 문제라는 걸 구글링해서 알고 있는 상태였다.

 

redirect 에러는 회원 가입 페이지를 구현하면서 회원 가입이 완료되면 로그인 페이지로 이동하도록 구현하고 싶었으나 redirect 명령어를 사용하면 404에러가 뜨고 url 창에 직접 경로를 쳐도 404가 뜬다는 걸 알게됐고 메인 페이지로의 이동만 가능했기 때문에 회원 가입 후 메인 페이지로 이동하도록 구현해놓은 상태다.

 

이번에 새로 고침하면 404뜨는 에러를 고치기 위해서 구글링하다보니 redirect 문제까지 해결할 수 있다는 것을 알았다.

 

미들웨어 connect-history-api-fallback를 사용하는 것.

 

구글링하면서 vue 포럼에서 이 미들웨어를 사용하는 것을 추천하길래 사용하려고 시도했더니 해결됐다.

 

 

 

connect-history-api-fallback 사용하기


 

Node.js에 아래 명령어로 설치한다.

npm install --save connect-history-api-fallback

 

 

backend/routes/app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
const history = require('connect-history-api-fallback'); //여기
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const session = require('express-session');



var indexRouter = require('./routes/index');

var app = express();


// view engine setup

var views = [
  path.join(__dirname, 'views')
]

app.set('views', views);
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());


app.use('/', indexRouter);
app.use(history()); //여기

app.use(express.static(path.join(__dirname, 'public'))); // 반드시 여기 위에 use 쓸 것!


/*---------후략-----------*/

 

주석 표시한 곳만 보면 되고 주의해야 할 점은 static 위에 history를 써야한다는 것이다.

 

처음에 안 되길래 구글링해보니 static이 위에 있어서 안됐던 거였다.

 

 

 

++다음날 확인해보니 / 페이지가 백엔드 페이지로 출력되는 것을 확인하고 프론트엔드 페이지로 나오도록 추가 작성 했다.

 

backend/routes/index.js

var express = require('express');
var path = require('path'); //추가된 부분
var router = express.Router();
router.use(express.urlencoded({extended:true}));
router.use(express.json())
var User = require('./mongodbuser');


/* GET home page. */
router.get('/', function(req, res, next) {
  res.sendFile(path.join(__dirname, '../public', 'index.html')); // 수정된 부분
});

/* 후략 */

 

 

 

 

닫는 글


 

이젠 서브페이지 새로고침, url 창에서 주소 입력해도 잘 이동한다.

 

이제 세션으로 로그인/로그아웃 구현만 남았다.

 

+ 2021.10.18

해결된 줄 알고 글을 작성했으나 알고보니 안됐다. 아래 포스팅을 보면 내가 왜 착각했는 지 나와있다. 

 

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

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

codelist.tistory.com

 

 

여는 글


 

먼저 내가 어떤 기능을 구현하고 싶었는 지 간단하게 설명하자면 회원가입 시 DB를 조회한 후 아이디가 이미 존재하면 이미 존재하는 아이디라고 alert를 통해 사용자에게 알리는 기능이었다.

 

그러나 어떻게 해도 Node.js와 Vue.js가 통신하지 못했다.

 

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

여는 글 제목에서 보다시피 해결하지 못했다. 저번 포스팅에서 id 중복체크 기능을 구현했고 이를 사용자에게 알리기 위해 팝업창을 띄우는 기능이었다. 3일 동안 해결하려 했지만(사실 3일이면

codelist.tistory.com

 

 

뜻밖에도 아임포트(결제기능)을 구현하면서 힌트를 얻었다.

 

Ajax를 사용하는 것.

 

아임포트 구현 코드에서는 Ajax를 사용했고 alert 창이 뜨는 걸 확인했다.

 

Ajax 사용할 생각을 못했던 이유는 몰라서가 아니라 오히려 알고 있었기 때문이다.

 

앞서 졸업작품(Django)에서 Ajax를 사용해 새로 고침하지 않고 페이지를 로드해서 사용했는데 Ajax는 이런 용도로 쓰는 거구나, 해서 alert랑 전혀 상관없는 줄 알았다.

 

 

 

기존 코드 vs Ajax 사용 코드


 

기존 코드

 

frontend/src/components/SignUpPage.vue

signup() {
            this.axios.post('http://localhost:3000/signup',  { 
            headers : {
                "Content-Type" : "application/x-www-form-urlencoded"
            },
            id : this.id,
            password : this.password,
            name : this.name,
            address : this.postcode,
            phone : this.phone
                
            }).then((response) => { //이 부분이 아예 동작 안함
                    alert(response.data.message); 
                
            
                
            }).catch((error) => {  
                this.error=error    
            
                
            })
        
        }

 

 

backend/routes/index.js

router.post('/signup', (request, response) => { //회원 가입
  console.log('success served');
  var ck = true;
  User.find((err, users) => { //id 중복체크 
      users.forEach((item) => {
        if(item.id == request.body.id){ // 평문끼리비교하는거라 배포시에는 이렇게 하면 안됨 암호화 필수
          ck = false;
          response.json({message : '사용할 수 없는 ID입니다.'})
          //response.redirect('http://localhost:3000');
        }
        
      })
    if(ck==true){
      User.create ({
        id:request.body.id,
        password:request.body.password,
        name:request.body.name,
        address:request.body.postcode + ' ' + request.body.roadAddress + ' ' + request.body.detailAddress + request.body.extraAddress,
        phone:request.body.phone,
      });
      response.redirect('/');
    }
});


});

 

 

Ajax 코드

 

frontend/src/components/SignUpPage.vue

signup() {
            jQuery.ajax({
                url: "http://localhost:3000/signup",
                method: "POST",
                headers: { "Content-Type": "application/json" },
                data: {
                    id : this.id,
                    password : this.password,
                    name : this.name,
                    address : this.postcode,
                    phone : this.phone
                    },
                error : function (){
                        alert("이미 존재하는 아이디입니다.");
                } 
            });
        },

 

 

backend/routes/index.js

router.post('/signup', (request, response) => { //회원 가입
  console.log('success served');
  var ck = true;
  User.find((err, users) => { //id 중복체크 
      users.forEach((item) => {
        if(item.id == request.body.id){ // 평문끼리비교하는거라 배포시에는 이렇게 하면 안됨 암호화 필수
          ck = false;
          response.status(400);
        }
        
      })
    if(ck==true){
      User.create ({
        id:request.body.id,
        password:request.body.password,
        name:request.body.name,
        address:request.body.postcode + ' ' + request.body.roadAddress + ' ' + request.body.detailAddress + request.body.extraAddress,
        phone:request.body.phone,
      });
      response.redirect('/');
    }
});


});

 

 

 

닫는 글


 

아직 고쳐야 하는 부분은 2가지다.

 

로그인/로그아웃 세션으로 구현하기, redirect 서브 페이지 안되는 거 해결하기

 

이 외에는 편의성 개선? 정도 인데 이 부분은 시간이나 여력이 되면 해보는 걸로!

 

 

여는 글


 

기능상으로는 이것이 마지막 포스팅이다.

 

이제는 고쳐야 할 부분만 남은 것 같다.

 

구현하는 데에 오래걸리진 않았고 테스트에서 약간 시간이 걸렸다.

 

테스트에 대해서는 밑에서 더 자세하게 이야기 하겠다.

 

 

 

결제 구현


 

먼저 frontend에 jQuery를 설치해야 한다.

 

npm install jQuery

 

나는 아래 포스팅을 거의 참고 했다.

 

[import] 아임포트 결제 모듈 만들기(코드 포함)

아임포트 결제 모듈 만들기 안녕하세요 이번에 결제 모듈을 만들면서 공부한 내용들을 정리하고자 포스팅합니다. 본인의 서버 환경과 서비스의 특징에 맞게 변경하여 사용하시면 됩니다. 아임

puzzle-puzzle.tistory.com

 

주의!! 코드 작성 후 관리자페이지에서 시스템설정->PG설정(일반결제및정기결제)에서 결제 수단을 등록해야 결제창이 뜬다.

 

내 모든 코드는 내 깃허브에 있다.

 

GitHub - codelistwriter/olrang: 올랑 상점 모든 코드

올랑 상점 모든 코드. Contribute to codelistwriter/olrang development by creating an account on GitHub.

github.com

 

나에게 맞게 고쳐서 작성하긴 했는데 내가 손댄 건 MongoDB에 맞게 DB코드를 바꾼다던지, 전달될 데이터를 수정한다던지 하는 간단한 수정이었고 코드 설명도 친절하셔서 매우 참고가 됐다.

 

 

 

테스트


 

 

앞에서도 언급했지만 의외로 구현보다는 테스트에 시간이 들었다.

 

테스트를 해보니 결제창도 잘 뜨고 결제도 잘 됐는데 주문이 내 DB에 안 들어가서 의아했기 때문이다.

 

DB에 들어가려면 backend 부분이 실행이 되어야 하는데 그냥 frontend에서 결제창->결제->끝 이렇게 되는 것 같다는 생각이 들었고 구글링도 해보고 어디까지 실행이 되는 건지, backend로 전달이 되긴 하는 건지 한참을 찾다가 결론을 내렸다.

 

이게 실제 결제가 아니라 테스트모드라 보안이나 DB 저장 부분까지는 실행이 안되는 건가?

 

물론 실제 결제가 아니더라도 실제 돈은 결제가 된다.

 

아래 사진은 내가 실제로 사용하는 농협 계좌이고 계좌 번호는 혹시 몰라 가렸다.

 

정확하게 말하면 PG사랑 계약을 해야 진짜 결제다.

 

근데 그러려면 사업자등록번호가 있어야한다고 해서 나는 테스트를 여기서 끝내기로 했다.

 

 

 

닫는 글


 

다음에는 프론트엔드에 ALRER 창 삽입하기를 구현할 것이다.

 

저번엔 안됐지만 이번에는 꼭 고쳐야지!

 

아래는 내가 구현한 첫 결제 기념 스크린샷이다.

 

 

필기


 

리눅스 마스터는 2급도 있는 데 왜 굳이 1급 치냐고 물어보면 2급 치고 1급 칠 바에 바로 1급 치는 게 좋지 않을까 하는 생각이었기 때문이다.

 

따려고 생각한 이유는 나는 백엔드 취업을 준비하는 중이라 리눅스 자격증이 있으면 좋을 것 같았기 때문이다.

 

그냥 필기+실기 같이 있는 책으로 샀고 리눅스 마스터 1급은 엄청 어렵다고 유명하대서 겁을 집어먹고 공부하기 시작했다.

 

공부하는 데 진짜 어려웠다.

 

학교에서 리눅스 수업을 3번이나 들었지만 학교에서는 리눅스를 다루는 데 치중한다면, 리눅스 마스터는 리눅스를 이용해서 서버, 보안, 네트워크를 다루는 내용이라 많이 달랐다.

 

그래도 학교에서 리눅스 명령어를 배워서 다행이라는 생각을 참 많이 했다.

 

시험 직전까지도 기출을 푸는 데 합격점 안팎을 넘나 들었다.

 

정보처리기사는 개편 때문에 제외하고 나는 컴퓨터 자격증 7개를 가지고 있고 그 만큼 많은 필기시험을 쳐봤다.

 

필기 시험인데 직전까지도 합격점이 아슬아슬하게 나오는 건 리눅스 마스터가 처음이었다.

 

또한 리눅스마스터는 시험이 매년 새로 출제돼 기출은 30% 정도만 나온다고 한다.

 

내가 봤던 시험도 마찬가지였다.

 

눈에 익은 문제는 30% 정도 뿐.

 

나머지 최소 30%는 내가 공부한 걸로 풀어야 했고 시험이 끝나고 가답안을 매겨보니 딱 60점이었다.

 

가답안의 답이 바뀌지 않는다면 합격인 상황이었는데 리눅스 마스터는 가답안이 자주 바뀌는 시험이었기 때문에 최종 발표까지 조마조마 했다.

 

 그리고 최종 발표 전날까지도 가답안을 확인 했고 다른 문제들의 답이 꽤 많이 바뀐 상태였으나 어차피 내가 틀린 문제들이었어서 동일하게 60점이었다.

 

다음날 결과를 확인해보니 58점인가 어쨌든 불합격이었다.

 

난 내가 잘못 매겼나 싶어서 가답안을 다시 확인해봤지만 아무리봐도 60점이었다.

 

바로 문의를 넣었고 그날 오후 4시가 넘어서야 60점으로 정정되어 합격할 수 있었다.

 

KAIT 측에서 정정되기 전의 답안으로 매겼다고 한다.

 

하루종일 진짜 떨어진 건가 하고 우울했는데 다행이다, 싶다가도 가답안이 자주 바뀌고 나 말고도 문의나 항의가 많고 최종 점수가 바뀔 정도로 실수가 많다는 것에 약간 화가 나기도 했다.

 

구글링해보니 나 말고도 이런 점에 불만이 있는 사람이 꽤 있었다.

 

 

실기


 

실기는 또 하필 나 칠 때 리눅스 버전이 달라졌다. (정보처리기사의 트라우마...)

 

처음에는 그냥 새로운 버전으로 하면 되지 하고 안일하게 넘어갔는 데 이게 엄청난 나비 효과를 불러온다.

 

실기는 필기보다 훨씬 어려웠다.

 

특히 iptable이 진짜 어려웠는데 바로 이게 문제였다.

 

iptable을 실컷 공부해갔더니 알고보니 달라진 리눅스 버전에서는 iptable을 더 이상 쓰지 않고 firewall을 사용하기 때문에 시험에도 iptable이 아니라 firewall이 나왔다.

 

처음 보는 firewall에 나는 순식간에 12점을 날렸고...

 

시험장 환경이 너무 열악했고....(마우스가 안돼서 창을 위아래로 내릴 수 없다보니 내가 현재 치고 있는 명령어가 화면 밑에 있어서 안 보였다. 안 그래도 명령어가 긴데 오타 확인이 안되자 같은 명령어를 여러 번치는 사태가 문제마다 발생했다.)

 

또 한 시험장에 파이썬, 리눅스, 그래픽스 등 여러 시험을 치다보니 (커닝 방지용인듯 한데 정작 내 바로 옆자리는 나랑 같은 시험 치는 분이었음) 감독관분들이 힘들어 하셨다.

 

안 그래도 컴퓨터 상태가 좋지 않아 자리도 많이 옮기고 감독관 분들은 다 다른 종류 시험 응시자에 대응해야 해서 고생하셨다.

 

내 자리는 마우스가 안됐고 다른 분들도 마우스가 안돼서 감독관께서 해결하려고 붙잡고 계시는 걸 보고 나는 그냥 감독관분을 부르지 않았다.

 

다른 분들이야 나도 잘 모르지만 그래픽스? 같은 건 마우스 써야 하지 않나.

 

난 어차피 리눅스고 잘 안 보이는 거 빼고는 마우스 쓸 일이 없어서 부르지 않았다.

 

어쨌든 정리하자면 시험장은 문제가 많아서 매우 어수선했고 마우스가 안돼서 자꾸 오타가 나는 사태가 발생했고 벌써 12점을 날린, 멘탈이 흔들리는 시험이었다.

 

덧붙이자면 원래 시험장은 대학교였고 시험 전날 수험표를 뽑으려고 들어가보니 직업전문학교로 바뀌었더라. 거리도 지하철 기준으로 끝과 끝으로(멀다는 뜻임). 바뀌었다는 연락도 없었음. 만약 내가 처음 장소를 확인한 날 수험표까지 뽑아버렸다면 큰일날 뻔했다.

 

이제 결론을 말하자면 6점 차이로 떨어졌다.

 

firewall 몰랐던 거 치고 선방했다고 생각한다...ㅠ

 

너무 아까워서 내년에 다시 칠 예정이다.

 

안 그래도 응시료 비싼 데 시험 환경에 신경 좀 써줬으면 좋겠다.

(게다가 나는 시험 시간보다 30분 일찍 도착했는데 밖에서 1시간 넘게 기다렸다. 컴 세팅 덜 됐다고 시험 시작 시간 30분 넘게 지났는데도 밖에서 기다리게 했다. 덕분에 밖에서 사람들이 줄을 일렬로 길게 서있었다.^^

*다른 사람들 후기보니까 일찍 들어가서 리눅스 확인하고 명령어 쳐보고 해야된다고 해서 일찍 간건데....)

 

 

 

+ 그리고 난 분명히 동일한 리눅스 환경으로 세팅해서 집에서 연습했음에도 불구하고 시험장에 갔을 때 리눅스 환경이 달랐다.

 

실기에서 제일 중요한 게 파일 경로이고(답이 주로 파일 경로/경로 안 파일 값이니까) 버전마다, 리눅스 종류마다 다르기때문에 실기 준비 시에 제일 중요하다고 할 수 있는데 내가 공부했을 때 이 값은 A라는 파일 경로에 있는 걸로 공부했는데 시험장 리눅스는 A라는 디렉토리가 아예 없더라.

 

그래서 틀렸는데 알고보니 AB라는 경로로 되어 있었다.

 

이것도 리눅스 버전이 바뀌면서 달라진 건가 싶긴 하지만 난 KAIT 홈페이지에 공지된 변경된 버전으로 공부했고 달라진 버전이라도 기출을 풀어보니 거의 동일했기 때문에 기출로 공부를 했는데 달라서 당황했다. 

 

 

 

요약


 

KAIT 대응이 좀 구리다.

 

리눅스 버전 확인 잘 하고 기출 비중이 작지만 반드시 풀고 갈 것!!!

 

그리고 아예 처음 보는 문제가 많이 나오지만 당황하지 말고 침착할 것!

 

시험장 복불복이 있다.

'자격증' 카테고리의 다른 글

정보처리기사 합격 후기  (0) 2021.09.24

 

 

필기


 

내가 4학년이었던 2020년에 딱 정보처리기사 시험 개편이 있었다.

 

시험이 완전히 바뀐다고해서 기출이 소용없을 것 같다는 판단에 (기출을 보긴 봤는데 출제 범위가 달라서 참고할래도 할 수가 없었다) 그냥 필기책 하나 사서 공부했다.

 

그러나 코로나때문에 시험일이 자꾸 밀려서 공부할 수 있는 기간이 늘어났다.

 

그래서 나는 아예 그 두꺼운 필기 책을 손으로 써가며 얇은 공책으로 요약본 한 권을 만들었고 그걸로 공부했다.

 

요약책을 만든 이유는 내 기준으로 중요하다고 생각하는 부분만 선택해서 집중적으로 공부하고 싶었기 때문이다.

 

나는 나름 핵심을 잘 분리하는 편이라 학교 시험 칠 때도 내가 나올 것 같다고 생각하는 부분은 대부분 적중하는 편이었다.

 

사실 그 두꺼운 책을 다 보기 싫기도 했다.

 

드디어 시험(2020년 1회 필기 시험)을 쳤는 데 너무 당황했다.

 

필기 책에 있는 내용에서 10%도 안 나왔다.

 

찍기 + 전공 지식으로 풀었다.

 

시험장을 나와서 느낌이 안 좋았다.

 

인터넷에 후기를 보니 다른 출판사의 책들도 비슷했나보다.

 

적중률이 왜 이렇게 낮냐고 욕이 많았다.

 

개편 후 첫 시험이라 대부분의 출판사가 갈팡질팡하고 있는 듯 했다.

 

실기 때 알게된 거지만 출판사마다 책 내용도 거의 달랐다.

 

그 만큼 뭐가 나올 지 모른다는 뜻이다.

 

오후 6시에 답안이 뜨고 매겨봤는 데 필기는 특히 과락이 있어서 걱정됐다.

 

1과목이 과락 턱걸이였으나 다행히 과락이 아니었고 찍은 게 생각보다 많이 맞아서 아슬아슬하게 합격했다.

 

나중에 알고보니 내가 친 필기 회차의 합격률이 5%라고 한다.

 

 

 

실기


 

실기는 3번 만에 합격했다.

 

첫 실기 시험은 2020년 2회 실기(1회 실기는 개편 전 필기까지만 합격한 사람들만 칠 수 있는 회차)였고 이번에도 개편된 실기 책을 사서 공부했다.

 

시험장에서 문제를 보는 데 개편 전 실기와 비슷하게 나와버렸다.

 

나는 개편된 실기로 공부했던 터라 당황했으나 개편 전 실기는 쉽기 때문에(전공 지식으로 풀 수 있는 정도) 최대한 풀었지만 1문제 차이로 떨어졌다.

 

시험장을 나오고 나서는 조금 억울했다.

 

이렇게 나올 줄 알았으면 개편 전 실기책으로 공부하지.

 

나는 바로 다음 회차 실기에 응시했고 전 만큼 의욕이 나지 않아 공부도 별로 하지 않은 채 응시했고 이번엔 완전히 개편 된 실기로 나오는 바람에 어려웠고 35점으로 불합격했다.

 

그러나 이번에는 깨달은 게 있었다.

 

생각보다 필기 내용이 많이 나온다는 것.

 

그 다음에는 올해인 2021년 2회차 실기에 응시했고 전에 만들어 둔 필기 요약본, 저번에 산 실기책, 그리고 이번에 새로 산 실기책 총 3권을 돌려가면서 공부했고 60점 턱걸이로 합격했다.

 

이 두 실기책도 마찬가지로 내용이 상당히 달랐다.

 

가답안이 나왔을 때 아무리 잘 쳐줘도 55점으로 떨어지겠구나 했는데 다행히 합격이었다. 

 

지금 생각해보면 실기책보다는 필기책이 훨씬 도움이 많이 됐다.

 

요약


 

실기 준비할 때 필기도 반드시 병행해야 한다.

'자격증' 카테고리의 다른 글

리눅스 마스터 1급 후기  (0) 2021.09.24

 

 

여는 글


 

설정하는 데 꽤 헤맸지만 엄청 간단하게 해결됐다.

 

설정은 정말 간단하다.

 

 

 

연동하기


 

참고한 포스팅 (감사합니다..)

https://snepbnt.tistory.com/394

 

[ MongoDB ] MongoDB compass 로 aws mongodb 연결하기

연결하는 방법은 생각보다 간단하다 1. 인스턴스 보안설정에 들어가서 인바운드 규칙을 설정한다. aws 는 인바운드 규칙을 통해 외부 접속을 통제하기 때문에 ec2 에 설치한 mongodb 를 외부에 있는

snepbnt.tistory.com

 

정말 간단했고 compass를 쓰는 나에게 딱이었다.

 

내가 막혔던 부분은 compass에서 ip를 치고 연결하는 부분이었다.

 

연결이 잘 되면 바로 연결하는 데 2초? 정도 걸리는 데 나는 계속 나침반 모양이 표시되더니 안됐었다.

 

하루종일 구글링하다가 갑자기 되길래 깜짝 놀랬는데 앞선 시도들과 뭐가 달랐는 지 생각해보니 이거 하나였다.

 

aws에서 인스턴스 돌리고 cmd에서 리눅스에 ssh 접속한 상태까지만이면 compass랑 연결이 안된다.

 

반드시 npm start 후에 compass랑 연결해야 연결이 된다.

 

연결하고 나면 그 후에는 자동으로 값 생성되고 알아서 잘 된다.

 

늘 그렇듯이 갑자기 되면 한동안은 어안이 벙벙하다.

 

 

 

닫는 글


 

이제는 mongoDB 후기를 남길 때가 된 것 같아서 남긴다.

 

NoSQL을 처음 써봤고 항상 SQL을 써오던 나는 비슷하지만 다른 구조를 가진 NoSQL에 약간의 낯섬과 거부감 같은 게 들었지만 쓰고나니까 왜 NoSQL이 나오게 됐는지, 왜 많이 쓰는 지 깨닫게 되었다.

 

다른 말 필요 없고 진짜 편하다.

 

명령어가 간단하고 SQL에서는 생각할 수 없는 융통성과 연결의 편리성이 있다.

 

무슨 느낌이냐면 나는 C언어와 JAVA를 먼저 배우고 Python을 배웠는데, 딱 이 느낌이었다.

 

사용하면서 이게 돼? 이게 되네? 라는 생각이 계속 들었다.

 

마치 별도로 선언하지 않았는데도 바로 변수를 쓸 수 있는 Python을 봤을 때의 충격 정도.

 

아무튼 mongoDB도 쓰기 좋다는 뜻이다.

 

 

여는 글


 

구글링하면 nodejs만 배포하거나 vue 배포만 하는 글이 많고 둘 다 있다고 하더라도 막 시작하는 (나처럼 코드가 이미 한가득 작성되어 있지 않은) 단계의 글이 많아서 해결하는 데 시간이 오래 걸렸다.

 

그러니 이 글은 아래 경우에 해당되는 사람이 배포 할 때 도움이 되는 글이다.

 

1. nodejs, vuejs 를 동시에 배포해야하고 개발 마무리 단계다.

 

2. 개발 라이브러리가 frontend, backend 따로 구분되어 있다.

 

 

 

AWS 세팅 및 서버 구동하기


 

세팅은 아래 포스팅을 거의 참고했다. (참고하기 전에 아래 글을 먼저 읽고 참고하길 바람)

 

 

GitHub과 Node.js Express를 이용한 자동배포 환경 만들기(feat. AWS-EC2, AWS CodeDeploy, AWS CodePipeline) 1편 - 까

1편에서는 AWS EC2에 Node.js Express 프로젝트를 배포하는 과정에 대해서 설명합니다. https://aws.amazon.com/ko/ 클라우드 서비스 | 클라우드 컴퓨팅 솔루션| Amazon Web Services 제조 AWS를 활용한 Siemens의..

ookm1020.tistory.com

 

이 포스팅을 따라하다가 막힌 부분이 있었고 나와는 다른 구조로 되어 있어서 그렇다는 걸 깨달았다.

 

 

 

ssh 접속 할 때

 

나는 aws 이름이 codewriter였기 때문에 codewriter@ip 로 했는데 계속 실패했다.

 

이거 때문에 며칠을 구글링했는데 그냥 기본이름인 ubuntu로 하니까 바로 됐다...

 

그리고 굳이 가상머신->리눅스로 하지 않아도 윈도우 cmd에서도 충분히 된다.

 

시작 메뉴에서 openssh 설치 후 cmd에서 ssh를 쳐보면 설치확인을 할 수 있고 여기서 바로 접속할 수 있다. (권한 문제가 있다면 구글링하면 많이 나오므로 생략)

 

구글링하다보니 cmd 사용을 꺼리거나 그냥 putty를 많이 사용하던데 본인의 선택이다.

 

난 배포 가능 여부가 급해서 그냥 cmd로 했다.  

 

[미래의 나를 위해 써두는 cmd 실행 명령어 순서]

바탕화면에 pem 파일이 있으므로 먼저 cd Desktop

ssh -i "olrangstore.pem" ubuntu@퍼블릭ip

(코드 갱신 시 git에 업로드 후 rm -rf olrang, git clone https://github.com/codelistwriter/olrang.git)

cd olrang

cd frontend/backend

npm run build/npm run start

 

 

 

GitHub에 파일을 업로드할 때 

 

나는 vscode로 개발했고 .gitignore가 있었다.

 

근데 그대로 올려서 clone으로 내려받았더니 npm start가 안됐다.

 

문제는 .gitignore에 node_modules가 포함되어 있어 GitHub에는 backend, frontend 하위의 저 폴더가 업로드 되지 않아 npm start 명령어가 먹히지 않았던 것이다.

 

구글링해보니 package.json이 저 폴더를 대체할 수 있으며 node_modules는 내용이 많아서 git에 올리지 않는다고 하는 글을 봤다.

 

근데 나는 node_modules 폴더를 올리지 않으니 서버 명령어가 안 먹혔고 올리고 난 후에는 잘 동작한다.

 

 

npm start 명령 수행 위치

 

나는 기본 경로(ubuntu@ip~)에서 npm start하면 안 먹힌다.

 

vscode에서 개발했다면 frontend 폴더에서 npm run build한 후 backend 폴더로 이동해 npm run start 명령어를 사용하는 방식으로 구동했을 텐데 여기서도 그렇게 해야한다.

 

 그러니까 기본 경로에서 cd 명령어를 이용해 frontend, backend 폴더로 이동한 후 vscode에서 하던 것처럼 구동 명령어를 해주면 된다.

 

 

 

닫는 글


 

배포를 진행하면서 진지하게 고민했는데 일단 결제 기능 구현되고 나면 부족했던 로그인, frontend에 alter 삽입하기 등을 다시 잡아볼 생각이다.

 

원래는 빨리 끝내고 포트폴리오를 하나 더 만들 생각이었는데 이것도 제대로 못하는 데 양이 많아봤자 무슨 소용이냐는 생각이 들었다.

 

 

아래는 public ip로 접속한 페이지!

 

 

 

현재는 DB 이용이 안된다.

 

개발 시에 로컬 기준으로 동작하도록 구현했기 때문이다.

 

다음은 배포한 주소에서도 DB사용이 가능하도록 하는 내용의 포스팅이다.

 

 

기록용!

 

구글링하면 해당 폴더 하위에 .git 폴더가 있어서 삭제하고 push하라고 한다.

 

근데 내 눈엔 아무리 봐도 .git 폴더가 안 보여서 삭제를 하고 싶어도 할 수가 없었다.

 

알고보니 파일 탐색기에서 숨김 폴더 보기를 체크해야 볼 수 있었다.

 

.git 폴더는 기본적으로 숨김 되어져 있다. 반드시 기억하자!

'포트폴리오(종료)' 카테고리의 다른 글

웹 애플리케이션 포트폴리오(Backend)  (0) 2021.07.11

 

++세션&쿠키로 로그인 구현

https://codelist.tistory.com/85

 

[Node.js] 세션 구현하기 (express-session)

세션 구현 시도 https://codelist.tistory.com/62 [Vue.js, Node.js] 쿠키로 로그인/로그아웃 구현 여는 글 쿠키는 보안상 좋지 않아서 쿠키만으로는 로그인/로그아웃을 구현하기엔 좋지 않다. 대부분은 세션+

codelist.tistory.com

 

 

여는 글


 

 

쿠키는 보안상 좋지 않아서 쿠키만으로는 로그인/로그아웃을 구현하기엔 좋지 않다.

 

대부분은 세션+쿠키를 사용하는 것 같다.

 

그래서 나도 처음엔 세션부터 구현하려고 했다.

 

세션에는 그냥 메모리에 저장하는 방식, 파일로 저장하는 방식, DB에 저장하는 방식이 있고 실제로는 파일이나 DB에 저장하는 방식이 좋다고 하고 많이 쓰인다고 한다.

 

그래도 일단 세션이 되는 지 안 되는 지 테스트 해볼겸 메모리 저장하는 방식을 택하고 구현을 했는데 안됐다.

 

세션에 값을 저장할 때 KEY를 생성해서 쓰던데, 예를 들어 req.session.user 이런 식으로.

 

근데 나는 user 라는 KEY 생성 자체가 안됐다.

 

그래서 내가 설정을 덜 했나보다, 키를 먼저 명시를 해줘야하나? 라고 생각해서 3일 동안 구글링했는데 다른 사람들은 별도로 명시하지 않고 바로 사용했고 명시하지 않아도 된다는 글도 있어서 그냥 내가 안되는 거구나, 생각하고 그럼 파일에 저장하는 형식으로 바꾸자, 라고 생각한 후 구현하기 시작했다.

 

근데 파일에 저장하는 형식도 안됐다.

 

보통 node.js 하위에 폴더를 생성하고, 로그인 하게되면 그 생성된 폴더 하위에 키나 데이터 등이 저장된 파일이 생기는데 나는 폴더는 생기는 데 파일이 안 생겼다.

 

그래서 DB에 저장하는 방식으로 바꿨다.

 

일단 나는 이미 DB를 쓰고 있기 때문에 구현하기 더 쉬울 것 같다고 생각했는데 로그인하면 값이 DB에 저장은 당연히 된다.

 

원래도 회원가입 때문에 CREATE 기능을 쓰고 있었으니까.

 

근데 세션을 못 쓰니까 로그인 유지를 어떻게 구현할까 고민하다가 쿠키를 사용하기로 했다.

 

쿠키에 값이 존재하면 로그인 된 상태라는 조건으로 구현하는 것으로.

 

그래서 여기까지는 나름 괜찮았다.

 

근데 이제 로그아웃이 문제였다.

 

로그아웃 버튼을 누르면 쿠키는 잘 삭제가 된다.

 

근데 DB에서 로그인할 때 넣은 session 값이 삭제가 안된다.

 

나는 mongoDB 쓰기 때문에 remove, deleteMany, deleteOne 이런 데이터 삭제 함수들을 써야했는데 이거 3개 다 동작하지 않았다.

 

그래서 여러 테스트를 해본 결과 삭제 함수만 동작이 안된다.

 

create, find 다 잘 되는 데 삭제만 안된다.

 

그래서 결론은, 로그인 가지고 일주일을 붙잡고 있었는데 쿠키로만 구현하게 됐다.

 

쿠키에는 보안상 password를 절대 넣어선 안된다.

 

그래서 나도 name을 넣기로 했다.

 

 

 

쿠키로 로그인/로그아웃 구현하기


 

모든 코드는 github에 올려져 있다.

 

 

backend/routes/index.js

router.post('/login', (req, res) => {
  console.log('로그인 중');
  User.find((err, users) => { // 평문끼리비교하는거라 배포시에는 이렇게 하면 안됨 암호화 필수
    users.forEach((list) => {
      if (req.body.id == '' || req.body.password == ''){
        console.log('로그인 불가');
        return;
      }

      if(list.id == req.body.id && list.password == req.body.password) {
          console.log('로그인 성공!');
          res.cookie('session', list.name);
          console.log(req.cookies.session);
          res.redirect('/');

      }else if (list.id != req.body.id && list.password == req.body.password)  {
          console.log('아이디가 틀렸습니다.');

      } else if (list.id == req.body.id && list.password != req.body.password) {
        console.log('비밀번호가 틀렸습니다.');

      } 
    })
  })
})

router.get('/logout', (req, res) => {
  User.find((err, users) => { // 평문끼리비교하는거라 배포시에는 이렇게 하면 안됨 암호화 필수
    users.forEach((list) => {
      if (req.cookies.session == list.name){
        res.clearCookie('session');
        res.redirect('/');
      }
    })
  })

})

 

 

backend/app.js

app.use('/login', userControll);

app.use('/logout', userControll);

 

 

frontend/src/components/LogInPage.vue

<template>
  <div class="loginpage">
      <form action="/login" method="post">
       <h2>LOG IN</h2> <br>
        <input type="text" name="id" placeholder="ID" autofocus pattern="^(?=.*\d)(?=.*[a-z]).{5,15}"> <br>
        <input type="text" name="password" placeholder="PASSWORD" pattern="^(?=.*\d)(?=.*[a-z]).{8,15}"> <br>
        <button @click="login()">LOG IN</button>
    </form>
  </div>
</template>

<script>
export default {
    name : "LogInPage",
        data (){
        return {
            id : '',
            password : '',

        }
    },
    methods : {
        login(){
            this.axios.post('http://localhost:3000/login',  { 
            headers : {
                "Content-Type" : "application/x-www-form-urlencoded"
            },
            id : this.id,
            password : this.password
                
            }).then((response) => { //이 부분이 아예 동작 안함
                    alert(response.data.message); 
                
            
                
            }).catch((error) => {  
                this.error=error    
            
                
            })

        }
    }

}
</script>


<style>

.loginpage {
    display: inline-block;
    width : 50%;
    background-color: #C8D4E0;
    padding: 5%;
    margin-bottom: 5%;
}

.loginpage input {
    margin: 3%;
    height: 30px;
    font-size: large;
}

.loginpage button {
    font-size: large;
    background-color: #7E868E;
    margin-top: 5%;
    width : 15%;
}

@media screen and (max-width:768px){
    .loginpage {
        width : 80%;
    }

    .loginpage input {
        height : 15px;
        font-size : small;
    }

    .loginpage button {
        font-size : small;
        width : 30%;
    }
}

</style>

 

 

frontend/src/components/LogOutPage.vue

<template>
  <div class="logoutpage">
    <form action="/logout" method="get">
        <button @click="logout()">LOG OUT</button>
    </form>
  </div>
</template>

<script>
export default {
    name : "LogOutPage",
        methods : {
        logout(){
            this.axios.get('http://localhost:3000/logout',  { 
                headers : {
                    "Content-Type" : "application/x-www-form-urlencoded"
                },
                    
                }).then((response) => { //이 부분이 아예 동작 안함
                        alert(response.data.message); 
                    
            
                }).catch((error) => {  
                    this.error=error    
                
                    
            })
        }
  }

}
</script>

<style>

</style>

 

페이지 연결은 frontend/router/index.js 에서 하면 된다.

 

 

 

닫는 글


 

내가 원하던 대로 구현하진 못했지만 이번 기회에 세션, 쿠키를 써볼 수 있는 좋은 경험이었다.

 

추후에는 요즘에 많이 쓰는 네이버/카카오 로그인 API를 구현해보고 싶다.

 

나는 자체적으로 회원가입을 구현해버려서 API를 쓰기엔 아까워서 쓰지 못했지만.

 

다음은 결제 기능이다.

 

결제 기능은 또 얼마나 헤매게 될 지 모르겠지만 워낙 구현하고 싶었던 기능이라서 기대된다.

 

 

 

++해결

 

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

여는 글 먼저 내가 어떤 기능을 구현하고 싶었는 지 간단하게 설명하자면 회원가입 시 DB를 조회한 후 아이디가 이미 존재하면 이미 존재하는 아이디라고 alert를 통해 사용자에게 알리는 기능이

codelist.tistory.com

 

 

 

아래 글은 해결X 삽질 기록

 

여는 글


 

 

저번 포스팅에서 id 중복체크 기능을 구현했고 이를 사용자에게 알리기 위해 팝업창을 띄우는 기능이었다.

 

3일 동안 해결하려 했지만(사실 3일이면 오래 붙잡은 편도 아니지만 계속 붙잡으면 다른 기능 구현할 시간이 없기 때문에 눈물을 머금고 넘긴다..) 도저히 못 하겠어서, 그래도 추후 고치게 된다면 같은 삽질은 하지 말자라는 개념으로 삽질 기록을 남기려고 한다.

 

 

시도해 본 방법


 

Node.js에서

 

 

1. response.send 사용하기

 

backend/routes/index.js

router.post('/signup', (request, response) => {
  console.log('success served');
  var ck = true;
  User.find((err, users) => { //id 중복체크
      users.forEach((item) => {
        if(item.id == request.body.id){
          ck = false;
          response.send("<script>alert('사용할 수 없는 ID입니다');</script>"); //이 부분
        }
        
      })
    if(ck==true){
      User.create ({
        id:request.body.id,
        password:request.body.password,
        name:request.body.name,
        address:request.body.postcode + ' ' + request.body.roadAddress + ' ' + request.body.detailAddress + request.body.extraAddress,
        phone:request.body.phone,
      });
    }
});


});

 

저렇게 하면 팝업창은 잘 뜨는데 뜨고 나면 페이지가 빈 화면으로 바뀐다.

 

뒤로가기해도 안된다.

 

 

2. 그래서 response.send 밑에 response.redirect를 넣어봤다.

 

일단 alert 띄우고 다시 회원가입페이지로 넘어가길 바랬는데 오류가 떴고 오류를 구글링해보니 send(또는 write, json까지 다 해봤다)와 redirect 연속 사용은 안된다는 내용인 것 같다.

 

서버에 한 번에 요청을 두 번 보내게 되서 에러가 난다는 듯 하다.

 

+ redirect 단독으로만 사용했을 때는 redirect('http://localhost:3000');은 되지만 redirect('http://localhost:3000/signup');은 404에러가 났다.

 

 

 

3. response.send말고 response.render를 사용해봤다.

 

 

render는 해당 페이지에 텍스트를 보낼 수 있다.

 

예를 들어 backend/routes/index.js

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

 

위 코드는 기본으로 제공되는 코드이고 저렇게 작성해 놓으면 backend/views/index.js에 <%= title %>에 Express라는 텍스트가 출력된다.

 

근데 render를 사용하려면 페이지 파일이 nodejs쪽에 있어야 했다.

 

즉 내 경우에는 backend/views 아래에 페이지 파일이 있어야했지만 나는 frontend/src 밑에 있었기 때문에 경로 에러가 떴고 render 기본 경로는 backend/app.js에서 고칠 수 있다고 해서 고쳤는데도 똑같은 경로 에러가 났다.

 

backend/app.js

var views = [
  path.join(__dirname, 'views')
]

app.set('views', views);

 

여기를 보면 기본 경로가 views로 되어있고 이 views는 backend/views 하위 파일들을 사용할 수 있도록 등록한다는 것을 의미한다.

 

그래서 나는 views 경로를 배열로 만들어서 frontend/src 경로도 연결해주었고 연결된 것까지 에러 출력된 것을 보고 확인했는데 에러가 떠서 포기했다.

(에러 코드에 보면 frontend/src/components에서 못 찾겠다고 출력된다.)

 

이외에도 popup 패키지 설치, renderVue 패키지 설치 등등 해봤지만 만족할 만한 결과를 얻지 못했다.

 

 

 

Vue.js에서

 

그렇다면 다시 response.json으로 돌아가서, 여기까지는 그래도 실행이 된다.

 

빈 화면에 텍스트만 나와서 그렇지.

 

그렇다면 vue에서 response를 받아서 alert를 실행하도록 하면 되지 않을까? 라고 생각했다.

 

이게 제일 이상적인 방법이기도 했고 구글링했을 때도 다른 분들은 잘 되는 듯 했다.

 

먼저 backend/routes/index.js에서

response.json({message : '사용할 수 없는 ID입니다.'})

 

이렇게 작성하고 frontend/src/components/SignUpPage.vue에서

 methods : {
        signup() {
            this.axios.post('http://localhost:3000/signup',  { 
            headers : {
                "Content-Type" : "application/x-www-form-urlencoded"
            },
            id : this.id,
            password : this.password,
            name : this.name,
            address : this.postcode,
            phone : this.phone
                
            }).then((response) => { // 여기
                    alert(response.data.message); 
                
                
            }).catch((error) => {  
                this.error=error    
            
                
            })
        
        },

 

이렇게 해주면 되지 않을까라고 생각했다.

 

실제로 이렇게 하면 실행된다는 포스팅을 여러 번 보기도 했고.

 

근데 난 안된다.

 

그래서 response 함수의 문제인가 해서 여러 번 테스트해봤다.

 

먼저 response를 받긴 하는 건지 궁금해서 console.log를 써서 확인해보려고 했는데 console.log가 아예 동작하지 않는다.

 

response를 못 받아서? 그래서 무조건 실행되도록 함수 밖에 써봤는 데도 안 먹히는 걸보고 frontend에서는 console 명령어가 아예 안 먹는 것 같다.

 

backend에서는 잘 돌아가지만. 

 

 

 

결론


 

backend에서는 respose.send든 json이든 write든 메시지를 잘 보낸다. 

 

앞에서도 말했지만 빈 화면에 텍스트를 잘 출력한다.

 

그렇다면 두 가지로 원인을 추측 해볼 수 있다.

 

node.js에서 Vue로 아예 전달이 안된다.

 

전달은 됐지만 Vue에서 node.js 메시지 핸들링을 못하고 있다.

 

내 경험상 보통 vue가 안 될때가 잦아서 아마 이번에도 후자의 이유이지 않을까...

 

 

닫는 글


 

Node.js 공부의 필요성을 뼈저리게 느꼈다.

 

로그인 기능처럼 필수 기능이 아니라서 일단은 넘어가긴 하는데...

(id 중복 생성은 안되게 해 놓은 상태고 그걸 사용자한테 알리는 기능이 안되는 것이다)