항상 백엔드를 간단하게 만들어 보고 싶다는 생각을 가지고 있었습니다.
최근 사이드 프로젝트를 시작하며 이번 기회에 프론트 구현을 위해 쓴 Next.js 위에서 파이어베이스를 활용해 한꺼번에 API를 구현해봤습니다.
원래는 간단하게 백엔드 작업을 할 때 Node.js로 작업한 후 heroku로 배포를 해왔는데, 이번에 하는 방법은 그보다 더 간소화된 방법입니다. 프론트와 별도로 repository를 생성하거나 별도로 배포 작업을 할 필요가 없습니다.
또, 파이어베이스를 활용해 인프라, DB 작업을 정말정말 간단하게 진행할 수 있습니다.
트래픽이 많지 않을 걸로 예상되거나 MVP를 빠르게 만들어 내야 하는 사이드 프로젝트의 경우에 유용한 방식입니다.
(저는 실제로 이 방식으로 API 10개 정도 되는 MVP 백엔드를 프로젝트 세팅부터 설계, 개발 완료까지 5시간 정도에 완주했습니다.)
바뀐 Next에 적응하기
Next.js 14를 활용하며, 원래 사용하던 /pages 방식의 라우팅이 아닌 /app 라우팅으로 세팅했습니다.
/pages 방식에서는 /pages 디렉토리 내에, 예를 들어 user.js나 user.ts 파일을 만든 후 handler 함수를 만들어 API 콜을 핸들링 했습니다.
// src/pages/api/users.js
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' });
}
하지만 새로운 방식인 /app 라우팅 방식에서는 /api 폴더를 만든 후 그 안에 라우팅 엔드포인트가 될 디렉토리를 생성한 후에 route.js나 route.ts 파일을 만들어주어야 합니다.
그 후 함수 이름을 HTTP 메서드에 맞게 GET이나 POST 등등으로 설정해주면, 해당 엔드포인트로 해당 HTTP 요청이 들어왔을 때 실행시켜주는 방식입니다.
// app/api/users/route.ts
export async function GET(req: NextRequest) {
return NextResponse.json({
name: "John Doe",
});
}
만약 query parameter을 받아야 한다면,
이렇게 searchParams에서 해당하는 쿼리 파람을 받아주면 됩니다.
export async function GET(req: Request) {
const {searchParams} = new URL(req.url);
const uid = searchParams.get('uid');
return NextResponse.json(uid);
}
또 Request Body를 받아야 한다면,
이렇게 req를 받아 구조분해할당 해서 사용하면 됩니다.
export async function POST(req: Request) {
const requestBody = await req.json();
const {uid, agentId} = requestBody;
return new Response;
}
더 자세한 내용은 아래 문서를 참고해보세요.
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
Routing: Route Handlers | Next.js
Create custom request handlers for a given route using the Web's Request and Response APIs.
nextjs.org
Firebase 세팅
가장 먼저 파이어베이스 세팅을 해주어야 합니다.
프로젝트에서 Firebase SDK를 설치해주어야 하는데요,
npm install firebase나
yarn add firebase 등 자신이 쓰는 패키지 라이브러리로 설치해주면 됩니다.
설치를 해주었다면 다시 파이어베이스 콘솔로 돌아와서,
파이어베이스에서 프로젝트 생성을 하고 나면 프로젝트 세팅에서 파이어베이스 세팅을 위한 모든 코드 스니펫을 제공합니다.


이 코드 스니펫을 복사해 src 폴더 안에 firebase 폴더를 만들어주고, index.ts 파일을 만들어준 후 붙여넣기 해줍니다.

