728x90
반응형

 

1. 모듈설치

npm install prisma

 

 

 

2. scheme.prisma 파일 생성

npx prisma init

src와 동일한 위치로 prisma 폴더가 생성되고 scheme.prisma 파일이 생성됩니다.

provider를 mysql로 변경하고 url에 DATABASE_URL 환경변수를 설정해줘야합니다.

 

 

 

.evn 파일에 local 환경변수 설정

DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DATABASE

USER : mysql Username

PASSWORD : mysql password

HOST : mysql Server Host

PORT : mysql port number

DATABASE : mysql DB name

 

 

 

3. prisma 파일 하이라이팅 확장 추가

 

확장에서 Prisma를 검색해서 설치합니다.

prisma 파일의 코드에 하이라이팅을 넣어주어 가독성이 높아집니다.

 

 

 

4. 기존 DB 데이터 모델 생성

npx prisma db pull

 

 

-  schema.prisma 파일에 연동된 DB 테이블이 prisma 데이터 모델로 추가되었습니다.

-  설정된 데이터 모델을 토대로 쿼리를 작성할 수 있습니다.

-  외래키가 설정되어있다면 테이블 간 관계도 인식하고 추가됩니다.

 

 

 

 

5. 데이터베이스 마이그레이션

이미 테이블에 데이터가 포함되어있고 데이터가 초기화 되면 안되는 데이터베이스의 경우는 마이그레이션을 초기화 합니다.

 

mkdir -p prisma/migrations/0_init

 

폴더를 생성합니다.

 

 

npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql

 

마이그레이션을 생성합니다.

 

  • --from-empty: 마이그레이션하려는 데이터 모델이 비어 있다고 가정합니다.
  • --to-schema-datamodel: 현재 데이터베이스 상태
  • --script: SQL 스크립트를 출력합니다.

마이그레이션 결과

 

 

npx prisma migrate resolve --applied 0_init

 

마이그레이션을 적용하는 명령어를 실행합니다.

 

 

 

 

6. 프리즈마 클라이언트 설치

npm install @prisma/client

 

프리즈마 쿼리를 사용하기 위해 프리즈마 클라이언트를 설치합니다.

 

 

 

npx prisma generate

 

프리즈마 클라이언트를 생성하는 명령어를 실행합니다.

 

 

 

7. 쿼리 실행

'use server'

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function getAllNotice() {
  try {
    const data = await prisma.notice.findMany();
    return data;
  } catch (error) {
    throw new Error(`Error getting all notice`);
  } finally {
    await prisma.$disconnect();
  }
}

 

findMany()를 사용하여 notice 테이블의 데이터를 모두 조회하는 쿼리를 실행하는 코드입니다.

 

 

 

 

[공식문서]

https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql

 

Add Prisma ORM to an existing project using TypeScript and PostgreSQL (15 min) | Prisma Documentation

Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your PostgreSQL database and generating a Prisma Client for database access.

www.prisma.io

 

728x90
반응형
728x90
반응형

1. 데이터베이스 생성

 

RDS 검색 후, 데이터베이스 생성을 시작합니다.

 

 

 

 

 

프리티어를 선택합니다.

 

DB 인스턴스 클래스 중 가장 성능이 낮은 db.t3.micro로 선택합니다.

스토리지는 최솟값인 20으로 설정하고 자동 조정 활성화도 체크 해제합니다.

 

 

로컬에서도 접근 가능하도록 퍼블릭 엑세스를 '예'로 설정합니다.

 

 

백업을 비활성화 합니다. (저는 비용이 무서워서 비활성화 했지만 일주일까지 설정하시는 분들도 있는것같습니다)

 

 

로그는 모두 비활성화하고 삭제 방지 활성화는 설정해도 좋을것같습니다.

 

 

 

2.  파라미터 그룹 생성

파라미터 그룹 생성 버튼을 클릭합니다.

 

 

Engine type 및 파라미터 그룹 패밀리를 생성했던 DB 설정에 맞게 선택하여 생성합니다.

 

 

 

3.  파라미터 그룹 설정 편집

생성한 파라미터 그룹을 편집합니다.

 

 

 

time_zone을 검색하고 Asia/Seoul을 입력합니다.

 

 

 

character_set_을 검색하고 utf8mb4을 입력합니다. (6개)

 

 

 

collation_을 검색하고 utf8mb4_general_ci을 입력합니다. (2개)

 

 

 

 

 

4.  데이터베이스에 파라미터 그룹 적용

생성했던 데이터베이스를 클릭합니다.

 

 

추가구성 > 파라미터 그룹을 새로 만든 그룹으로 적용합니다.

 

 

즉시 적용으로 설정하고 편집을 완료합니다.

 

 

 

 

 

 

 

 

 

