사용자가 작성한 코드를 컴퓨터 언어로 번역하여 (
컴파일 과정)
컴파일된 코드를 실제 실행할 수 있는 상태로 만들어 (빌드)
빌드가 완성된 실행 가능한 파일을 다른 사용자가 접근할 수 있는 환경에 배치하는 것
→실무에서는 컴퓨터 종료 시, 서버가 꺼지기 때문에 yarn start:dev 명령어가 24시간 실행되고 있는( 서버가 켜져있는 ) 컴퓨터에서 배포를 진행
❓클라우드 사용 이유
서버 사용자가 많아지면 트래픽 증감 문제 발생 →Cloud Provider에서 컴퓨터를 빌려서, 빌린 컴퓨터를 사용하여 배포를 진행
Cloud Provider i.e) 아마존, Google, Microsoft
클라우드 서비스 i.e) AWS(아마존), GCP(구글), Azure(마이크로소프트)

📍up과 up -d의 차이
up
- 언제든지 control + c 로 서버 종료 가능 : 해당 터미널내에서만 서버가 열리게 되는 Foreground Process(포그라운드 프로세스)
- 서버가 올라가는 로그를 눈으로 확인 가능
- 서버 종료가 쉽게 이루어지기 때문에 실제 배포는 포그라운드에서 진행되지 않음
up -d
- 화면 뒤에서 서버가 실행되는 Background Process(백그라운드 프로세스)
- 서버가 올라가는 로그가 눈에 보이지 않음
- 실제 배포는 백그라운드로 이뤄짐
모든 사람들이 3000번 port로 접속할 수 있게끔 방화벽을 여는 작업이 필요
소스 IP 범위를 입력 : 0.0.0.0/0 범위로 지정한다면 누구든지 접속 가능하다는 뜻
TCP는 연결이 성공해야지만 통신이 가능하고, 신뢰성 있는 데이터를 전송(정확성 추구).UDP는 연결 없이 통신이 가능하고, 신뢰성을 보장해 주지 않아 안전성이 떨어짐, but 속도 빠름리눅스에서 특정 명령을 실행하거나 파일에 접근하기 위해서는 루트(root) 권한이 필요
사용자가 root 권한을 사용하기 위해서 sudo라는 명령어를 사용
sudo 명령에 대한 사용 권한은 해당 사용자 계정이 sudo 그룹에 소속되어 있느냐에 의해 결정됨
sudo 그룹에 소속된 사용자만이 sudo 명령을 사용할 수 있음
사용자에게 sudo 권한을 부여하거나 해제하고 싶을 시, sudo 그룹에 사용자를 추가/삭제하면 됨.
local : 우리가 각자의 컴퓨터로 계속 작업하고 있었던 환경 →localhost를 사용하는 개발 환경, 여기서 배포하면 내 컴퓨터에서만 접근 가능
dev : 나 혼자만의 작업환경을 넘어서, 프론트엔드와 백엔드를 합쳐서 테스트 해 볼 환경이 필요, 개발자들이 실제 서버 환경에서 테스트 하면서 개발 가능
네번째로 prod 단계
prod : 개발을 완성한 다음에 실제로 서비스를 배포하고 운영하는 환경, 여기에 있는 DB는 실제 유저의 DB이기 때문에 매우 중요하고 함부로 삭제하면 안됨
세번째로 stage 단계
stage : 예를 들어 버전 1을 prod에 배포하고 서비스를 운영, 새로운 기능을 추가한 버전2를 dev에서 개발자들이 만듦
버전 2가 실제 서비스에 배포해도 될 정도의 수준으로 완성을 했다면, prod 환경이랑 동일하게 stage 환경을 만들어 stage에 배포를 함 → 기획자, PM, 디자이너 등이 stage에 올라간 것으로 테스트를 함
📍stage는 실서비스 수준으로 배포하기 때문에, 여기서 버그가 발생되지 않는다면 테스트용으로 만들어진 DB만 제외하고, prod로 배포
// auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService, //
) {}
setRefreshToken({ user, res }) {
const refreshToken = this.jwtService.sign(
{ email: user.email, sub: user.id },
{ secret: process.env.REFRESH_TOKEN_KEY, expiresIn: '2w' }, // 수정
);
// 개발환경
res.setHeader('Set-Cookie', `refreshToken=${refreshToken}; path=/;`); // path 설정 반드시 필요!! (소셜로그인에서!!)
// 배포환경
// res.setHeader('Access-Control-Allow-Origin', 'https://myfrontsite.com')
// res.setHeader(
// 'Set-Cookie',
// `refreshToken=${refreshToken}; path=/; domain=.mybacksite.com; SameSite=None; Secure; httpOnly;`
// )
}
getAccessToken({ user }) {
return this.jwtService.sign(
{ email: user.email, sub: user.id },
{ secret: process.env.ACCESS_TOKEN_KEY, expiresIn: '1h' }, // 수정
);
}
}
// jwt-access.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
export class JwtAccessStrategy extends PassportStrategy(Strategy, 'access') {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // req.headers.Authorization...
secretOrKey: process.env.ACCESS_TOKEN_KEY, // 수정
});
}
validate(payload) {
console.log(payload); // { email: c@c.com, sub: qkwefuasdij-012093sd }
return {
email: payload.email,
id: payload.sub,
};
}
}
// jwt-refresh.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-jwt';
export class JwtRefreshStrategy extends PassportStrategy(Strategy, 'refresh') {
constructor() {
super({
jwtFromRequest: (req) => {
const cookie = req.headers.cookie; // console로 찍히는 것 확인
const refreshToken = cookie.replace('refreshToken=', ''); //토큰만 뽑아오기
return refreshToken;
},
secretOrKey: process.env.REFRESH_TOKEN_KEY, // 수정
});
}
validate(payload) {
console.log(payload); // { email: c@c.com, sub: qkwefuasdij-012093sd }
return {
email: payload.email,
id: payload.sub,
};
}
}
// docker-compose.dev.yaml
version: '3.7'
services:
my-backend:
build:
context: .
dockerfile: Dockerfile
# volumes: // 배포 후 refresh 발생을 방지하기 위해 주석 처리
# - ./src:/myfolder/src
env_file:
- ./.env.dev
ports:
- 3000:3000
my-database:
platform: linux/x86_64
image: mysql:latest
environment:
MYSQL_DATABASE: 'mydocker'
MYSQL_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
수학을 잘 못하시나보네요