사용자가 작성한 코드를 컴퓨터 언어로 번역하여 (
컴파일 과정
)
컴파일된 코드를 실제 실행할 수 있는 상태로 만들어 (빌드
)
빌드가 완성된 실행 가능한 파일을 다른 사용자가 접근할 수 있는 환경에 배치하는 것
→실무에서는 컴퓨터 종료 시, 서버가 꺼지기 때문에 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
수학을 잘 못하시나보네요