내일배움캠프 스파르타 코딩클럽
이어서 오늘은 인증, 인가에 대해 살펴보고 게시판 프로젝트를 이어가 보도록 하겠다.
인증(Authentication) :
서비스를 이용하려는 사용자가 인증된 신분을 가진 사람이 맞는지 검증하는 작업을 뜻한다.
일반적으로, 신분증 검사 작업에 해당. 일반적인 사이트의 로그인 기능에 해당함.
인가(Authorization) :
이미 인증된 사용자가 특정 리소스에 접근하거나 특정 작업을 수행할 수 있는 권한이 있는지를
검증하는 작업을 뜻한다. 예를 들어 놀이공원에서 자유 이용권을 소지하고 있는지 확인하는 단계
인증된 사용자 즉, 로그인 된 사용자만 게시글을 작성할 수 있는지 검증한다면, 이 과정을 인가
과정이라고 부름. 인가 기능은 사용자 인증 미들웨어를 통해서 구현할 예정.
[ 회원가입 기능구현 ]
< README.md >
< src / app.js >
< prisma / schema.prisma >
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Users {
userId Int @id @default(autoincrement()) @map("userId")
email String @unique @map("email")
password String @map("password")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
UserInfos UserInfos?
// 사용자(Users) 테이블과 사용자 정보(UserInfos) 테이블이 1:1
// 1명의 사용자는 1개의 사용자 정보를 가진다.
Posts Posts[]
// 사용자(Users) 테이블과 게시글(Posts) 테이블이 1:N
// 1명의 사용자는 여러개의 게시글을 작성할 수 있다. (배열사용)
Comments Comments[]
// 1명의 사용자는 여러개의 댓글을 작성할 수 있다. (배열사용)
@@map("Users")
}
model UserInfos {
userInfoId Int @id @default(autoincrement()) @map("userInfoId")
UserId Int @unique @map("UserId")
name String @map("name")
age Int? @map("age")
// null을 허용 할때는 ? 를 사용 , Optional Parameter(?)
gender String @map("gender")
profileImage String? @map("profileImage")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
// Users 테이블과 관계를 설정합니다.
// 무결성 제약조건 사용자가 삭제된다면 사용자 정보 또한 같이 삭제되도록 Cascade 설정
// onDelete | onUpdate 참조하는 부모모델이 삭제 or 수정될 경우 자식모델이 어떤행위를 할 지 설정합니다.
@@map("UserInfos")
}
model Posts {
postId Int @id @default(autoincrement()) @map("postId")
UserId Int @map("UserId")
// 사용자(Users) 테이블을 참조하는 외래키
title String @map("title")
content String @db.Text @map("content")
// @db.Text 긴 텍스트 사용시, 텍스트 데이터를 효율적으로 저장하고 사용할 수 있음.
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
// Users 테이블 관계를 설정합니다.
Comments Comments[]
// 1개의 게시글에서 여러개의 댓글을 작성할 수 있다.
@@map("Posts")
}
model Comments {
commentId Int @id @default(autoincrement()) @map("commentId")
UserId Int @map("UserId")
PostId Int @map("PostId")
content String @map("content")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
Post Posts @relation(fields: [PostId], references: [postId], onDelete: Cascade)
@@map("Comments")
}
< src/routes/users.router.js >
여기서 알고가야 할 한가지
위와같이 express 는 중괄호로 묶이지 않았고
prisma 같은 경우 중괄호로 묶여있다.
그럼 중괄호를 신경 안쓰고 코딩을 하면 어떻게 될까?
SyntaxError 가 발생하고 만다.
그러면 왜 express 는 중괄호를 사용하지 않아도 되고 prisma 는 중괄호를 사용해야 할까?
- Default Export와 Named Export -
express 같은경우 export 를 할때 export default express 로 하였다.
허나 prisma 는 Named Export 인
export const prisma = new PrismaClient(); 이런 변수 선언과 내보내기를 바로하는 형식으로 작성되거나
export { prisma }; 이미 선언된 변수를 중괄호에 넣음으로써 Named Export 방식으로 쓰였다는 것이다.
그리고 이 또한 알고 가야할 부분이다.
prisma.users.create() 는 users가 prisma schema에서 작성한 Users 와 다르게 users 로 작성해야한다.
그럼 어떻게 설정했든 모두 소문자로 작성을 해야하는건가?
그것은 아니다.
위에 prisma.userinfos.create()는 중간에 대문자 I 가 포함되어있다.
즉 아래와 같이 camelCase로 작성을 해야 한다는 것이다.
- 모델 이름 vs. 테이블 이름:
- Prisma 스키마에서 모델 이름은 Users와 UserInfos이다.
- 하지만 Prisma Client에서 이 모델들을 호출할 때는 일반적으로 소문자와 camelCase로 작성해야 한다.
즉, users와 userInfos로 작성해야 한다.
- PascalCase와 camelCase:
- Prisma 스키마 파일에서는 모델 이름을 PascalCase로 정의하지만, Prisma Client에서는 해당 모델을 소문자로 시작하는 camelCase로 접근한다.
- UserInfos 모델은 Prisma Client에서 userInfos로 접근해야 한다.
이것은 prisma.호출 을 할때 적용되며 그 이후의 create ({}) 내부에 작성되는 key들은 Schema에서 작성한 대문자를
그대로 반영해 줘야한다. UserId: user.userId, 이것처럼 말이다.
[ bcrypt 모듈을 사용한 리펙터링 ]
위와 같이 password 를 평문으로 저장하는것을 단방향 암호화 한 결과 값으로 데이터베이스에 저장 하기 위해
bcrypt 를 사용하여 리펙터링을 해보도록 하겠다.
해싱 암호화
< src/routes/users.router.js >
단순하게 평문 저장하였던 password 를 위와 같이 salt 값 을 지정해주고
( 10 정도가 적당, 높으면 높을수록 보안성은 높지만 시간지연 위험성이 높아진다.)
bcrypt.hash를 통해 암호화된 hashedPassword 를 데이터베이스 password 에 할당해준다.
그럼 평문 저장된 암호를 지우기 위해 일단 전체 데이터를 삭제해보도록 하겠다.
터미널에 npx prisma db push --force-reset 를 입력하게 되면
이렇게 데이터가 정상적으로 모두 삭제 되는 것을 알 수 있다.
[ 로그인 기능 구현, 사용자 인증 미들웨어 ]
< README.md >
< src/routes/users.router.js >
insomnia 를 통해 확인해 본다면
미들웨어 같은경우는 아래처럼 작성할 수 있다.
[ 사용자 조회 API ]
이번엔 사용자 인증을 집어넣어 그 미들웨어가 완료되면 진행하게끔 만든
사용자 조회 API 코드를 만들어 보도록 하겠다.
위와 같이 authMiddleware 를 집어넣어 인자값이 3개가 될경우 위와같이 작동하게 할 수 있다.
저번 < auth.middleware > 에서 try 마지막 구문에 next() 를 적어 실행시킨것을 볼 수 있다.
그 next 는 authMiddleware 가 모두 인증되어야 만 현재 사용자 조회 API 를 실행시킬 수 있다.
이렇게 해서 사용자 조회 까지 구현을 해보았고
다음엔 엑세스, 리프레시 토큰에 대해 알아 보도록 하겠다.
'TIL' 카테고리의 다른 글
Nodejs 강의 숙련 게시판 프로젝트(7) winston, 에러핸들링 미들웨어 (0) | 2024.05.27 |
---|---|
Nodejs 강의 숙련 게시판 프로젝트(6) 엑세스, 리프레시 토큰발급 / 엑세스 검증 및 재발급 (0) | 2024.05.24 |
Nodejs 강의 숙련 게시판 프로젝트(4) prisma (0) | 2024.05.23 |
Nodejs 강의 숙련 JWT(Json Web Token) (3) ps.콜백함수 (0) | 2024.05.23 |
Nodejs 강의 숙련 MySQL(2) (0) | 2024.05.22 |