티스토리 뷰

제목을 보고 찾아오셨다면 웹 개발을 이제 막 배우기 시작한 단계이거나 학원을 수료한지 얼마 안 돼서, React와 Spring boot를 연동하려니 어려움을 겪는 분들이 될 것입니다. 이런 분들이 읽는다고 생각하고 작성하겠습니다.

 

여러분을 위해 한 가지 시나리오를 정해서 예제를 통해 그대로 연동하는 방법을 알려드리겠습니다. 저의 글 쓰는 재주가 부족하여 그냥 따라해보는 게 거의 전부일 것입니다.

이 글을 작성하는 시점의 저는, 아는 게 굉장히 부족하므로 적절하지 못하거나 설명이 부족한 내용이 있을 수도 있습니다. 여러분이 한 번 따라해보며 '대충 이런 식으로 연동이 되는구나~' 하고 이해하는 것이 목표입니다.

찍어 먹어보기 튜토리얼 쯤 된다고 생각하시면 됩니다.

 

환경

배포는 Centos Stream 9 (리눅스)에서 진행하겠습니다.
또, Nginx를 통해 웹 서버를 운영하겠습니다.

저는 이 글에서 개발도 리눅스에서 진행하지만, 상관 없습니다.

Windows를 쓰고 계시다면 Virtualbox, Mac OS를 쓰고 계시다면 Fusion을 사용하시면 리눅스가 설치된 컴퓨터를 따로 준비할 필요가 없습니다. 둘 다 개인적인 용도로는 무료로 사용할 수 있다고 압니다. 다만 Fusion은 가입을 해야합니다.

 

IDE

클라이언트(프론트엔드)는 Visual Studio Code(vscode), 서버(백엔드)는 Intellij Community edition을 사용하겠습니다.
이 글이 필요한 분들 중에는 Intellij Untimate edition을 사용하기 어려운 경우가 있을 수 있으니 Intellij Community edition으로 선택  했습니다.

 

Backend (server)

우선 Spring boot로 서버(백엔드)를 준비 해보겠습니다.

spring initializer 사이트에서 준비를 해보겠습니다.

세팅은 이와 같이 하여 다운로드 받겠습니다.

최근 Gradle이 인기가 있는 것 같지만, 저는 메이븐이 익숙하므로 메이븐으로 설정했습니다. Gradle이 편한 분은 Gradle을 선택하셔도 문제 없을 것입니다.

Spring boot 버전은 그냥 기본적으로 선택 돼 있던 3.1.2를 선택했습니다만, 마음에 드는 버전을 선택해도 문제는 없을 것입니다.

저는 Project Metadata를 기본으로 채워져있는 채로 두었으나, 프로젝트를 진행하려는 여러분은 알맞게 채워주시기 바랍니다.
(그냥 그대로 두셔도 무방하긴 합니다)

Packaging은 Jar를 선택하겠습니다.

자바 버전은 17을 선택했습니다만, 원하는 버전으로 선택해도 문제는 없을 것입니다.

Dependencies(의존성)는 Spring Web만 선택했습니다.

다운로드 받은 파일 압축을 해제하고, Intellij에서 열어줍니다.

저는 demo 폴더에 있는 내용을 /home/gear/workspace/server로 옮긴 뒤에 열었습니다.

우선 우측 하단에서 진행되고 있는 내용이 모두 진행 될때까지 기다립니다.

아마 자동으로 진행 될테지만, 우측의 m 모양 아이콘을 누르고 새로고침 모양을 누릅니다.

그리고 매우 간단한 코드를 작성해봤습니다.

"/" 경로로 POST 요청을 하면 HttpOnly 쿠키를 생성해주고, GET 요청을 하면 해당 쿠키 값을 가져옵니다.
* HttpOnly 쿠키란?
기본적으로 javascript에서 document.cookie로 쿠키에 접근이 가능합니다. 하지만 HttpOnly 속성이 있는 쿠키는 javascript로 접근이 불가능합니다.
딱히 간단한 예제가 떠오르지 않아서 그냥 이렇게 만들어 봤습니다.

