Firebase Hosting 서비스를 사용하여 지금까지 개발한 서버를 올려보도록 하자.

 

1. 개발 탭의 [Hosting] 을 선택한다.

 

2. [시작하기] 버튼을 눌러 시작한다.

 

3. "npm install -g firebase-tools" 명령어를 통해 firebase tools 를 설치한다.

 

4. 넘어간다.

 

5. [Appnickname] 을 설정 후 [연결 및 계속하기] 버튼을 눌러 다음으로 넘어간다.

 

6. 넘어간다.

 

7. firebase tools 설치가 완료되면 firebase hosting 을 할 프로젝트를 세팅할 폴더를 하나 만든 후 그 위치로 이동한다.

이동 후 "firebase login" 을 실행하여 구글 로그인을 진행한다.

 

8. "firebase init" 을 실행한다.

Yes 선택

 

9. 서버에 추가할 Firebase 서비스를 선택한다.

밑 사진에서는 Database, Firestore, Functions, Hosting, Storage 를 추가한 것이다.

 

10. Project Setup

호스팅 할 Firebase Project를 선택해준다.

 

11. Database Setup

기본인 "database.rules.json" 으로 진행한다.

 

12. Firestore Setup

기본인 "firestore.rules" 와 "firestore.indexes.json" 으로 진행한다.

 

13. Functions Setup

JavaScript, Yes, Yes 를 선택한다.

 

14. Hosting Setup

public, No 를 선택한다.

 

15. Storage Setup

기본인 "storage.rules" 로 진행한다.

 

16. 기본적인 Firebase Hosting 프로젝트가 만들어졌다.

 

17. Firebase Hosting 프로젝트가 있는 곳에서 "firebase serve" 를 실행한 후 "http://localhost:5000" 으로 접속 시

 

기본적인 firebase hosting 모습이 보인다.

 

 

인제 node.js 로 구현한 기존의 서버를 방금 구축해둔 Firebase Hosting 프로젝트 폴더로 옮겨줘야한다.

 

먼저, firebase hosting 프로젝트 폴더에 있는 "firebase.json" 파일을 열어서 아래와 같이 수정해준다.

 

firebase.json

{
  "database": {
    "rules": "database.rules.json"
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites":[{
      "source": "/**",
      "function": "api1"
    }
  ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}
,
    "rewrites":[{
      "source": "/**",
      "function": "api1"
    }
  ]
  
 이 부분을 추가해준것이다.

 

새로 입력되는 URL들은 "api1" 이라는 함수를 호출해서 사용하겠다는 의미이다.

 

 

1. node.js 서버의 "package.json" 의 "dependencies" 항목의 node_modules 들을 Firebase Hosting 폴더에도 설치해줘야한다.

Firebase Hosting 프로젝트 폴더의 "functions" 폴더로 이동한다.

 

2. "npm install ~~~~~~~~~ --save" 로 node.js 서버와 node_modules 를 똑같이 설치해준다.

 

3. node.js 서버의 "views" 폴더를 "functions" 폴더에 "view" 로 이름을 변경한 후 이동시킨다.

 

public 폴더 안에 있는 "stylesheets" 폴더는 hosting 폴더의 public 폴더에 옮겨준다.

 

4. node.js 서버의 "routes" 폴더의 js 파일들을 "functions" 폴더로 옮긴다.

 

functions 폴더 안에 있는 "index.js" 파일에 node.js 서버의 "app.js" 의 내용을 복사 붙여넣기 한다.

붙여넣기 후 hosting의 index.js의 내용을 아래와 같이 수정한다.

 

index.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const functions = require('firebase-functions');

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

const mainRouter = require('./main');
const rpostsRouter = require('./rPosts');
const cpostsRouter = require('./cPosts');
const storageRouter = require('./storage');

var app1 = express();

// request 용량 늘려주기
var bodyParser = require('body-parser');
app1.use(bodyParser.json({limit: '50mb'}));
app1.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

// view engine setup
app1.set('views', path.join(__dirname, 'view'));
app1.set('view engine', 'ejs');

app1.use(logger('dev'));
app1.use(express.json());
// https://sjh836.tistory.com/154
app1.use(express.urlencoded({ extended: true }));
app1.use(cookieParser());
app1.use(express.static(path.join(__dirname, 'public')));

//app1.use('/', indexRouter);
//app1.use('/users', usersRouter);

