12월 12일 화 TIL

장숭혁·2023년 12월 12일
0

TIL작성

목록 보기
29/60

🥲 myselectshopApplication이 동작하지 않은 이유

복습을 위해 다시 프로그램을 실행시켰으나, 다음과 같은 오류가 발생하였다.

ERROR 10704 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
APPLICATION FAILED TO START
Description:
The bean 'jpaAuditingHandler' could not be registered. A bean with that name has already been defined and overriding is disabled.

이 오류는 동일한 이름의 빈이 이미 정의되어 있고, 빈을 재정의하는 것이 비활성화되어 있기 때문에 발생하는 오류이다.

이전에는 오류가 나지 않는 상태의 코드로 깃을 타고 과거로 돌아가 해결하였으나, 이번에는 오류를 직접 해결해 보고자 하였다.

ChatGPT가 제시한 대로
spring.main.allow-bean-definition-overriding=true
이 코드를 properties에 추가하였다.

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-12-12T12:53:16.287+09:00 ERROR 11257 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server ....

라는 오류가 새롭게 나왔다. 웹 서버를 시작하는 데 문제가 발생한 것으로 보였는데 다시 ChatGPT에 물어보았더니
1. 포트 충돌
2. 웹 서버 설정에 문제 - SSL 설정
를 문제 후보로 보여주었다. 그래서 재부팅을 하고 실행해 보았고 SSL이 무엇인지 알아보았다.

SSL(Secure Sockets Layer) 설정은 웹 애플리케이션에서 보안 통신을 구현하기 위해 사용되는 규약입니다. SSL은 데이터를 암호화하여 클라이언트와 서버 간에 안전하게 전송할 수 있도록 도와줍니다.

  • 암호화
  • 인증 : 사용자는 웹 서버가 신뢰할 수 있는지 확인할 수 있습니다.
  • 무결성 : 데이터가 전송 중 변조되지 않았는지 확인할 수 있습니다.

SSL은 HTTP 프로토콜에 보안 기능을 추가하여 HTTPS 프로토콜을 생성합니다. HTTPS 프로토콜은 웹 브라우저의 주소 표시줄에 암호화된 연결을 나타내는 암호화된 연결을 나타내는 녹색 자물쇠 아이콘으로 표시됩니다.

  • TLS 1.0: SSL의 후속 버전으로, 현재 가장 널리 사용되는 버전입니다.

이것을 따로 설정하지 않았으므로 다른 오류를 찾아 보았다.

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig' defined in file [/Users/user/Desktop/nullparty/myselectshop/build/classes/java/main/com/sparta/myselectshop/config/WebSecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 3: Error creating bean with name 'jwtAuthenticationFilter': Requested bean is currently in creation: Is there an unresolvable circular reference?

이 오류를 보면 webSecurityConfig와 jwtAuthenticationFilter에 문제가 있어 보였다. 순환참조가 발생하는듯 하였는데 이 두 클래스 사이에서 그런현상이 발생하는 듯 보였다. 그래서

@Configuration
@EnableWebSecurity // Spring Security 지원을 가능하게 함
@RequiredArgsConstructor
public class WebSecurityConfig {

    private final JwtUtil jwtUtil;
    private final UserDetailsServiceImpl userDetailsService;
    private final AuthenticationConfiguration authenticationConfiguration;
    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    //jwtAuthenticationFilter가 사용되지 않고 있었는데 작성되어 있었음

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

그래서 jwtAuthenticationFilter를 주석처리 하였더니 정상동작 하였다.

AuthenticationConfiguration과 JwtAuthenticationFilter

  • AuthenticationConfiguration: 이 클래스는 Spring Security의 인증 매니저(AuthenticationManager)를 설정하는 역할을 한다. AuthenticationManager는 인증 요청을 처리하고, 인증에 성공한 사용자에 대한 Authentication 객체를 생성하는 역할을 한다. AuthenticationConfiguration에서 getAuthenticationManager() 메소드를 통해 AuthenticationManager를 얻을 수 있다.