처음 GET 요청을 하면 이렇게 기본값을 응답합니다.

개발자도구를 통해 이렇게 POST 요청을 하고나면,

다시 GET 요청을 해보면 이렇게 다른 응답을 하는 것이 보입니다.

 

Frontend (client)

이제 프론트엔드에서 이 API를 사용해봅시다.

우선 React 프로젝트를 준비합니다.

폴더를 하나 만든 뒤, 해당 폴더의 경로에서 다음과 같이 명령어를 입력하여 준비를 합니다.

cd client # client라는 경로를 만들었다고 가정하고, 해당 폴더로 이동합니다.
npm init -y
npm install react react-dom
npm install -D vite

그러고나서 해당 폴더를 vscode로 엽니다.

 

몇 가지 폴더와 파일을 만들어줄건데, 다음과 같습니다.

App.jsx, index.html, jsconfig.json, vite.config.js, pages 폴더, 그 안에 페이지가 될 컴포넌트를 준비합니다.

vite.config.js 내용은 다음과 같습니다:

import path from "path";

/** @type import("vite").UserConfig */
export default {
  esbuild: {
    jsxInject: `import React from "react";`
  },
  resolve: {
    alias: [
      { find: "@pages", replacement: path.resolve(__dirname, "pages") }
    ]
  },
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:8080",
        rewrite: (uri) => uri.replace(/^\/api/, "")
      }
    }
  }
}

/** @type import("vite").UserConfig */는 자동완성을 도와줍니다.

- esbuild.jsxInject 옵션을 통해 jsx 파일들에 공통적으로 react를 import 하게 해줍니다.
- resolve.alias 옵션을 통해 import Home from "./pages/Home"; 대신 import Home from "@pages/Home"; 으로 사용할 수 있게 해줍니다. 지금은 App.jsx와 Home.jsx만 있어서 별로 안 유용해 보일 수 있겠지만, 꽤나 유용할겁니다.
- server.proxy 설정을 통해 백엔드(서버)와 통신을 하도록  해줍니다. "http://localhost:8080/"으로 요청하지 않고, "/api/"로 요청할 수 있게 됩니다. SOP로 고생하지 않게 해줍니다.
rewrite에서 요청 경로의 /api를 제거하는 게 보이는데, 백엔드 서버에서는 "/api/"가 아니라 "/"에 대해 처리하도록 개발 했기 때문입니다.

프록시는 이런 식으로 됩니다:
사용자 ──┤요청├──▶ vite 개발서버(프록시) ──┤요청├──▶ 백엔드 서버
사용자 ◀──┤응답├── vite 개발서버(프록시) ◀──┤응답├─┘
사용자 입장에서 보면 모든 걸 vite 개발 서버에 요청하고, vite 개발 서버가 응답 해 주지요.

예시:
사용자 ──┤GET /api/hello├──▶ vite 개발서버(프록시) ──┤GET /hello├──▶ 백엔드 서버
사용자 ◀──┤200 OK├── vite 개발서버(프록시) ◀──┤200 OK├──┘
설정에 따라 백엔드 서버에 요청할 때 /api/hello에서 /api가 제거되어 /hello로 요청이 됩니다.

jsconfig.json 내용은 다음과 같습니다:

{
  "compilerOptions": {
    "paths": {
      "@pages/*": ["./pages/*"]
    }
  }
}

vite.config.js에서 alias를 설정 해주어서 동작은 제대로 하겠지만, vscode에서는 이를 인식하지 못합니다. 그래서 자동완성도 안 되고, 이상한 경로라고 인식하여 오류 메시지를 띄우기 때문에 불편합니다.
jsconfig.json에서 설정해주어야 자동완성도 되고, 맞지 않는 경로라는 오류 메시지도 안 볼 수 있습니다.

 

