배포 방법
296
작성한 질문수 16
제가 백엔드 강의는 수강한 적이 없어서요, 대신 노드js 교과서 책을 구매해서 가지고 있는데..
우선 프론트는 네트리파이로 배포 완료했습니다
https://admirable-donut-f22cc6.netlify.app/
백엔드 배포는 선생님 책 노드js 교과서 722쪽 AWS 배포하기 부터 보면서 하면 별 문제없지 진행할 수 있을까요? 추가적으로 백엔드쪽 코드 수정이 필요할지..
배포할 레포 구조는 아래 처럼 루트 폴더 하위에 백엔드, 프론트 폴더 각각 있습니다

답변 2
0
저는 제 프로젝트를 배포하는 작업을 진행 중인데, Node.js 교재에서 제공하는 AWS를 이용한 백엔드 배포 방법을 따르고 있습니다. 설명은 직관적이지만 실제로 설정할 때 문제가 생길까봐 걱정이 됩니다. 프론트엔드는 이미 Netlify에 배포되어 있기 때문에 백엔드 코드가 큰 변경 없이 잘 작동할지 확인하고 싶습니다.
그런데 다른 호스팅 옵션을 찾아보다가 Vultr을 발견했어요. 백엔드 호스팅을 위해 정말 좋은 선택인 것 같습니다. 최적화된 VPS 호스팅, 자동 백업, 보안 데이터베이스 관리 등 유용한 기능이 많이 있어서 훨씬 더 쉬운 작업을 할 수 있게 되더군요.
Node.js 앱을 작업 중이거나 MySQL 데이터베이스에 신뢰할 수 있는 호스팅이 필요하다면 Vultr을 추천드립니다. 특히 Managed Databases 서비스는 데이터베이스 관리를 정말 쉽게 해주기 때문에 유용하게 사용할 수 있습니다.
Vultr에서 MySQL을 설치하는 데 유용한 가이드를 공유할게요:
저는 이제 백엔드 배포를 위해 Vultr로 전환할 생각을 하고 있는데, 이 서비스를 사용해보면 여러분에게도 정말 좋은 선택이 될 거라고 확신합니다!
0
백엔드쪽은 책 따라서 하시면 되는데요. cors는 전체 허용을 해두셔야 합니다. 프론트 백엔드 도메인이 서로 다를 것 같아서요. 그래서 로그인 시 쿠키가 전달 안 되는 문제가 있을 수도 있습니다. 쿠키 대신 토큰 로그인을 하는 게 좋으나 책에는 그 부분은 없습니다.
0
AWS lightsail에서 mysql-server 설치하는데 에러가 나서요
책 내용 중
$ sudo apt-get update
$ sudo apt-get install -y gnupg
$ sudo wget https://dev.mysql.com/get/mysql-apt-config_0.8.23-1_all.deb
$ sudo dpkg -i mysql-apt-config_0.8.23-1_all.deb
$ sudo apt update
$ sudo apt-get install -y mysql-server -> 여기서 에러
에러 메세지 -> lightsail mysql server has no installation candidate
비번 설정하시고, Use Legacy Authentication Method 선택하세요.
$ sudo mysql -uroot -p

인스턴스를 지우고 다시 해봐도 똑같습니다
강좌에 백엔드 배포 영상도 있으면 좋을텐데 아쉽네요 ㅜ
0
라이트세일 우분투 고르셨나요? 우분투라면 아래 링크 방법으로 설치 가능합니다.
https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-20-04
데비안같긴 한데 데비안이라면
https://www.digitalocean.com/community/tutorials/how-to-install-the-latest-mysql-on-debian-10
입니다.
0
https://www.digitalocean.com/community/tutorials/how-to-install-the-latest-mysql-on-debian-10
데비안 기준으로 알려주신 위 링크에서 진행 중 아래 단계에서 에러가 나서요

에러 화면

한 5시간째 gpt, 구글링 다 해보고 있는데 mysql 설치가 안되네요 ㅜ
0
데비안 버전 문제로 보이는데요. 중간에 wget 쪽에 문자열을 아래처럼 최신 deb 파일로 수정한 뒤 진행하시면 될겁니다. (라이트세일에서 확인완료)
wget https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb
0
최신 deb 파일로 하니 설치는 잘 되었는는데
이후 mysql 비밀번호 설정하고 git clone 받아서
아파치 서버 종료하고
클론 받은 폴더에서 패키지 설치 후 npm sequelize db:create --ene production 하
access denied for user 'root'@'localhost' 에러가 나서요