[참고한 글]

https://velog.io/@zosungwoo/AWS-%ED%94%84%EB%A6%AC%ED%8B%B0%EC%96%B4-AWS-RDS-for-MySQL-%EC%83%9D%EC%84%B1-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B7%B8%EB%A3%B9-%ED%8E%B8%EC%A7%91

 

[AWS] 프리티어 AWS RDS for MySQL 생성, 파라미터 그룹 편집

AWS RDS for MySQL을 프리티어로 생성해보고, 타임존과 한글 및 이모지 사용을 위해 파라미터 그룹 편집을 진행해보자.

velog.io

https://dream-and-develop.tistory.com/415?category=1081124

 

[AWS] RDS MySQL 인스턴스 생성 및 데이터베이스 연결과 한글 설정

AWS에서 제공하는 RDS 서비스를 이용해, MySQL 인스턴스를 생성해보자. 데이터베이스 생성 표준 생성 방식으로 데이터베이스를 생성하자. 엔진 옵션 MySQL 엔진을 사용할 것이기 때문에, MySQL을 선택

dream-and-develop.tistory.com

 

728x90
반응형

'Web > AWS' 카테고리의 다른 글

AWS RDS(DB) 파이썬으로 접속 / MariaDB  (0) 2021.08.18
728x90
반응형

* Next.js에 Tailwind css를 적용시킨 후 따라해주세요.

 

1.  next-themes 설치

# NPM
npm install next-themes

# Yarn 
yarn add next-themes

 

 

 

2.  Root Layout에  ThemeProvider 추가

import "@/styles/globals.css";
import { ThemeProvider } from 'next-themes';

...

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html suppressHydrationWarning>
      <body>
        <ThemeProvider attribute='class'>
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

 

- ThemeProvider가 children을 감싸도록 작성합니다.

- 경고 표시를 무시하기 위해 html 태그에 suppressHydrationWarning를 입력합니다.

- 추가적인 설정이 없다면 system이 기본 테마로 설정됩니다.

 

 

 

3.  tailwind.config.js에  다크모드 설정 추가

// tailwind.config.ts

import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      backgroundImage: {
        "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
        "gradient-conic":
          "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
      },
    },
  },
  darkMode: 'class', // 다크 모드를 클래스 기반으로 설정
  plugins: [],
};
export default config;

 

darkMode: 'class' 를 추가하여 클래스 기반으로 다크모드일때의 스타일을 지정할 수 있도록 설정합니다.

 

 

 

4.  다크모드 스타일 지정

export default function Page() {

  return (
    <div className="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100">
    	기본인 light 모드에서는 text-gray-600의 색상에서 hover시 text-gray-900으로 색이 변경되며 더욱 진해집니다.
        dartk 모드에서는 text-gray-300의 색상에서 hover시 text-gray-100으로 색이 변경되며 더욱 밝아집니다.
    </div>
  );
}

 

 

 

 

 

5.  테마 변경 컴포넌트

import { useState } from "react";
import { useTheme } from "next-themes";
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined';
import BedtimeOutlinedIcon from '@mui/icons-material/BedtimeOutlined';
import MonitorIcon from '@mui/icons-material/Monitor';

const ThemeSelector: React.FC = () => {
  const { theme, setTheme } = useTheme();
  const [themeToggle, setThemeToggle] = useState(false);

  const themeShowToggle = () => {
    setThemeToggle(!themeToggle);
  };

  const handleChange = (themeValue: string) => {
    setTheme(themeValue);
    setThemeToggle(false);
  };

  return (
    <div className="relative">
        <div className="text-blue-500 mr-6 cursor-pointer" onClick={themeShowToggle}>
          {theme === 'light'
            ? <LightModeOutlinedIcon id="theme_light"/>
            : theme === 'dark'
            ? <BedtimeOutlinedIcon id="theme_dark"/>
            : <MonitorIcon id="theme_system"/>}
        </div>
        {themeToggle &&
          <div className="absolute top-16 right-4 w-28 bg-white shadow-lg py-1 rounded-md border-solid border border-gray-300 text-gray-900 font-medium text-sm dark:text-gray-100 dark:bg-backDarkColor">
            <div className={["flex flex-row cursor-pointer px-3 py-1 hover:bg-gray-100 dark:hover:bg-zinc-800", theme === 'light' && "text-blue-500"].join(' ')} onClick={() => handleChange('light')}>
              <LightModeOutlinedIcon className={[theme === 'light'?"text-blue-500":"text-gray-400", "w-5 mr-2"].join(' ')}/>
              Light
            </div>
            <div className={["flex flex-row cursor-pointer px-3 py-1 hover:bg-gray-100 dark:hover:bg-zinc-800", theme === 'dark' && "text-blue-500"].join(' ')} onClick={() => handleChange('dark')}>
              <BedtimeOutlinedIcon className={[theme === 'dark'?"text-blue-500":"text-gray-400", "w-5 mr-2"].join(' ')}/>
              Dark
            </div>
            <div className={["flex flex-row cursor-pointer px-3 py-1 hover:bg-gray-100 dark:hover:bg-zinc-800", theme === 'system' && "text-blue-500"].join(' ')} onClick={() => handleChange('system')}>
              <MonitorIcon className={[theme === 'system'?"text-blue-500":"text-gray-400", "w-5 mr-2"].join(' ')}/>
              System
            </div>
          </div>
        }
    </div>
  );
};