package.json의 scripts에는 다음과 같은 내용을 추가해줍니다:

{
  /* 생략 */
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  /* 생략 */
}

- npm run dev: 실시간으로 적용된 화면을 보며 개발 하게 해줍니다
- npm run build: 빌드하여 배포할 수 있게 해줍니다
- npm run preview: 빌드한 결과를 미리 보여줍니다.

index.html에는 다음과 같이 작성합니다:

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script type="module" src="/App.jsx"></script>
</head>
<body>
  <div id="container"></div>
</body>
</html>

script 요소를 보면 App.jsx를 불러오고, type이 module입니다.
리액트 화면 그리기를 위한 요소 #container도 준비 해뒀습니다.

App.jsx는 다음과 같이 작성했습니다:

import Home from "@pages/Home";
import { createRoot } from "react-dom/client";

const container = document.querySelector("#container");
const root = createRoot(container);

root.render(
  <Home />
);

import React from "react";는 필요 없습니다. vite.config.js에서 자동으로 삽입하도록 설정했기 때문입니다.

 

Home.jsx는 다음과 같이 작성했습니다:

import { useState } from "react";

export default function Home() {
  const [name, setName] = useState("");

  const onChange = ({ target }) => {
    setName(target.value);
  }

  const send = async () => {
    await fetch("/api/", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ name })
    });

    setName("");
  };

  const update = async () => {
    const response = await fetch("/api/");
    const name = await response.text();

    setName(name);
  };

  return (
    <div>
      <h1>hello, {name}</h1>

      <input type="text" value={name} onChange={onChange} />
      <button type="button" onClick={send}>send</button> <br />
      <button type="button" onClick={update}>update</button>
    </div>
  );
}

 

한 번 따라 만든 서버와 클라이언트를 실행하여 올바르게 동작하는 것을 확인 해본 뒤에, 배포를 진행 해보세요.

 

배포는 앞서 말씀드렸다시피 Linux(Centos Stream 9)에서 진행하겠습니다.

 

서버 폴더에서 터미널을 열어, mvnw를 통해 빌드 해줍니다.
Windows에서 진행할 경우 mvw 말고 mvw.cmd로 입력 해주시면 될겁니다.

./mvnw package # 리눅스 or 맥북일 경우
.\mvnw.cmd package # windows일 경우

spring initializer를 통해 만들어진 프로젝트에는 실행 가능한 mvnw가 있습니다. 이를 통해 빌드 해줍니다.

빌드가 잘 된 모습입니다. 테스트를 해보겠습니다.

이렇게 실행 해준 뒤 npm run dev로 실행 된 클라이언트에서 테스트 해보면 잘 될 것입니다.

 

우선 demo-0.0.1-SNAPSHOT.jar를 app.jar로 이름 바꾼 뒤 적당한 위치에 옮겼습니다.
이름 안 바꿔도 되고, 안 옮겨도 되는데 개인적으로 그게 편해서 그렇게 했습니다.

아래부터는 정말 리눅스 서버에서 진행하는 내용입니다.

빌드한 파일들 옮기기

 1) demo-0.0.1-SNAPSHOT.jar (저는 app.jar로 이름 바꿨으므로 이제부턴 app.jar로 부르겠습니다)
 2) React 빌드 결과인 dist 폴더 이하 파일들

배포할 리눅스 서버가 아닌 다른 곳에서 작업한 경우 FTP를 통해 파일(demo-0.0.1-SNAPSHOT.jar와, 클라이언트 빌드 결과인 dist 폴더)들을 옮겨주어야 합니다. 가령 파일질라를 통해 전송이 가능합니다.


JRE(여기선 JDK) 준비

배포만 하겠다면 JDK가 아닌 JRE를 설치 해야겠지만, 저는 그냥 JDK를 설치 하겠습니다.
패키지 매니저를 통해 쉽게 설치할 수 있겠지만, 저는 openjdk.org에서 바이너리 파일을 받아 설치 하겠습니다.