app1.use('/main', mainRouter);
app1.use('/rPosts', rpostsRouter);
app1.use('/cPosts', cpostsRouter);
app1.use('/storage', storageRouter);

// catch 404 and forward to error handler
app1.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app1.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

const api1 = functions.https.onRequest(app1);

module.exports = {
  api1
  
};

 

express에서 제공하는 방식으로 코드를 작성하고, functions 함수를 이용하여 생성한 api1을 firebase.json 설정으로 넘기는 코드이다.

Firebase 호스팅에서는 express를 Firebase functions을 통하여 구현한다.

 

설정 후 터미널에서 "firebase serve" 로 로컬서버를 열어 테스트를 해본다.

 

Ctrl + C 를 통해 로컬 서버 종료 후 최종적으로 "firebase deploy" 로 Firebase Hosting 서버에 배포하도록 설정한다.

 

firebase deploy 를 실행시킬 경우 6개의 오류와 32개의 경고가 표시되며 배포가 중지된다.

 

Eslint는 코딩 스타일을 점검하는 라이브러리이다.

대략적인 설명은 https://forest71.tistory.com/170 글에서 참고할 수 있다. 

 

firebase deploy 시에는 코딩 스타일 준수를 요구하는데,

위의 6개의 에러는 에러라기보다는 규칙 위반으로 심각한 오류를 발생시킬 수 있다는 의미이다.

 

경고는 수정을 하지 않아도 배포가 되므로 수정하지 않고 넘어가도 된다.

52:8   error    Each then() should return a value or throw  promise/always-return 에러의 경우 말그대로 return 을 넣으라는 것이다.

.then(function(firebaseUser)
	{
		// 세션 설정
    //setSession(req, res, firebaseUser.user);
    
		res.render('main/index', {title : "이메일 로그인 완료!!!"});
	})
    
 를
 
 .then(function(firebaseUser)
	{
		// 세션 설정
    //setSession(req, res, firebaseUser.user);
    
		res.render('main/index', {title : "이메일 로그인 완료!!!"});
        return;
	})

 

68:37  error    Use '===' to compare with null              no-eq-null
68:56  error    Expected '===' and instead saw '=='         eqeqeq

에러의 경우는

if (!firebase.auth().currentUser || req.session.userid == null)

를

if (!firebase.auth().currentUser || req.session.userid === null)

 

storage.js 에서 발생한 오류도 위와 같은 오류이므로 설명와 같이 수정하면된다.

 

router.get('/Read', function(req, res, next) {
  firebaseAdmin.firestore().collection('posts').doc(req.query.postsno).get()
  .then((snapshot) => {
    var childData = snapshot.data();

    // 글에 포함된 이미지 링크들 추출
    var gsLinks = getSrc(childData.postsmemo);

    const config = {
      action: 'read',
      expires: '03-17-2030'
    };

    function callback() {
      childData.postsdate = dateFormat (childData.postsdate, "yyyy-mm-dd TT hh:mm:ss");	
      res.render('storage/Read', {row: childData});
    }

    var imgCount = 0;

    if (gsLinks !== null)
    {
      gsLinks.forEach(element => {
        var file = refFromURL(element);
        //console.log(file);
    
        file.getSignedUrl(
        config, (error, url) => {
          if (error) {
            console.log(error);
          }
          childData.postsmemo = childData.postsmemo.replace(element, url);
          imgCount++;
    
          if (imgCount === gsLinks.length)
            return callback();
        });
      });
      return;
    }
    else return callback();
  }).catch((err) => {
    console.log(err);
  });
});

 

then() 에 return 을 추가하고 gsLinks != null 를 gsLinks !== null 로 수정한다.

 

모든 에러를 수정한 후 다시 한번 firebase deploy 로 배포를 시도한다.

 

+  Deploy complete! 

 

라는 문구가 터미널에 표시가 되면 배포가 완료된 것이다. 만약 또 오류와 함께 실패할 경우 오류를 수정해주고 다시 배포를 하자.

 

Firebase console 에 접속하여 Hosting 에 들어가보면 아래와 같이 새로운 배포가 올라가져 있는 것을 확인할 수 있다.

 

위에 있는 도메인을 통해 배포한 웹사이트에 접속해보자.

"firebase 프로젝트 이름.web.app/storage/list" 로 접속하면 아래와 같이 화면이 뜬다면 성공한 것이다.

 

 

 

참고

https://forest71.tistory.com/170

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기