20210407-TIL

나영원·2021년 4월 8일
0

T.I.L.

목록 보기
137/145

오늘 할일

  • 알고리즘 문제풀이

  • 포트폴리오 수정

  • 프로젝트 준비

  • 채용공고 읽기

오늘 한 것 & 배운 내용

개발자취업 강의 복습

  • 이력서를 통해 지원하는 것 뿐만 아니라 CV레터를 통해 자기소개와 포트폴리오 이력서를 한번 더 작성해 지원하는 것은 정말 좋은 방법인 것 같다

    • 자기소개를 다르게 하는 것보다는 포트폴리오에 내용을 그대로 활용하되 앞뒤에 회사에 대한내용과 왜 이렇게 지원하게 됬는지에 대해서 작성하면 더 좋은 자기소개서가 되는 것 같다
    • 기존에 작성하던 자기소개서가 너무 형식에 맞추려고 급급하였다면 조금 더 지원동기와 포부가 자연스러워 질 수 있으면 좋을 것 같다
  • 개발 공부를 계속 이어나가면서도 어떻게 이것들을 잘 보여줄 것인지는 꾸준히 고민을 하면서 보충해나가야 되는 부분인 것 같다

    • 어느 하나를 끝내놓고 한다라기 보다 꾸준히 동시에 해나가는게 양쪽 모두에 시너지를 줄것 같다
    • 개발공부는 나의 포트폴리오의 내용이 되어줄 것이고 포트폴리오는 채워나가기 위해 공부를 꾸준히 하여야 한다는 필요를 느껴 선순환이 되기를 기대한다

유튭강의

배달의민족 합격한 신입 개발자 이력서 공개합니다.

  • 링크

  • https://www.youtube.com/watch?v=Yc56NpYW1DM&t=261s

  • 내용 요약

    • 노션으로 깔끔하게 정리된 이력서가 눈에 들어왔다

      • 너무 딱딱하게 이력서를 작성한게 아닌가 싶어서 조금더 정리된 이력서가 필요할 것 같다
    • 기술들에 대해서 분야별로 잘 정리해두었는데 눈에 들어왔다

      • 백엔드 뿐아니라 다른 분야에도 충분히 관심을 가지면 이렇게 좋은 포트폴리오가된다는 것을 배웠다
    • 깃험, 블로그에서 꾸준히 좋은 개발자로 성장하기위한 기록들을 남겼다

      • TIL에 그치는게 아니라 어떤공부를하고 있는지에 대해서 명확히 보이는 블로그 게시글과 깃험 로그들을 볼수 있었다
      • 무엇보다 꾸준히 커밋을 남기는 것도 중요한 것 같다(잘지켜지지 못하고 있어서)
    • 가장 중요한건 이것은 레시피이고 좋은 재료(경험)이 있어야 좋은 이력서가 완성된다고 마무리해주셨다

  • 느낀점

    • 어떻게하면 좋은 개발자가 되고, 그러기 위해 좋은 개발경험들을 쌓아갈 수 있을지 고민을 많이해봐야될 것 같다

    • 블로그를 TIL을 넘어서 주제별로 내용을 정리해나갈 수 있도록 하면 좋을 것 같다

알고리즘 문제 풀이

  • QuickSort & Selection 복습

    • 어제 풀던 K번째 수 문제를 QuickSelection을 적용하여 다시 풀어보면서 개념을 복습하기 위해 다시 구현해서 풀어보았다

    • 어제 풀었던 방식보다 직관적이라고 생각한 방식으로 풀었는데 결과를 측정하니 시간초과가 발생했다

    • 다양한 예제를 찾다보니 pivot에 위치를 어떻게 줄것인가에 관한 부분이 다른것을 발견할 수 있었다

      • 이에 따라 연산속도가 차이가 나가는거 같은데 어떻게 다른지는 조금더 공부해봐야될 것 같다
    • 최종풀이

      • pivot에 위치를 mid에서 뽑아서 맨처음으로 보냈다가 정렬이 끝난후 i에 위치에 있는값과 맨처음값을 바꿔주는 방식으로 적용한 예제를 참고하였다

      • 이렇게 하면 스왑이 조금이라도 덜 일어나서 성능에 도움이 되는 것 같다

스프링부트와 AWS로 혼자 구현하는 웹서비스

