[강의]Next.js API 만들기

김하은·2024년 1월 13일
0

코드잇 강의 정리

목록 보기
2/60

API 라우팅

리퀘스트 핸들러 함수

  • 예를 들어서 /api/short-links로 들어오는 리퀘스트를 처리하려면 /pages/api/short-links.js 또는 /pages/api/short-links/index.js 경로로 파일을 만들고 함수를 default export하면 됨
export default async function handler(req, res) {
  ...
}

리퀘스트 객체

리스폰스 객체

  • 함수 체이닝 방식으로 사용하기 때문에, res.status(201).send()처럼 함수를 이어서 사용할 수 있음

Mongo DB 시작하기

  • 데이터: 컴퓨터가 이해할 수 있는 형태로 저장한 정보
  • 데이터베이스: 데이터를 따로 저장하고 관리하는 프로그램

Next.js에서 환경 변수 사용하기

환경 변수(Evironement Variable)

  • 우리가 평소에 사용하는 서비스들은 보통 서버 하나, 데이터베이스 하나로 실행되지 않음
  • 환경 변수: 프로그램에서 실행 환경에 다라 다른 값을 지정할 수 있는 변수
  • 꼭 서버와 데이터베이스를 여러 개 쓰는 경우가 아니더라도 데이터베이스 주소와 같은 값을 소스코드에 그대로 쓰는 것은 위험하며 환경 변수로 사용하는 것이 좋음
  • Node.js 환경에서는 환경변수들을 process.env라는 객체를 통해서 참조할 수 있음

Next.js에서 환경 변수 추가하기

  • Next.js에서는 기본적으로 dotenv라는 라이브러리를 지원함
  • 이 라이브러리는 .env 같은 이름의 파일에서 환경 변수들을 저장해 두면, Node.js 프로젝트를 실행할 때 환경 변수로 지정해 주는 라이브러리임
  • 이때 주의할 점은 .env 파일 같은 건 소스 코드에 포함시키면 안 된다는 것임
  • Next.js 프로젝트에서는 기본적으로 dotenv 설정이 되어 있어서, .env.local 같은 파일을 추가하면 손쉽게 환경 변수를 추가할 수 있음
// .env.local
MONGODB_URI=mongodb+srv://admin:blahblah@.clusterName.blahblah.mongodb.net/databaseName?retryWrites=true&w=majority
  • 이렇게 추가한 값을 process.env.MONGODB_URI 로 참조할 수 있음
export default function handler(req, res) {
  const DB_URI = process.env.MONGODB_URI;
  // 데이터베이스 접속 ...
}

Next.js에서 사용하는 특별한 환경 변수

  • 위에서 추가한 데이터베이스 주소는 유저의 아이디와 비밀번호를 포함한 아주 민감한 정보임
  • 환경 변수가 웹 사이트에 노출되는 사고를 막기 위해서 Next.js에서는 클라이언트 사이드에서 사용하는 환경 변수에 특별한 접두사(prefix)를 사용함
  • NEXT_PUBLIC_ 이라고 이름을 붙이면 이 환경 변수는 클라이언트 사이드에서도 사용할 수 있음
  • 예를 들어서 클라이언트 사이드에서 현재 사이트의 호스트 주소를 저장해 두고 참조하고 싶다면 아래와 같이 NEXT_PUBLIC_HOST 라는 이름으로 사용하면 됨