이렇게 해주면 next에서 파이어베이스를 활용해 api를 만들 준비가 모두 되었습니다.
Next.js에서 Firebase 사용하기
이제 본격적으로 넥스트에서 파이어베이스를 사용해 API를 만들어보겠습니다.
여기까지 잘 따라왔다면, 기본적인 사용법은 Node.js에서 파이어베이스를 사용하는 것과 동일합니다.
그 말인 즉슨, 파이어베이스 Docs에서 Node.js 쪽이나 Javascript 설명을 보면 됩니다.
Firestore 사용하기
가장 먼저 파이어베이스의 NoSQL DB인 Firestore를 사용해보겠습니다.
Firestore는 Collection > Document > Field의 뎁스로 이루어져 있습니다.
이걸 우선 알고 시작하면 파이어스토어의 데이터 구조를 빠르게 이해할 수 있습니다.
Firestore 초기화
Firestore를 사용하기 위해서는 따로 패키지를 설치해줄 필요는 없고 (처음에 설치한 firebase 패키지에 포함되어 있습니다.) firebase/index.ts에서 firestore 초기화만 해주면 됩니다.
아까 만든 firebase/index.ts 가장 하단에 아래 코드를 추가해줍니다.
export const myFirestore = getFirestore(firebaseApp); // my를 자신의 프로젝트 이름으로 바꿔주세요.
그냥 firestore나 db로 만드는 경우도 있지만,
그렇게 만드는 경우 firestore 패키지의 변수인지, 우리 프로젝트의 변수인지 헷갈릴 뿐더러 realtimeDB와 헷갈릴 수도 있어서, 저는 <프로젝트 이름>Firestore 이렇게 이름을 짓는 방식을 선호합니다.
Firestore에 데이터 추가하기
Firestore에 이제 데이터를 추가해 볼 수 있는 상태가 되었는데요,
가장 간단한 방식으로 데이터를 추가할 때는 addDoc()을 사용해주면 됩니다.
AddDoc()을 사용하면 파이어스토어가 자동으로 도큐먼트 ID를 생성해 도큐먼트를 추가해줍니다.
또한, 해당하는 이름의 Collection이 없다면 Collection도 자동으로 생성해줍니다.
const collectionRef = collection(myFirestore, "cities");
await addDoc(collectionRef, {
name: "Tokyo",
country: "Japan"
});
이렇게 CollectionRef를 생성해주고, collection() 안에는 아까 초기화한 Firestore 변수명과 해당 도큐먼트를 추가할 컬렉션 이름을 차례로 넣어줍니다.
그 후 해당 addDoc() 하면 해당되는 데이터가 도큐먼트로 추가됩니다.
만약, 도큐먼트 이름을 직접 생성하고 싶다면, addDoc 대신 setDoc을 활용해볼 수 있습니다.
이미 있는 도큐먼트를 업데이트 하고 싶다면 updateDoc을 활용합니다.
https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ko
Cloud Firestore에 데이터 추가 | Firebase
Firebase 데모 데이가 시작되었습니다. Google 최고의 기술을 활용하여 AI 기반 풀 스택 앱을 빌드하고 성장시키는 방법에 관한 데모를 시청하세요. 의견 보내기 Cloud Firestore에 데이터 추가 컬렉션을
firebase.google.com
이 방법을 활용해 간단하게 POST api를 만들어 볼 수 있습니다.
Firestore에서 데이터 가져오기
이번에는 데이터를 가져오는 방법에 대해 살펴보겠습니다. GET api에서 많이 쓰일 것 같네요.
getDoc()을 활용해 볼 수 있는데요,
doc() 안에 myFirestore, 컬렉션명, 가져오고 싶은 도큐먼트명을 차례대로 입력해주면 됩니다.
const docRef = doc(myFirestore, "cities", "SF");
const docSnap = await getDoc(docRef);
하지만, 사실 도큐먼트 이름을 정확히 알아서 가져오는 경우보다,
도큐먼트 안에 있는 필드로 쿼리를 돌려서 특정 도큐먼트만 가져오려는 경우가 더 많을 것 같은데요,
(특정 유저와 관련된 데이터만 가져오기 위해 쿼리해와야 하는 것 같은 경우)
그럴 때는 query()를 활용해 볼 수 있습니다.
const q = query(collection(myFirestore, "cities"), where("capital", "==", true));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
where()을 활용해 cities내 컬렉션들 중 capital 필드가 true인 도큐먼트만 가져오는 코드입니다.
마찬가지로 pagination도 쿼리 개수를 제한하는 limit()과 쿼리 시작점을 설정하는 startAt()/startAfter()을 활용해 간단히 구현 가능합니다.
더 자세한 내용은 아래 공식문서를 첨부합니다.
https://firebase.google.com/docs/firestore/query-data/get-data?hl=ko#get_a_document
Cloud Firestore로 데이터 가져오기 | Firebase
Firebase 데모 데이가 시작되었습니다. Google 최고의 기술을 활용하여 AI 기반 풀 스택 앱을 빌드하고 성장시키는 방법에 관한 데모를 시청하세요. 의견 보내기 Cloud Firestore로 데이터 가져오기 컬렉
firebase.google.com
Storage 사용하기
이미지 등을 올리고 관리하려면 Firestore가 아닌 Storage를 사용해야 합니다.
Storage 초기화
파이어스토어와 같이 스토리지도 firestore/index.ts에서 초기화해줍니다.
export const myStorage = getStorage(); // my 부분을 자신의 프로젝트 명으로 변경해줍니다.
Storage에서 데이터 url 가져오기
스토리지에 올려둔 데이터의 url을 가져오기 위해선 getDownURL()을 사용해주면 됩니다.
아까 만들어준 myStorage와 스토리지 내에 저장된 데이터의 경로를 적어줍니다.
저는 Firestore의 도큐먼트 id로 모든 이미지를 저장해두어 그렇게 경로를 작성했습니다.
const thumbnail: string = await getDownloadURL(ref(myStorage, 'blog/thumbnail/' + doc.id + '.png')).then((url) => {
return url;
});
이렇게 이미지의 url을 받아 프론트에 API로 내려주면 프론트에서 사용할 수 있습니다.
Authentication 사용하기
파이어베이스에 많은 서비스들이 있지만, 간단한 MVP를 만들기 위해서 사용될 서비스들만 살펴보고 있습니다.
마지막으로 살펴볼 건 회원가입과 로그인을 관리하는 Authentication입니다.
구글로그인을 예시로 들어보겠습니다.
파이어베이스 콘솔에서 Authentication 제품을 찾아줍니다.