아래 링크에서 다운로드 받을 수 있습니다:
https://jdk.java.net/archive/

17 버전 이상인(아까 spring initializer에서 17 버전을 선택 했으므로) JDK 중에서 운영체제에 맞는 것을 골라 다운로드 합니다.
Linux/AArch64 혹은 Linux/x64 중에서 골라야겠지요. 일반적으로 Linux/x64를 고르면 될 것입니다.

lscpu | grep Arch

명령어를 통해 확인할 수 있을텐데, 저는 m2 맥북에서 가상머신으로 동작하고 있으므로 aarch64가 나왔습니다. 그렇지 않은 분들은 대개 x64를 고르시면 될겁니다.

 

tar.gz 파일을 다운로드 받아 파일질라로 옮겨주시거나, 마우스 우클릭 하여 링크 주소를 복사하고 리눅스 서버에서,

curl -O https://download.java.net/java/GA/jdk20.0.1/b4887098932d415489976708ad6d1a4b/9/GPL/openjdk-20.0.1_linux-x64_bin.tar.gz

와 같이 명령어를 입력하여 다운로드 받을 수도 있습니다.

진행이 어려운 경우 구글에 "linux jre 설치"와 같은 키워드로 검색하거나 Chat GPT를 활용하여 jre 설치를 진행하시면 되겠습니다.

 

다운로드가 완료되고 나면, 압축을 해제하고 파일을 옮겨주겠습니다.
적당한 경로가 맞는지는 모르겠지만, 저는 /usr/local/lib/jdk 이하 경로에 옮겨주겠습니다.

압축 해제는 tar 명령어를 통해 합니다.

# 다운로드
curl -O https://download.java.net/java/GA/jdk20.0.1/b4887098932d415489976708ad6d1a4b/9/GPL/openjdk-20.0.1_linux-x64_bin.tar.gz

# 압축 해제
tar zxvf openjdk-20.0.1_linux-x64_bin.tar.gz

# 파일 목록 확인
ls

# 아래와 같은 결과가 나왔다고 가정
jdk-20.0.1
openjdk-20.0.1_linux-x64_bin.tar.gz

# /usr/local/lib/jdk 폴더 생성
sudo mkdir /usr/local/lib/jdk

# 폴더 이동
mv jdk-20.0.1 /usr/local/lib/jdk

cd /usr/local/lib/jdk
ls # openjdk-20.0.1 하나만 조회 될 것입니다.

# 심볼릭 링크 생성
sudo -s openjdk-20.0.1 default

# 환경변수 설정
sudo vim ~/.bash_profile

vim으로 ~/.bash_profile까지 입력하고나면 아래와 같은 화면을 볼 수 있을 것입니다:

방향키를 통해 맨 아래로 내려오면 볼 수 있는 모습일겁니다.
i 키를 눌러서 하단에 "-- 끼워넣기 --" 혹은 "-- insert --"가 보이도록 해주세요.

그리고 아래에 다음과 같은 내용을 입력 해줍니다:

export JAVA_HOME=/usr/local/lib/jdk/default
export PATH=$PATH:$JAVA_HOME/bin

 

입력을 마치고 esc 키를 입력하여 "-- 끼워넣기 --" 혹은 "-- insert --"가 사라지게 한 뒤 콜론(:)을 입력해서 아래에 콜론(:)이 나타나게 합니다:

그러면 명령어를 입력 할 수 있는데, wq 혹은 x를 입력하고 엔터를 입력 해줍니다.

 

그 뒤에 다음과 같이 명령어를 입력 해봅니다:

source ~/.bash_profile
java --version

이처럼 나온다면 올바르게 진행 한 것입니다. JDK 설치는 끝났습니다.

 

서버 실행

그럼 다음으로 백엔드 서버를 실행하도록 하겠습니다. 일반적으로 8080 포트로 실행하지 않을까 싶습니다.
그러므로 그냥 그대로 실행하겠습니다.

 

