본문 바로가기

내일배움캠프 4기 스프링/내배캠 TIL📘

12. 23 개인 과제 수행/ 스프링 심화 강의/ 디자인 패턴/ @Anotation

728x90

1. 개인 과제 수행

1) 어제 만들었던 댓글 생성 메서드의 퀄리티 높이기

@OneToMany(cascade = CascadeType.All) List<Comment> commentList = new ArrayList<>();에서 만들어지는 Post-CommentList 테이블로 인해 마치 다대다 관계에서 처리하는 것같이 값을 저장하는 부분 개선 노력

https://wordbe.tistory.com/entry/Spring-Data-Jpa-JPA

 

JPA 기본 - cascade, fetch, query

JPA Cascade Cascade란 엔티티 상태를 전파시키는 옵션이다. 엔터티 상태란 다음 4가지를 말한다. Transient : 객체가 단지 선언되고 생성만 되었을 뿐 JPA 는 알지 못하는 상태다. Persistent : JPA가 관리중인

wordbe.tistory.com

cascade : 연관관계가 있는 엔티티의 변화를 반영한다

fetch : 객체를 가져온다

https://www.youtube.com/watch?v=brE0tYOV9jQ 

https://www.youtube.com/watch?v=hsSc5epPXDs 

2) 더티체킹에 대한 경험치 +1 :

내가 코멘트 객체를 만들고 ResponseDto타입 객체로 반환하기 전에 DB에 저장을 하지 않았지만 DB에 저장이 된 이유:

Post타입의 객체를 만들 때 JPA가 내가 지시하지 않았어도 1차 캐시 공간에 미리 만들어진 Post타입의 객체가 있는지 확인한다. 이후 없을 때 새로 만들어서 1차 캐시 공간에 저장한다.

그 후 @Transactional 주기가 끝날 때, 나는 그 전에 Comment 타입의 객체를 만들고 그 곳에 RequestDto타입에서 받은 값을 할당한 후 그 객체를 Post 클래스에서 참조한commentList에 추가하고 주기를 끝낸다.

그렇게 되면 JPA는 더티체킹을 하며, post.commentList에 변화가 있다는 것을 알게 되고, 내가 별도로 명령하지 않아도 DB에 변경된 값인, comment가 추가된 commentList를 저장하는 것이다.

 

3) 영속성 컨테스트에 대한 이해 높이기 :

https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.html

 

3.영속성 관리 · jpa

 

ultrakain.gitbooks.io

4) 즉시로딩과 지연로딩

https://ict-nroo.tistory.com/132

 

[JPA] 즉시 로딩과 지연 로딩(FetchType.LAZY or EAGER)

즉시 로딩과 지연 로딩프록시 학습 처음에 했던 질문. Member를 조회할 때 Team도 함께 조회 해야 할까?비즈니스 로직에서 단순히 멤버 로직만 사용하는데 함께 조회하면, 아무리 연관관계가 걸려

ict-nroo.tistory.com

2. 스프링 심화 강의

1) Spring Security

프로젝트 생성중에 만난 스프링 부트 버전 이슈 ~ 강의 상으론 2.7.6 버전으로 제작되어 3.0.1 버전에는 코드 호환이 맞지 않아 한 번 갈아 엎었다. 버전 관리의 중요성을 체감할 수 있었다.

** Authentication 객체를 만들기 위해 필요한 과정 중 일부 : WebSecurityCustomizer & UserDteailsServiceImpl

package com.sparta.springsecurity.config;


import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // h2-console 사용 및 resources 접근 허용 설정
        return (web) -> web.ignoring() // 해당 경로로 들어오는 모든 요청에 대한 인증을 무시하겠다.
                .requestMatchers(PathRequest.toH2Console())
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF 설정
        http.csrf().disable();

        http.authorizeRequests()
                // 해당 URL은 인증없이 허용한다
                .antMatchers("/h2-console/**").permitAll()
                .antMatchers("/css/**").permitAll()
                .antMatchers("/js/**").permitAll()
                .antMatchers("/images/**").permitAll()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .anyRequest().authenticated();

        // 로그인 사용 ~ default : FormLogin
        // Custom 로그인 페이지 사용
        // Custom 로그인 페이지를 사용하기로 스프링에 통지하면, 스프링은 디폴트 비밀번호를 생성하지
        // 않고, 기존의 UserDetails, UserDetailsService를 사용한 인증 또한 진행하지 않는다.
        http.formLogin().loginPage("/api/user/login-page").permitAll();

        return http.build();
    }

}
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;

    @Override // username을 파라미터로 받아 레포지토리에서 유저 정보를 참조하여 객체 생성후 객체 인스턴스를 파라미터로 하는 생성자 메서드 호출
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        System.out.println("UserDetailsServiceImpl.loadUserByUsername : " + username);

        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));

        return new UserDetailsImpl(user, user.getUsername(), user.getPassword());
    }
    // UserService 안에서 loadUserByUsername 메서드를 호출한 값을 UserDetails 타입의 객체를 생성한 뒤 할당한다.
    // UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    // 그 객체의 인스턴스를 활용하여 Authentication 타입의 객체를 생성한다.
    // Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());

3. 디자인 패턴 및 @Annotation 특강

18개의 디자인 패턴에 대한 강의. 그동안 스쳐지나가며 들었던 패턴에 대해 조금 더 자세히 접근할 수 있었다.

어노테이션에 대해서도 그 이해도를 확 높일 수 있었으며, 수강생의 집중력까지 배려해주는 튜터님의 정성을 느낄 수 있는 시간이었다.

 

728x90