슬기로운 개발자생활/DevOps

심플 API 디자인패턴

개발자 소신 2024. 1. 5. 08:12
반응형

아직은 부족한 실력이지만, 백엔드 서버 개발을 하면서 찾아보고 알게 된 API 작성법에 대한 글을 남겨보고 나도 이 글을 통해 원칙을 세워보자 한다.

API (Application Programming Interface)

  • API는 간단하게 특정 비즈니스 로직을 서버에서 처리하고 그 결과를 네트워크 통신을 통해 전달하는 메커니즘이다. 최근에는 클라가 서버 데이터에 액세스하는 REST API가 메인이고 이 글도 REST API를 다룬다.

순서

1.  API 원칙
2.  REST API 샘플
3.  Router 규칙
4.  문서화
5.  참고자료

1. API 원칙

  1. 당연스럽게도 하나의 API하나의 일만 '잘' 해야한다.
  2. 에러가 발생할 수 있는 사항은 가능한 빨리 확인, 처리한다.
  3. 클라이언트에서 예외처리를 요구하는 리턴을 전달하지 않는다. (null 대신 [])

2. REST API 샘플

  • auth.js
authRouter.post('/login', async (req, res) => {
  // try-catch 문으로 미처 예상하지 못한 에러 처리
  try {
    // 필수값 여부 확인으로 빠르게 에러 반환
    const {username,password} = req.body
    if(!username || !password) return res.status(400).send({err:'username와 password은 필수입니다.'})

    const user = await User.findOne({username:username})

    // user 정보 확인 후 에러 처리
    if(await bcrypt.compare(password,user.password)==false) return res.status(400).send({err:'비밀번호가 틀렸습니다.'})
    if(user.withdraw) return res.status(400).send({err:`${user.username}는 탈퇴한 사용자입니다.`})

    const {accessToken,refreshToken} = generateTokens(user._id)

    return res.status(201).send({userId:user._id, username, nickname:user.nickname, isAdmin:user.isAdmin, accessToken, refreshToken})
  } catch (error) {
    console.log(error)
    return res.status(500).send({ err: error.message })
  }
})

간단한 로그인 로직이지만,

  • 가장 먼저 서버가 다운되지 않도록 try-catch문으로 예외상황에 대한 처리
  • 필수값에 대한 처리로 빠른 에러 반환
  • 유저 정보 확인 후 두 번째 에러상황 처리
  • 마지막으로, 토큰 생성 로직 실행 후에 최종 결과를 반환

하는 식으로 구현하였다.

3. Router 규칙

  • 내가 배운 것 + 일반적으로 사용하는 API 서버 url 양식을 정리해봤다.
// server.js (*메인 서버 실행 파일, app.js, main.js)

app.use('/api/v1',require('./src/routes'))
  • 메인 파일에서는 routes 정보가 정리된 index.js를 가져온다
// src/routes/index.js
const router = require('express').Router()

router.use('/auth', require('./auth'))
router.use('/item', require('./item'))
router.use('/follow', require('./follow'))
router.use('/vote', require('./vote'))
router.use('/phone', require('./phone'))
router.use('/profile',require('./profile'))
router.use('/like', require('./like'))
router.use('/search', require('./search'))
module.exports = router
  • routes/index.js에서는 각 비즈니스 로직별로 구분하여 가져왔다.

routes를 이런식으로 분리해놓았을 때 프로젝트 구조가 깔끔하게 정리됐기 때문에 더 좋은 방식이 있거나 컨벤션이 따로 만들어지지 않는이상 위의 방식을 지키고자 한다.

위의 경우, 로그인 할 때 /api/v1/auth/login 으로 post method를 호출해야한다.

4. 문서화

  • 혼자 개발할때는 문서화까진 안해도 뭐..., 하지만 협업때는 필수다.

1. 기능명세서 (비즈니스 로직 문서)

  • API 서버에서 어떤 로직들을 처리하는지에 대한 문서
  • 위의 경우에는 회원 관리, 핸드폰 인증, 프로필 관리, 팔로우/팔로잉, 아이템 관리 등

2. API 명세서

  • 기능명세서에서 나온 메인 기능에서 하위 세부기능들을 URL에 각각 할당하고 method와 parameter, data에 대한 내용을 담는다.

API 명세서

5. 참고자료

반응형