스프링 시큐리티와 Oauth 2.0으로 로그인 기능 구현

  • 참고자료

  • 지난번에 하던 예제를 오랜만에 이어서 진행하였다

    • 복습을 위해 처음부터 다시 내용을 읽고 구현한 내용들을 되집어가는 식으로 진행하였다

3. 구글 로그인 연동하기

  • Oauth용 정보를 담기위해 application-oauth.yml 만들기

    • 여기까진 프로젝트에서 해본내용인데 application.yml에 spring.profiles.include=oauth를 추가 해주는 것은 생소해서 더 검색을 해보았다
    • 찾아보니 profile 자체는 운영환경(프로덕션, 테스트) 에 따라서 어떤 설정을 사용할지 설정해주는 옵션이었고 거기다 include를 붙이면 해당 프로필에서 어떤 yml을 포함해서 돌릴 것인지 결정해주는 것이었다
      • 즉 새로만든 oauth용 yml파일에 설정을 같이 적용하라는 뜻으로 해석된다
    • 지난 프로젝트에서 운영 /테스트 환경에 따라 yml을교체해주느라 고생을 했는데 이 옵션을 사용했으면 훨씬 깔끔하게 정리하여 진행했을 것 같다
  • SecurityConfig 작성하기

    • oauth2Login() 을 통해 Oauth로그인에 대한 설정을 할 수 있었다
      • userInfoEndpoint를 통해 로그인이 성공하였을 겅우 정보를 넘겨줄 UserService를 지정해 줄 수 있다
      • 이외에도 authorizationEndpoint(), RedirectionEndpoint(), 등의 설정을 추가해줄 수 있다
  • CustomOauth2UserService클래스 작성(OAuth2UserService<OAuth2UserRequest, OAuth2User> 구현)

    • UserInfoEnpoint에서 전달된 정보가 OAuth2UserRequest담겨 loadUser 메소드에 전달된다
    • Oauth2UserSevie에 DefaultOauth2UserServcie 객체를 생성한다
      • 생성된 객체에서 loadUser(userRequest)를 하면 OAuth2User 객체를 만들수있다
    • 전달 받은 정보들을 활용하기 위해서 UserRequest에서 RgistartionId, UserNameAttributeName와 oAuth2User객체를 활용하여 OAuthAttriuttes 객체를 만든다
    • SaveOrUpdate 메소드를 작성하고 attributes를 입력받아 getEmail로 메일을 찾아 entity가 있으면 update해서 저장하고 아니면 attirbute로 Entity를 만들어 저장한다
      • attributes.toEntity 메소드를 활용하여 Entity로 만든다
        • 뒤에서 만들 OauthAttribute클래스에 포함된 메소드이다
    • 저장된 Entity를 SessioUser객체로 만들어 httpSession에 저장한다
  • OAuthAttributes 클래스 작성하기

    • CustomOauth2UserService에서 넘겨준 값들을 활용하는 하나의객체로 만들기 위해 attributes, nameAttributeKey, name, email, picture 변수를 선언하고 생성자를 만든다

    • 입력값에 따라 객체를 만들기위해 static 메소드 of를 만들어주고 또 registationId(소셜로그인제공사) 별로 생성자를 따로만들어주기 위해 ofGoogle 메소드를 만들고 파라미터의 값들을 활용해 OAuthAttributes 객체를 생성해서 리턴한다

    • OAuthAttributes 객체를 바로 User 객체(Etntity)로 변환할 수 있는 toEntity() 메소드를 작성하여 User 생성자에 자기자신의 변수의 값들을 채워넣어서 리턴한다

  • SessionUser 클래스 작성하기(Serializable)

    • 세션을 저장하기 위해서는 직렬화를 해야하는데 Serializable 을 implments함으로 가능하다

    • User클래스는 Entity이기 때문에 바로 Serialzable을 구현하기는 어려우니 SessionUser를 만든다

      • Entity는 다른 Entity와 관계 때문에 연결된 대상까지 직렬화 되는 비효율이 발생될 수 있기 때문에 따로 직렬화 기능 가진 세션 Dto를 만드는게 좋다