pwd # 현재 작업중인 경로 확인
ls # 파일 및 폴더 목록 확인

 

demo-0.0.1-SNAPSHOT.jar(저는 app.jar로 바꾸었으므로 앞으로는 app.jar로 부르겠습니다)를 실행해줍니다:

nohup java -jar app.jar &

위에서 테스트 할 때는 그냥 java -jar app.jar였는데 nohup이랑 &가 붙었습니다.

만일 위에서 테스트 할 때 처럼 그냥 java -jar app.jar로 실행하면, 터미널 종료 시 서버도 같이 꺼지게 됩니다. 그래서 터미널을 종료해도 계속 실행될 수 있도록 nohup 명령어를 통해 실행해줍니다.

&는 백그라운드에서 실행되도록 합니다.

 

잘 실행중인지 확인을 해보겠습니다:

ps -ef | grep app.jar

java -jar app.jar가 보입니다. 잘 실행중인 것으로 보입니다만, 몇 가지 확인을 해보겠습니다.

lsof -i :8080 # 띄어쓰기 주의
curl http://localhost:8080

lsof는 열린 파일 목록을 확인하게 해주며, -i 옵션을 통해 포트를 지정하여 확인할 수 있습니다.

curl은 서버와 통신을 해보기 위한 명령어입니다. 올바르게 no-name이 출력되고 있습니다.

 

* 재부팅하면 백엔드 서버는 자동으로 실행되지 않습니다. 직접 실행해주어야 합니다.
자동 실행 어떻게 할 수 있는지는 추후 아래에 추가 할지도 안 할지도...
키워드만 남겨보겠습니다: /etc/rc.local

 

클라이언트

이젠 프론트엔드 배포입니다. nginx를 통해 배포하겠습니다.

nginx 설치는 다음과 같은 과정을 따릅니다. 공식 사이트를 참고하여 설치 진행하겠습니다.

공식 사이트에서 우측의 documentation 링크 -> 본문의 Installing nginx 링크 -> 본문의 Installation on Linux에 있는 packages 링크를 타고 들어가면 다음과 같은 주소로 가집니다:
http://nginx.org/en/linux_packages.html

Centos는 RHEL을 기반으로 만들어졌으므로 RHEL and derivatives를 클릭합니다.

 

아래 명령어를 입력합니다:

sudo yum install -y yum-utils
sudo vim /etc/yum.repos.d/nginx.repo

여기까지 입력하고 나면 vim이라는 편집기를 통해 /etc/yum.repos.d라는 경로의 nginx.repo라는 파일에 텍스트를 입력할 수 있게 됩니다. 만일 command not found 같은 문구가 뜨고, 진행되지 않는다면 vim 대신 vi로 입력 해보시기 바랍니다.

i를 입력하여 입력모드로 바꿔준 뒤, 사이트에서 안내한 다음 글을 붙여넣기(shift + insert) 합니다:

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

입력 모드로 바꿔주면 다음과 같은 문구가 하단에 뜨게 됩니다:

위 처럼 "계속하려면 엔터 혹은 명령을 입력하십시오" 같은 문구가 나오면 그냥 엔터 입력 해준 뒤 붙여넣기 해주면 되고, 이런 문구 없이 "-- 끼워넣기 --"만 조용히 뜬다면 바로 붙여넣기 해주시면 됩니다.

붙여넣기를 하고나면 esc를 입력하여 하단의 "-- 끼워넣기 --"가 없어지도록 한 뒤

콜론(:)을 입력합니다(shift + ;)

이렇게 하단에 콜론(:)이 나타나면 x 혹은 wq를 입력하고 엔터 쳐줍니다.
* 저처럼 읽기 전용 파일을 고치고 있다는 경고 문구가 나타났던 분들은 x! 혹은 wq!와 같이 느낌표를 붙여서 입력 해주셔야 할겁니다.
* 그래도 여전히 진행이 안 되는 분들은 root 계정으로 진행하셔야 할겁니다.

 

