0.서비스 설명
우연히 저랑 비슷하게 공부하시는 분의 유튜브를 보다가
카페관련 어플을 만드시는거 보고 나도 이번에 공부하는걸로 저렇게 만들어보고 싶다라는 생각이 들었습니다.
메인에서는 오늘의 카페를 랜덤으로 뿌려주고, 리스트 페이지에서는 카페리스트를 뽑아오고 거기서 나만의 리스트를 만들고 리뷰도 쓸수있도록 하면 좋을것 같았습니다.
거기에 회원가입/로그인 기능까지!
포폴에도 도움이 될수 있으면서, 제가 공부한것을 녹여낼수 있고, 거기에 배우고 싶었던 백엔드 찍먹까지 할 수 있으면 좋겠다 생각했습니다.
아직 진행중이고 처음 접한 부분들이 많아서 중간중간 글을 올리고 수정할 생각입니다.
회원가입/로그인/리뷰작성 등 필요한 백단을 한번도 해본적이 없어서 초보자에게 쉬운게 어떤게 있을까 찾아보다가
nextauth, firebase, sqlite, prima 가 눈에 들어왔다.
고민하다가 더 간단해보이는 sqlite를 하고 차후 프로젝트에서는 firebase, nextauth로 해보자 마음 먹었다.
SQLite를 함께 사용하려고 했는데,
prisma를 사용할 경우 별도의 설치없이 파일 한부분만 수정하면 바로 작업할수 있어서 편했다.
1. Prisma 란?
Prisma는 Node.js와 TypeScript 애플리케이션을 위한 오픈 소스 ORM(Object-Relational Mapping)입니다.
데이터베이스 스키마를 정의하고, 이를 기반으로 Prisma Client API를 생성하여 애플리케이션에서 데이터베이스 쿼리를 쉽고 안전하게 실행할 수 있게 해줍니다.
장점
- 타입 안전성: TypeScript와의 깊은 통합을 통해 컴파일 타임에 쿼리의 타입 안전성을 보장합니다.
- 자동 완성 및 유효성 검사: Prisma Client는 자동 완성과 쿼리 유효성 검사를 지원하여 개발 과정을 간소화하고 오류를 줄여줍니다.
- 간결한 쿼리 구문: 복잡한 쿼리도 명료하고 이해하기 쉬운 코드로 작성할 수 있습니다.
- 마이그레이션 지원: Prisma Migrate를 통해 데이터베이스 스키마 변경 사항을 버전 관리하고, 마이그레이션을 손쉽게 적용할 수 있습니다.
- 다양한 데이터베이스 지원: PostgreSQL, MySQL, SQLite, SQL Server 등 다양한 데이터베이스를 지원합니다.
단점
- 학습 곡선: Prisma는 사용하기 쉬운 ORM이지만, ORM 자체에 익숙하지 않은 개발자에게는 새로운 개념과 패턴을 학습해야 할 필요가 있습니다. 또한 Prisma의 고유 기능과 사용법을 익혀야 합니다.
- 제어의 제한: Prisma는 많은 데이터베이스 작업을 추상화하고 간소화하지만, 이로 인해 데이터베이스에 대한 세밀한 제어가 어려울 수 있습니다. 특히 복잡한 쿼리나 최적화가 필요한 경우, Prisma의 추상화가 제한적일 수 있습니다.
- 종속성: 프로젝트가 Prisma에 종속될 수 있으며, 나중에 다른 ORM이나 직접 쿼리 방식으로 전환하려고 할 때 마이그레이션 비용이 발생할 수 있습니다.
2. SQLite란?
SQLite는 서버리스 아키텍처를 가진 경량화된 관계형 데이터베이스 관리 시스템(RDBMS)입니다.
별도의 서버 프로세스 없이 직접 응용 프로그램에 내장되어 작동하며, SQL(Structured Query Language)을 사용하여 데이터를 관리합니다.
장점
- 서버리스: SQLite는 별도의 서버 설정이나 관리가 필요 없으며, 데이터베이스 파일을 직접 읽고 씁니다.
- 경량: 매우 작은 라이브러리 사이즈로, 리소스가 제한된 환경에서도 효율적으로 사용할 수 있습니다.
- 포터블: SQLite 데이터베이스 파일은 플랫폼 독립적이므로, 다양한 시스템 간에 손쉽게 이동할 수 있습니다.
- 신뢰성: 원자성, 일관성, 격리성, 지속성(ACID)을 보장하는 트랜잭션을 지원합니다.
- 용도: 경량 애플리케이션, 임베디드 시스템, 테스트 환경, 프로토타입 개발 등에 적합합니다.
단점
- 동시성 및 확장성: SQLite는 읽기 중심의 애플리케이션에서 잘 작동하지만, 고동시성을 요구하거나 쓰기 작업이 많은 애플리케이션에서는 성능 병목 현상이 발생할 수 있습니다. 데이터베이스가 파일 기반으로 작동하기 때문에, 여러 사용자의 동시 쓰기 요청을 효율적으로 처리하는 데 한계가 있습니다.
- 서버 기반 데이터베이스 기능 부족: SQLite는 풀 스택 서버 기반 데이터베이스(예: PostgreSQL, MySQL)에서 제공하는 몇몇 고급 기능이 없습니다. 예를 들어, 사용자 관리, 복잡한 롤과 권한 설정, 복제 및 클러스터링 등이 부족합니다.
- 대용량 데이터 처리 제한: SQLite는 대규모 데이터 처리에는 적합하지 않을 수 있습니다. 데이터베이스 파일 크기에는 이론적으로 제한이 없지만, 실제 사용에서는 파일 시스템의 한계와 성능 이슈로 인해 대용량 데이터 처리에는 적합하지 않을 수 있습니다.
3. Prisma와 SQLite의 결합
Prisma와 SQLite를 함께 사용하면,
Prisma의 강력한 ORM 기능과 SQLite의 경량 및 서버리스 특성을 결합할 수 있습니다.
이 조합은 개발 초기 단계나 소규모 프로젝트, 테스트 환경 구축에 특히 유용합니다.
Prisma를 통해 SQLite 데이터베이스를 쉽게 정의하고, 안전하고 간편한 방식으로 데이터에 접근할 수 있으며, SQLite의 경량화된 특성으로 인해 배포와 유지보수가 간단해집니다.
간단한 애플리케이션, 개발 초기 단계, 소규모 프로젝트 또는 프로토타입 개발에는 SQLite와 Prisma의 조합이 매우 유용할 수 있습니다.
반면, 대규모 데이터 처리, 고성능과 고가용성이 요구되는 애플리케이션, 복잡한 데이터베이스 관리가 필요한 경우에는 다른 옵션을 고려할 필요가 있습니다.
4. Prisma 설치/사용
1단계: 프로젝트 설정
- Next.js 프로젝트 생성
npx create-next-app@latest your-project-name cd your-project-name
- Prisma 설치:이 명령어는 prisma 폴더와 .env 파일을 생성합니다.
npm install prisma --save-dev
npx prisma init
- SQLite 설치: Prisma는 SQLite를 지원하므로 별도의 설치는 필요하지 않습니다.
- 다만 스키마 파일 내의 datasource db 부분은 다음과 같아야 합니다:
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
- .env 파일에서 데이터베이스 URL을 설정합니다.
DATABASE_URL="file:./dev.db"
2단계: Prisma 스키마 설정
- prisma/schema.prisma 파일을 열고 다음과 같이 User 모델을 추가합니다.
model User {
id Int @id @default(autoincrement())
email String @unique
password String
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
- Prisma 클라이언트 생성:
npx prisma generate
- 데이터베이스 마이그레이션:
npx prisma migrate dev --name init
3단계: API 라우트 설정
- 회원가입 API (pages/api/signup.js)
/app/api/signup/route.ts
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
import type { NextApiRequest, NextApiResponse } from "next";
import { NextResponse } from "next/server";
const prisma = new PrismaClient({
log: ["query", "info", "warn", "error"],
});
export async function POST(req: Request) {
console.log(req);
try {
const requestBody = await req.json();
const { email, password, name } = requestBody;
const hashedPassword = bcrypt.hashSync(password, 8);
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
name,
},
});
return NextResponse.json({
message: "User created",
user,
});
// res.status(201).json({ message: "User created", user });
} catch (error) {
return NextResponse.json({
message: "Internal server error",
});
}
}
- 로그인 API (pages/api/login.js)
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import { NextResponse } from "next/server";
const prisma = new PrismaClient({
log: ["query", "info", "warn", "error"],
});
export async function POST(req: Request, res: Request) {
try {
const requestBody = await req.json();
const { email, password } = requestBody;
const user = await prisma.user.findUnique({
where: {
email,
},
});
if (user && bcrypt.compareSync(password, user.password)) {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, {
expiresIn: "8h",
});
return NextResponse.json({
message: "Logged in successfully",
user,
});
} else {
return NextResponse.json({
error: "Invalid email or password",
});
}
} catch (error) {
return NextResponse.json({
error: "Internal server error",
});
}
}
4단계: 환경 변수 설정
.env 파일에 JWT 비밀키를 추가합니다. 이 키는 토큰을 서명하는 데 사용됩니다
JWT_SECRET=your_secret_key
5단계: 프론트엔드 구현
Next.js에서 Form을 사용하여 이메일, 비밀번호 입력 필드를 구현하고, 회원가입 및 로그인 요청을 위해 위에서 생성한 API 엔드포인트(/api/signup, /api/login)로 POST 요청을 보냅니다.
6단계: 데이터 확인 / 빌드
prisma를 사용할 경우 아래의 명령어로 데이터가 잘 저장되어있는지 확인할 수 있습니다.
// 프리즈마 스튜디오로 확인
npx prisma studio
// 빌드할 때 presma generate 명령어 추가
// package.json
"postinstall": "prisma generate",
"build": "prisma generate && next build",
7단계: 보안 고려 사항
보안 고려 사항에 대해 이어서 설명드리겠습니다.
- HTTPS 사용:
- HTTPS는 HTTP에 데이터 암호화를 추가한 프로토콜입니다. 데이터가 인터넷을 통해 전송될 때, HTTPS는 SSL(Secure Sockets Layer) 또는 TLS(Transport Layer Security)를 사용하여 데이터를 암호화합니다.
- 이는 데이터가 도청되거나 변조되는 것을 방지하여 웹 애플리케이션의 보안을 강화합니다.
- 웹 사이트를 운영할 때는 항상 HTTPS를 사용하여 사용자 데이터의 기밀성과 무결성을 보장해야 합니다.
- 사용자 입력 검증: 사용자로부터 받는 모든 입력은 잠재적인 위험을 내포하고 있으므로, 서버에서 처리하기 전에 반드시 검증해야 합니다. 입력 검증을 통해 SQL 인젝션, XSS(Cross-Site Scripting), CSRF(Cross-Site Request Forgery) 같은 공격을 방지할 수 있습니다.
- SQL 인젝션 방지: 사용자 입력을 그대로 SQL 쿼리에 포함하는 것은 위험합니다. 악의적인 사용자는 SQL 쿼리를 조작하여 민감한 데이터에 접근하거나 데이터를 손상시킬 수 있습니다. 이를 방지하기 위해 입력 값을 직접 쿼리에 포함시키지 않고, 준비된 문장(Prepared Statements)을 사용해야 합니다. 또한, ORM(Object-Relational Mapping) 라이브러리를 사용하면 SQL 인젝션 공격에 대한 보호를 강화할 수 있습니다.
- 추가적인 보안 조치:
- XSS 방지: 사용자 입력을 웹 페이지에 그대로 출력할 때는 스크립트가 실행되지 않도록 적절하게 이스케이핑(Escaping) 처리를 해야 합니다. 프론트엔드 프레임워크에서 제공하는 데이터 바인딩 기능을 사용하면 XSS 공격을 방지할 수 있습니다.
- CSRF 방지: 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 하도록 만드는 공격입니다. 토큰 기반의 방어 메커니즘을 사용하거나 적절한 HTTP 헤더를 설정하여 CSRF 공격을 방지할 수 있습니다.
- 최신 보안 패치 적용: 사용 중인 소프트웨어(운영체제, 웹 서버, 데이터베이스, 프레임워크 등)의 보안 패치를 정기적으로 확인하고 적용하여 알려진 취약점을 해결해야 합니다.
웹 애플리케이션을 개발할 때 이러한 보안 고려 사항을 철저히 적용하여 사용자 데이터를 보호하고 안전한 서비스를 제공해야 합니다.
추가적으로 로그인 하고, 로그인 세션 체크 하는 부분들을 추가로 올릴 예정입니다.
하나도 모르는거라 다 차장보면서 하다보니 시간이 더 오래걸리고 그렇네요 ㅎㅎ
다들 화이팅입니다!
'토이 프로젝트' 카테고리의 다른 글
[what is your mbti] socket.io로 채팅 구현하기 (0) | 2024.07.05 |
---|---|
MBTI가 어떻게 되세요? (feat: what is your mbti) (1) | 2024.06.30 |
Next.js | 영화 서비스 (2) | 2024.04.04 |
댓글