POTATO THAT WANT TO BE HUMAN

[Next.js] mysql2 + API 만들기 (Next.js Route Handlers) 본문

FRONTEND/Next.js

[Next.js] mysql2 + API 만들기 (Next.js Route Handlers)

녜힝 2024. 2. 16. 13:54
반응형

Next.js로 개인프로젝트 진행 중 난관에 부딪혔다.

 

계획: Next.js에 mysql 연결해서 end point API를 만들어서 client component에서 사용해야겠다!

현실: 한 번에 성공할거라고 기대하셨나요? (´・ω・`)?

 

그래 어떻게 한 번에 성공하겠어

라는 생각으로 6시간을 헤맸다 .. Next.js 내부에서 db연동하고 api를 만들어 쓰는 레퍼런스는 별로 없던 것이 가장 큰 문제였다. api를 위한 서버를 따로 구성하는 사람이 많았다. node.js나 express등등.. 포기할 수 없다. 그렇게 구글링으로 셀 수 없이 많은 시도를 하며 3시간을 보내고 깨달았다. 아! 이렇게해서는 해결할 수 없다! 공식문서부터 살펴보기 시작했다. 그렇게 발견했다. 완벽한 답은 아니였지만 일단 접근법을 알아냈다. 결국 6시간만에 해결할 수 있었고, 나같이 헤맬 사람들을 위해 험난했던 과정과 방법에 대해 작성해본다.

 

필자의 프로젝트 환경 (참고)

- Next.js14 사용
- App Router 사용

 

 

일단 대략적인 순서는 다음과 같다.

(필자는 가장 익숙한 mySQL을 사용했다. mongoDB 등 다른 DB도 연결 후의 로직은 이론 상 비슷하다.)

1. Next.js 프로젝트에 mySQL 설치하기
2. db 연결하기
3. API 만들기

 

아주 간단해보인다. 그래도 방심하면 안 된다.

 

📌 Next.js 프로젝트에 mySQL 설치하기

진행 중인 Next.js 프로젝트에 mySQL을 설치해야 한다. 명령어는 다음과 같다.

npm install mysql2

 

mySQL2 에 대해 알아보자

  • promise를 지원한다.
  • 기존에 사용했던 connection을 재사용하여 새로운 connection을 구축할 때 생기는 오버헤드를 모두 피해 쿼리 지연시간을 향상시키기 위해 createPool을 사용한다.
  • pool은 쿼리가 수행되면 connection은 자동 해제된다.

 

📌 db 연결하기

db 연결과 API 생성은 함께 살펴보자.

 

먼저 app 폴더 하위에 _lib 폴더를 생성해주었다. (mySQL 라이브러리를 사용한다는 의미에서 작명했다.)

_lib 폴더 하위에 db.ts 파일을 생성해주었다. 이 db.ts 파일에서 DB 연결과 관련된 작업이 이루어질 것이다.

db.ts의 코드는 다음과 같다.

// app/_lib/db.ts
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB
});

// SQL SELECT 공통 함수
export const selectSQL = async (sqlQuery :string) => {
    try {
        const [rows] = await pool.query(sqlQuery);
        return rows;
    } catch (err) {
        console.error(err);
    }
}

mysql.createPool을 사용해 pool을 만들어준다.

다음으로 SQL 쿼리문에 대한 공통함수를 만들어야 한다.

(간단하게 예시를 들기 위해 select문에 대한 함수만 작성했다.)

인자로 query를 받아 pool.query()를 실행한다. 이 공통함수가 실행되기 위해 살펴봐야 할 다음 주제는 Next.js의 Route Handlers 이다.

 

📌 Route Handlers

공식문서 링크 : https://nextjs.org/docs/app/building-your-application/routing/route-handlers

Next.js에는 Route Handlers 라는 개념이 있다.

App Router를 사용하는 경우에는 Route Handlers를, 그렇지 않은 경우에는 API Routes를 사용한다.

공식 문서에서 API Routers에 대해 보면 이렇게 설명한다.

 

필자의 경우 클라이언트 컴포넌트에서 사용할 API가 필요하여 Route Handlers를 이용하였다.

Route Handlers 공식문서를 보면 이런 설명이 있다.

 

 

폴더 구조를 살펴보자.

 

우리가 클라이언트 컴포넌트에서 api를 호출할 때 /api/getData 형식으로 사용할 것이기 때문에

app 폴더 하위로 api 폴더를 생성해줘야 한다.

 

 

api 폴더 하위에는 route.js 또는 route.ts 파일을 생성한다.

이름은 반드시 route 여야 한다. 그래야 Next.js 프레임워크에서 읽어갈 수 있기 때문이다.

 

route 파일 내부에서는 HTTP Methods명으로 함수를 만든다.

반드시 HTTP Methods명이어야 한다. 사용할 수 있는 HTTP Methods로는 GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS이 있다. 상황에 맞게 잘 사용하자.

 

📌 API 생성하기

이제 Route Handlers를 사용해 API를 만들어보자.

필자는 DB 테이블별로 SQL문을 구분하기 위해 api 폴더 하위에 테이블명.ts 파일을 생성하여 구분하였다.

테이블명.ts 파일에서는 직접적으로 쿼리문을 작성하여 데이터를 조회, 삭제, 등록, 수정할 수 있다.

 

예를 들어 TbUser테이블에서 user의 정보에 대해 조회하려고 한다.

그렇다면 TbUser.ts 파일을 생성하고 다음과 같이 코드를 작성한다.

// app/api/tbUser.ts
import { selectSQL } from "../_lib/db";

export const getUserData = () => {
    const query = 'SELECT * FROM TB_USER;';

    return selectSQL(query);
}

getUserData 라는 유저 정보 조회 함수를 만들어준다.

함수 내에서는 db.ts에서 만든 selectSQL 함수를 이용해 조회할 수 있다.

이렇게 만든 getUserData는 route.ts에서 사용한다.

 

route.ts 코드는 다음과 같다.

// app/api/login/route.ts
import { NextApiRequest, NextApiResponse } from "next";
import { NextResponse } from "next/server";
import { getUserData } from "../tbUser";

export async function GET(req: NextApiRequest, res: NextApiResponse) {

  const data = await getUserData();

  return NextResponse.json(data);
}

타입스크립트를 사용한다면 NextApiRequestNextApiResponse를 import해 사용할 수 있다.

return은 NextResponse 또는 Response 모두 사용가능하다.

 

 

헷갈릴 수 있다. 당연하다. 나도 6시간을 헤맸다..

 

그럼 마지막으로 정리를 해보자.

 

먼저 폴더 구조를 살펴보자.

app
├── api
│    └── login
│    │   └── route.ts
│    └── tbUser.ts
└── page.tsx

상황은 이렇다.

1. 나는 tbUser 테이블의 정보를 조회하고싶다.

2. 그러기 위해서 /api/login 이라는 tbUser 테이블 조회 API를 만들어야 한다.

 

/api/login API를 만들기 위해서 api폴더 하위에 login폴더를 만들고 login 폴더에 route.ts를 생성해야 한다.

테이블별로 구분하기 위해 api폴더 하위로 테이블명.ts를 만들었다. (이 파일명은 꼭 테이블명이 아닌 사용자 임의로 지어도 된다.)

그렇게 만든 테이블명.ts 에서 selectSQL 함수를 가져와 DB 조회/등록/수정/삭제 함수를 만든다.

테이블명.ts에서 만든 함수를 route.ts에서 사용하고 가져온 데이터는 NextResponse 또는 Response로 return한다.

 

 

 

 

글재주가 없어 이해에 어려움이 있을 수 있지만 근본적으로 돌아가는 원리를 파악하면

정보 조회뿐만 아니라 등록, 수정, 삭제 API 까지 생성할 수 있다.

아직 Next.js에 능숙하지 않아 정확하지 않은 정보가 있을 수 있으니, 피드백은 환영한다!

반응형
Comments