[Next.js] 중고마켓 앱

Jungmin Ji·2024년 1월 17일
0

Nextjs

목록 보기
4/9
post-thumbnail

인증 및 인가 기능 구현하기

리액트 앱 생성하기

next-market-app으로 폴더를 생성했다.
터미널에서 CNA (맞겠지?)
npx create-next-app@latest ./

src하위에 components 폴더생성
컴포넌트를 생성하여 layout에서 import

import Navbar from '@/components/Navbar';
import할때 @가 붙는것은 alias가 자동으로 붙어서 깔끔하게 경로작성가능하다.

NavBar.tsx
useState를 사용하려면 클라이언트 컴포넌트라고 use client로 명시를 해야한다.

'use client' 

import Link from "next/link";
import { useState } from "react";
import NavItem from "./NavItem";

const Navbar = () => {
  const [menu, setMenu] = useState(false);

  const handleMenu = () => setMenu(!menu);
  return (
    <nav className="relataive z-10 w-full bg-orange-500 text-white">
      <div className="flex items-center justify-between mx-5 sm:mx-10 lg:mx-20">
        
        <div className="flex items-center text-2xl h-14">
          <Link href="/">Logo</Link>
        </div>

        {/* sm보다 클때 */}
        <div className="text-2xl sm:hidden">
          {(menu === false) ? <button onClick={handleMenu}>+</button> : <button onClick={handleMenu}>-</button>}
        </div>

        <div className="hidden sm:block">
          <NavItem />
        </div>
      </div>
      <div className="block sm:hidden"> 
        {(menu === false) ? null : <NavItem mobile />}
      </div>
    </nav>

  )
}

export default Navbar;

NavItem.tsx

import Link from 'next/link'
import React from 'react'

const NavItem = ({mobile} : {mobile?: boolean}) => {
  return (
    <ul
      className={`text-md justify-center flex gap-4 w-full items-center ${mobile && "flex-col h-full"}`}
    >
      <li className="py-2 text-center border-b-4 cursor-pointer">
        <Link href="/admin">Admin</Link>
      </li>
      <li className="py-2 text-center border-b-4 cursor-pointer">
        <Link href="/user">User</Link>
      </li>
      <li className="py-2 text-center border-b-4 cursor-pointer">
        <button>Sign out</button>
      </li>
      <li className="py-2 text-center border-b-4 cursor-pointer">
        <button>Sign in</button>
      </li>
    </ul>
  );
}

export default NavItem

스타일링만 완료.

User, Admin 페이지 생성하기

일반유저와 어드민 페이지가 있는데 일단 생성부터. (나중에 권한별로 접근 제한)

  • user페이지 : 로그인된 회원만 볼 수 있는 페이지
  • admin페이지 : 관리자만 볼 수 있는 페이지

app의 하위폴더에 admin과 user폴더 생성후 page.tsx 생성.
파일 시스템 라우팅이 잘되는것을 확인할 수 있다.

Prisma, Postgres 설정하기

Prisma

dev dependency로 prisma 설치
npm install -D prisma
npx prisma init

www.prisma.io

env파일에 데이터베이스 url등록이 필요
데이터베이스 url: postgres

.env파일 생성

DATABASE_URL="postgresql://postgres:password@localhost:5432/nextjsapp"

Postgres

웹 Postgres 사용하기

https://railway.app/ -> 추천. 무료이나 한달에 500시간 제한있다.
https://supabase.com/


Start a New Project로 프로젝트 생성


New Project를 postgres 사용해서 생성


database url 복사

.env파일에 데이터베이스 URL 넣기

도커를 이용해서 Postgres실행을 추천.

도커이용 Postgres사용하기

docker-compose.yml

version: "3"
services: 
    db:
        image: postgres:latest
        restart: always
        ports: 
          - "5432:5432"
        environment:
            POSTGRES_USER: "postgres"
            POSTGRES_PASSWORD: "password"
        volumes: 
          - ./data:/var/lib/postgresql/data

실행 명령어: docker-compose up
도커허브에서 포스트그레스 이미지를 가져오는데 시간이 걸리긴함.
env 넣는방법: DATABASE_URL="postgresql://username:password@localhost:5432/dbname"

윈도우에서 도커 설치

www.docker.com/get-started/

그냥 설치하고 재부팅하니 잘 됨.

버전 확인

ORM에 대해서

ORM이란? (Object Relatioanl Mapping)

몽고DB는 ODM(Object Data Modeling)라이브러리.

ORM이란,
객체와 관계형 데이터베이스의 데이터를 자동으로 변형 및 연결하는 작업.
ORM을 이용한 개발은 객체와 데이터베이스 변형에 유연하게 사용할 수 있다.

객체지향 프로그래밍은 클래스사용 <- (ORM으로)매핑 -> 관계형데이터베이스는 테이블사용

객체 모델과 관계형 모델간 불일치 존재... ??

ORM vs Pure Javascript

orm: const boards = Board.find({title: 'Hello', status: 'PUBLIC'});

pure javascript:

db.query('SELECT * FROM boards WHERE title = 'Hello' AND staus='PUBLIC', (err, result) => {
	if(err) {
    	throw new Error('Error')
    }
    boards = result.rows;
})

ORM과 Node.js의 추상화 계층

개발에서 추상화(Abstraction)라는것은 추상화를 많이 하면 할수록 어떠한 복잡한 로직을 알지 못하더라도 그 로직을 간단하게 사용할 수있게 해줌. 불필요한 정보는 숨기고 중요한 정보만을 표현해서 프로그램을 간단하게 해줌)