export default ThemeSelector;

 

* MUI(Material UI) 아이콘이 사용된 코드입니다.

* 다듬어지지 않은 예시 코드입니다. 실제로 사용시에는 새로 만들거나 다듬어서 사용하시길 추천드립니다.

 

- useTheme()를 통해 현재 설정된 theme를 불러올 수 있고, setTheme를 사용하여 테마 설정을 변경할 수 있습니다.

   (system, light, dark 등으로 설정)

 

 

 

 

 

 

[next-themes 공식문서]

https://github.com/pacocoursey/next-themes

 

GitHub - pacocoursey/next-themes: Perfect Next.js dark mode in 2 lines of code. Support System preference and any other theme wi

Perfect Next.js dark mode in 2 lines of code. Support System preference and any other theme with no flashing - pacocoursey/next-themes

github.com

728x90
반응형
728x90
반응형

Sourcetree로 원격 프로젝트를 클론하는 도중 올바른 경로가 아니라는 문제가 발생하였습니다.

이 경우에는 git repository 경로에는 문제가 없는데도 에러가 발생하게 됩니다.

 

저는 같은 문제를 두 번 정도 겪어보아서 두가지 해결 방법을 공유드리겠습니다.

 

 

1. git 버전 변경으로 해결할 수 있는 문제

 

설정 -> Git -> Git 버전 : 내장 Git로 되돌리기 클릭

 

 

 

2. 연결된 계정에 SSH 키가 설정되지 않은 경우

 

설정 -> 계정 -> SSH 오류가 발생한 계정 더블클릭 -> 프로토콜을 HTTPS로 변경

 

 

 

 

 

 

앞으로도 관련해서 오류가 발생하게 된다면 추가로 해결 방법을 남겨두겠습니다.

728x90
반응형
728x90
반응형

* git 연동 후 vercel에 등록된 상태로 진행해주세요*

 

1.  Postgres Database 생성

 

Storage -> Create Database 클릭

 

 

 

 

Postgres -> Database 설정

 

- Database Name : 데이터베이스명을 입력합니다.

- Region : 데이터센터의 물리적 위치를 선택합니다. (프로그램이 실행되는 위치와 가까운 장소를 선택할수록 빠른 통신이 가능합니다)

 

 

 

 

2. 프로젝트에 DB 연결

 

생성된 postgres database로 접속후 -> Getting Started -> Connect Project 클릭

 

 

 

 

vercel에 연결되어있는 프로젝트 중 DB에 연결할 프로젝트를 선택합니다.

 

저는 기본설정으로 연결하였습니다.

 

 

 

 

vercel link

vercel env pull .env.development.local

 

vscode로 프로젝트에 접속하여 로컬에서도 postgres를 사용할 수 있도록 설정합니다.

 

* .env.development.local 파일에는 postgres 관련 민감한 정보들이 들어있으니

    git 또는 외부에 공유되지 않도록 주의해야합니다.

 

 

 

 

3. 테이블 생성 및 데이터 추가

 

vercel -> Storage -> 생성한 postgres -> Data -> Query 로 접근

 

아래 쿼리들을 실행하여 데이터를 넣고 테스트 해봅시다.

 

 

CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    author VARCHAR(100)
);

 

해당 쿼리는 게시글 테이블을 생성합니다.

 

INSERT INTO posts (title, content, author) VALUES
    ('첫 번째 게시물', '첫 번째 게시물의 내용입니다.', '홍길동'),
    ('두 번째 게시물', '두 번째 게시물의 내용입니다.', '이순신'),
    ('세 번째 게시물', '세 번째 게시물의 내용입니다.', '강감찬'),
    ('네 번째 게시물', '네 번째 게시물의 내용입니다.', '유관순'),
    ('다섯 번째 게시물', '다섯 번째 게시물의 내용입니다.', '김유신');

 

해당 쿼리는 게시글 테이블에 데이터를 넣습니다.

 

 

 

데이터가 잘 들어왔다면 프로젝트에서 조회해봅시다.

 

 

 

 