<백엔드 코드>

app.js
const express = require("express");
const dotenv = require("dotenv");
const morgan = require("morgan");
const session = require("express-session");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const path = require("path");
const hpp = require("hpp");
const helmet = require("helmet");
const passport = require("passport");
dotenv.config();
const { sequelize } = require("./models");
const passportConfig = require("./passport");
const apiRouter = require("./routes/api");
const webSocket = require("./socket");
const app = express();
app.set("PORT", process.env.PORT || 3095);
sequelize
.sync()
.then(() => {
console.log("DB 연결 성공");
})
.catch(console.error);
passportConfig();
const prod = process.env.NODE_ENV === "production";
if (prod) {
app.enable("trust proxy");
app.use(morgan("combined"));
app.use(helmet({ contentSecurityPolicy: false }));
app.use(hpp());
} else {
app.use(morgan("dev"));
app.use(
cors({
origin: true,
credentials: true,
webSocket: true,
})
);
}
app.use(express.static(path.join(__dirname, "public")));
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
},
};
if (prod) {
sessionOption.cookie.secure = true;
sessionOption.cookie.proxy = true;
}
app.use(session(sessionOption));
app.use(passport.initialize());
app.use(passport.session());
app.use("/api", apiRouter);
app.get("*", (req, res, next) => {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
const server = app.listen(app.get("PORT"), () => {
console.log(`listening on port ${app.get("PORT")}`);
});
webSocket(server, app);config.js
require('dotenv').config();
module.exports = {
"development": {
"username": "root",
"password": process.env.SEQUELIZE_PASSWORD,
"database": "sleact",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": process.env.SEQUELIZE_PASSWORD,
"database": "sleact",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": process.env.SEQUELIZE_PASSWORD,
"database": "sleact",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
.env
COOKIE_SECRET=sleactcookie
MYSQL_PASSWORD=jsmaster
SEQUELIZE_PASSWORD=jsmasterpackage.json
{
"name": "sleact-ts-back",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"dev": "nodemon app",
"start": "cross-env NODE_ENV=production PORT=80 pm2 start app.js"
},
"author": "ZeroCho",
"license": "MIT",
"dependencies": {
"bcrypt": "^5.1.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"helmet": "^4.4.1",
"hpp": "^0.2.3",
"morgan": "^1.10.0",
"multer": "^1.4.2",
"mysql2": "^2.2.5",
"nodemon": "^2.0.7",
"passport": "^0.6.0",
"passport-local": "^1.0.0",
"pm2": "^4.5.4",
"sequelize": "^6.5.0",
"sequelize-cli": "^6.2.0",
"socket.io": "^4.7.5"
}
}
0
앗 .env도 ignore에 포함됐었군요 ㅜ .env도 추가하니 잘 실행 완료되었는데
회원가입에서 500 에러가 나고 있습니다 ㅜ
app.js:2 POST http://43.201.1.136/api/users 500 (Internal Server Error)

<회원가입 클릭 시 코드>
const onSubmit = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
if (!missmatchError && nickname) {
console.log('회원가입 시도');
setSignUpError('');
setSignUpSuccess(false);
// localhost 3090(프론트)가 3095(백엔드)로 보내는 요청
axios
.post('/api/users', {
email,
nickname,
password,
})
.then(() => {
setSignUpSuccess(true);
})
.catch((error) => {
console.log(error.response);
setSignUpError(error.response.data);
})
.finally(() => {});
}
},
[email, nickname, password, passwordCheck, missmatchError],
);http://43.201.1.136/api/users 주소 접속해보면 정상적으로 보이는데.. 어디서 잘못되었는지 모르겠습니다
500 에러(Internal Server Error)의 경우에는 사용자가 아닌 서버 자체의 오류로 인해서 사이트의 모든 페이지에 접근이 불가능한 상태가 발생이라고 하는
서버쪽 코드를 수정해야할까요?
0
브라우저에 /api/users 치는 건 GET이고요. 지금 에러가 나는건 POST입니다. 서버에서 에러 로그 확인해서(pm2 monit) 에러 메시지 따라서 수정해야 합니다.
혹시 sequelize db:create 같은 명령어 수행하셨나요? 데이터베이스, 테이블이 생성되어 있어야 합니다.
0
넵 데이터는 npx sequelize db:create --env production 명령어로 생성했습니다

pm2 monit 실행 했을 때는 아무 내용이 안 나오더라구요

이상한게 회원가입 1번째 클릭엔 500에러인데 2번쨰 클릭에는 이미 사용 중인 아이디라고 403 에러가 뜨고 있습니다
회원가입 정보 db는 추가되고 있는 것 같아요

회원가입 실패한 정보로 로그인 시도를 해보면 200 코드로 나오고 있습니다

db를 초기화해야 할까요?
0

cannot read properties of null(reading 'addMembers') 라고 나오고 있습니다
해당 코드 부분

강의 초반에 아래 단계를 진행했었는데
npm i npx sequelize db:create // mysql db에 sleact 데이터(로우) 생성
npx sequelize db:seed:all // 워크스페이스 > 채널에 가짜 데이터 생성
npm run dev // 테이블 생성
여기서도 똑같이 npx sequelize db:seed:all 이것도 해줘야 하는건가요?
0
아 이제 회원가입은 되는데 로그인이 안 되네요... ㅋㅋㅋ

login response 값으로 {"id":11,"nickname":"qwer","email":"qwer"} 잘 나오는데
user response 값은 false로 나오고 있습니다

<Login.tsx 코드>
const Login = () => {
// useSWR은 get으로 요청한 데이터를 받아와서 저장한다.
// mutate : 내가 원할 때 SWR 호출하기
const { data, error, mutate } = useSWR('/api/users', fetcher, {
dedupingInterval: 5000, // 주기적으로 호출하지만, dedupingInterval 기간 내에는 캐시에서 불러온다
});
const [logInError, setLogInError] = useState(false);
const [email, setEmail, onChangeEmail] = useInput('');
const [password, setPassword] = useInput<string>('');
const onChangePassword = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
},
[email, password, data],
);
const onSubmit = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
setLogInError(false);
axios
.post(
'/api/users/login',
{ email, password },
{
withCredentials: true,
},
)
.then(() => {
mutate();
})
.catch((error) => {
setLogInError(error.response?.status === 401);
});
},
[email, password],
);
if (data) return <Navigate to="/workspace/sleact/channel/일반" />;
return (
<div className="max-w-[400px] mx-auto px-[20px]">
<h1 className="flex flex-col items-center justify-center pt-[60px] pb-[20px]">
<LogoChat color="#444791" />
<span className="mt-[10px] text-primary text-[20px] font-bold">ReChat</span>
<span className="blind">Slack</span>
</h1>
<TextField label="이메일 주소" type="email" value={email} onChange={onChangeEmail} />
<TextField label="비밀번호" type="password" value={password} onChange={onChangePassword} />
{logInError && <p className="mb-[20px] mt-[-10px] text-red-500 font-normal">로그인 실패</p>}
<Button text="로그인" onClick={onSubmit} />
<p className="mt-[10px] text-center">
Slack을 처음 사용하시나요?
<Link to="/sign" className="ml-[4px] text-[#004174]">
회원가입
</Link>
</p>
</div>
);
};로컬에서 돌릴 땐 아무 문제 없는데..
이건 에러 메세지도 보이지 않네요 어디를 봐야 하는 걸까요?
0
네 로컬 서버 환경에서 테스트 해보면 로그인 후의 /api/users 데이터를 console.log로 조회해보니 아래와 같이 담겨있습니다

