Port를 이미 사용 중이라고 하는 문제
Error : org.springframework.boot.web.server.PortInUseException: Port 8080 is already in use
원인
IDE 상에서는 프로세스가 종료되었으나 실제 프로세스가 종료되지 않은 경우
해결
- macOS 프로세스 종료
- lsof 명령어로 해당 port를 사용하는 프로세스 조회 후 종료
- 프로젝트를 하면서 제일 많이 만났던 문제라 이제는 명령어를 눈감고도 친다
lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 12345 user 128u IPv6 0x5210d6 0t0 TCP 127.0.0.1:8080 (LISTEN)
kill -9 <조회 시 뜬 PID>
Launching Spring application Address already in use
참고)
lsof -n -i -p | grep 8080
lsof
: 현재 실행중인 프로세스 확인-n
: 호스트네임 제거-i
: IPv[46] 파일들 선택-P
: 포트의 이름 제거
LocalDateTime이 Array type으로 응답 가는 현상 발생
- 트러블까지는 아니나, 프론트에서 날짜관련 라이브러리를 사용하고 있어 String으로 받길 요구
원인
@EnableWebMvc
사용 → @EnableWebMvc가 serializer, deserializer 설정을 가지고 있어 커스텀으로 config를 등록해두어도 덮어씌우기 때문
해결
- SpringBoot의 경우 spring-boot-starter-web import 해주면 MVC 관련된 bean 들에 대한 설정을 대신 해줌
그러나 현재 나는 cors 설정을 위해 기본 동작하는 빈 커스터마이징 필요- 현재
@EnableWebMvc
를 사용했으나 기존에 설정된 bean 설정을 유지하고 기능을 확장하고 싶은 것이므로@EnableWebMvc
없이WebMvcConfigurer
타입의@Configuration
클래스를 추가하는 것으로도 충분! - 별다른 MVC 설정을 한 것은 없지만, @SpringBootApplication 어노테이션을 붙여줌으로써 기본적인 스프링 부트 MVC 설정도 같이 제공 됨
- @Configuration 과 WebMvcConfigurer 을 같이 쓰면 MVC 확장
- 현재
⇒ @EnableWebMvc
제거
@EnableWebMvc showing date in array formate
Developing with Spring Boot
@EnableWebMvc
테스트코드 @AfterEach 내에서 deleteAll() 사용 시, 다른 도메인 테스트까지 영향이 가 전체 테스트에서 EntityNotFoundException 발생
> Task :processTestResources
> Task :testClasses
> Task :test
RouteController를 통해 > 후보지를 루트에 등록한다 FAILED
org.springframework.orm.jpa.JpaObjectRetrievalFailureException at RouteControllerTest.java:89
Caused by: javax.persistence.EntityNotFoundException at RouteControllerTest.java:89
53 tests completed, 1 failed
원인
- 테스트 클래스들이 MysqlTestContainer를 상속받아 구현되었기 때문에, 통합 테스트수행시 컨테이너를 공유해서 사용하기 때문
- 그렇다면 테스트가 병렬로 실행되는건가? 더 알아봐야함
해결
- deleteAll()을 deleteById()로 수정해 각각의 테스트에서 사용하는 데이터만 삭제
Redis의 BGSAVE 관련 문제
io.lettuce.core.RedisCommandExecutionException: MISCONF Redis is configured to save RDB snapshots
원인
BGSAVE에 의한 Write Block
Persistent를 위해 BGSAVE로 RDB를 만들고, 실패할 경우 Write command를 전부 거부하기 때문에
해결
해당 옵션(BGSAVE 옵션) 해제
[root@localhost ~]# redis-cli
127.0.0.1:6379> config set stop-writes-on-bgsave-error no
OK
127.0.0.1:6379> quit
[root@localhost ~]#
MISCONF Redis is configured to save RDB snapshots
Security ignoring이 적용이 안되는 문제
web.ignoring().antMatchers(..)
는 파라미터로 전달하는 패턴에 대해 security filter chain을 생략함
-> 토큰 재발급 요청을 security filter ignoring 되도록 설정했으나,
직접 만든 custom filter를 제외하지 않아 계속해서 header의 만료된 access token을 검증하면서 발생하는 이슈
원인
- custom filter를 bean으로 등록한 게 문제
- custom filter를 bean으로 등록하게 되면
해당 filter가 security filter chain에 포함되는 게 아니라 default filter chain에 포함되게 되기 때문에
해당 패턴에 접근하게 됐을 때 그대로 filter를 적용하게 되는 것
- custom filter를 bean으로 등록하게 되면
해결
-
bean으로 등록해주던 걸 아래처럼 변경한다
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider()), UsernamePasswordAuthenticationFilter.class)
-
또는, OncePerRequestFilter의 shouldNotFilter() 메서드를 재정의해서 custom filter에서 해당 요청을 무시하도록 한다 (내가 적용한 해결법)
@Override protected boolean shouldNotFilter(HttpServletRequest request) { return request.getRequestURI().endsWith("reissue") && request.getMethod().equalsIgnoreCase("POST"); }
Spring webSecurity.ignoring() doesn’t ignore custom filter
Token 재발급 요청 시 500 error 이슈
{
"message": "Cannot invoke \"String.equals(Object)\" because the return value of \"org.prgrms.wumo.global.repository.KeyValueRepository.get(String)\" is null"
}
원인
null 가능성이 있는 변수(keyValueRepository.get(memberId
))와 equals 과정에서 에러 발생 -> 변수 위치 변경
해결
- 전
if (!keyValueRepository.get(memberId).equals(refreshToken)) {
throw new ExpiredTokenException("인증 정보가 만료되었습니다.");
}
- 후
if (!refreshToken.equals(keyValueRepository.get(memberId))) {
throw new ExpiredTokenException("인증 정보가 만료되었습니다.");
}
- 결과 : null인 경우더라도 false로 처리되어 의도한 exception throw 함
{
"message": "인증 정보가 만료되었습니다."
}
CORS 에러
원인
React와 SpringBoot의 host와 port가 다르기 때문
해결
Java Config를 통해 Spring MVC 설정에서 CORS 설정함
=> Spring MVC쪽에서 설정을 하더라도 security가 자동으로 spring에 선언해 둔 cors 구성을 사용함
- 그 외 해결법
- spring에서 설정하는 법 : controller or method에 @CrossOrigin annotation을 달아주면 됨
- spring security에서 설정하는 법 : CorsWebFilter를 사용하기 위해 CorsConfigurationSource로 설정