Introduction
웹 애플리케이션을 구축하는 것은 복잡한 작업이 될 수 있지만, 최근 몇 년간 등장한 기술 스택 덕분에 개발 속도를 크게 향상할 수 있는 방법들이 많아졌습니다. 프론트엔드 개발자들은 주로 JavaScript 또는 TypeScript에 익숙한데, 최근에는 서버와 클라이언트 모두 JavaScript로 통합할 수 있는 환경이 마련되면서 프론트엔드 개발자가 웹 전체를 빠르게 구축할 수 있는 강점을 갖추게 되었습니다.
실제로 얼마 전, 저는 부산 지역의 사설 도서관들의 도서 관리 서비스를 구축해야 했습니다. 각 사용자 별 계정을 생성하고, 해당 계정이 속한 도서관에 접근해 도서를 추가하고 삭제할 수 있어야 했으며, 사용자들이 저장된 도서 정보들을 검색할 수 있어야 했죠. 즉 웹 애플리케이션의 가장 기본적인 동작인 1) 인증/인가 2) 데이터 저장, 수정, 삭제 3) 데이터 조회 를 구현해야 했습니다.
이전이었다면 이러한 기본적인 애플리케이션을 만드는데만 해도 제법 귀찮고 복잡한 과정을 거쳐야 했을 것입니다. 하지만 아래 언급할 여러 기술 스택들을 적극적으로 활용함으로써, 저는 금요일 퇴근 후 하루 + 주말 반나절 이라는 짧은 시간만에 개발부터 배포까지 손쉽게 완료할 수 있었습니다. 이번 글에서는, 부산 사설 도서관 도서 관리 서비스를 구축하며 사용했던 빠른 개발 방법들을 소개하고, Next.js의 서버 컴포넌트, Supabase와 RLS, Radix UI와 Vercel의 활용을 통해 이틀도 안 되는 시간 안에 완성한 비결을 공유하겠습니다.
Next.js Server Component를 통한 백엔드 구축
Next.js 13부터 도입된 app directory와 서버 컴포넌트(Server Component) 기능은 프론트엔드와 백엔드를 결합하여 효율적인 애플리케이션 구조를 제공하는 방식입니다. 이 덕분에 프론트엔드 개발자도 별도의 Node.js 백엔드 서버 없이 데이터베이스와 직접 통신할 수 있는 서버 로직을 안전하게 구현할 수 있습니다.
서버 컴포넌트
서버 컴포넌트는 페이지를 렌더링하기 전에 서버에서 데이터를 불러와 HTML을 완성한 뒤 클라이언트로 전달합니다. 이러한 방식은 프론트엔드에서 API 요청을 별도로 처리할 필요 없이 서버에서 완성된 데이터를 가져올 수 있기 때문에 보안성과 성능 최적화에 강점을 가지고 있습니다. 또한, Next.js의 서버 액션(Server Actions)을 활용하면, 클라이언트 코드와는 독립적으로 서버에서만 실행되는 로직을 구현할 수 있어 데이터베이스 접근이 노출되지 않습니다.
import { Pool } from 'pg';
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_DATABASE,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT as unknown as number,
});
export default async function Page() {
const query = `SELECT * FROM books`;
const { rows } = await pool.query(query);
return (
<div>
{rows.length > 0 ? rows.map(book => <div>{book.name}</div>) : <p>No books found!</p>}
</div>
);
}
이 예시에서 서버 컴포넌트는 직접 DB에 접근하여 쿼리를 실행하고, 이를 바탕으로 HTML을 생성해 클라이언트에 전달합니다. 클라이언트는 DB 접근에 대한 정보를 전혀 알 수 없으므로 보안적으로 안전하며, 백엔드와 프론트엔드의 통합 작업이 매우 간소화됩니다.
Supabase를 통한 DB 및 인증, 권한 관리
백엔드 구축에서 필수적인 요소는 데이터베이스의 구조 설계와 인증, 인가 로직의 구현입니다. 이때 Supabase는 PostgreSQL 기반의 DB를 제공하면서도 빠르고 쉽게 데이터베이스와 인증 시스템을 구축할 수 있도록 도와줍니다.
Supabase
Supabase는 초기 설정이 간단하며, SQL 쿼리를 설사 한 줄도 모르더라도 웹 콘솔에서 테이블을 생성하고 제어할 수 있습니다. 또한 Role-Based Access Control (RLS, Row-Level Security)를 지원해, 각 사용자별 권한 제어를 쉽게 설정할 수 있습니다. 이를 통해 각 도서관 계정마다 접근 가능한 데이터를 제한하는 등의 기본 인가 기능을 손쉽게 구현할 수 있었습니다.
-- 자신의 도서만 삭제할 수 있는 권한 부여 RLS 정책
CREATE POLICY "Library book delete"
ON books
FOR DELETE
USING (user_id = auth.uid());
// action/book
/**
*
* @param libraryId 도서관 식별자
* @description 해당 도서관의 모든 도서 삭제
*/
export async function deleteAllBooks(libraryId: number) {
const supabase = createClient();
const { error } = await supabase
.from('book')
.delete()
.eq('library_id', libraryId);
if (error) {
console.error('Error deleting old books:', error.message);
throw new Error('Failed to delete existing books');
}
}
이를 통해 Next.js server action에서 인증과 관련된 어떠한 추가 구현을 하지 않고도, 인증되지 않았거나 다른 도서관에 대한 삭제 요청을 DB단에서 막을 수 있습니다.
Radix UI로 빠른 UI 구축
UI 구성 요소는 사용자와의 상호작용에서 매우 중요한 역할을 합니다. Radix UI는 React 기반의 기능성 컴포넌트 라이브러리로, 접근성(Accessibility)과 유연성을 염두에 두고 설계되었습니다. 이를 통해 프론트엔드 개발자는 기본적인 UI 요소들을 직접 구현할 필요 없이 빠르고 쉽게 적용할 수 있습니다.
Radix UI의 장점
- 내장된 접근성(A11y): 모든 UI 컴포넌트가 WCAG 준수를 목표로 설계되어, 추가적인 접근성 로직 없이도 쉽게 접근성 있는 UI를 만들 수 있습니다.
- 유연한 스타일링: Radix UI는 디자인 시스템과 결합하기 쉽게 만들어졌습니다. Styled-components, Emotion, Tailwind 등 어떤 스타일링 도구를 사용하더라도 유연하게 컴포넌트를 확장할 수 있습니다.
import * as Dialog from '@radix-ui/react-dialog';
function LibraryDialog() {
return (
<Dialog.Root>
<Dialog.Trigger>도서관 정보</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>도서관 이름</Dialog.Title>
<Dialog.Description>도서 목록</Dialog.Description>
<Dialog.Close>종료</Dialog.Close>
</Dialog.Content>
</Dialog.Root>
);
}
위와 같은 Radix UI 컴포넌트를 활용하면 빠르게 기본적인 UI 기능을 구성할 수 있으며, 커스터마이징을 통해 프로젝트 요구사항에 맞는 UI를 구현할 수 있습니다.
Vercel을 통한 빠른 배포
Vercel은 Next.js를 만든 회사에서 제공하는 배포 플랫폼으로, Next.js 애플리케이션과 완벽하게 호환되는 환경을 제공합니다. 특히 서버리스(Serverless) 아키텍처를 기반으로 하여, Next.js의 서버 컴포넌트와 API 라우트가 Vercel에서 최적화된 형태로 실행되기 때문에, 배포 속도가 매우 빠르고 간단합니다.
Vercel의 주요 장점
- 자동화된 배포: GitHub 또는 GitLab과 연동하면, 코드가 push 될 때마다 자동으로 빌드 및 배포가 진행되며, 도메인 설정도 자동으로 이루어집니다.
- 서버리스 함수: Next.js API 라우트를 사용해 작성된 서버 로직이 자동으로 서버리스 함수로 변환되어, 스케일링 문제없이 안정적으로 동작합니다.
- 전역 CDN: Vercel은 전역 CDN을 통해 애플리케이션을 최적의 성능으로 사용자에게 제공하며, 이를 통해 전 세계 어디에서나 빠른 응답 속도를 보장할 수 있습니다.
- 손쉬운 배포 프리뷰: 각 브랜치마다 자동으로 프리뷰 URL이 생성되기 때문에, 배포 전에 팀원들과 변경 사항을 빠르게 공유하고 테스트할 수 있습니다.
Vercel을 사용하면 Next.js 애플리케이션을 별도의 설정 없이도 자동화된 방식으로 배포할 수 있으며, 복잡한 인프라 관리 없이도 안정적이고 빠른 서비스를 제공할 수 있습니다.
JavaScript로 풀스택 애플리케이션 구축
기존 프론트엔드 개발자들이 웹 애플리케이션을 구축할 때 가장 문제가 되었던 부분은 다음과 같았습니다
- DB: 브라우저 스토리지 외에도 데이터를 안전하게 저장하고 관리할 데이터베이스가 필요했습니다.
- 백엔드 서버: 데이터베이스와 애플리케이션 간 통신을 위한 백엔드 서버를 별도로 구축해야 했습니다.
- 복잡한 인증, 인가 로직 구현: 사용자의 권한을 구분하고 안전하게 인증하는 로직을 수작업으로 구현해야 했습니다.
- 사용자 친화적 UI 스타일링: 복잡한 UI 컴포넌트를 직접 스타일링하는 작업은 시간과 비용이 많이 소요되었습니다.
- 환경 구성 및 배포 과정의 복잡성: 서버 설정, 배포 과정, 도메인 관리 등 인프라 작업이 번거로웠습니다.
이러한 문제점들이 Next.js, Supabase, UI Framework(Radix UI), Vercel이라는 네 가지의 조합으로 해결할 수 있는 것이죠.
- Next.js: 서버 컴포넌트를 통해 백엔드 없이도 데이터베이스와 안전하게 통신하고, 서버에서 필요한 데이터를 처리하여 브라우저로 전달할 수 있습니다.
- Supabase: 실시간 데이터를 관리하고, 복잡한 쿼리 없이도 손쉽게 데이터베이스를 설정할 수 있으며, RLS를 통해 인증과 인가를 간편하게 구현할 수 있습니다.
- Radix UI와 같은 UI Framework: 사용자 친화적이고 접근성 높은 UI 컴포넌트를 빠르게 구축할 수 있습니다.
- Vercel: 인프라에 대한 고민 없이, 애플리케이션을 빠르고 안정적으로 배포할 수 있습니다.
이러한 도구들의 조합을 통해 프론트엔드 개발자들은 더 나은 생산성과 효율성을 바탕으로, 더 빠르고 안전한 애플리케이션을 구축할 수 있게 되었습니다. 기존에 백엔드와 인프라 관련 설정에 들였던 시간을 절감할 수 있어, 실제 비즈니스 로직에 더 집중할 수 있는 환경을 제공합니다.
'source-code > FrontEnd' 카테고리의 다른 글
지속 가능한 프론트엔드 단위 테스트 작성법 (2) | 2024.10.09 |
---|---|
next.js에 FSD 폴더 구조 패턴 적용하기 (1) | 2024.09.24 |
[chrome extension] 이미지 파일 안전하게 불러오기 (0) | 2024.08.09 |
Feature-Sliced Design(FSD) 도입기 (0) | 2024.08.03 |
[chrome extension] dynamic import시 Cannot find module 에러 해결하기 (0) | 2024.07.26 |