  • JwtAuthenticationFilter: 이 클래스는 사용자의 로그인 요청을 처리하고, 로그인이 성공하면 JWT 토큰을 생성하여 응답 헤더에 추가하는 역할을 한다. JwtAuthenticationFilter는 UsernamePasswordAuthenticationFilter를 상속받아 작성되었으며, 이 필터는 Spring Security에서 제공하는 기본 로그인 처리 필터이다.

  • WebSecurityConfig 클래스에서는 authenticationManager(authenticationConfiguration) 메소드를 통해 AuthenticationManager를 생성하고, 이를 JwtAuthenticationFilter의 setAuthenticationManager() 메소드에 설정하여 JwtAuthenticationFilter가 인증 요청을 처리할 수 있도록 한다.

Jackson이란 무엇인가?

  • 주로 RESTful 웹 서비스에서 클라이언트와 서버 간의 JSON 데이터를 주고받을 때 Jackson을 사용한다. @RestController와 같은 어노테이션을 이용하여 JSON 응답을 만들거나, HTTP 요청으로부터 JSON 데이터를 Java 객체로 변환할 때 Jackson이 내부적으로 활용된다. 이를 위해 Spring MVC에서는 Jackson을 기본 JSON 바인딩 라이브러리로 사용한다.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.sparta.myselectshop.Star1 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

  • 이 오류는 직렬화, 역직렬화 대상 클래스에 @Getter가 없을때 발생한다.
    Jackson은 객체의 공개된(getter를 통해 접근 가능한) 속성을 찾아 JSON으로 변환한다.
  • writeValueAsString(Object obj): 주어진 자바 객체를 JSON 문자열로 변환합니다.
  • readValue(String content, Class valueType): JSON 문자열을 주어진 클래스 타입의 자바 객체로 변환합니다.
  • writeValue(File resultFile, Object obj): 주어진 자바 객체를 JSON 문자열로 변환하고, 이를 파일에 기록합니다.
  • readValue(File src, Class valueType): 파일로부터 JSON 문자열을 읽어와 주어진 클래스 타입의 자바 객체로 변환합니다.
  • Jackson 라이브러리의 ObjectMapper를 사용하기 위해서는 기본 생성자와 setter 혹은 getter가 필요하다.

    - ObjectMapper + setter
    public class User {
      private String name;
      private int age;
    
      public User() {
      }
    
      public void setName(String name) {
          this.name = name;
      }
    
      public void setAge(int age) {
          this.age = age;
      }
    }
    String json = "{\"name\":\"John\", \"age\":30}";
    ObjectMapper mapper = new ObjectMapper();
    User user = mapper.readValue(json, User.class);

    위 코드에서 readValue 메소드는 JSON 문자열을 User 객체로 변환한다. 이때 User 클래스의 setter 메소드를 사용하여 객체의 속성을 설정한다.

    - 	ObjectMapper + getter
     public class User {
       private String name;
       private int age;
    
       public User(String name, int age) {
           this.name = name;
           this.age = age;
       }
    
       public String getName() {
           return name;
       }
    
       public int getAge() {
           return age;
       }
    }
    User user = new User("John", 30);
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(user);

    위 코드에서 writeValueAsString 메소드는 User 객체를 JSON 문자열로 변환한다. 이때 User 클래스의 getter 메소드를 사용하여 객체의 속성 값을 가져온다

     -   ObjectMapper + setter + getter
      
    
    public class User {
      private String name;
      private int age;
    
      public User() {
      }
    
      public String getName() {
          return name;
      }
    
      public void setName(String name) {
          this.name = name;
      }
    
      public int getAge() {
          return age;
      }
    
      public void setAge(int age) {
          this.age = age;
      }
    }
    String json = "{\"name\":\"John\", \"age\":30}";
    ObjectMapper mapper = new ObjectMapper();
    User user = mapper.readValue(json, User.class);
    json = mapper.writeValueAsString(user);

    위 코드에서 ObjectMapper는 JSON 문자열을 User 객체로 변환하고, 다시 User 객체를 JSON 문자열로 변환한다. 이때 User 클래스의 setter와 getter 메소드를 모두 사용한다.

    json 문자열의 각 key값과 객체의 필드 이름은 같아야 매핑이 될 수 있다.

profile
코딩 기록

0개의 댓글

관련 채용 정보