4. 어노테이션 기반으로 개선하기

  • LoginUser 어노테이션 작성

    • Session에 등록된 유저 정보를 가져오기 위해 반복되는 코드를 제거하기 위해 어노테이션을 작성한다

    • 조건용으로 사용되기에 본문 내용은 따로 적지 않아도된다

  • handlerMethodArgumentResolver 인터페이스를 구현한 LoginUserArgumentResolver 클래스를 작성한다

    • handlerMethodArgumentResolver는 조건에 맞는 메소드가 있다면 구현체가 지정한 값을 해당 메소드의 파라미터로 넘겨줄 수 있다
    • 조건을 지정해주는 supportsParameter 메소드를 Override한다
      • MethodParameter를 받아와 LoginUser 어노테이션이 달려있는지 확인한다
      • 파라미터의 타입입이 SessionUser 클래스인지 확인한다
    • 전달할 값을 설정하는 resolveArgument 클래스를 작성한다
      • httpsession에서 getAttribute를 한 값을 return한다
  • 직접 작성한 LoginUserargumentresolver를 WebMvcConfigurer 에 추가해주기 위해 Webconfig 클래스를 작성한다

    • WebMvcFongigurer 를 implements 하고 addArgumentResolvers를 Override한다
      • 파라미터로 내려온 argumentResolvers List에 loginUserArgumentResolver를 add 해준다
  • 마지막으로 IndexController에 index 메소드에 @LoginUser SessionUser user 파라미터를 추가해준다

    • 이제 필요한곳 어디서든 @LoginUser 어노테이션을 붙이면 session에 정보를 가져올 수 있게 되었다

세션 저장소로 데이터베이스 사용하기

  • 세션저장소 선택옵션

    • 톰캣 세션
      • 기본 설정
      • WAS가 2대이상 구동되는 환경에서 세션공유를 위해서 추가설정 필요
    • DB
      • 여러 WAS간의 공용 세션을 사용할 수 있는 가장 쉬운 방법
      • 로그인 요청시 마다 DB IO가 발생하여 성능 이슈가 발생할 수 있음
      • 로그인 요청이 많이 없는 백오피스or사내 시스템 용도로 사용
    • 메모리 DB(Redis, Memcached)
      • B2C 서비스에서 가장 많이 사용하는 방식
      • 실제 서비스에서는 Embedded가 아닌 외부 메모리 서버를 사용한다
  • spring-session-jdbc 등록

    • build.gradle에 spring-session-jdbc 의존성을 추가한다
    • application.properties에 spring.session.store-type: jdbc를 추가한다
    • 이렇게만 설정하면 JPA에서 알아서 DB에 Session을 위한 테이블을 추가한다
  • DB에서 Session이 추가된것 확인하기

    • he-console을 보니 SPRING_SESSION, SPRING_SESSION_ATTRIBUTES가 생성되어있다
    • 로그인을 해보니 SPRING_SESSION_ATTRIBUTES에 SESSION이 추가되는 것을 확인할 수 있었다
  • 설정만으로 간단하게 추가되서 어떻게 구현되서 동작하는지 더 알아볼 필요가 있는 것 같다

6. 네이버로그인

  • 네이버 API 등록
    • 구글에서 한것과 크게 다르지 않아서 간단하게 실습할 수 있었다
  • application-oauth.yml에 naver 설정 추가하기
    • 네이버는 스프링 시큐리티를 공식지원하지 않기 때문에 수동으로 설정값을 입력해야한다
      • registartion에서 client-id, secret, redirect-uri 등을 입력해주어야 햇다
        • redirect-uri은 {baseUrl}/{action}/oauth2/code/{registrationId} 이런방식으로 입력하면 됫는데 yml에서는 /(슬래시)를 그대로 사용할 수 없어 따옴표로 묶어주어서 사용하니 작동하였다
        • client-id를 잘못입력하여 로그인창이 안뜬느 상태가 되어 디버깅을 진행하였다.. 언제나 오타조심
      • provider에서 authoization-uri, token-rui, user-info-uri 등의 정보와 user-name-attribute: response로 해주었다
        • 네이버 로그인 성공이후 반횐되는 json파일에 reponse라는 key안에 value로 회원정보가 담겨있기 때문에 respone를 attribute로 받아주면 된다
  • 스프링 시큐리티 설정 등록
    • OAuthAttributes에서 네이버인지 판단해서 생성해주는 builder만 하나 추가해주면 쉽게 설정이 가능했다
      • 이게 확장 가능한 코드 구현이라는 것 같다..
      • registartionId에 naver라고 들어오는것을 조건 처리하여 ofNaver라는 정적메소드를 만들어 객체를 생성해주면된다
  • 마지막으로 index.mustache에 링크를 추가해주고 href를 ""/oauth2/authorization/naver" 로 주면 버튼까지 완성이 된다