근데 배포 환경에서는 login response 값에 유저 정보가 있어도 로그인이 되지 않아 /api/users 에는 false로 나오고 있습니다
0
로그인 후에 mutate()를 호출하면 자연스레 /api/users 요청이 다시 가게 됩니다. 네트워크 탭에서 응답을 확인하세요. 그리고 로그인 응답에 쿠키도 정상적으로 심어졌나 확인하시고요.
0
네트워크 탭에서 응답 확인한 내용입니다
login 요청에는 정보가 있으나 user는 여전히 false 이고

애플리케이션 탭에서도 쿠키가 생성되지 않았습니다

해당 부분 강의도 다시 들어봤는데 swr 사용하기(쿠키 공유하기) 강좌 10분 40초에서 지금 제 상황과 완전 동일한 에러에 대해서 설명해주신 내용대로 프론트 서버와 백엔드 서버의 도메인이 다를 경우 쿠키 생성도 안되고 데이터 전달도 안될 때 해야하는 설정 withCredentials: true 옵션도 되어 있습니다.
근데 지금 배포 환경에서는 프론트와 백엔드 도메인도 동일한 상황이라 위 이슈와는 연관은 없어보여서요. Login.tsx 코드를 수정해야할 게 있을까요?
<Login.tsx 코드>
const Login = () => {
// useSWR은 get으로 요청한 데이터를 받아와서 저장한다.
// mutate : 내가 원할 때 SWR 호출하기
const { data, error, mutate } = useSWR('/api/users', fetcher, {
dedupingInterval: 5000, // 주기적으로 호출하지만, dedupingInterval 기간 내에는 캐시에서 불러온다
});
const [logInError, setLogInError] = useState(false);
const [email, setEmail, onChangeEmail] = useInput('');
const [password, setPassword] = useInput<string>('');
const onChangePassword = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
},
[email, password, data],
);
const onSubmit = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
setLogInError(false);
axios
.post(
'/api/users/login',
{ email, password },
{
withCredentials: true,
},
)
.then(() => {
mutate();
})
.catch((error) => {
setLogInError(error.response?.status === 401);
});
},
[email, password],
);
if (data) return <Navigate to="/workspace/sleact/channel/일반" />;
return (
<div className="max-w-[400px] mx-auto px-[20px]">
<h1 className="flex flex-col items-center justify-center pt-[60px] pb-[20px]">
<LogoChat color="#444791" />
<span className="mt-[10px] text-primary text-[20px] font-bold">ReChat</span>
<span className="blind">Slack</span>
</h1>
<TextField label="이메일 주소" type="email" value={email} onChange={onChangeEmail} />
<TextField label="비밀번호" type="password" value={password} onChange={onChangePassword} />
{logInError && <p className="mb-[20px] mt-[-10px] text-red-500 font-normal">로그인 실패</p>}
<Button text="로그인" onClick={onSubmit} />
<p className="mt-[10px] text-center">
Slack을 처음 사용하시나요?
<Link to="/sign" className="ml-[4px] text-[#004174]">
회원가입
</Link>
</p>
</div>
);
};
0

