윤상석 님의 NestJS 강의를 토대로 한 기록 포스팅 입니다.
NestJS와 DB 연결하기, 환경변수 설정
우선 이번 프로젝트는 몽구스의 도움을 받아 몽고디비를 사용할 것이다.
mysql을 사용하고 싶으면 type orm doc을 읽으면서 사용해보자
몽구스의 도움을 받아보자
npm i @nestjs/mongoose mongoose
몽고디비 atlas로 들어가서 connect 그리고 connect your application선택 후 url 복사
mongodb+srv://acyc0909:<11041104>@cluster0.oiunfvx.mongodb.net/cats?retryWrites=true&w=majority
cats는 데이터베이스 이다.
이 url은 밖에 노출이 되면 안되니 환경 변수를 설정. process.env._______
npm i --save @nestjs/config
app.moduel에 configModule.forRoot()추가
process.env.@@@@@로 .env파일에 있는 환경 변수를 사용한다.
이후 세세한 옵션들은 공식문서를 보며 사용하는 데이터베이스에 맞게 설정하면 된다.
DB 스키마, Controller 설계 & validation
이런 로직을 사용해서 개발 할떄와 배포시의 로깅 처리를 해줄 수 있다.
vaidation 처리를 위한 라이브러리 설치
npm i --save class-validator class-transformer
main에서 vaidation를 동록하면 사용 가능 !
회원가입 서비스 개발&DTO패턴
DTO : 데이터를 오브젝트로 변환하는 객체 +스키마를 service에서 사용하려면 DI를 해줘야한다.
또한 데이터베이스의 스키마를 컨트롤 하려면 각 모듈에서 imports를 해줘야한다.
패스워드 암호화를 위한 라이브러리 설치
npm i bcrypt
npm i -D @types/bcrypt
bcrypnpm i bryptt b
NestJS 협업을 위한 API만들기,Cors문제
프론트 개발자에서 설명을 해주는 문서작성을 위한 express 기반 라이브러리
npm i --save @nestjs/swagger swagger-ui-express
main에서 스웨거 사용을 위한 기본 틀
setup 메서드의 첫 번째 인자 인 api이 스웨거의 엔드포인트이다.
즉, localhost:3000/api 이 url로 들어가면 스웨거 문서가 나온다.
각각 api 마다 컨트롤러 단에서 설명을 붙여줄 수 있다.
dto 파일에서 ApiProperty를 사용해서 스웨거에서 예시 값을 보여줄 수 있다.
response 용 dto를 만들어서 응답 예시도 보여줄 수 있다.
또한 이제 postman을 사용 안해도 스웨거 내에서 api 통신 테스트를 할 수 있다.
PickType을 사용해서 상위 클래스를 상속받아 필요한 속성만 가져올 수 있다.
CORS 문제를 해결하기 위해 main에 코드 추가
origin은 개발할때는 true이다.
하지만 이렇게 하면 어떤 프론트 사이트여도 접근을 할 수 있으니
배포시에는 특정 Url로 사용해야 한다.
백엔드와 프론트 무도 credential을 true로 해줘야한다.
Repository 패턴과 레이어 분리
데이터 베이스에 접근하는 로직이 더 복잡해진다면 비지니스 로직에 집중할 수 없게 되고
그 로직 자체를 테스팅하는것도 어렵고 중복 코드가 많이 발생하게 되어 가독성이 떨어지게 된다.
또한 한 데이터 베이스로 접근하는 로직에서순환 참조가 일어날 수 있다.
물론 순환참조를 해결 할 수 는있지만 가독성이 떨어지게 된다.
그래서 Repository패턴으로 데이터베이스와 직접적으로 연결하는 로직들을
분리 시켜주면 다른 모듈에서 데이터베이스로 접근을 할 떄 단방향적으로
레포지토리 하나만 접근을 하면되고 각각의 비지니스 로직에 집중을 하게 되고 모듈간의 책임 분리도 확실해 진다.
또한 mysql, mongodb, postgrql등등
데이터의 출처가 여러개가 될 때 레포지토리가 없을 경우는
각각의 서비스 단에서의 쿼리문이 달라지게된다.
하지만 레포지토리가 있으면 한 곳에서 쿼리를 다 다듬을 수 있어서
통일한 방식으로 데이터를 접속해서 데이터를 다룰 수 있다.
즉 , Repository는 데이터베이스 중앙 통제실이라고 생각을 하면 편하다.
레포지토리 또한 의존성 주입이 가능한 클래스 이다.
JWT로그인 서비스 & 순환참조모듈과 passport와 인증전략
로그인 서비스를 구현하는 방법은 많다.
쿠키, 세션을 이용할 수도 JWT를 이용할 수도 그냥 토큰을 이용할 수도 있다.
하지만 JWT를 사용하면 웹 백엔드 뿐만 아니라 모바일 애플리케이션에서의 백엔드도 지원하기 위함이다.
발급 받은 jwt는 안전한 곳에 저장을 한다.
보통 로컬스토리지 또는 http onlycookie에 저장을 한다.
secret key를 활용해서 디코딩한 후 request.user에 저정한 후
그 user의 정보를 사용해 글쓰기 api 로직이 실행 된 후 response를 해준다.
필요한 라이브러리 설치
$ npm install --save @nestjs/passport passport passport-local
$ npm install --save-dev @types/passport-local
$ npm install --save @nestjs/jwt passport-jwt
$ npm install --save-dev @types/passport-jwt
아래 로그인과 인증 부분은 순서가 약간 뒤섞여 있으니 한 파트로 보고 구성 및 생각
먼저 auth 모듈로 가서 필요한 모듈들을 imports한다.
PassportModule.register({ defaultStrategy: "jwt", session: false })//stratagy(인증)에 대한 설정
JwtModule.register({ //로그인할 때 쓰인다.
secret: "secretKey",
signOptions: { expiresIn: "1y" },
JWT 로그인
import { JwtService } from '@nestjs/jwt';
사전 사후의 의존성 주입과 모듈간의 import, export를 처리 해준뒤 (이게 처음 제일 어렵)
jwtlogin API를 작성한다.
Header는 환경세팅으로 처리가 되어 있고
알고리즘도 디폴트로 nesjwt에 저장이 되어 있고 secret key는 환경변수에 저장되어 있다.
()
즉,payload만 만들어 주면 된다.
그 후 jwtService의 sign 메소드payload를
넣어주면 토큰이 나온다.
jwtService는 auth module에서 Import 한 JwtModule에서 공급해주는 공급자이다.
인증
그리고 UseGuard 데코레이터를 사용해서 인증을 한다.
Guard 또한 의존성 주입이 가능한 클래스이다.
passport의 AuthGuard를 상속 받았는데 AuthGuard 는 stratagy를 자동으로 실행시켜준다.
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),// 헤더의 토큰으로 부터 토큰을 추출한다.
secretOrKey: process.env.JWT_SECRET,
ignoreExpiration: false,// 만료기간을 무시하지 않고 만료기간을 정한다.
guard에서 stratagy를 자동으로 실행 해주고
그다음 validate(인증부분)를 실행 한다.
클라이언트에게 받은 body(json) 즉, payload로
부터 요청을 보낸 유저에 대한 인증을 진행한다.
여기서 payload인자에는 즉 클라이언트의 모든 요청 정보다 담겨있다.
Validate 함수
payload 인자를 받습니다.
이 인자는 request 객체에서 가져옵니다.
request 객체는 express 프레임워크에서 제공하는 객체로, HTTP 요청에 대한 정보를 포함합니다.
payload 인자는 요청의 본문에서 파싱된 JSON 데이터입니다.
payload 인자로 JWT 토큰을 받습니다.
validate 메서드는 다음과 같이 작동합니다.
1. jwtFromRequest 옵션에 지정된 방법으로 JWT 토큰을 추출합니다.
2. secretOrKey 옵션에 지정된 비밀 키로 JWT 토큰을 해독합니다.
3. JWT 토큰이 유효한지 확인합니다.
JWT 토큰이 유효한 경우 validate 메서드는 payload(이메일) 인자를 가진 유저(cat)의 정보를 반환합니다.
JWT 토큰이 유효하지 않은 경우 validate 메서드는 UnauthorizedException 예외를 발생시킵니다.
JWT 토큰이 유효한지 확인하는 방법은 다음과 같습니다.
1. JWT 토큰의 헤더와 바디를 분리합니다.
2. 헤더에서 alg와 typ 속성을 확인합니다. alg 속성은 토큰의 알고리즘을 나타냅니다. typ 속성은 토큰의 유형을 나타냅니다.
3. 바디에서 sub 속성을 확인합니다. sub 속성은 토큰의 발행자입니다.
4. 토큰의 만료일을 확인합니다. 토큰의 만료일이 현재 시간보다 이전이면 토큰은 유효하지 않습니다.
5. 토큰의 서명을 확인합니다. 토큰의 서명이 유효하지 않으면 토큰은 유효하지 않습니다.
5-1. JwtMoudle.register(로그인)의 secret key와 JwtStrategy(인증)의 secret key가 같아야 인증이 된다.
JWT 토큰이 모든 조건을 만족하면 토큰은 유효합니다. 그렇지 않으면 토큰은 유효하지 않습니다.
Custom decorator
그러면 이렇게 인증된 유저의 정보를 사용할 수 있다.
또한 로그아웃은 프론트 단에서 jwt토큰을 제거하면 로그아웃 처리된 된것이므로
따로 로그아웃 api를 만들 필요가 없다
Swagger API 보안 설정
npm install express-basic-auth
그리고 main에 와서 미들웨어를 추가해 준다.
로그인과 패스워드는 당연하게도 환경변수에 저장한다.
Multer와 미디어 파일 서비스(mp3,mp4,img등)
npm i -D @types/multer
단일 파일
여러개의 파일
모듈에도 imports를 해준다.
dest: 저장될 파일의 위치(서버 폴더안에 있음)
하지만 프론트혹은 포스트맨으로 api를 쏴보면 upload 폴더에 쓰레기 값이 저장된다.
이유 : 두번째 인자인 옵션을 설정안해서.
그래서 multer.option이라는 폴더를 생성해서 정제해준다.
multer를 사용할떄 두번째 인자로 options가 온다.
위 의 파일(옵션)이 그 두번째 인자로 갈것이다.
1. 폴더를 인자로 받아 upload라는 폴더에 다른 폴더를 만들어 준다.( api 분리를 위해// 고양이 사진 업로드 api , 블로그 리뷰 사진 업로드)
2. 그리고 storage라는 메서드에서 folder를 인자로 받고 createfolder메소드가 실행
3.createfolder는 fs.mkdirSync(path.join(__dirname, '..', `uploads`));를 실행하여 폴더를 만든다.
path.join _dirname은 현재 디렉토리를 말하며 .. 은 부모폴더를 말한다.
즉, 현재 폴더의 부모폴더로 가서, uploads라는 폴더를 만들어라 라는 뜻이다.
4.fs.mkdirSync(path.join(__dirname, '..', `uploads/${folder}`)); ==> upload폴더 안에 인자로 받은 폴더명을 가진 폴더를 생성.
여기까지 createfolder를 사용해서 폴더를 만들었다.
5. 그리고 옵션을 설정한 diskStorage메서드 의 반환값에서 '어디에 저장할지'와 '파일이름'을 지정한다.
cb의 두번째 인자가 저장할 경로.
그리고 filename에서는 extname이라는 메서드로 올린파일의 확장자를 추출한다.
그리고 파일 이름이 같으면 에러가 나니 만든 시간을 합쳐서 이름을 겹치지 않게 한다.
이제 위에서 작성한 옵션을 세번째 인자로 준다.
그리고 dist 파일의 upload의 cat로 가보면 업로드한 사진을확인할 수 있다.
여기까지 파일을 업로드 받아 저장을 했다.
이제 저장된 파일을 다시 프론트로 보내는 과정을 보자.
그럼 데이터베이스에는 뭐가 저장이 될까? ==> 바로 그 사진이 있는 경로가 저장이 된다.
서버에 있는 static 파일들을 제공하기 위해 미들웨어를 추가 해야 한다.
또한 express애플리케이션이라고 명시를 해줘야한다.
위와 같이 제네릭으로 명시를 해준다.
prefix: 'media' ==> 바로 url로 접근을 할 수 있게 한다.
반환문을 위와 같이 작성하여 서버에 저장된 파일들을 반환해 준다.
그리고 서비스 단을 이어 붙여 서비스로직과 레포지토리 파일을 작성.
또한 스키마 단에서 디폴트 이미지를 설정해야 한다.
POSTMAN에서 이미지 업로드 테스트 하는법
코드에서 쓴 key인 image와 text가 아닌 file로 변경해 준다. 그리고 파일을 올려서 테스트 가능.
고양이끼리 소통 API(댓글, 좋아요) -DB설계, 컨트롤러 정의
댓글 형태를 리스트 형태로 response로 보내보고자 한다.
id는 누구의 게시글
body에는 dto로 누가 썼는지와 내용이 있다.
id: 댓글의 id
고양이끼리 소통 API(댓글, 좋아요) - 서비스 완성
'모카 스터디 > Nest' 카테고리의 다른 글
NestJS 랜덤 채팅 웹 앱 (풀스택, 소켓 프로그래밍) (0) | 2023.08.01 |
---|---|
프로젝트 배포와 서버 운영 (0) | 2023.08.01 |
NestJS 개요 및 객체지향 디자인 패턴 (0) | 2023.08.01 |
NestJS를 위한 express 핵심 원리 (0) | 2023.08.01 |
Nest JS 로그 및 설정 [John Ahn] (0) | 2023.07.30 |