스프링 공부 77

[코틀린 + 스프링] 코틀린? 이거 왜 익숙한데..?

이번 넹매추라는 프로젝트를 코틀린으로 한 달동안 구현을 해보며 느낀 부분들을 정리해보았다.코틀린에 대한 지식적인 부분이라기보단, 경험적으로 정리하는 글이라는 점을 알아두면 좋을 것 같다.하와와...너무 무서운 거시에요!처음에 내가 코틀린이라는 것을 이야기들었을 때 이런 생각이 들었다.당시의 나는 NestJS, 자바 스프링만을 써본 상황이었다.자바 스프링 독학과 네이버 부스트캠프에서 곰터뷰를 만들어보며 NestJS를 공부했었다.이런 나에게 같이 프로그래밍 공부를 시작했던 동기(그 친구는 우아한 테크코스에 있었다)가 말해준 것이,우리 취업하면 코틀린 써야할껄?이었다진짜 개무서웠다.여기에서 새로운 것을 또 공부해서 써야한다고?내가 공부한 것들도 완벽까지는 아닐것이다, 분명 더 깊은 무언가가 있을 것이다 라는 ..

@EventListner

이 어노테이션을 알기 전에, Event가 무엇인지 알아야 한다. 우리가 게임에서 이야기하는 이벤트란, 일정 기간동안 진행하는 행사를 말한다. 개발에서 이벤트를 말할 때, 우리가 생각해야 하는 것은 이 행사라는 단어다. How Event? 이벤트란 무엇인가라고 한다면, 행사라고 바로 앞에 적혀있다. 이를 조금 더 자세하게 말하자면 애플리케이션 상에서 나타나는 사건이다. 프론트엔드 개발자라면 더욱 이해하기 쉽다. onClickEvent, hober와 같은 부분들이 모두 JS의 이벤트를 기반으로 동작하는 함수들이다. 이런 함수들을 잘 읽어보면, 사용자가 일으키는 일련의 사건을 통해 해당 로직들을 동작시킨다는 것이다. 하지만, 나는 백엔드를 공부하고 있다. 이 이벤트를 통해 요청을 받는다면, 이에 대한 응답을 ..

[ChatUniv] KOMORAN을 이용한 자연어 처리

질문에 대한 명사들의 통계를 내기 위한, 자연어 처리 라이브러리들을 보고있었다. 이걸 통계로 적용시키고, 각 문자열에서 단어들만을 파싱하기 위한 외부 라이브러리를 디깅하던 중, 두 가지 라이브러리가 눈에 들어왔다. mecab과 KOMORAN이라는 친구였다. 물론 요즘 부스트캠프를 통해 js를 하루종일 만지다 보니 mecab을 적용시켜보는 것은 아주 수월했다 (솔직히 오픈소스에 대한 접근, 활용성은 자바보단 js가 더 편한 느낌도 든다.) 그래서, 둘 다 시도를 해보고, 프로젝트 내부에 코드를 적용시킬 수 있는 KOMORAN을 최종적으로 선택했다. 그렇다면, KOMORAN을 어떻게 쓸까? 2가지 순서가 존재한다. build.gradle에 해당 리포지토리 등록, 의존성 주입 코드 적용 해당 순서대로 정리를 ..

[ChatUniv] No Offset?이게 왜 좋을까?