7. 기존 테스트에 시큐리티 적용하기

  • 시큐리티 적용전 테스트를 적용한뒤에도 통과되게 설정해주어야 했다
  • 문제1. CustomOauth2UserService를 찾을수 없음
    • 원인
      • test는 기본적으로 application.yml을 사용하는데 applcation-oauth.yml을 읽지 못해서 생기는 문제이다
    • 해결
      • test에도 resources 폴더를 만들어 application.yml을 작성한 후에 형식만 갖춘 oauth설정을 입력해준다
        • 실제로 Oauth 테스트를 하는게 아니기 때문에 이정도 조치로도 테스트가 통과하게 된다
  • 문제2. 302 Status Code
    • 원인
      • 인증되지 않은 사용자의 요청은 스프링 시큐리티에서 이동시키기 때문에 200이 아닌 302코드가 내려와서 생긴 문제이다
    • 해결
      • spring-security-test 의존성을 추가한다
      • 기존의테스트를 MockMvc 테스트로 변경한다
        • mockMvc 변수를 선언한뒤 BeforeEach로 각테스트마다 객체를 생성해서 요청을 하도록만든다
        • 각 테스트 위에 @WithMockUser(roles = "USER")를 MockUser로 요청이 가도록 한다
        • MockMvc 객체를 이용해 요청을하고 응답을 받는다
  • 문제3. @WebMvcTest에서 CustomOauth2UserService를 찾을 수 없음
    • 원인
      • WebMvcTest에서는 WebSecurityConfigurerAdpater, WebMvcConfigurer를 비롯한 ContollerAdvice, Controller를 읽지만 Repository, Service, Component는 스캔대상이 아니기 때문에 CustomOauth2UserService를 읽을수없었다
    • 해결
      • 스캔대상에서 SecurityConfig를 제거한다
        • @WebMvcTest에 excludeFilters 를 추가해 SecurityConfig.class를 제외한다
      • 요청에 대한 인증은 위에 했던것처럼 @WtihMockUser 를 통해서 한다
  • 문제4. @EnableJpaAuditing 에러
    • 원인
      • @EnableAduiting을 사용하기 위해선 @Entity가 붙은 클래스가 필요하지만 WebMvcTest에서는 @Entity 클래스가 없기 때문에 생기는 오류
    • 해결
      • @SpringBootApplication을 스캔할 때@EnableAuditing 어노테이션을 읽어 에러가 발생하기 때문에 두개의 어노테이션을 분리해준다
      • JpaConfig 클래스를 작성하여 @EnableAuditing, @Configuaration 어노테이션을 달아주고 Applciation.java에서는 지워준다
  • 배운점
    • 지난번 프로젝트때 WebMvcTest환경에서 인증된 요청을 구현해보고 싶었는데 방법을 찾지 못해 모두 SpringBootTest로 전환해서 진행했는데 @WithMockUser를 통해 간단하게 MockUser를 생성할수있는 것을 알아 도움이 많이 되었다
    • 또한 MockMvc에서는 Controller만 bean으로 생성되기 때문에 생성되지 않은 bean을 어떻게 처리해줄 것인가를 통해 더 다양한 상황에 테스트를 진행할 수 있는거구나 라는 경험을 하게되었다

포트폴리오 수정

  • 주요 공부들을 마치고 남은 시간을 이용해서 포트폴리오를 수정하는데 부담도 덜하고 시간도 딱알맞은 것 같아서 앞으로도 이렇게 진행해야될 것 같다

  • 이미 어느정도 틀이 나와있기 때문에 작성한 문구들을 다시 읽어보며 더 자연스러운 표현으로 고쳐가는 과정을 거쳤는데 차근차근 뭔가 만들어내가는 과정이 즐겁게 느껴졌다

내일 할일

  • 알고리즘 문제풀이
  • 스프링 개발 실습
  • 포트폴리오 수정
  • 채용공고 읽기
profile
배우는 개발 일기

0개의 댓글