근데 로그인 후에 401 (Unauthorized) 에러가 뜨면서 갑자기 로그아웃 됐다가 알아서 다시 로그인 됐다를 반복하는데.. 이것도 쿠키 문제인가요?
채널리스트나 유저리스트도 간헐적으로 못 불러오는 것 같아요
기본 셋팅과 관련하여
0
91
1
초기 셋팅 back과 front만 남겨두고 다 지운 후 진행 방법
0
96
2
focus 시에만 화면 업데이트 되는 이유 + 해결방법
0
149
2
useEffect 개수 관리
0
109
2
라이브러리 서치 방법
0
103
2
함수 정의 패턴
0
77
1
npm run dev 에러
0
152
3
npx webpack 후 에러
0
178
2
'void' 형식 식의 truthiness를 테스트할 수 없습니다.ts(1345)
0
143
2
사용자 가입시 에러발생 (TypeError: Cannot read properties of null (reading 'addMembers')
1
178
2
초기세팅중 packge.json 에러떠요
0
155
2
CORS - Access-Control-Allow-Origin 누락 문제
0
431
3
로그인 페이지 무한 새로고침 현상
0
598
2
Module not found: Error: Can't resolve './App' 에러
0
955
1
npm run dev 시 빌드가 매우 느려졌습니다
0
989
2
alias 경로 설정 오류
0
448
2
fetcher 함수의 data 값이 두번 찍히는 이유
0
275
1
제네릭 질문
0
217
2
ts-node 대신 tsx 사용여부
0
373
1
배포 관련 질문
0
247
1
[nginx + https] 서비스를 실행하면 niginx가 아닌 서비스 화면을 보여주게 하고 싶습니다.
0
385
2
[배포하기] webpack에 aws 퍼블릭 IPv4 주소 와 포트 주소를 작성하고 나서 빌드후 실행하면 오류가 발생합니다.
0
336
1
users 호출 시 쿠키가 담기지 않는 이슈 질문드립니다.
0
247
2
CORS 에러 질문입니다.
0
267
1