그 후 구글 로그인을 활성화해주고, 안내에 따라 설정해주면 됩니다.


이 부분에 대한 더 자세한 내용은 잘 설명된 블로그 링크를 첨부합니다.
사실 이 부분은 API 폴더에서보다 프론트에서 작업해주는 게 더 편한데요,
아까 만들어뒀던 firebase/index.ts에서 초기화 한 번만 해주고,
export const myAuth = getAuth(firebaseApp);
아래처럼 코드를 써주기만 하면 됩니다.
function handleGoogleLogin() {
const provider = new GoogleAuthProvider();
signInWithPopup(myAuth, provider)
.then((data) => {
setUserData(data.user);
const user = tarsAuth.currentUser;
user?.providerData.forEach((profile) => {
console.log("Name", profile.displayName); // TODO: 프론트에 이름 표시할 때 이거 쓰세요
});
console.log(user?.uid); // TODO: api에 uid 보낼 때 이걸로 보내주세요
})
.catch((err) => {
console.log(err);
});
}
정말 간단하게 사용법들을 살펴봤는데요,
이 블로그 글에서 기본적인 개념과 Docs 보는 방법에 대한 그림을 성공적으로 그렸다면, 이 블로그에 나와있지 않은 내용들에 대한 문제를 해결할 때도 수월해지지 않을까 생각합니다.
이렇게, 기본적인 Next.js API와 Firebase의 몇가지 서비스 사용법만 알면 프론트와 같이 작업하며 간단히 API를 만들 수 있습니다.
'Backend' 카테고리의 다른 글
DB Connection Pool에 대해 (0) | 2025.01.31 |
---|---|
사람들은 왜 자바가 아닌 코틀린에 열광할까? (0) | 2025.01.05 |
Nest.js에서 prisma exception 데코레이터로 깔끔하게 핸들링하기 (0) | 2024.11.24 |
WebFlux에서 chunked 스트리밍 request 받기 (3) | 2024.10.27 |
Node.js + TypeScript를 heroku로 배포하기 (0) | 2023.04.08 |
항상 백엔드를 간단하게 만들어 보고 싶다는 생각을 가지고 있었습니다.
최근 사이드 프로젝트를 시작하며 이번 기회에 프론트 구현을 위해 쓴 Next.js 위에서 파이어베이스를 활용해 한꺼번에 API를 구현해봤습니다.
원래는 간단하게 백엔드 작업을 할 때 Node.js로 작업한 후 heroku로 배포를 해왔는데, 이번에 하는 방법은 그보다 더 간소화된 방법입니다. 프론트와 별도로 repository를 생성하거나 별도로 배포 작업을 할 필요가 없습니다.
또, 파이어베이스를 활용해 인프라, DB 작업을 정말정말 간단하게 진행할 수 있습니다.
트래픽이 많지 않을 걸로 예상되거나 MVP를 빠르게 만들어 내야 하는 사이드 프로젝트의 경우에 유용한 방식입니다.
(저는 실제로 이 방식으로 API 10개 정도 되는 MVP 백엔드를 프로젝트 세팅부터 설계, 개발 완료까지 5시간 정도에 완주했습니다.)
바뀐 Next에 적응하기
Next.js 14를 활용하며, 원래 사용하던 /pages 방식의 라우팅이 아닌 /app 라우팅으로 세팅했습니다.
/pages 방식에서는 /pages 디렉토리 내에, 예를 들어 user.js나 user.ts 파일을 만든 후 handler 함수를 만들어 API 콜을 핸들링 했습니다.
// src/pages/api/users.js
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' });
}
하지만 새로운 방식인 /app 라우팅 방식에서는 /api 폴더를 만든 후 그 안에 라우팅 엔드포인트가 될 디렉토리를 생성한 후에 route.js나 route.ts 파일을 만들어주어야 합니다.
그 후 함수 이름을 HTTP 메서드에 맞게 GET이나 POST 등등으로 설정해주면, 해당 엔드포인트로 해당 HTTP 요청이 들어왔을 때 실행시켜주는 방식입니다.
// app/api/users/route.ts
export async function GET(req: NextRequest) {
return NextResponse.json({
name: "John Doe",
});
}
만약 query parameter을 받아야 한다면,
이렇게 searchParams에서 해당하는 쿼리 파람을 받아주면 됩니다.
export async function GET(req: Request) {
const {searchParams} = new URL(req.url);
const uid = searchParams.get('uid');
return NextResponse.json(uid);
}
또 Request Body를 받아야 한다면,
이렇게 req를 받아 구조분해할당 해서 사용하면 됩니다.
export async function POST(req: Request) {
const requestBody = await req.json();
const {uid, agentId} = requestBody;
return new Response;
}
더 자세한 내용은 아래 문서를 참고해보세요.
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
Routing: Route Handlers | Next.js
Create custom request handlers for a given route using the Web's Request and Response APIs.
nextjs.org
Firebase 세팅
가장 먼저 파이어베이스 세팅을 해주어야 합니다.
프로젝트에서 Firebase SDK를 설치해주어야 하는데요,
npm install firebase나
yarn add firebase 등 자신이 쓰는 패키지 라이브러리로 설치해주면 됩니다.
설치를 해주었다면 다시 파이어베이스 콘솔로 돌아와서,
파이어베이스에서 프로젝트 생성을 하고 나면 프로젝트 세팅에서 파이어베이스 세팅을 위한 모든 코드 스니펫을 제공합니다.


