- 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');
}
}
vercel에 연동된 Next.js프로젝트에 postgres를 연동하던중 아래와 같은 오류가 발생하였다.
Error while fetching side menu data: VercelPostgresError: VercelPostgresError - 'missing_connection_string': You did not supply a 'connectionString' and no 'POSTGRES_URL' env var was found.
오류상으로는 'connectionString', 'POSTGRES_URL'에 대해서만 나와서 다른 문제라고는 생각하지 못했는데
생각보다 간단한 문제로 나던 오류였다.
💊 해결 방법
postgres 데이터를 직접 불러오는 파일이 클라이언트 컴포넌트 상태라서 생기는 문제였다.
'use server'를 파일 상단에 입력하여 서버 컴포넌트로 변경시키는 것으로 간단하게 해결되었다.
'use server'
import { sql } from "@vercel/postgres";
interface MenuItem {
id: number;
name: string;
description: string;
link: string;
sub_menus: SubMenuItem[];
}
interface SubMenuItem {
id: number;
name: string;
description: string;
link: string;
}
export async function getSideMenuData(): Promise<MenuItem[]> {
try {
const { rows }: { rows: MenuItem[] } = await sql`SELECT
m.id AS id,
m.name AS name,
m.description AS description,
m.link AS link,
COALESCE(json_agg(json_build_object('id', sub.id, 'name', sub.name, 'description', sub.description, 'link', sub.link)) FILTER (WHERE sub.id IS NOT NULL), '[]') AS sub_menus
FROM
side_menu AS m
LEFT JOIN
side_menu AS sub ON m.id = sub.parent_id
WHERE
m.parent_id IS NULL
GROUP BY
m.id;
`;
return rows;
} catch (error) {
throw new Error('Failed to fetch side menu data');
}
}