4. 데이터 조회하기

npm install @vercel/postgres

 

postgres 데이터를 조회할 수 있는 라이브러리를 설치합니다.

 

 

 

/* /services/posts.ts */

'use server'

import { sql } from "@vercel/postgres";

export interface Posts {
	id : number,
	title : string,
	content : string,
	author : string,
}

export async function getPostsData(): Promise<Posts[]> {
	try {
		const { rows }: { rows: Posts[] } = await sql
			`SELECT id, title, content, author FROM posts;`;
		return rows;
	} catch (error) {
		throw new Error('Failed to fetch posts data');
	}
}

 

조회 쿼리를 통해 직접 게시글 목록을 조회하는 파일입니다.

 

 

/* page.tsx */

'use client'
import { Posts, getPostsData } from "@/services/posts";
import { useEffect, useState } from "react";

const defaultPosts: Posts = {
  id: 0,
  title: "",
  content: "",
  author: "",
};

export default function Page() {
  const [posts,getPosts] = useState<Posts[]>([defaultPosts]);

  useEffect(() => {
    fetchData();
  },[]);

  const fetchData = async () => {
    try {
      const postsData = await getPostsData();
      getPosts(postsData);
    } catch (error) {
      throw new Error('Failed to fetch posts data');
    }
  };

  return (
    <div>
      <div className="overflow-x-auto">
        <table className="min-w-full bg-white">
          <thead>
            <tr>
              <th className="px-6 py-3 bg-gray-100 text-left text-xs leading-4 font-medium text-gray-600 uppercase tracking-wider">제목</th>
              <th className="px-6 py-3 bg-gray-100 text-left text-xs leading-4 font-medium text-gray-600 uppercase tracking-wider">내용</th>
              <th className="px-6 py-3 bg-gray-100 text-left text-xs leading-4 font-medium text-gray-600 uppercase tracking-wider">작성자</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-200">
            {posts.map((post)=>(
              <tr key={post.id}>
                <td className="px-6 py-4 whitespace-no-wrap">{post.title}</td>
                <td className="px-6 py-4 whitespace-no-wrap">{post.content}</td>
                <td className="px-6 py-4 whitespace-no-wrap">{post.author}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

 

조회된 데이터가 테이블에 출력될 수 있도록 처리합니다.

 

 

 

 

 

postgres에 쿼리로 넣었던 데이터가 정상적으로 조회되는것을 볼 수 있습니다.

 

 

 

 

DROP TABLE posts;

 

마지막으로 테스트용 테이블인 posts를 삭제하고 프로젝트에 맞게 사용하시면 됩니다.

728x90
반응형
728x90
반응형

📜 오류 발생

 

맥북을 새로 구매하여 기존에 작업하던 프로젝트를 맥북에서도 이어서 개발할 수 있도록 세팅하였습니다.

개발도 이어서 진행하고 Sourcetree로 commit 후 push를 진행하려고 하자 아래와 같은 오류가 발생하였습니다.

fatal: Authentication failed for {깃 주소}

 

 

인증 관련해서 발생한 문제같아서 알아보니 현재 깃허브에서는 인증을 토큰으로 진행한다고 합니다.

토큰을 발급받고 적용하여 문제를 해결해보도록 하겠습니다.

 

 

 

 

💊 해결 방법

1. github에서 토큰 발급 받기

 

setting -> Developer settings 클릭

 

 

 

 

Personal access tokens -> Tokens (classic) -> Generate new token -> Generate new token (classic) 클릭

 

 

 

 

Note : 토큰을 어디에 쓸지 명시합니다. ex) Macbook , Desktop ...

Expiration : 토큰 만료 기간입니다. 90 Days 라면 앞으로 90일 동안 해당 토큰을 통해 권한을 유지할 수 있습니다.

select scopes : 해당 토큰을 통해 접근할 수 있는 범위입니다.

 

 

 

 

설정을 마치셨다면 노란색으로 가려진 부분에 발급받은 토큰이 보여집니다.

페이지를 벗어나면 다시 볼 수 없으니 바로 복사해서 저장해두세요.

 

 

 

2. SourceTree에 토큰 적용

 

Sourcetree로 들어와서 설정을 열어줍니다.

 

 

 

 

 

원격 -> 원격 저장소 경로에서 토큰을 적용할 경로를 더블 클릭합니다.

 

 

 

 

URL / 경로에 git repository URL이 들어있습니다.

발급 받았던 토큰을 아래 예시와 같이 넣으면 됩니다. (토큰@ 을 추가하면 됩니다)

https://토큰@github.com/xxx/project.git

 

 

 

토큰 적용을 완료하셨다면 위 오류가 해결될 수 있습니다.

728x90
반응형

+ Recent posts