Java, 스프링부트 다시 시작

가온·2025년 2월 22일

벨로그를 너무 일기처럼 쓰고 있다.
다만 내 일기와 다른 점은...
일기는 기분 정말 좋거나 나쁠 때만 써서 절대 공유할 수 없다는 점이고...
벨로그는 이제 나름 기술 블로그 명목으로 쓰고 있으니 누가 볼 수도 있다는 생각에 나름 가공해서 쓴다는 것...?

그렇게 써보는 오늘의 일기.
요즘 나는 기획하고 피보팅하고 지원사업 문서 작성하고...
그래서 공유 공간 하나를 얻었고, 아나운서 분의 1대1 발표 피드백도 받았고, 다른 창업가분들이랑 네트워킹도 다니고 있다.
항상 창업가와 개발자, 제너럴리스트와 스페셜리스트에 대한 고민이 많았는데, 요즘 타 창업팀들을 만나면서 꼭 하나만 고르는 게 답이 아니라는 생각이 든다. 정말 다양한 형태의 답안지들이 있었다.
그렇게 즐겁게 답안지를 보다 개발을 잊어버렸다.
큰일이다.

그러나 개발을 하고 있다.
모순이다.

기억이 나는데 기억이 나지 않는다.
될 것 같은데 안되고, 안될 것 같은데 된다.
이게 개발인걸까? 내 손이 개발인걸까?

더 개발을 까먹기 전에 벨로그를 일기가 아닌 기술 블로그로써 심폐소생을 해보려고 한다.

사실 공부든 개발이든 정리하면서 했어야했는데, 정리를 하다 말아서 또 산재되어 있다.

그냥 이것저것 산재되어 있던 것들을 긁어모으는 것부터 시작해야겠다.

JAVA

※주의※

자바 언어는 대소문자를 구분한다.

public class HelloJava {

	public static void main(String[] args) {
		System.out.println("hello java");
		}
}
  • publuc class HelloJava → 클래스
  • public static void main(String[] args) → main 메서드
  • System.out.println(”hello java”); →값을 콘솔에 출력하는 기능
  • java는 한 문장 끝낼 때마다 ; 필수
  • 실행하면 시작 지점인 main을 찾고 첫 줄로 들어가서 한 줄씩 수행
  • {} → 블럭, 클래스의 범위 → 스페이스 4번으로 구분(읽기 쉽게, 관례)

Java부터 다시 공부하자라는 마음으로 Java강의를 듣고 있었다.
매우 기초만 정리해놨네... 초반에 정리하다가 말았기 때문이고 캡쳐한 이미지는 제외했기 때문이고 많이 듣지 못했기 때문이다. 변명이 세 가지면 그럴듯한 이유가 될까? 안되는 것 같다...
근데 일단 유료 강의가 훨씬 이해가 잘된다. 근데 정리하면서 듣는 게 꽤 어려운 일이다.

Swagger 적용하기

(🔥 Gradle + Java 버전)

1) Springdoc OpenAPI (Swagger) 의존성 추가

🔹 Gradle (build.gradle)

dependencies {
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
}

2) Swagger 관련 경로 Spring Security에서 예외 처리

🔹 SecurityConfig.java 수정

@Configuration
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // CSRF 비활성화
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(
                    "/api/users/register", "/api/users/login", //  로그인, 회원가입 허용
                    "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html" //  Swagger 허용
                ).permitAll()
                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

저번에도 그렇고 이번에도 스웨거를 이용한다.
저번에 했으니까 이번에도 할 수 있겠지~라는 막연한 생각과
저번에 내가 정리를 잘 해놨겠지라는 잘못된 믿음이
오늘의 내가 정리를 하게 했다.
미래의 나는 오늘의 나를 고마워할까 정리를 왜 이렇게 해놨냐고 원망할까?
집정리는 언제하지?

스프링 시큐리티 관련

로그인, 회원가입을 구현하는데, Jwt를 적용하는 순간 뭔가 문제가 생겼다.
이것저것 건들다가 코드가 꼬였던 것 같다.
깃에 안 올려놔서 스스로 롤백을 했다.
기억을 더듬어 삭제해나갔다는 이야기다.
깃을 애용하자...
이것도 저번에 했던 건데, 뚝딱 나오지 않았다.
내가 정리해놨을 줄 알았는데, 겪었던 에러만 써놨더라...
그 땐 어떻게 했을까? 일단 또 써놔야지

1. SecurityConfig에서 발생하는 순환 참조 문제

오류 메시지:

python-repl
복사
... in 'com.morip.moripbeta.config.SecurityConfig' cannot be applied to '()'...
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig ...
↑     ↓
| inMemoryUserDetailsManager ...
└─────┘

원인:

  • SecurityConfig에서 생성자 주입으로 UserDetailsService를 받고 있는데,기본적으로 스프링 부트의 auto-configuration이 제공하는 InMemoryUserDetailsManager 빈이 생성됩니다.
  • 이 auto-configured UserDetailsService 빈이 SecurityConfig의 생성자 주입에 사용되고,그 과정에서 순환 참조(보통 SecurityConfig → UserDetailsService → SecurityConfig)가 발생하게 됩니다.
  • 즉, SecurityConfig가 인스턴스화되는 도중에 필요한 UserDetailsService 빈을 생성하려고 하는데,그 과정에서 이미 SecurityConfig에 의존성이 생겨 순환참조 문제가 발생합니다.

처음 보는 에러였다.

해결 방법
@Bean으로 UserDetailsService 명시적으로 정의하기
Spring Boot가 자동으로 InMemoryUserDetailsManager를 등록하는 것을 막고, 명시적으로 UserDetailsService를 직접 빈으로 등록하면 순환 참조 문제가 해결됨.

@Bean
public UserDetailsService userDetailsService(UserRepository userRepository) {
    return username -> userRepository.findByEmail(username)
            .map(user -> User.withUsername(user.getEmail())
                    .password(user.getPassword())
                    .authorities(Collections.emptyList())  // 필요한 경우 권한 추가 가능
                    .build())
            .orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + username));
}

처음 보는 에러였는데, 이렇게 하니 해결이 되었다.
admin이랑 일반 사용자 역할을 나눠보려다가 오류를 겪고 일단 권한은 없앴다. 당장은 필요없으니까

와 정말 정리를 안해두고 있었구나

왜 생각이 바로바로 떠오르지 않을까? 싶었는데 정리를 안해서였을지도 모르겠다.

한국인에게는 2번의 새해가 있다고 한다.
1월 1일과 설날.
그리고 학생에게는 한 번의 새해가 더 주어진다고 한다.
개강...
이제 방통대 개강도 했으니 정말 모든 2025년도 새해를 다 써버렸다.
2025년은 기록을 하면서 정리를 하면서 할 일을 해가자
기억은 믿을 수 없다. 남는 건 기록뿐일지도 모르겠다.

그럼 기록하면서 2025년에는 꼭 저질러보자
파이팅!

0개의 댓글