cat /etc/yum.repos.d/nginx.repo

이렇게 입력 시 위의 붙여넣은 내용인 [nginx-stable] 어쩌고 내용이 나오면 정상입니다.

그런 다음 마지막 설치 명령어를 입력해주면  설치가 됩니다:

sudo yum install -y nginx

 

배포

nginx 상태를 확인 해보겠습니다.

systemctl status nginx

 

실행중이지 않기 때문에 위와 같은 모습을 보여줍니다.

* 맨 아래 lines 1-4/4 (END)와 같은 글자가 보이고 입력할 수 없는 상태가 됐다고 당황할 필요 없습니다. q를 입력하면 아래와 같이 정상적으로 돌아옵니다:

 

nginx 실행은:

sudo systemctl start nginx

* 마찬가지로 q를 입력하면 됩니다.

 

다만, 노란색으로 disabled라고 써있는 게 보일겁니다. 이는 서버 재부팅 시 nginx가 실행되지 않는다는 의미로 받아들이면 됩니다.
재부팅시에도 실행되도록 하려면 다음과 같은 명령어를 입력합니다:

sudo systemctl enable nginx

enabled로 바뀐 모습을 확인할 수 있습니다.

 

curl 명령어로 한 번 잘 실행중인지 확인 해보겠습니다:

curl -I http://localhost

# 아래와 동일합니다
curl -I http://localhost:80

-I 옵션을 붙여서 헤더만 확인 해봤습니다.

 

이번엔 react 배포 파일을 nginx에서 제공할 수 있도록 해보겠습니다.

우선 nginx 설정을 확인 해보겠습니다:

cd /etc/nginx/conf.d
pwd # 그냥 현재 작업중인 경로가 어딘지 확인 해보라고 적어봤습니다. 안 쳐봐도 됩니다.
ls # 파일 및 폴더 목록 확인 해보라고 적어봤습니다.
vim default.conf

 

아직은 내용을 수정하지 않을 것입니다. 내용 확인만 해보고 :q 명령어를 통해 빠져나갑니다:

 

location 안에 있는 root라는 내용을 보면 /usr/share/nginx/html이라는 경로가 적힌 게 보일겁니다.
수정하지 말고 :q로 빠져나온 뒤 해당 경로로 가봅니다.
실수로 무엇인가 수정 하셨다면 :q!로 빠져나오면 됩니다.

 

cd /usr/share/nginx/html
pwd # 안 쳐봐도 됩니다.
ls # 파일 및 폴더 목록 확인
cat index.html # index.html 내용 확인

index.html과 50x.html이 보입니다.
한 번 index.html 내용을 확인 해보겠습니다.

 

curl 명령어를 통해 확인 해보면 동일한 내용을 확인 해볼 수 있습니다:

curl http://localhost

 

즉 nginx는 여기 있는 파일들을 제공해주고 있습니다.
그러면 리액트 빌드 결과로 덮어씌우면 아까 저희가 만든 사이트가 보여지겠지요:

cd /home/gear/workspace/deploy # 저는 여기에 빌드 결과인 dist 폴더를 뒀습니다.
ls # 그냥 목록 확인 해보는겁니다.
sudo cp -R dist/* /usr/share/nginx/html/

dist 폴더 내에 있는 모든 파일들을 /usr/share/nginx/html에 옮겼습니다.

확인 해보면 다음과 같습니다:

cd /usr/share/nginx/html
ls # 잘 옮겨졌나 확인 (assets가 있는지 보면 됩니다)
curl http://localhost # 아까와는 다른 결과를 보이는 것을 확인할 수 있습니다.

 

하지만 프록시 설정은 vite 개발 서버에 적용된 것이므로, 올바르게 동작하지 않을 것입니다:

centos에 설치된 firefox에서 http://localhost로 접속한 뒤 update 버튼을 클릭해본 모습입니다.
no-name 대신 html 파일 내용이 보여지고 있습니다.

이제 프록시 설정을 해야합니다:

cd /etc/nginx/conf.d
sudo mv default.conf default.conf-backup # 백업 해두려고 한 것입니다만, 사실 필요 없습니다.
# 그냥 sudo rm default.conf 하셔도 됩니다.
sudo vim default.conf

default.conf를 지우고 (혹은 이름을 변경하여 백업 해두고) 새로 작성 해줍니다.
* 단, 백업 해둘 경우 이름이 .conf로 끝나지 않게 해줘야 합니다.

# was는 제가 임의로 정한 이름으로, 다른 이름으로 해도 됩니다
# 다만 다른 이름으로 정하셨으면, 아래에서도 was 대신 그 이름으로 적어주셔야 합니다.
upstream was {
    server localhost:8080; # 8080 포트로 실행 중이므로
}

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        index /index.html;
        try_files $uri /index.html;
    }

    location ^~/api {
        rewrite ^/api(.8) $1 break;
        proxy_pass http://was; # 위에서 정한 upstream 이름
    }
}

만일 저장이 안 된다면 root 계정으로 진행 하셔야 할 것입니다.

try_files

try_files는 무엇이냐면, 가령 React에서 react-router-dom을 통해 /blog와 같은 경로에 대해 라우팅 처리를 했다고 해보겠습니다.
이 때 웹 브라우저에서 주소창에 http://localhost/blog를 입력하면 nginx에서는 /blog에 대한 파일을 찾을 것입니다.
하지만 실제로 그런 파일이 있어서가 아니라 그냥 /blog라는 주소로 요청이 오면 자바스크립트로 그려줄 뿐이죠.
그래서 페이지를 못 찾는다는 응답을 받게 될 것입니다.
그러므로 파일을 못 찾으면 index.html이 응답하도록 하기 위해 이런 설정을 한 것입니다.

^~/api

/api로 시작하는 주소는 Spring boot로 만든 서버로 요청을 넘기게 됩니다.

rewrite ^/api(.*) $1 break;

그런데 백엔드에서는 /api로 시작하는 주소에 대한 처리를 하지 않았습니다. 그래서 앞의 /api는 지워준 다음 요청을 넘겨야 합니다.

 

설정 적용

설정 내용을 저장만 한다고 끝나지 않습니다. 설정이 올바른지 확인하고, 설정 내용을 적용 해주어야 합니다:

nginx -t # 설정이 올바른지 확인 해줍니다.
systemctl reload nginx

이처럼 success라는 문구가 떠야 합니다.

그렇지 않으면...

이렇게 test failed라는 문구가 뜨고, 어디가 잘못됐는지 알려줍니다.

cat 명령어를 통해 확인 해보니 알려준대로 "일부러 이상하게"라는 문구가 적혀있네요.

하지만 설정을 마치고나서 실행해보면

이렇게 백엔드와 통신하는 부분에서 502 Bad Gateway가 발생할 수 있습니다.

이 때에는 SELinux 설정을 의심해볼 수 있습니다:

sestatue
getsebool httpd_can_network_connect

sestatus 명령어를 통해 확인 해보니 SELinux가 enabled 되어 있는 것을 확인할 수 있습니다.
current mode는 enforcing이네요.
그리고 httpd_can_network_connect 값이 off로 돼 있습니다.
사실 전 정확하게는 모르겠지만 이러면 SELinux 정책에 의해 Nginx와 백엔드 간의 통신이 막히는 것 같습니다.

따라서 설정을 변경해주어야 합니다.

setsebool -P httpd_can_network_connect 1 # 값 바꾸기
getsebool httpd_can_network_connect # 값 확인

httpd_can_network_connect 값이 on으로 바뀐 모습

-P를 붙여줘야 재부팅 시에도 다시 적용이 됩니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함