개요Dktechin 주관 기업실무 프로젝트를 진행하면서 Argument Resolver를 이용해서 컨트롤러에서 조건을 어노테이션으로 받아 조금 더 가독성있고 간단하게 사용하는 방법을 알게되어서 정리해보려고 한다.이 방법을 통해서 검색 조건 파라미터들을 @SearchParam이라는 어노테이션으로 받아서 MemberSearchParam, BoardSearchParam 등 여러 Record 객체로 만들어서 사용했다.HTTP 메시지 컨버터컨트롤러에서 변수 바인딩 처리 방법특정 변수에 바인딩@RequestParam 사용가변 경로 변수 바인딩@PathVariableHttp Body 변수 바인딩@RequestBody(주로 DTO 사용)파일과 같은 Multipart@RequestPart이 때 Argument Resol..
개요이 때까지 Service 테스트는 필수적으로 해왔는데 Controller 테스트는 postman으로 해보고 되면 되는구나하고 넘겼다.과거의 나 반성해라!근데 유닛 테스팅에 대해 공부하던 중 Controller 테스트도 하는 것이 무조건 좋다고 해서(Postman은 http에 비해 상당히 제약이 적기 때문이다.)그래서 Controller 테스트 코드 작성한거랑 발생한 오류들에 대해 정리해볼 것이다. Test 코드Test 코드 어노테이션@WebMvcTest(controllers = EpisodeController.class)@MockBean(JpaMetamodelMappingContext.class)@AutoConfigureMockMvc 먼저 Service 테스트 코드와 다르게 @SpringBootTes..
개요Spring Boot와 TypeScript 기반으로 웹 애플리케이션을 제작하고 있는데 유저 프로필 이미지를 받아 저장하는로직이 필요했다.이를 위해서 프론트에서 보낸 이미지를 MultiPartFile로 받아서 S3에 저장하는 방식으로 구현하기로 했다.S3 생성이나 키 생성과 같은 AWS 관련 할 일은 생략하겠다.Spring Boot S3 연결연결을 위해서는 AWS의 access키랑 secret키를 등록해야 한다. 오타에 조심하자.. }안써서 1시간 고생했다.cloud: aws: s3: bucket: ${bucket-name} credentials: access-key: ${access-key} secret-key: ${secret-key} region: ..
문제 발생 @Builder를 사용해서 엔티티의 1:N 관계를 정의하던 중 new ArrayList()로 필드를 초기화 해도 NullPointException 에러가 발생했다. List가 Builder 패턴을 이용해서 엔티티를 초기화할 때 Null값으로 된 것이다. Cannot invoke "java.util.List.add(Object)" because the return value of "semicolon.MeetOn_WhenToMeet.domain.when_to_meet.domain.WhenToMeet.getTimeTableList()" is null java.lang.NullPointerException: Cannot invoke "java.util.List.add(Object)" because t..
개요 Spring Cloud Eureka로 웹 서비스 토이? 프로젝트를 진행하던 중 프론트 개발자의 요청으로 Swagger를 배포하여 API 연결할 일이 생겼다. 근데 각 서버마다 자신의 포트로 Swagger를 열면 상당히 불편할 것 같다는 결론이 나왔다. 하나의 uri로 모든 서버의 Swagger-ui로 접근할 수 있게 해달라는 부탁명령이 내려왔다. Swagger란? 개발한 Rest API를 편리하게 문서화하여 이를 사용하는 사용자가 편리하게 API를 호출하고 테스트할 수 있게 도와주는 프로젝트 이다. Spring Boot 기준 밑 dependency를 추가해주면 간단하게 쓸 수 있다. implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui..
개요 Next.js와 Spring Boot를 기반으로 하는 웹 애플리케이션 프로젝트에서 카카오 소셜 로그인을 구현하게 되었다. JWT를 기반으로 인증, 인가 관련 기능을 구현하기로 해서 클라이언트에게 엑세스 토큰과 리프레시 토큰을 발급하여 로컬 스토리지에 저장하고 사용하는 방식을 택했다. 이를 개선해보려고 한다. 엑세스 토큰, 리프레시 토큰 엑세스 토큰 유효 기간이 매우 짧은 토큰으로 따로 DB에 저장하지 않고 받은 값을 Spring Security의 필터체인을 통해 검사하고 유효 여부를 판단한다. 주로 30분 정도로 짧은 시간 내에 인증을 위해서 사용한다. 리프레시 토큰 유효 기간이 엑세스 토큰에 비해 비교적 긴 토큰이다. 엑세스 토큰이 만료되었을 때 새로운 엑세스 토큰을 발급하기 위해 사용한다. 문제..
* 그냥 제 생각대로 만들어서 해결했습니다. 정답x 고민 회원 가입 로직을 구현하던 중 Private 메소드에 대한 테스트를 어떻게 진행해야 할 지에 대한 고민이 생겼다. 외부에서 접근하지 않는 메소드로 굳이 Public으로 작성할 이유가 없었기 때문이다. 실제 문제: 이메일 인증을 완료하고 회원 가입을 승인해주는 로직에서 이메일 인증을 보내기 전에 데이터베이스에 같은 이메일이 존재하는 지 확인하고 존재하지 않는다면 인증 코드를 보내고 아니면 예외를 발생시켜야 했다. 이 때 이메일 중복 확인 메소드를 Private으로 설정했고 테스트 코드를 작성할 때 이메일 중복 확인이 잘 되는지 확인하고 싶었다. 코드: AuthService private void checkDuplicatedEmail(String em..
세션 대신 JWT를 사용하기 위해 각종 코드를 적용하면서 코드를 그대로 가져오려니 이해안되는 부분이 많았다. 코드도 복잡하고 동작 과정도 모르는 상태로 사용하려니 JWT 형식 변경이나 유지보수에 어려움이 있을게 뻔해서 자주 볼 수 있게 정리해보려고 한다. 참조 https://blog.javabom.com/minhee/session/spring-security-1/spring-security https://bcp0109.tistory.com/301 JWT 적용을 위해 봤던 코드 및 로직들 1. Why JWT? JWT의 특징 사용자 인증에 필요한 모든 정보를 토큰에 담아 클라이언트(React)에 저장하기 때문에 별도의 DB 테이블이 필요 없다. 일반 토큰과의 가장 큰 차이점 분산 마이크로 서비스 환경에서 클..
이전에 세션을 통해서 로그인 인증 기능을 구현하려고 했지만 12시간에 노력 끝에 포기했다... JWT로 넘어가기로 했지만 해결 못해서 분하다. CORS 문제 때문이라고 하는데 도대체 이게 뭘까? 해결은 못했고 왜 안되는지 원인이라도 확실하게 알고 가야겠다. CORS란? Cross-Origin Resource Sharing의 약자로 교차 출처 리소스 공유라고 한다. 여기서 Origin은 프로토콜 + 도메인 + 포트 모두를 합친 것을 뜻한다. 이 때 리소스를 요청할 때 요청한 쪽의 Origin과 요청받은 쪽의 Origin이 다르면 CORS에러가 발생한다고 한다. a. CORS 동작 원리 CORS 동작 원리를 모두 정리하기에는 내용이 너무 방대하고 어렵다.... https://velog.io/@jh100m1/..
과제 프로젝트를 진행하던 중 어느정도 기능 구현이 완성되고 실 테스트 단계에 들어갈 때, 관리 시스템에 로그인 기능이 꼭 필요하다는 결론이 나왔다. 남은 시간이 별로 없었기에 여러 방법 중 코드 구현이 비교적 짧은 Session 기반 로그인 기능을 사용해보았지만 리액트와 연도에서 근본적인 문제가 발생했다. 1. 문제 발생 Session(이하 세션) 인증 로직을 구현하고 React에 쿠키를 통해 세션 정보를 보낼 때 세션이 유지되지 않는 문제가 발생했다. 분명히 포스트맨이나 테스트 코드로는 세션이 존재하고 쿠키값도 넘어와서 사용했지만 React에서만 유지되지 않았다. 이 문제를 CORS 이슈라고 하는 것 같다. 이는 다음에 다뤄보겠다. React와 Spring의 포트가 다르기 때문에 React에서 서버에서..