NextJS Templates
Back4App, Next.js 및 Vercel을 이용한 회의실 예약 앱 튜토리얼
23 분
이 튜토리얼에서는 bookit , 회의실 예약 시스템을 구축할 것입니다 프론트엔드 프레임워크로는 next js 를 사용하고, 백엔드 서비스로는 back4app 을 사용합니다 사용자 인증, 방 관리 및 예약 기능을 구현하고, 앱을 vercel 에 배포할 것입니다 1 필수 조건 이 튜토리얼을 완료하려면 다음이 필요합니다 back4app 계정 (가입은 back4app https //www back4app com/ ) back4app 프로젝트 ( 이 가이드 https //www back4app com/docs/get started/welcome ) 로컬 머신에 node js 설치 ( 설치 가이드 https //nodejs org/ ) javascript, next js 및 rest api에 대한 기본 지식 (필요한 경우, javascript 기초 https //www back4app com/docs/javascript guide ) 2 back4app 설정하기 back4app 계정에 로그인하고 프로젝트 대시보드로 이동합니다 왼쪽 사이드바에서 데이터베이스 를 클릭하여 데이터 브라우저에 접근합니다 데이터 모델링을 위해 다음 클래스를 생성해야 합니다 2 1 사용자 클래스 생성하기 기본적으로 parse는 사용자 인증을 처리하므로 이 클래스를 수동으로 생성할 필요가 없습니다 parse는 다음 필드를 자동으로 관리합니다 이메일 로그인용 이메일 주소 비밀번호 비밀번호 (해시됨) 사용자 이름 선택적 사용자 이름 2 2 방 클래스 만들기 데이터 브라우저에서 data browser , 클릭하여 클래스 만들기 , 선택하고 사용자 정의 , 그리고 클래스를 룸 , 이름을 지정합니다 다음 열을 추가합니다 열 이름 유형 설명 이름 문자열 방 이름 설명 문자열 방 설명 용량 번호 방이 수용할 수 있는 인원 수 편의 시설 배열 편의 시설 목록 (tv, wifi 등) 가격 번호 시간당 가격 이미지 파일 이미지 url 소유자 포인터 지점을 사용자 클래스 2 3 예약 클래스 만들기 또 다른 사용자 정의 클래스를 만들기 예약 다음 열을 추가하세요 열 이름 유형 설명 방 포인터 다음으로 가리킴 room 클래스 사용자 포인터 다음으로 가리킴 user 클래스 체크인 날짜 예약의 시작 날짜/시간 체크아웃 날짜 예약의 종료 날짜/시간 3 next js 및 parse sdk 설정하기 새로운 next js 프로젝트 생성하기 npx create next app bookit app cd bookit app parse js sdk 설치하기 npm install parse pages/ app js 파일에서 back4app 자격증명으로 parse 초기화하기 import parse from 'parse'; parse initialize('your app id', 'your javascript key'); parse serverurl = 'https //parseapi back4app com'; function myapp({ component, pageprops }) { return \<component { pageprops} /> } export default myapp; 'your app id' 및 'your javascript key' 를 back4app 앱 자격증명으로 교체하세요 4 사용자 인증 구현하기 4 1 사용자 등록 등록 양식이 있는 새 페이지 pages/signup js 생성하기 import { usestate } from 'react'; import parse from 'parse'; export default function signup() { const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const handlesignup = async (e) => { e preventdefault(); const user = new parse user(); user set('username', email); user set('email', email); user set('password', password); try { await user signup(); alert('signup successful!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handlesignup}> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="email" /> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="password" /> \<button type="submit">sign up\</button> \</form> ); } 4 2 사용자 로그인 사용자 로그인을 위한 pages/login js 생성하기 import { usestate } from 'react'; import parse from 'parse'; export default function login() { const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const handlelogin = async (e) => { e preventdefault(); try { await parse user login(email, password); alert('login successful!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handlelogin}> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="email" /> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="password" /> \<button type="submit">login\</button> \</form> ); } 4 3 보호된 경로 보호된 경로의 경우, next js api 경로를 사용하고 사용자가 인증되었는지 확인할 수 있습니다 import parse from 'parse'; export default async function handler(req, res) { const user = parse user current(); if (!user) { return res status(401) json({ message 'unauthorized' }); } // proceed with the request } 5 방 관리 5 1 사용 가능한 방 표시 다음과 같이 사용 가능한 방을 나열하기 위해 pages/index js 를 생성하세요 import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function home() { const \[rooms, setrooms] = usestate(\[]); useeffect(() => { const fetchrooms = async () => { const room = parse object extend('room'); const query = new parse query(room); const results = await query find(); setrooms(results); }; fetchrooms(); }, \[]); return ( \<div> \<h1>available rooms\</h1> {rooms map(room => ( \<div key={room id}> \<h2>{room get('name')}\</h2> \<img src={room get('image') url()} alt={room get('name')} /> \<p>capacity {room get('capacity')}\</p> \<p>price ${room get('price')} per hour\</p> \</div> ))} \</div> ); } 5 2 방 추가하기 새 방을 추가하기 위해 pages/add room js 를 생성합니다 (권한이 있는 사용자용) import { usestate } from 'react'; import parse from 'parse'; export default function addroom() { const \[name, setname] = usestate(''); const \[description, setdescription] = usestate(''); const \[capacity, setcapacity] = usestate(0); const \[price, setprice] = usestate(0); const handleaddroom = async (e) => { e preventdefault(); const room = parse object extend('room'); const room = new room(); room set('name', name); room set('description', description); room set('capacity', capacity); room set('price', price); try { await room save(); alert('room added successfully!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handleaddroom}> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="room name" /> \<textarea value={description} onchange={(e) => setdescription(e target value)} placeholder="description">\</textarea> \<input type="number" value={capacity} onchange={(e) => setcapacity(parseint(e target value))} placeholder="capacity" /> \<input type="number" value={price} onchange={(e) => setprice(parseint(e target value))} placeholder="price" /> \<button type="submit">add room\</button> \</form> ); } 5 3 방 세부정보 방에 대한 자세한 정보를 보려면 pages/rooms/\[id] js 를 생성합니다 import { userouter } from 'next/router'; import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function roomdetails() { const router = userouter(); const { id } = router query; const \[room, setroom] = usestate(null); useeffect(() => { if (!id) return; const fetchroom = async () => { const room = parse object extend('room'); const query = new parse query(room); query equalto('objectid', id); const result = await query first(); setroom(result); }; fetchroom(); }, \[id]); if (!room) return \<div>loading \</div>; return ( \<div> \<h1>{room get('name')}\</h1> \<img src={room get('image') url()} alt={room get('name')} /> \<p>{room get('description')}\</p> \<p>capacity {room get('capacity')}\</p> \<p>price ${room get('price')} per hour\</p> \</div> ); } 6 예약 시스템 6 1 방 예약하기 예약 양식을 추가하여 pages/rooms/\[id] js 에 예약 기능을 추가하세요 const \[checkin, setcheckin] = usestate(''); const \[checkout, setcheckout] = usestate(''); const handlebooking = async () => { const booking = parse object extend('booking'); const booking = new booking(); booking set('room', room); booking set('user', parse user current()); booking set('checkin', new date(checkin)); booking set('checkout', new date(checkout)); // check for double booking (example logic) const query = new parse query(booking); query equalto('room', room); query greaterthanorequalto('checkin', new date(checkin)); query lessthanorequalto('checkout', new date(checkout)); const overlap = await query first(); if (!overlap) { try { await booking save(); alert('booking successful!'); } catch (error) { alert('error ' + error message); } } else { alert('room is already booked for the selected time range '); } }; 6 2 예약 보기 및 취소하기 예약을 보기 위해 pages/my bookings js 를 생성하세요 import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function mybookings() { const \[bookings, setbookings] = usestate(\[]); useeffect(() => { const fetchbookings = async () => { const booking = parse object extend('booking'); const query = new parse query(booking); query equalto('user', parse user current()); const results = await query find(); setbookings(results); }; fetchbookings(); }, \[]); const handlecancel = async (id) => { const booking = bookings find(b => b id === id); if (booking) { await booking destroy(); setbookings(bookings filter(b => b id !== id)); } }; return ( \<div> \<h1>my bookings\</h1> {bookings map(booking => ( \<div key={booking id}> \<p>room {booking get('room') get('name')}\</p> \<p>check in {new date(booking get('checkin')) tolocalestring()}\</p> \<p>check out {new date(booking get('checkout')) tolocalestring()}\</p> \<button onclick={() => handlecancel(booking id)}>cancel booking\</button> \</div> ))} \</div> ); } 7 vercel에 배포하기 vercel cli 설치 npm install g vercel 다음 js 앱을 배포하려면 vercel 프롬프트에 따라 앱을 vercel에 배포하세요 배포가 완료되면, 앱은 공개 url에서 실시간으로 제공됩니다 8 결론 이 튜토리얼에서는 bookit 앱을 next js 를 프론트엔드로 사용하고 back4app 을 백엔드로 사용하여 구축했습니다 사용자 인증, 방 관리 및 예약 기능을 구현했습니다 마지막으로, 앱을 vercel 에 배포했습니다 이제 검색, 결제 통합 또는 알림과 같은 추가 기능으로 앱을 확장할 수 있습니다