페이징을 최적화 시키기 위한 방법이 무엇일까를 이야기하게 되었다. 근데, 이전에 페이징을 왜 최적화 시켜야할까? 라는 생각이 들었다. 우리는 JPA에서 offset, limit를 이용해 페이징을 만들 수 있고, 이를 통해 우리가 데이터베이스에서 모든 데이터를 리스트로 받아오고 연산할 필요가 없는데? 이에 대한 내용은, 실제 offset limit을 어떻게 두는지에 따라 달라진다. 우리가 어떤 쿼리를 쓸까? 실제 pageable를 이용하면 어떤 방식의 쿼리가 나올까? 두 개의 다른 프로젝트의 코드지만, 비교를 위해 가져왔다. @Override public Page searchMessage(MessageSearchRequestDto messageSearchRequestDto) { Pageable pageab..

[스프링] 37. MemberController 조회, 삭제 기능 만들기

http.exceptionHandling() .authenticationEntryPoint(jwtAuthenticationEntryPoint) .accessDeniedHandler(jwtAccessDenialHandler) .and() .authorizeRequests() .antMatchers("/api/auth/sign_in", "/api/auth/join").permitAll() .antMatchers("/api/auth/reissue").access("hasAuthority('USER') or hasAuthority('MANAGER') or hasAuthority('ADMIN')") .antMatchers("/api/members/**").access("hasAuthority('USER') or ..

[스프링] 36. MemberController.edit을 조금 다듬어서 테스트해보자.

일단, 다듬는 이유부터 말하자면, 실제 웹사이트에서 회원 정보 수정을 할 때를 생각해보았을 때, 이게 이상하다고 느꼈기 때문이다. 보통 회원정보를 수정하면, 한 페이지에서 이메일, 닉네임, 비밀번호 수정등을 모두 하는데, 지금 만든 프로젝트에서는 각 정보마다 수정을 따로 해주어야 하기 때문이다. 이걸 동적으로 하면 되겠다는 생각이 들었다. 기존의 코드를 조금 인용해서, @Transactional public void editMember(EditMemberRequestDto editMemberRequestDto, Member member){ if(editMemberRequestDto.getNickname() == null && editMemberRequestDto.getEmail() == null && e..

[스프링] 35. AuthController.reissue 테스트부터 프로젝트 코드까지

토큰을 재발행하기 위해서는 어떤 과정이 필요할까를 생각해보았다. 필터체인에서 권한 검증을 받는다(여기서 토큰이 검증되지 않을 경우 예외처리된다) HttpServletRequest에서 토큰을 가져온다. 가져온 토큰을 AuthService.reissue에 집어넣는다. 서비스에서 나오는 TokenResponseDto을 HttpServletResponse에 담아준다. 응답을 준다. 정도로 생각했다. 저번과 마찬가지로, 성공과 실패 경우를 생각해보려고 했다. 하지만, 생각해보니, 이에 대한 문제를 생각하지 않아도 될 것 같은 이유가, 모든 경우에 대한 예외를 Spring Security를 만들 때 적용시켜두었다. 그래서 간단하게, 토큰이 정상적으로 있을 때, 토큰이 없을 때, 토큰이 정상적이지 않을 때를 테스트해..

[스프링] 34. AuthController.signIn을 테스트해보자.

로그인을 할 때, 입력값과 출력값을 생각해보자. 입력 아이디 비밀번호 출력 Access Token Refresh Token 발생가능한 예외사항 아이디가 존재하지 않을 때 아이디를 입력하지 않았을 때 비밀번호가 일치하지 않을 때 비밀번호를 입력하지 않았을 때 이 정도의 경우들을 생각할 수 있다. 발생가능한 예외사항부터 처리하고, 성공하는 경우들을 만들어보려고 한다. 예외를 크게 두 방식으로 묶어보자면, @Valid로 인해 생기는 예외(Validation 이용) 자체적으로 Service에서 확인했을 때 발생하는 예외 이렇게 두 가지가 있다. 일단, Validation을 위한 에러에서는, @RestControllerAdvice public class ValidationExceptionAdvice { @Exce..

[스프링] 33. 잠깐 쉬면서 만들었던 것들을 리펙토링 한 과정을 요약해보자.

일단, 블로그 포스팅을 잠깐 쉬면서, 코드를 다시 한번 돌아보았다. 좌충우돌 만드는 게시판 수준이라지만, 그래도 나름 '생각' 이라는 것을 해보면서 쓰고있다. + 플레이리스트에 아이묭(aimyon) 노래를 틀면서 하기 시작했는데, 기존에 듣던 재즈보다 힘차게 하는 느낌이다(TMI) 기존에, 회원가입 로직을 위해서 Member -> MemberRepository(+MemberCustomRepository) -> MemberService -> MemberController RefreshToken -> RefreshTokenRepository -> RefreshTokenServie -> RefreshTokenController 로 만들려던 계획을 조금 수정했다. DDD라는 것을 조금 찾아보면서, Member,..

[스프링] 32. MemberController.register 중복과 기타사유의 예외 테스트

이전에 null값으로 인한 예외가 발생되는 것을 컨트롤러 테스트를 만들어 검증해보았다. 이번엔, 중복 발생시 / 비밀번호가 서로 다를 시 / 이메일이 형식에 맞지 않을 시 를 검증할 것이다. 일단 중복이 발생하기 위해서는, 몇가지 선행되어야 할 내용이 있다. 매 순간 비교하기 위한 데이터 하나와, 기존의 데이터가 있어야 한다. 매 단위테스트마다 db를 초기화시켜 다른 테스트가 영향을 받으면 안된다. 이런 점을 맞추기 위해, 테스트를 실행하는 RegisterRequestDto를 반환하는 로직을 하나 만들었다. private static RegisterRequestDto makeTestRegister() { return RegisterRequestDto.builder() .username("test") .n..