최종 프로젝트 회고록

Kim DongKyun·2023년 3월 14일
0

Weekly I Learned

목록 보기
8/8

개요

최종 프로젝트를 마무리했다. 새로 배운 내용들에 대한 리뷰와 간단한 회고를 작성한다. 또 이력서를 준비하기 위해서 내가 사용 해 본 기술들 위주로 리뷰한다.


Java / Spring

이번 프로젝트에 사용했던 내용들

1. CRUD

ORM 기술인 JPA가 제공하는 엄청난 편의가 있지만, 데이터의 정합성을 위해 일어나는 N+1 문제나, 조회 속도 향상을 위해 어떤 것을 사용해서 문제들을 핸들했는가?

  • JPQL
    간단한 쿼리를 짜기에 용이하다. fetch join을 통해서 조회가 간단하다. 더하여 Depth가 두 개 이상인 경우에 두 개의 쿼리를 통해 해결하려고 노력했다.(서브쿼리를 최대한 지양했다)
  • QueryDSL
    복잡한 쿼리, Join이 많이 일어나는 쿼리를 작성하기에 편하다. 컴파일 시점에 오류를 잡아주고, 동적 쿼리를 BooleanExpressions 를 통해서 쉽게 작성 할 수 있다.
  • Fetch Join
  • Batch Size 활용(application.yml에 디폴트로 설정)
    엔티티 컬렉션 조회 시 나가는 쿼리의 in절에 내가 설정한 BatchSize만큼의 조건절이 발생한다.
  • ResponseDTO 정적 팩토리 매서드 사용
    하나의 인스턴스를 보장해서 사용했다.

2. 인증, 인가

JWT를 사용했다. 액세스 토큰과 리프레쉬 토큰을 사용했고, 엑세스 토큰 재발급 시 리프레쉬 토큰 또한 재발급하는 RTR(Refresh Token Rotation)을 사용했다.

  • 소셜 로그인(카카오)
    Oauth2를 사용한 카카오 로그인을 구현했다. 스프링 시큐리티에서 제공하는 Oauth2 라이브러리를 사용하지 않았다.
    Oauth2 4 가지 Grant Type 중 인증 코드(Authorization code) 방식을 사용했는데, 이 방식을 통해 사용자의 정보를 가져 온 후 우리의 인증 서비스 로직을 거치도록 했다.

  • 진행중인 부분
    다양한 소셜 로그인을 팩토리 패턴을 사용해서 시도 해 보고 있다.

@Component
public class AuthProviderFactory {
    private final List<AuthProviderService> authProviderServiceList;
    private HashMap<AuthProvider, AuthProviderService> authProviderMap = new HashMap<>();
    public AuthProviderFactory(List<AuthProviderService> authProviderServiceList) {
        this.authProviderServiceList = authProviderServiceList;
        for(AuthProviderService authProviderService : this.authProviderServiceList){
            this.authProviderMap.put(authProviderService.getAuthProvider(), authProviderService);
        }
    }
    public AuthProviderService getService(AuthProvider authProvider){
        return this.authProviderMap.get(authProvider);
    }
}
    @Override
    public TokenResponseDto socialLogin(AuthProvider authProvider, String code) throws JsonProcessingException {
        Oauth2UserInfoDTO userInfo = authProviderFactory.getService(authProvider).getUserInfo(code);

//        Oauth2UserInfoDTO userInfo = kakaoAuthProviderService.getUserInfo(code);

//        // 1. "인가 코드"로 "액세스 토큰" 요청
//        String accessToken = getToken(code);
//
//        // 2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기
//        Oauth2UserInfoDTO oauth2UserInfoDTO = getKakaoUserInfo(accessToken);

        // 3. 필요시에 회원가입
        registerUserIfNeeded(userInfo);

        return jwtProvider.createTokenKakao(userInfo.getEmail());
    }

3. 웹소켓

STOMP / SOCKJS를 사용한 실시간 채팅 기능

-> 리뷰받은 바로는 샌드버그 사서 API 연동한다고 들었는데, 공부해서 나쁠 것은 없을 듯 하다. 이 부분은 내가 진행하지 않아서 더 공부 필요함 정리하자면

STOMP : 프로토콜이며, PUB/SUB 구조. HTTP 헤더에 해당하는 부분도 있어서 인증도 가능하다
SOCKJS : 웹소켓 환경이 구성되지 않을 시 사용하는 라이브러리. 폴링 등 다른 HTTP 방식으로 전환 가능하게 해준다.

추가적으로, 카프카를 이용한 "메시지 큐" 나 "이벤트 브로커" 키워드도 정리해보자.


4. CI/CD

EC2 클라우드에 서버를 띄우고, Github Actions, AWS CodeDeploy를 이용한 CI/CD. 서비스의 스냅샷은 S3 에 올려놨다.

-> 아직 이해가 안된다. 이거 좀 자세히 꼭 공부해야 할 듯. 그냥 따라한 느낌


회고

1. Keep

  • 스프링 내부 동작, JPA / Transaction / 영속성 컨텍스트 / DB 관련에서는 더 나아진 듯. 원래도 너무 관심있던 분야라...

  • QueryDSL 사용에 익숙해졌다. 동적 쿼리나 프로젝션 개념(프로젝션 종류까지)

  • 인증/인가 너무 어려웠는데 조금 자신 붙었다.

2. Problem

  • 배포 / CICD 부족
  • 웹소켓 부족
  • 왜 PostgreSQL을 사용했는가?

3. Try

  • 배포나 CI/CD 다시 공부해야 한다
  • 웹소켓 부분 다시 공부해야 한다.
  • PostgreSQL vs MariaDB 다시 해야할듯. 써보고 경험해야 정확히 알 듯 하다.
  • Docker를 이용해서 서버를 띄우는 걸 시도해보자

0개의 댓글