MONGODB_URI=mongodb+srv://admin:blahblah@cluster0.blahblah.mongodb.net/databaseName?retryWrites=true&w=majority
NEXT_PUBLIC_HOST=http://localhost:3000
export default Home() {
  // 페이지 컴포넌트에서는 아래와 같이 사용
  return (
    <>호스트 주소: {process.env.NEXT_PUBLIC_HOST}</>
  );

Mongoose 문법 정리

데이터베이스 연동하기

  • 가장 먼저 mongoose.connect() 함수를 사용해서 커넥션을 만들고 사용함
  • 이때 Next.js 환경에서 커넥션을 불필요하게 여러 개 만들 수 있기 때문에, 캐싱 기법을 사용하는데 복잡할 수 있기 때문에 공식 리포지터리에 있는 코드(next.js/examples/with-mongodb-mongoose)를 참고해서 구현하는 걸 권장함
  • 연동이 잘 되었는지 확인하려면 아래와 같이 mongoose.connection.readyState라는 값을 확인하면 됨
  • 문서에 따르면 접속한 상태에서는 1이라는 값이 출력되어야 함
import mongoose from 'mongoose';
// ...
await dbConnect();
console.log(mongoose.connection.readyState);

모델 만들기

  • mongoose.Schema()를 사용해서 스키마를 생성함
  • 스키마는 모델이 어떤 속성을 가질지 정하는 용도이며 mongoose.model() 을 사용해서 모델을 생성함
  • 이때 모델의 이름을 첫 번째 아규먼트로 넘겨주는데, 이 이름은 mongoose.models[ ... ]로 참조할 수 있기 때문에 잘 지정했는지 반드시 확인해야 함
  • 예를 들어서 ShortLink라는 모델은 아래와 같이 만들 수 있는데 참고로 모듈 파일을 import할 때마다 모델을 생성하는 일이 일어나지 않도록 mongoose.models['ShortLink'] || mongoose.model('ShortLink',shortLinkSchema)처럼 작성함
import mongoose from 'mongoose';

const shortLinkSchema = new mongoose.Schema(
  {
    title: { type: String, default: '' },
    url: { type: String, default: '' },
    shortUrl: { type: String, default: '' },
  },
  {
    timestamps: true,
  }
);

const ShortLink =
  mongoose.models['ShortLink'] || mongoose.model('ShortLink', shortLinkSchema);

export default ShortLink;

모델 다루기

  • 생성: Model.create()
    • 아규먼트로 전달한 값으로 도큐먼트를 생성함
const newShortLink = await ShortLink.create({
  title: '코드잇 커뮤니티',
  url: 'https://www.codeit.kr/community/general',
});
  • 여러 개 조회: Model.find()
    • 조건에 맞는 모든 도큐먼트를 조회함
    • 이때 조건으로 쓰이는 객체는 MongoDB의 문법을 따름
    • 간단하게는 속성과 값을 키와 밸류로 하는 객체를 넣어줄 수 있음
const shortLinks = await ShortLink.find(); // 모든 도큐먼트 조회

const filteredShortLinks = await ShortLink.find({ shortUrl: 'c0d317' }) // shortUrl 값이 'c0d317'인 모든 도큐먼트 조회
  • 아이디로 하나만 조회: Model.findById()
    • 아규먼트로 넘겨준 아이디에 해당하는 도큐먼트를 조회함
const shortLink = await ShortLink.findById('n3x7j5');
  • 아이디로 업데이트하기: Model.findByIdAndUpdate()
    • 첫 번째 아규먼트로 넘겨준 아이디에 해당하는 도큐먼트를 업데이트함
    • 두 번째 아규먼트로는 업데이트할 값을 넘겨줌
const updatedShortLink = await ShortLink.findByIdAndUpdate('n3x7j5', { ... });
  • 아이디로 삭제하기: Model.findByIdAndDelete()
    • 아규먼트로 넘겨준 아이디에 해당하는 도큐먼트를 삭제함
await ShortLink.findByIdAndDelete('n3x7j5');

그 외에 자주 사용하는 함수 소개

아이디 값으로 조회하거나 업데이트하는 것 외에도 조건(MongoDB 문법)으로 사용하는 다양한 함수들이 있음

  • 조건으로 하나만 조회
    • 아규먼트로 조건을 넘겨주고 해당하는 도큐먼트를 하나만 조회함
const shortLink = await ShortLink.findOne({ shortUrl: 'c0d317' });
  • 조건으로 업데이트하기
    • 첫 번째 아규먼트로 넘겨준 조건에 해당하는 도큐먼트를 업데이트함
    • 두 번째 아규먼트로는 업데이트할 값을 넘겨줌
await ShortLink.updateOne({ _id: 'n3x7j5' }, { ... }); // 업데이트만 하고 업데이트 된 값을 리턴하지는 않음

const updatedShortLink = await ShortLink.findOneAndUpdate({ _id: 'n3x7j5' }, { ... });
  • 조건으로 삭제하기
    • 아규먼트로 넘겨준 조건에 해당하는 도큐먼트를 삭제함
await ShortLink.deleteOne({ _id: 'n3x7j5' }, { ... }); // 삭제만 하고  기존 값을 리턴하지는 않음

const deletedShortLink = await ShortLink.findOneAndDelete({ _id: 'n3x7j5' }, { ... });
profile
아이디어와 구현을 좋아합니다!

0개의 댓글