이때껏 Sveltekit로 간단한 사이트를 몇 개 만들었다. 매번 수동으로 Dokku를 설정하는 것이 번거로워서 이 글에 설정법을 간단히 정리한다.
이 글은 adapter-node
만을 다룬다. adapter-node
의 기본 설정 방법은 https://svelte.dev/docs/kit/adapter-node 에서 확인할 수 있다.
다른 어뎁터로 빌드했다면 적용되지 않는다.
Dokku에 프로젝트를 올리면 herokuish가 package-lock.json
와 package.json
를 확인하여 npm 프로젝트로 인식한다. 그리고 알아서 nodejs 빌드팩으로 프로젝트를 빌드한다. 우리는 빌드 설정 및 실행만 잡아주면 된다.
node.js 빌드팩에 대해서는 https://devcenter.heroku.com/articles/nodejs-support 에서 자세히 확인 할 수 있다.
우선 adapter-node
를 설치한다
npm i -D @sveltejs/adapter-node
svelte.config.js
에 adapter-node
를 연결하고, build output 경로를 설정한다. 최상단의 import adapter
와 kit → adapter 아래의 out
필드를 수정하자.
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter({out: 'build'})
}
};
export default config;
이제 npm run build
를 실행하면 build
폴더 아래에 결과물이 나온다. Dokku가 이것을 실행하게 해야한다.
루트 디렉터리에 Procfile
을 만들고, 아래와 같이 내용을 설정한다.
web: node build
이제 [Sveltekit 빌드 + 알아서 실행] 까지 된다. 하지만 POST 요청시 Cross-site POST form submissions are forbidden
라는 오류가 발생한다. 그러므로, 우리는 Origin 설정을 해야한다. 쉘에서 아래 명령어를 실행한다.
dokku config:set 프로젝트명 ORIGIN=사이트의_http(s)주소
# 예시: dokku config:set samgukji-front ORIGIN=https://samgukji.esm.kr
이렇게만 하면 알아서 Sveltekit이 빌드 및 실행된다.
Cross-site POST form submissions are forbidden 문제
결론적으로 ORIGIN
값을 “브라우저가 보는 사이트 주소”로 설정하면 된다. 사실 이것 때문에 몇시간을 삽질했다.
필자는 다음과 같은 서버 구조를 가지고 있다:
- 사용자는
https://app.esm.kr
로 접속한다. - 로드벨런서는 주소 경로에 따라서
http://app-svelte.inner.esm.kr
과http://app-backend.inner.esm.kr
로 요청을 나눈다. (경로가 /api 로 시작하면 API 서버로 요청을 넘긴다.) - 각 주소에 따라 적절한 VM에 연결이 넘어간다.
- 각 VM에서 Dokku를 통해 설치된 nginx를 거쳐 내부 컨테이너로 HTTP 요청을 넘긴다.
- 로드벨런서 까지는 https를 사용하나, 내부망 통신은 전부 http를 사용한다.
Cross-site POST form submissions are forbidden
오류는 Sveltekit 서버 프로그램이 인식한 도메인(주소)과 실제 받은 요청의 도메인이 다르면 발생한다. 어느 방식으로 인식하는지 몰라서 (1) 로드 벨런서의 Nginx에서 Http Host 헤더도 수정해 봤고, (2) 내부 도메인도 app.esm.kr로 바꾸어봤다. (3) HTTP_PROTO_FOR 등도 설정하여 프로토콜 설정등도 해보았다. 그 외에도 여러 삽질을 했으나 번번히 실패했다.
이 문제는 브라우저가 HTTP 헤더에 담긴 Origin
값과 환경 변수의 들어간 ORIGIN
설정 값과 일치해야 해결된다. 프로토콜(https)도 맞춰줘야 한다. 내부망에서 http를 쓰든, https를 쓰든 상관 없다. 사용자가 https://samgukji.esm.kr
로 접속한다면 ORIGIN=https://samgukji.esm.kr
로 설정하고, http로 접속한다면 ORIGIN=http://samgukji.esm.kr
로 설정한다.
몇가지 실험을 해 보니까, HTTP 헤더의 Host
값 하고는 영 관련이 없어 보인다. HTTP 헤더의 Origin
값을 중점적으로 체크하자.
체크 하는 방법?
sveltekit에 들어오는 모든 요청은 /src/hook.server.js
의 handle
함수를 거치게 된다. 별다른 수가 없다면, 여기서 console.log
를 찍어보고 판단하자. (파일이 없으면 만들면 된다.)
import { redirect } from '@sveltejs/kit'
export async function handle({ event, resolve }) {
console.log(event)
return await resolve(event)
}
그리고 dokku logs ~~~~ -t
를 이용하여 출력을 확인하면 된다. 아래와 같이 나올 것이다:
답글 남기기