본문 바로가기
Side Projects/프로젝트 사이

11. SAI(RestAPI) 사용 설명서

by devraphy 2022. 9. 14.

1. SAI는 어떻게 동작하나요?

- SAI는 JWT를 기반으로 요청과 응답을 제공하는 RestAPI 서버입니다.

- JWT는 회원가입, 일반 로그인에서 제공됩니다. 

 

a) Filter

- 회원가입과 일반 로그인을 요청할 때에는 JWT를 기반한 검증을 수행하지 않습니다. 

- 그 외의 요청을 할 때에는 반드시 유효한 JWT를 쿠키로 보유하고 있어야 합니다.

- 이 부분은 Filter를 이용하여 구현했습니다. 

- 아래의 코드는 JwtFilter 클래스의 한 부분입니다. 

 

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;

        /* 해당 URL로 요청할 시에는 Cookie의 JWT 검증 안함 */
        if (servletRequest.getRequestURI().equals("/api/join") ||
                servletRequest.getRequestURI().equals("/api/email/validation") ||
                servletRequest.getRequestURI().equals("/api/login")) {
            chain.doFilter(request, response);
        }

        /* 그 외 URL로 요청할 시에는 Cookie의 JWT 검증 */
        else if (jwtCookieService.validateAccessToken(servletRequest, servletResponse)) {
            log.info("JwtFilter | Success: 토큰 검증 완료");
            chain.doFilter(request, response);
        }

        /* Cookie의 JWT 검증 실패한 경우 */
        else {
            log.error("JwtFilter | Fail: 토큰 검증 실패");
            servletResponse.setContentType(APPLICATION_JSON_VALUE);
            servletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.writeValue(servletResponse.getOutputStream(), new ErrorResponse(ErrorCode.UNAUTHORIZED));
        }
    }

 

 

2. 기본 사용 방법

a) 회원가입 

- SAI는 회원 가입에서 3가지 정보(이메일, 비밀번호, 회원 이름)를 요구합니다.

 

 

- 회원가입 또는 일반 로그인에 성공하면 다음과 같이 JWT를 쿠키에서 제공합니다.

 

 

b) 회원가입 - 중복 아이디(이메일) 

- 프런트 쪽에서 이메일 중복 검사를 한다는 가정하에 작성된 코드이므로 중복 이메일을 이용하여
  회원가입을 시도하면 아래의 사진과 같이 500 에러를 응답하도록 구현했습니다. 

 

- 이와 같은 이유로 이메일 중복 검사 API를 따로 구현해두었습니다. 

 

 

- 이 과정에서 중복 이메일이 DB에 입력되어 DataIntegrityValidationException이 발생하는데요, 

  이에 대한 처리를 아래의 사진처럼 구현했습니다. 

 

 

- DB에 문제없이 데이터가 입력되는지 확인하기 위해 Flush()를 강제 호출하여  
  Service에서 결과를 반환하기 전에 오류가 발생한다면 이를 캐치하게 하도록 했습니다.  

 

- 아래의 사진에서 확인할 수 있듯이, Excpetion Handler 클래스를 생성하여 내부의 Runtime Exception에서
  해당 오류를 잡아내고 이에 따라 할당된 응답을 전달합니다. 

 

 

3. 자동 로그인

a) 기본 메커니즘

- 자동 로그인의 경우 JWT 검증을 통해 진행됩니다.

- 기존에 회원가입 또는 일반 로그인 요청에 성공했다면 JWT를 쿠키로 보유하고 있을 테니까요

 

- 자동 로그인의 경우, Refresh 토큰의 유효성 검증을 통해 진행되며 검증을 통과한 경우 

   Access 토큰과 Refresh 토큰을 재발행(갱신)하는 방식으로 로직을 구현하였습니다. 

 

- 아래의 코드는 자동 로그인 구현 처리 로직이며, MemberService 클래스의 일부분입니다.

 

// MemberApi - 자동 로그인
public void autoLoginApi(HttpServletRequest servletReq, HttpServletResponse servletResp) throws Exception {

    servletResp.setContentType(APPLICATION_JSON_VALUE);

    if (jwtCookieService.validateRefreshToken(servletReq)) {

        String refreshToken = jwtCookieService.getRefreshToken(servletReq);
        String email = jwtProvider.getUserEmail(refreshToken);
        Member member = memberService.findByEmail(email);
        String role = member.getRole();

        jwtCookieService.setTokenInCookie(email, role, servletReq, servletResp);

        log.info("Login Service | autoLoginApi() Success: refresh 토큰 로그인 성공 및 토큰 갱신");
        objectMapper.writeValue(servletResp.getOutputStream(), new MemberResultResponse(Boolean.TRUE));

    } else {
        log.warn("Login Service | autoLoginApi() Fail: 토큰 검증 실패");
        servletResp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        objectMapper.writeValue(servletResp.getOutputStream(), new ErrorResponse(ErrorCode.UNAUTHORIZED));
    }
}

 

4. 대표 기능

a) 숙지해주세요!

- 회원가입, 자동 로그인, 일반 로그인을 제외한 나머지 API는 모두 Filter에서 제공하는 JWT 유효성 검증을
   통과해야만 요청이 가능합니다. 

 

- 본 포스팅의 가장 상단에 남겨놓은 Filter의 내부 메서드 코드에서 확인할 수 있듯이, 유효하지 않은 
   JWT를 사용한 요청은 다음과 같은 응답을 제공합니다. 

 

 

b) 대표 기능 - 수치화(1) 

- SAI는 사람 간의 교류를 바탕으로 인간관계를 수치화하기 위한 목적을 가지고 있습니다.

- 최초에 친구를 등록할 때 아래의 사진처럼 관계 상태(Relationship Status)를 결정하게 됩니다. 

 

 

- 5가지 상태(great, positive, normal, negative, bad) 중 하나를 입력함에 따라 Enum이 선택되고, 
   선택된 Enum 값에 따라 정수 값이 등록됩니다. 

 

 

c) 대표 기능 - 수치화(2) 

- SAI는 이미 벌어진 일에 대한 기록을 리뷰하는 방식으로 인간관계를 수치화합니다.

- 그러므로 Event를 등록하고 이에 대한 평가를 기반으로 해당 Event에 참여한 친구 객체의 점수가 수정됩니다.

 

 

- 수정된 친구 객체의 점수에 따라 상태 값(Enum)이 업데이트됩니다. 

 

 

c) 대표 기능 - 수치화(3) 

- Event 등록과는 반대로 Event를 삭제하는 경우, 해당 Event의 평가에 따른 친구 객체의 점수 변화는
  복구되어야 하겠죠? 그래서 다음과 같은 로직으로 구현했습니다. 

 

 

d) 그 외 기능에 대하여 

- 이 외 기능에 대한 사용 방법 또는 입력 데이터에 대한 설명은 API 문서에 예시가 작성되어 있으니,
  이를 참고해주시면 감사하겠습니다. 

 

https://restsai.herokuapp.com/swagger-ui/index.html

 

Swagger UI

 

restsai.herokuapp.com

 

e) 업데이트(22년 11월 19일)

- Heroku 유료화로 인하여 해당 앱은 배포를 중지시킨 상태로, 더이상 동작하지 않습니다.

- 코드는 Github을 참고해주시면 감사하겠습니다. 

댓글