이 코드 스니펫을 복사해 src 폴더 안에 firebase 폴더를 만들어주고, index.ts 파일을 만들어준 후 붙여넣기 해줍니다.

이렇게 해주면 next에서 파이어베이스를 활용해 api를 만들 준비가 모두 되었습니다.
Next.js에서 Firebase 사용하기
이제 본격적으로 넥스트에서 파이어베이스를 사용해 API를 만들어보겠습니다.
여기까지 잘 따라왔다면, 기본적인 사용법은 Node.js에서 파이어베이스를 사용하는 것과 동일합니다.
그 말인 즉슨, 파이어베이스 Docs에서 Node.js 쪽이나 Javascript 설명을 보면 됩니다.
Firestore 사용하기
가장 먼저 파이어베이스의 NoSQL DB인 Firestore를 사용해보겠습니다.
Firestore는 Collection > Document > Field의 뎁스로 이루어져 있습니다.
이걸 우선 알고 시작하면 파이어스토어의 데이터 구조를 빠르게 이해할 수 있습니다.
Firestore 초기화
Firestore를 사용하기 위해서는 따로 패키지를 설치해줄 필요는 없고 (처음에 설치한 firebase 패키지에 포함되어 있습니다.) firebase/index.ts에서 firestore 초기화만 해주면 됩니다.
아까 만든 firebase/index.ts 가장 하단에 아래 코드를 추가해줍니다.
export const myFirestore = getFirestore(firebaseApp); // my를 자신의 프로젝트 이름으로 바꿔주세요.
그냥 firestore나 db로 만드는 경우도 있지만,
그렇게 만드는 경우 firestore 패키지의 변수인지, 우리 프로젝트의 변수인지 헷갈릴 뿐더러 realtimeDB와 헷갈릴 수도 있어서, 저는 <프로젝트 이름>Firestore 이렇게 이름을 짓는 방식을 선호합니다.
Firestore에 데이터 추가하기
Firestore에 이제 데이터를 추가해 볼 수 있는 상태가 되었는데요,
가장 간단한 방식으로 데이터를 추가할 때는 addDoc()을 사용해주면 됩니다.
AddDoc()을 사용하면 파이어스토어가 자동으로 도큐먼트 ID를 생성해 도큐먼트를 추가해줍니다.
또한, 해당하는 이름의 Collection이 없다면 Collection도 자동으로 생성해줍니다.
const collectionRef = collection(myFirestore, "cities");
await addDoc(collectionRef, {
name: "Tokyo",
country: "Japan"
});
이렇게 CollectionRef를 생성해주고, collection() 안에는 아까 초기화한 Firestore 변수명과 해당 도큐먼트를 추가할 컬렉션 이름을 차례로 넣어줍니다.
그 후 해당 addDoc() 하면 해당되는 데이터가 도큐먼트로 추가됩니다.
만약, 도큐먼트 이름을 직접 생성하고 싶다면, addDoc 대신 setDoc을 활용해볼 수 있습니다.
이미 있는 도큐먼트를 업데이트 하고 싶다면 updateDoc을 활용합니다.
https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ko
Cloud Firestore에 데이터 추가 | Firebase
Firebase 데모 데이가 시작되었습니다. Google 최고의 기술을 활용하여 AI 기반 풀 스택 앱을 빌드하고 성장시키는 방법에 관한 데모를 시청하세요. 의견 보내기 Cloud Firestore에 데이터 추가 컬렉션을
firebase.google.com
이 방법을 활용해 간단하게 POST api를 만들어 볼 수 있습니다.
Firestore에서 데이터 가져오기
이번에는 데이터를 가져오는 방법에 대해 살펴보겠습니다. GET api에서 많이 쓰일 것 같네요.
getDoc()을 활용해 볼 수 있는데요,
doc() 안에 myFirestore, 컬렉션명, 가져오고 싶은 도큐먼트명을 차례대로 입력해주면 됩니다.
const docRef = doc(myFirestore, "cities", "SF");
const docSnap = await getDoc(docRef);
하지만, 사실 도큐먼트 이름을 정확히 알아서 가져오는 경우보다,
도큐먼트 안에 있는 필드로 쿼리를 돌려서 특정 도큐먼트만 가져오려는 경우가 더 많을 것 같은데요,
(특정 유저와 관련된 데이터만 가져오기 위해 쿼리해와야 하는 것 같은 경우)
그럴 때는 query()를 활용해 볼 수 있습니다.
const q = query(collection(myFirestore, "cities"), where("capital", "==", true));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
where()을 활용해 cities내 컬렉션들 중 capital 필드가 true인 도큐먼트만 가져오는 코드입니다.
마찬가지로 pagination도 쿼리 개수를 제한하는 limit()과 쿼리 시작점을 설정하는 startAt()/startAfter()을 활용해 간단히 구현 가능합니다.
더 자세한 내용은 아래 공식문서를 첨부합니다.
https://firebase.google.com/docs/firestore/query-data/get-data?hl=ko#get_a_document
Cloud Firestore로 데이터 가져오기 | Firebase
Firebase 데모 데이가 시작되었습니다. Google 최고의 기술을 활용하여 AI 기반 풀 스택 앱을 빌드하고 성장시키는 방법에 관한 데모를 시청하세요. 의견 보내기 Cloud Firestore로 데이터 가져오기 컬렉
firebase.google.com
Storage 사용하기
이미지 등을 올리고 관리하려면 Firestore가 아닌 Storage를 사용해야 합니다.
Storage 초기화
파이어스토어와 같이 스토리지도 firestore/index.ts에서 초기화해줍니다.
export const myStorage = getStorage(); // my 부분을 자신의 프로젝트 명으로 변경해줍니다.
Storage에서 데이터 url 가져오기
스토리지에 올려둔 데이터의 url을 가져오기 위해선 getDownURL()을 사용해주면 됩니다.
아까 만들어준 myStorage와 스토리지 내에 저장된 데이터의 경로를 적어줍니다.
저는 Firestore의 도큐먼트 id로 모든 이미지를 저장해두어 그렇게 경로를 작성했습니다.
const thumbnail: string = await getDownloadURL(ref(myStorage, 'blog/thumbnail/' + doc.id + '.png')).then((url) => {
return url;
});
이렇게 이미지의 url을 받아 프론트에 API로 내려주면 프론트에서 사용할 수 있습니다.
Authentication 사용하기
파이어베이스에 많은 서비스들이 있지만, 간단한 MVP를 만들기 위해서 사용될 서비스들만 살펴보고 있습니다.
마지막으로 살펴볼 건 회원가입과 로그인을 관리하는 Authentication입니다.
구글로그인을 예시로 들어보겠습니다.
파이어베이스 콘솔에서 Authentication 제품을 찾아줍니다.

