Firebase 동적 호스팅에서 Heroku로 이전

2020년 8월 30일

이전 Firebase 동적 호스팅에 Next.js 배포하기라는 글에서 Next.js를 Firebase 동적 호스팅에 올렸었습니다. 글의 말미에 속도도 잘 나오지도 않아서 Firebase 동적 호스팅을 사용한 Next.js의 배포에 대한 부정적인 의견을 작성하였습니다.

usage

글을 작성한뒤 얼마 더 사용해보고 Firebase 비용 부분을 확인해보니 몇번 호출하지 않았음에도 불구하고 CPU인 부분에서 무료 등급을 초과하는 비용이 발생하였습니다. 그래서 바로 Firebase 동적 호스팅을 내리고 Heroku로 이전 준비를 하였습니다.

개인 테스트용 공간이 목적이다 보니 무료로 쓸 수 있는 공간면에서는 Heroku도 좋을 것이라고 생각했습니다. 서비스가 재시작되기까지 초기 로드가 느리다 하지만 Firebase 동적 호스팅도 초기 속도가 오래 걸렸고 한번 로드가 된 이후에는 속도도 나쁘지 않을 것 같았습니다.

Heroku에 배포하기 위한 설정은 Getting Started on Heroku with Node.js를 참고하니 크게 어려운 것이 없었습니다. 설정을 하고 개인용 도메인을 연동하기 위해서 시도를 하였지만 무료 플랜에서는 개인용 도메인을 설정할 수 있지만 SSL을 사용할 수 없었습니다. 그래서 인지 https로 접근하면 인증서 문제로 사이트에 접속이 불가능했습니다.

개인 도메인을 설정하는 것을 포기하고 Redirect만 시키는 방법을 고려했지만, 필자는 Name Cheap에서 도메인을 구매해서 GCP 네트워크 서비스의 Cloud DNS에 대한 설정을 하고 있는데, 이 Cloud DNS에서 다른 host로 Redirect 설정을 할 수 없는 문제가 있었습니다.

그래서 이번에 Firebase 동적 호스팅 설정했던 것도 있고 이 정도 수준의 요청이라면 Firebase를 사용해도 무료 등급안에서 사용이 가능할 것 같아서 이를 사용하고자 했습니다.

const server = express();

const MAPPING = [['labs.smilecat.dev', 'smilecat-labs.herokuapp.com']];
const DEFAULT_REDIRECT = 'blog.smilecat.dev';

server.get('*', async (req, res) => {
  const protocol = req.headers['x-forwarded-proto'] as string;  const hostname = req.headers['x-forwarded-host'] as string;
  const pathname = req.headers['x-forwarded-url'] as string;  let redirect: string | null = null;

  MAPPING.forEach(([h, r]) => {
    if (hostname !== h) {
      return;
    }
    redirect = r;
  });

  if (!redirect) {
    redirect = DEFAULT_REDIRECT;
  }

  const originalUrl = fullUrl(protocol, hostname, pathname);
  const redirectUrl = fullUrl(protocol, redirect, pathname);

  logger.info(`
  from: ${originalUrl},
  to: ${redirectUrl},
  headers: ${JSON.stringify(req.headers, null, 2)},
  `);
  res.set('Location', redirectUrl);
  res.set(
    `Cache-Control', 'public, max-age=${60 * 60 * 12}, s-maxage=${60 * 60 * 24}`
  );
  res.status(302);
  res.end();
});

export default server;

function fullUrl(protocol: string, host: string, pathname: string): string {
  return url.format({
    protocol,
    host,
    pathname,
  });
}

설정 및 코드 작성은 Firebase 동적 호스팅에 Next.js 배포하기라는 글에서 언급했던 것에서 크게 다른 부분은 없습니다. 다만 요청의 host를 사용하면 Firebase Functions의 주소로 들어오기 때문에 req.headers'x-forwarded-xxxx'를 참고하여 사용해야 하는 부분 정도만 주의하면 될 것 같습니다.

추가 1

Setting up a Custom Domain name and FREE SSL certificate for Heroku Apps라는 글에서 CloudFlare을 통해서 Heroku 무료 플랜에서 SSL 사용을 할 수 있다고 하여 이에 대해 적용을 해서 사용해보고 있습니다. 이번에 Cloud DNS를 CloudFlare의 DNS로 이전해서 관리해볼 생각입니다.

추가 2

CloudFlare을 통해서 Heroku 무료 플랜에서 SSL에 대한 처리가 되긴 하였습니다. 다만 필자의 경우에는 3차 도메인 중 lab만을 Heroku에서 사용하고, 다른 3차 도메인 중에는 Firebase에서 Blog호스팅 용도로 사용하는 경우도 있는데 이 경우에 반대로 오류가 발생하는 문제가 있어 적용하지 못했습니다.

추가 3

다시 한번 설정을 시도해 보니 Heroku의 DNS TargetCNAME으로 등록하고 SSL/TLS를 가변으로 설정하고, Firebase를 사용하는 레코드들에 대해서는 프록싱을 제외해주면 당초 의도했던 대로 Heroku에 도메인을 설정하는 것과 Firebase Hosting 도메인 모두 잘 동작합니다.

Recently posts
© 2016-2023 smilecat.dev