검색 웹 서비스 모델링 : 기능 구현 및 회고

정재헌·2023년 1월 3일
0

검색 웹 서비스 모델링

검색 웹 서비스를 모델링을 2차 프로젝트로 진행하였다. 2주의 기간 동안, 소셜 로그인 오픈소스 api를 활용한 로그인 및 회원가입 / query parameter를 적용한 가게 리스트 페이지 구현 / 가게 리뷰 페이지 기능 구현 총 4가지의 기능 구현을 담당하게 되었다.

  • 로그인 및 회원가입 기능 구현 : 카카오 소셜 로그인 api / jsonwebtoken

유저의 회원가입 및 로그인 과정에서 사용자의 접근성을 용이하게 하기 위하여 소셜 로그인 api를 적용하였다.
이를 위해, 먼저 프론트엔드로부터 카카오 인증 서버가 전달해주는 인가 코드를 전달 받는 것부터 시작하여, 카카오 authorization server의 access token, 그리고 이를 다시 카카오 resource server에 보내어 유저 정보를 받아 왔다.
그리고, 기존 우리 서비스의 유저인지에 대한 확인을 거친 후, 우리 서비스의 유저가 아닌 경우에는 회원가입을 시킨 후 JWT 토큰을 발급을 하였고, 우리 서비스의 유저로 판단되는 경우에는 서비스 이용을 위한 JWT 토큰을 발급하였다.

<카카오 인증 서버 및 카카오 리소스 서버에 요청 보내기 및 응답 받기>

const axios = require('axios')

const getAccessTokenByKakao = async(code) => {
    const result = await axios({
        method: 'post',
        url: 'https://kauth.kakao.com/oauth/token',
        params: {
            "grant_type": 'authorization_code',
            "client_id": process.env.RESTAPI_KEY,
            "redirect_url": process.env.REDIRCT_URL,
            "code": code
        }
    })
    return result.data.access_token
}

const getUserInfoByKakao = async(getAccessTokenByKakao) => {
    const result = await axios({
        method: 'get',
        url: 'https://kapi.kakao.com/v1/oidc/userinfo',
        headers: {
            "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
            Authorization: `Bearer ${getAccessTokenByKakao}`
        }
    })
    return result.data
}

module.exports = { getAccessTokenByKakao, getUserInfoByKakao }

<사용자 회원가입 여부 판단하여, JWT 토큰 발급하기>

const { userDao } = require('../models')
const jwt = require('jsonwebtoken')

const { getAccessTokenByKakao, getUserInfoByKakao } = require('./kakaoService')

const kakaoSignIn = async(code) => {

    const kakaoAccessToken = await getAccessTokenByKakao(code)
    const kakaoUserInfo = await getUserInfoByKakao(kakaoAccessToken)

    const socialId = kakaoUserInfo.sub
    const userInfo = await userDao.getUserBySocialId(socialId)

    if(!userInfo){

        const newUser = await userDao.createUser(kakaoUserInfo)
        const payLoad = {userId: newUser.insertId}
        const accessToken = jwt.sign(
            payLoad,
            process.env.JWT_SECRET,
            { algorithm: process.env.ALGORITHM, expiresIn: process.env.JWT_EXPIRES_IN}
        )
        return accessToken   
    }

        const payLoad = { userId: userInfo.id }
        const accessToken = jwt.sign(
            payLoad,
            process.env.JWT_SECRET,
            { algorithm: process.env.ALGORITHM, expiresIn: process.env.JWT_EXPIRES_IN } 
        )
        return accessToken
    }

module.exports = { kakaoSignIn }
  • query parameter를 활용한 리스트 페이지 기능 구현

위치 기반으로 검색이 이루어지는 웹 서비스의 특성을 반영하여, 유저의 현재 위치 정보를 전달 받아 그 유저의 현재 위치를 기반으로 하여 주변 정보를 전달하는 구조로 기능을 구현하였다.
이를 위해, 프론트엔드로부터 먼저 사용자의 현재 위치의 위도와 경도를 전달 받았고, 이를 다시 REST API 방법을 활용하여 카카오 지도/로컬 api 서버에 현재 위치에 기반한 주변 정보를 요청하였다.
카카오 REST API는 데이터베이스에 저장 대신 실시간 요청으로만 가능하여 데이터베이스에 저장하지 않고, 바로 유저에게 데이터를 전달해주는 구조로 코드를 구현하였다.

<터미널에서 확인한 위치 기반 데이터 정보-거리순>

  • 가게 리뷰 페이지 기능 구현

평가 작성하기를 통하여 사용자가 가게에 대한 평가를 남길 수 있다. 이를 위해, request query와 body에 사용자가 남긴 평가에 대한 데이터를 전달 받아 데이터베이스에 저장하는 구조로 코드를 구현하였다.
해당 과정 중에는 사용자에 대한 JWT 토큰 검증을 넣어, 우리 서비스의 사용자가 맞는지를 먼저 확인하도록 하였고, 이 과정에서 payload에 담긴 유저 정보를 통해 우리 서비스의 어떤 유저인지를 확인할 수 있다.
그리고 MySQL query에서 JOIN을 활용하여 어떤 사용자가 어떤 가게에 대하여 평가를 남기는지에 대해서 정확한 데이터 저장이 이루어지도록 하였다.

  • 회고

query parameter를 완벽하게 적용하지는 못한 것 같다. query builder를 통해 어떤 request가 오던지 그에 맞는 데이터를 반환할 수 있도록 구조화해보는 보완이 필요하다고 생각한다. 리팩토링 과정 속에서 query builder를 적용해보고자 한다.

profile
백엔드 개발자

0개의 댓글