그 후 구글 로그인을 활성화해주고, 안내에 따라 설정해주면 됩니다.


이 부분에 대한 더 자세한 내용은 잘 설명된 블로그 링크를 첨부합니다.
사실 이 부분은 API 폴더에서보다 프론트에서 작업해주는 게 더 편한데요,
아까 만들어뒀던 firebase/index.ts에서 초기화 한 번만 해주고,
export const myAuth = getAuth(firebaseApp);
아래처럼 코드를 써주기만 하면 됩니다.
function handleGoogleLogin() {
const provider = new GoogleAuthProvider();
signInWithPopup(myAuth, provider)
.then((data) => {
setUserData(data.user);
const user = tarsAuth.currentUser;
user?.providerData.forEach((profile) => {
console.log("Name", profile.displayName); // TODO: 프론트에 이름 표시할 때 이거 쓰세요
});
console.log(user?.uid); // TODO: api에 uid 보낼 때 이걸로 보내주세요
})
.catch((err) => {
console.log(err);
});
}
정말 간단하게 사용법들을 살펴봤는데요,
이 블로그 글에서 기본적인 개념과 Docs 보는 방법에 대한 그림을 성공적으로 그렸다면, 이 블로그에 나와있지 않은 내용들에 대한 문제를 해결할 때도 수월해지지 않을까 생각합니다.
이렇게, 기본적인 Next.js API와 Firebase의 몇가지 서비스 사용법만 알면 프론트와 같이 작업하며 간단히 API를 만들 수 있습니다.
'Backend' 카테고리의 다른 글
DB Connection Pool에 대해 (0) | 2025.01.31 |
---|---|
사람들은 왜 자바가 아닌 코틀린에 열광할까? (0) | 2025.01.05 |
Nest.js에서 prisma exception 데코레이터로 깔끔하게 핸들링하기 (0) | 2024.11.24 |
WebFlux에서 chunked 스트리밍 request 받기 (3) | 2024.10.27 |
Node.js + TypeScript를 heroku로 배포하기 (0) | 2023.04.08 |