데이터베이스도 사용하는 방법에 따라 추상화가 많이 되어있는 라이브러리를 사용할 수도 있고 그렇지 않은 라이브러리를 사용해서 데이터베이스를 컨트롤 할 수 있다.

추상화정도를 3단계로 나눈다.

저수준: 데이터베이스 드라이버

데이터베이스 드라이버는 데이터베이스 연결(때때로 연결 풀링)을 처리한다. 이수준에서는 원시 SQL문자열을 작성하여 데이터베이스에 전달하고 데이터베이스에서 응답을 받는다.
Node.js생태계에는 이 계층에서 작동하는 많은 라이브러리가 있다.

  • mysql: MySQL(mysql를 위한 데이터베이스 드라이버)
  • pg: PostgreSQL(postgres를 위한 데이터베이스 드라이버)
  • sqlite3: SQLite(sqlite를 위한 데이터베이스 드라이버)

이러한 각 라이브러리는 기본적으로 동일한 방식으로 작동한다. 데이터베이스 인증정보를 가져오고, 새 데이터베이스 인스턴스를 인스턴스화하고, 데이터베이스에 연결하고, 문자열 형식으로 쿼리를 보내고 결과를 비동기적으로 처리한다.

중간수준: 쿼리빌더

단순한 데이터베이스 드라이버 모듈과 완전한 ORM을 사용하는 것의 중간 수준.
이 계층에서 작동하는 가장 주목할만한 모듈은 Knex이다.

기본 SQL쿼리와 매우 유사하다. 또 문자열을 연결하여 SQL을 형성하는 경우(보안 취약점이 종종 발생)보다 훨씬 더 편리한 방식으로 프로그래밍 방식으로 동적쿼리를 생성할 수 있다.

고수준

최고수준의 추상화. ORM으로 작업할때 일반적으로 더 많은 설정을 사전에 수행해야한다. ORM의 요점은 이름(object relational mapping)에서 알 수 있듯이 관계형 데이터베이스의 데이터를 애플리케이션의 객체(클래스 인스턴스)에 매핑하는 것이다.

  • typeorm
  • sequelize
  • prisma

ORM 사용의 단점

  • SQL이 아닌 ORM자체를 배우게 된다.
    (각각 특정 ORM자체를 배우는 시간도 오래걸리며 ORM들 마다 다른 문법을 사용하는곳이 많다. )
  • ORM을 이용해서 복잡한 호출을 하면 성능이 좋지 않을 수 있다.

ORM 사용의 장점

  • 하나의 소스 코드를 이용해서 여러 데이터베이스로 쉽게 교체가능
  • 중복 코드 방지
  • SQL 인젝션 취약점으로부터 보호
  • 모델 유효성 검사 지원
  • Typescript 지원

pgAdmin 사용법

데이터베이스를 보는 Tool

Window 에서 PostgresSQL 설치

https://www.postgresql.org/download/windows/

Mac 에서 PostgresSQL 설치

https://postgresapp.com/downloads.html

도커 실행을 먼저 하고 (docker-compose up)
운영체제에 맞게 설치 후 pgAdmin 실행

Next Auth를 위한 디비 스키마 생성하기

postgreSQL 포트번호 변경방법(연결 에러)

설치할때 포트번호 5433으로 설치하다가 db연결안돼서 한시간동안 씨름했는데

C:\Program Files\PostgreSQL\16\data경로에 postgresql.conf폴더에서 포트번호 5432로 수정하고 서비스 restart하면된다.

서버 resister후
npx prisma db push를 하면 db에 push한다는 명령인데

pgAdmin에서 새로고침하면
DB url 마지막의 데이터베이스가 생성되는것을 확인 할 수 있다.

데이타베이스에 연결이 안될때.. pgAdmin 서버에서 다시 등록해보고 안되면 서비스에서 postgresql을 restart해서 재등록하면된다...

DB Schema 작성하기

테이블, 컬럼을 작성하려면 먼저 DB Schema가 필요하다. 작성 후 npx prisma db push한다.

잘 작성된 schema를 다음 공식문서에서 복사하여 prisma/schema.prisma파일에 붙여넣는다.

@auth/prisma-adapter

model User {
  id             String    @id @default(cuid())
  name           String?
  hashedPassword String?
  email          String?   @unique
  emailVerified  DateTime?
  image          String?
  accounts       Account[]
  sessions       Session[]
}

User테이블에 비밀번호가 기본적으로 없는데 hashedPassword라고 추가해준다.
hashedPassword는 복구화 할 수 없는 비밀번호라는 뜻..

String에 ?를 붙이면 optional하게 사용한다는 의미다.
구글로그인이나 깃헙 로그인을 한다면 비밀번호가 없기때문에 optional하게 넣는다.


SQL에서 변경된 테이블구조 확인할 수 있음.

extension 설치

스키마파일이 하이라이팅이 안되어있어서 불편한데 Prisma extension을 설치하면 syntax highlighting과 formatting, auto-completion, ... 기능이 지원된다.

Prisma 문법

  • @id, @@id모두 : 기본키 지정
  • @unique, @@unique : 유니크한 값
  • cuid, uuid: cuid/uuid 사양에 따라 고유한 식별자 생성
  • @relation : 데이터 관계 지정
    예) Account의 관계
    user User @relation(fields: [userId], references: [id], onDelete: Cascade) : Account의 userId(fields)는 User의 id(references)와 같다. onDelete: Cascade는 해당 유저를 지우면 해당 유저의 Account도 지워짐 설정.

push

npx prisma db push를 하여 데이터 push를 한다.


pgAdmin을 새로고침하면
스키마 파일을 토대로 테이블이 생성된것을 확인할 수 있다.

profile
FE DEV/디블리셔

0개의 댓글

관련 채용 정보