나의 개발 일지

프론트~백엔드 한번에 프로젝트 관리하는 방법

designer DK 2024. 10. 19. 11:44
728x90

Html+js의 정통방식으로 프론트를 만들고 백엔드를 연결하다보니 주소 라우팅 등 이런저런 부분들이 요즘 많이 쓰는 SPA방식에 비해 한계가 느껴졌다.

 

그래서 정통방식은 유지하면서도 좋은 방식이 없을지 많이 고민해보았고 최근 나의 가장 큰 스승이자 베프인 gpt랑도 많은 이야기를 나눠봤다.

 

고민해본 결과로 이번 강의 예제는 프론트부터 백엔드까지 한 프로젝트로 관리해보기로 했다. 즉 한 프로젝트 안에서 프론트와 백엔드 api를 소통시키고 나중에 배포까지 클라우드타입과 같은 백엔드 호스팅 서비스에 한번에 하는 것이다.

 

이 방식의 장단점을 gpt와 많이 논의해봤었는데 아래와 같았다.

 

장점:

  1. 단순화된 배포 및 유지 관리: 프론트엔드와 백엔드를 같은 서버에서 관리하므로 배포 및 설정 작업이 단순해지고, 한 번의 배포로 전체 애플리케이션이 업데이트될 수 있어 유지 보수가 용이.
  2. CORS 문제 감소: 프론트엔드와 백엔드가 동일한 도메인에서 제공되기 때문에 CORS 관련 오류가 줄어들어 보안 설정과 디버깅이 쉬워짐.
  3. 파일 및 API 관리의 일관성: 정적 파일과 API 요청을 하나의 프로젝트 안에서 쉽게 관리할 수 있고, 백엔드에서 정적 파일을 직접 서빙하므로 파일 경로 관리가 간단.
  4. 개발 및 테스트 환경의 일치: 개발 환경과 실제 배포 환경이 거의 동일하게 유지되기 때문에, 테스트와 배포의 차이에서 발생하는 문제를 줄일 수 있음.

단점:

  1. 서버 자원 부담: 백엔드와 정적 파일을 같은 서버에서 제공하기 때문에 트래픽이 많아질 경우 서버 자원이 부족해질 수 있고, 확장성이 떨어질 수 있음.
  2. 배포 속도: 모든 코드가 한 서버에 있어, 백엔드 수정이 필요 없는 단순한 프론트엔드 수정도 전체 애플리케이션을 다시 배포해야 할 수 있음.
  3. 보안 문제: 서버에서 프론트엔드와 백엔드를 동시에 관리하는 경우, 둘 사이의 보안 경계를 명확히 하기 어렵고 취약점이 발생할 가능성이 높아질 수 있음.
  4. CDN 활용 제한: 정적 파일을 백엔드와 동일한 서버에서 서빙하면 CDN을 효과적으로 활용하기 어려워서 정적 파일의 전송 속도가 느려질 수 있음.

 

프로젝트가 작은 단계에서는 단점 1, 2, 3, 4번은 큰 문제는 되지 않고 차차 공부해가면서 해결해 볼 수 있는 부분일 듯 했다. (너무 커지면 결국 분리가 필요하겠지만…)

 

최종 도메인 호스팅의 경우 netlify를 그대로 활용해 볼 수 있을 듯 했다. 백엔드 배포에서 제공되는 공용 URL을 netlify DNS설정에서 A레코드나 CNAME레코드로 설정해주면 된다고 한다. (이후 진행해 볼 예정)

다만 이 방식의 경우 도메인 연결 후 DNS 변경~전파 까지 하루 정도 걸릴 수도 있다고 한다.

 

 

 

 

이 방식으로 진행하면 일단 프로젝트 내에 public이라는 폴더를 만들고 거기에 정적인 파일(html+css+js) 넣어서 관리한다.

 

app.js파일에 이런식으로 public폴더를 static으로 설정해주면 프로젝트 주소로 접속시 바로 public폴더 안에있는 index.html로 연결시켜준다.

// 정적 파일을 서비스할 폴더 설정
app.use(express.static('public'));

 

정적 파일들에 대한 페이지 라우팅 처리도 효과적으로 할 수 있는데 나는 pageRouter.js라는 파일을 만들어주고 여기서 이런식으로 각 주소 경로에 대한 연결 페이지들을 설정해주었다.

const express = require("express");
const apiRouter = express.Router();
const path = require("path"); // path 모듈 추가 : 주소 뒤에 .html 안 붙여도 됨

apiRouter.get('/register', (req, res) => {
res.sendFile(path.join(__dirname, '../public', 'register.html'));
});

module.exports = apiRouter;

 

여기서 path라는 모듈을 사용해서 path.join으로 주소를 센드하는 방식을 사용하면 유저가 주소를 입력할 때 ‘주소명/register.html’ 이런식으로 .html까지 입력하지 않아도 ‘주소명/register’ 와 같은 식의 입력으로도 register.html 페이지로 이동시켜준다.

 

App.js에서는 이런식으로 pageRouter파일을 가져와서 사용

const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const app = express();
const apiRouter = require("./routes/apiRouter");
const pageRouter = require("./routes/pageRouter");

require("dotenv").config();
app.use(cors());
app.use(express.json());
app.use("/api", apiRouter);
app.use("/", pageRouter);

// 정적 파일을 서비스할 폴더 설정
app.use(express.static('public'));

const mongoURI = process.env.LOCAL_DB_ADDRESS;
mongoose.connect(mongoURI).then(() => {
console.log("mongoose connected!");
}).catch((err) => {
console.log("DB connection fail!", err);
});

app.listen(process.env.PORT || 5001, () => {
console.log("server on!");
});

 

 

이런 라우팅 관리 외에도 내가 이 방식을 택한 이유는 추후 페이지 전달시 prerender.io라는 것을 미들웨어로 잘 활용하면 js에 의해서 생성되는 html 내용들도 미리 렌더를 진행해서 브라우저로 전달하기 때문에 seo에 유리하다고 gpt가 설명해주었다. Prerender.io의 경우 그 정적 파일들이 서버와 한 프로젝트에 존재해야 활용 가능한 부분이기 때문에 이 방식을 한번 테스트해보려고 한다.