1. 어려웠던 부분 : 오늘 항해99에서 제공된 스프링 주특기 심화주차 강의를 다 듣고, 심화주차 과제 구현을 시작했다. 과제 레벨1 까진 JWT토큰을 검증하는 코드 대신 스프링시큐리티를 사용하여 로직을 구현하는 부분이었는데, 강의를 본 후 비교적 쉽게 구현할 수 있었다. 근데 이어서 게시글과 댓글에 좋아요를 구현하는 부분은 도무지 감이 잡히질 않아서 인광선생님의 개인과외를 받으면서 구현에 성공했다.

또, 지난번에 다대일 양방향 연관관계를 매핑하다가 순환참조 오류가 나서 일단 임시방편으로 @JasonIgnore을 사용했는데, 오늘 기술매니저님이 Dto를 잘 바꿔보라고 팁을 주셨다. 호 ^^ 힌트를 주셔도 잘 모르는 나. 내일 다시 해보는 걸로.

 

2. 느낀 점 : 오늘 저녁에 2시간 동안 최원빈 튜터님의 CRUD세션을 들었다. 입문주차 과제구현을 직접 라이브 코딩을 해주시면서 어떤 흐름으로 코드가 구현이 되는지 설명해주셨다. 진짜 목소리가 너무 좋으셔서 세션이나 강의 들을때마다 잠이 미친듯이 오는데, 오늘은 진짜 나한테 너무 필요한 부분인 것 같아서 최대한 집중해서 들으려했다. 뭔가 아직도 기계처럼 다다닥 코드를 구현할 수 있는 수준은 아니지만, 그래도 자꾸 보다보니 대애충은 알 것 같은 느낌. 내일 오늘 완성한 코드를 다시한번 찬찬히 뜯어보고 특히 내가 제일 약한 부분이 매개변수와 참조변수를 넣어주는 부분인데, 이 부분을 다시 한번 잘 생각해 보면서 코드를 뜯어봐야겠다.

 

3. 새로 알게 된 내용 : 오늘 자바스터디를 통해 예외처리에 대한 공부를 다시 복습했는데, 마침 오늘 들었던 강의도 예외처리 부분이라 좀 더 이해가 쉬웠던 것 같다. 예외는 에러와 달리, 개발자나 사용자의 실수로 발생하는 문제를 의미한다. 따라서 예외가 발생할 경우를 잘 처리해준다면 프로그램 종료라는 큰 재난 없이 프로그램이 잘 굴러갈 수 있다. 또, 테스트 코드를 작성하는 부분도 배웠는데, 아직 테스트코드를 직접 구현하진 못할 것 같지만, 테스트 코드가 얼마나 유용한지는 알 수 있는 강의내용 이었다.

 

4. 셀프칭찬 (오늘 잘한 일) : 하루하루 어려운 스프링을 마주하면서 스스로를 의심한다. 의심할 때마다, 최대한 빨리 그 생각에서 벗어나려 했다. 어쨌든 시작했으니 끝을 봐야하고, 할 수 있는 만큼 최선을 다했다면 꼭 개발자가 되지 않더라도 후회는 없을 것 같다. 앞으로 남은 시간도 이런 마음가짐으로 너무 스트레스 받지 않고 할 수 있는 만큼 최선을 다하고 하루 끝에선 잘 견딘 나를 칭찬해 주자 : ) 

 

5. 내일 할 일 : 자바 공부 - 스레드, 과제 구현한 코드 다시 보기, 이번주 강의자료 재정리 하기.

 


[오늘 공부한 부분]

  • 자바 언어스터디 - 예외 처리
  • 스프링 시큐리티 강의 

[23] Spring Security

 

[23] Spring Security

Spring Security ① Spring Security 란? 'Spring Security' 프레임워크는 스프링 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어 준다. 마치 '스프링' 프레임워크가 웹 서

leejincha.tistory.com

[24] ERD(Entity Relationship Diagram)

 

[24] ERD(Entity Relationship Diagram)

프로젝트를 구현하기 전 미리 설계해야 할 부분이 두 가지 있다면, 1. ERD 설계 2. API 설계 일 것이다. 지난 번에 Restful한 API 에 대한 글을 정리했으므로 오늘은 ERD를 정리해 보려 한다. RESTful API 설

leejincha.tistory.com

[25] JPA 다양한 연관관계 매핑

 

[25] JPA 다양한 연관관계 매핑

엔티티의 연관관계를 매핑할 때는 3가지를 고려해야한다. 다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M) 단방향, 양방향 : (객체 참조) 연관관계의 주인 : 양방향일 때, 연관 관계에서

leejincha.tistory.com

 

엔티티의 연관관계를 매핑할 때는 3가지를 고려해야한다.

  1. 다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M)
  2. 단방향, 양방향 :  (객체 참조)
  3. 연관관계의 주인 : 양방향일 때, 연관 관계에서 관리 주체

연관관계 매핑 : 비즈니스 로직, 비즈니스 요구사항에 따라 개발자가 더 적절한 관계 설정 방법을 선택

 


다중성

다대일(@ManyToOne)

일대다(@OneToMany)

일대일(@OneToOne)

다대다(@ManyToMany)

 

※ 보통 다대일과 일대다 관계를 많이 사용하고 다대다 관계는 실무에서 거의 사용하지 않는다.

 

단방향, 양방향

  • 데이터베이스 테이블은 외래 키 하나로 양 쪽 테이블 조인이 가능하다.
  • 데이터베이스는 양방향으로 쿼리가 가능하기 때문에 단방향이니 양방향이니 나눌 필요가 없다.
  • 반면, 객체는 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능하다.
  • 그렇기 때문에 두 객체 사이에 하나의 객체만 참조용 필드를 갖고 참조하면 단방향 관계, 두 객체 모두가 각각 참조용 필드를 갖고 참조하면 양방향 관계라고 한다.
  • 사실, 엄밀하게는 양방향 관계↔️는 없고 두 객체가 단방향 참조를 각각 가져서 양방향 관계처럼 사용하고 말하는 것

 

연관관계 주인

  • 두 객체(A, B)가 양방향 관계, 다시 말해 단방향 관계 2개(A→B, B→A)를 맺을 때, 양방향 참조가 존재하기 때문에 어느 쪽에서 외래키를 관리할지 정해야한다.
  • 외래 키를 가진 테이블을 매핑한 엔티티에서 외래 키를 관리하는게 효율적이다.
  • 따라서 이곳을 연관관계의 주인으로 선택한다. 외래 키를 가진 엔티티가 주인이라고 생각하면 쉽다. 
  • 일대다, 다대일 관계에서 항상 '다'쪽이 외래키를 가진다. 주인이 아닌 쪽은 외래 키를 변경할 수 없고 읽기만 가능하다.  

 


다대일(N : 1) 단방향

게시판(Board)과 게시글(Post)의 관계로 이해해 보기! 

  • 요구 사항
    • 하나의 게시판(1)에는 여러 게시글(N)을 작성할 수 있습니다.
    • 하나의 게시글은 하나의 게시판에만 작성할 수 있다.
    • 게시글과 게시판은 다대일 관계를 갖습니다.

데이터베이스를 기준으로 다중성(게시글N : 게시판1)을 결정했다. 즉, 외래 키를 게시글(N)이 관리하는 일반적인 형태.

다대일 단방향에서는 다 쪽인 Post에서 @ManyToOne 만 추가해준 것을 확인할 수 있다. 반대로 Board에서는 참조하지 않는다. (단방향이기 때문)

@Entity
public class Post {
    @Id @GeneratedValue
    @Column(name = "POST_ID")
    private Long id;

    @Column(name = "TITLE")
    private String title;

    @ManyToOne
    @JoinColumn(name = "BOARD_ID")
    private Board board;
    //... getter, setter
}

@Entity
public class Board {
    @Id @GeneratedValue
    private Long id;
    private String title;
    //... getter, setter

 

다대일(N : 1) 양방향

다대일 양방향으로 만드려면 일(1) 쪽에 @OneToMany 를 추가하고 양방향 매핑을 사용했으니 연관 관계의 주인을 mappedBy 로 지정해준다. mappedBy로 지정할 때 값은 대상이 되는 변수명을 따라 지정하면 된다. 여기서는 Post 객체(대상)의 board라는 이름의 변수이기 때문에 board로 지정

@Entity
public class Post {
    @Id @GeneratedValue
    @Column(name = "POST_ID")
    private Long id;

    @Column(name = "TITLE")
    private String title;

    @ManyToOne
    @JoinColumn(name = "BOARD_ID")
    private Board board;
    //... getter, setter
}

@Entity
public class Board {
    @Id @GeneratedValue
    private Long id;
    private String title;

    @OneToMany(mappedBy = "board")
    List<Post> posts = new ArrayList<>();
    //... getter, setter
}

 

일대다(1 : N) 단방향  

(참고로 실무에서는 일대다(1:N) 단방향은 거의 쓰지 않는다.)

데이터베이스 입장에서는 무조건 다(N)쪽에서 외래키를 관리한다. 일(1)쪽 객체에서 다(N) 쪽 객체를 조작(생성,수정,삭제)하는 방법!

@Entity
public class Post {
    @Id @GeneratedValue
    @Column(name = "POST_ID")
    private Long id;

    @Column(name = "TITLE")
    private String title;
  //... getter, setter
}

@Entity
public class Board {
    @Id @GeneratedValue
    private Long id;
    private String title;

    @OneToMany
    @JoinColumn(name = "POST_ID") //일대다 단방향을 @JoinColumn필수
    List<Post> posts = new ArrayList<>();
    //... getter, setter
}

@OneToMany에 mappedBy가 없어진다. 양방향이 아니기 때문. 대신 @JoinColumn을 이용해서 조인을 한다.

실제 사용은 아래와 같다.

//...
Post post = new Post();
post.setTitle("가입인사");

entityManager.persist(post); // post 저장

Board board = new Board();
board.setTitle("자유게시판");
board.getPosts().add(post);

entityManager.persist(board); // board 저장
//...

위와 같은 시나리오로 동작을 살펴보면, post를 저장할 때는 멀쩡하게 insert 쿼리가 나가지만 그 다음이 문제이다.

board를 저장할 때는 Board를 insert하는 쿼리가 나간 후에 post를 update하는 쿼리가 나간다.

왜냐하면 board.getPosts().add(post); 부분 때문!

Board 엔티티는 Board 테이블에 매핑되기 때문에 Board 테이블에 직접 지정할 수 있으나, Post 테이블의 FK(BOARD_ID)를 저장할 방법이 없기 때문에 조인 및 업데이트 쿼리를 날려야 하는 문제가 있다.

 

치명적인 단점

  • 일만 수정한 것 같은데 다른 수정이 생겨 쿼리가 발생하는 것.
    • Board를 저장했는데 왜 Post가 수정이 되지? 이런 생각을 하게 만듦.
    • 업데이트 쿼리 때문에 성능상 이슈는 그렇게 크지는 않음.

 

정리 : 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자. 엔티티를 매핑한 테이블이 아닌 다른 테이블의 외래 키를 관리한다는 것은 성능 문제도 있지만 관리도 부담스럽다. 해결법은 다대일 양방향 매핑을 사용하는 것이다. 

 

일대다(1 : N) 양방향

(실무 사용 금지 )

일대다 양방향 매핑은 존재하지 않는다. 대신 다대일 양방향 매핑을 사용해야한다. (다대일 양방향과 일대다 양방향은 사실 똑같은 말이다) 양방향 관계에서 @OneToMany는  주인이 될 수 없다. 관계형 데이터베이스 특성상 일대다, 다대일 관계는 항상 '다'쪽에 외래 키가 있다. 따라서 연관관계의 주인은 항상 @ManyToOne이다. 

 

그렇다고 일대다 양방향 매핑이 완전히 불가능하지는 않다. 일대다 단방향 매핑 반대편에 같은 외래 키를 사용하는 다대일 단방행 매핑을 읽기 전용으로 추가하면 된다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    
    private String username;
    
    @ManyToOne
    @JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
    private Team team;
    

    ...
 
}

@Entity
public class Team {
    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    
    @OneToMany
    @JoinColumn(name = "TEAM_ID") //MEMBER테이블의 TEAM_ID(FK)
    private List<Member> members = new ArrayList<Member>();
    
    private String name;
    
    ...
    
}

둘 다 같은 키를 관리하므로 문제가 될 수 있지만 Member의 JoinColumn속성을 보면 읽기만 가능하게 했다. 이 방법은 다대일 양방향처럼 보이게하지만 일대다 단방향 매핑이 가지는 단점을 그대로 가진다. 웬만하면 다대일 양방향 매핑을 사용하자.

 


[ 참고 자료 ]

 

 

https://jgrammer.tistory.com/entry/JPA-%EB%8B%A4%EC%96%91%ED%95%9C-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91-1-%EB%8B%A4%EB%8C%80%EC%9D%BC-%EC%9D%BC%EB%8C%80%EB%8B%A4-1

 

[JPA] 다양한 연관관계 매핑 (1) 다대일, 일대다

엔티티의 연관관계를 매핑할 때는 3가지를 고려해야한다. 다중성 단방향, 양방향 연관관계의 주인 먼저 두 엔티티가 일대일 관계일지 일대다 관계인지 다중성을 고려한다. 다음으로, 두 엔티티

jgrammer.tistory.com

 

https://jeong-pro.tistory.com/231

 

JPA 연관 관계 한방에 정리 (단방향/양방향, 연관 관계의 주인, 일대일, 다대일, 일대다, 다대다)

JPA에서 가장 중요한 것 JPA에서 가장 중요한 것을 뽑자면, "객체와 관계형 데이터베이스 테이블이 어떻게 매핑되는지를 이해하는 것"이라고 생각합니다. 🏅 왜냐하면 JPA의 목적인 "객체 지향 프

jeong-pro.tistory.com

 

'Coding > Spring' 카테고리의 다른 글

[27] Spring AOP  (0) 2022.12.14
[26] OAuth / 소셜 로그인  (0) 2022.12.14
[24] ERD(Entity Relationship Diagram)  (0) 2022.12.13
[23] Spring Security  (0) 2022.12.13
[22] 항해99 주특기 숙련주차 시험 Spring  (0) 2022.12.08

프로젝트를 구현하기 전 미리 설계해야 할 부분이 두 가지 있다면, 

1. ERD 설계

2. API 설계 

일 것이다. 지난 번에 Restful한 API 에 대한 글을 정리했으므로 오늘은 ERD를 정리해 보려 한다.

RESTful API 설계 가이드 (참고 자료)

 


1. ERD

① ERD (Entity Relationship Diagram)

  • 개체-관계 모델. 테이블간의 관계를 설명해주는 다이어그램이다.
  • 프로젝트에서 사용되는 DB의 구조를 한눈에 파악할 수 있다. 즉, API를 효율적으로 뽑아내기 위한 모델 구조도라고 생각하면 된다.
  • DB를 개발하기 전에 보다 많은 아이디어를 도출하고, 데이터베이스 설계의 이해를 높이기 위해 데이터 모델링을 실시한다.
  • 쿼리문을 작성할 때 테이블들이 구조화된 다이어그램을 보면서 도움을 받을 수 있다.
  • 데이터의 다양한 특징을 확인할 수 있어 요구사항을 그에 맞게 개발할 수 있다.

 

ERD의 Notation

 

 

  • 기본 요소는 Entity, Attribute, Relationship 
  • 확장하여 Weak Entity, Multivalued Attribute, Weak Relationship 이 있다.

     

Entity

  • Entity는 관리하고자 하는 정보의 실체이며, 사람, 객체 혹은 개념이라고 이해하면 된다.
  • 데이터베이스를 설계할때, 쉽게는 테이블이 Entity로 정의될 수 있다.
  • 모든 Entity는 하나 이상의 식별자 (UID)를 지녀야 하며, UID가 없다면 Entity라고 할 수 없다.
  • 존재하는 다른 Entity에 의존적인 Entity를 Weak Entity라고 한다.

 

 

Attribute

  • Attribute는 Entity를 구성하고 있는 구성 요소이다.
  • 데이터 타입을 반드시 같이 명시해줘야 한다.

  • Key Attribute : 다른 객체들과 중복되지 않는 고유한 값을 가진 Attribute로, 객체를 식별하는 데 사용된다.
  • Composite Attribute : 독립적인 Attribute들이 모여서 생성된 Attribute를 의미한다.
  • Multi-Valued Attribute : 하나의 Attribute가 여러개의 값을 가지는 Attribute를 의미한다.
  • Derived Attribute : 이는 다른 Attribute가 갖고 있는 값으로부터 유도된 속성을 의미한다.

 

Relationship

  • Entity간의 관계(상호작용)를 의미한다.
  • 두 Entity간에 선을 긋고, 관계 명칭을 기록하게 된다.
  • 선택 사항을 표시한다.
    • 점선은 선택적인 사항을 의미한다. 예를 들어, 사원과 부서 Entity가 있을때 부서 입장에서는 사원을 배치 받을수도, 받지 않을 수도 있다.
    • 실선은 필수적인 사항을 의미한다. 사원 입장에서는 부서가 필수적으로 배정받아야 한다.
  • 관계 형태를 표시한다.
    • 삼지창 모양은 하나 이상을 의미한다.
    • 단선은 하나를 의미한다. 부서는 여러명의 사원을 가질 수 있으나, 사원은 하나의 부서에만 배치된다.

 

Cadinality and Ordinality

  • Entity들 간의 관계에 대한 추가 정보
  • One to many, many to many 관계를 나타낼 수 있음

여러 기호들로 관계를 표현할 수 있으나, 기호들만 숙지하여도 충분히 표현이 가능하다.

 

 

 

2. ERD 설계 사이트

https://www.erdcloud.com/

 

ERDCloud

Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool.

www.erdcloud.com

 

위의 링크에서 구현할 코드의 ERD를 만들 수 있다.

아래 다이아그램은 이번 주특기 심화주차 레벨2 ERD를 설계한 모델인데, 확실히 ERD를 통해 직관적으로 테이블의 연관관계를 파악할 수 있다.

 

 

 

 

3. IntelliJ 에서 작성한 ERD 확인 하는법

 

 

  • 위와 같이 Show Entity Relationship Diagram 을 클릭하면 아래와 같이 작성한 코드의 테이블 관계를 확인 할 수 있다.

 

 

4. [DATABASE] 식별과 비식별 관계

  • 기본키(PK) :  테이블의 하나의 행의 여러 정보들 중 이를 식별해 낼 수 있는 정보
  • 외래키(FK) : 테이블간의 관계(참조하는 테이블과 참조되는 테이블 간의 관계)를 나타내는 정보
  • 외래키를 사용하여 참조하고 참조되는 두 테이블간의 관계에 따라 식별관계와 비식별관계로 나눌 수 있다.

 

식별관계 : 식별관계는 실선으로 나타내 준다.

  • 상품과 주문의 다대다 관계의 두 테이블이 있다. 상품 테이블에서는 상품번호가 기본키이고 주문테이블은 주문번호가 기본키이다.
  • 상품과 주문테이블 사이에 주문_상품 테이블을 만들어 일대다 관계로 연결하면 아래와 같다.
  • 상품테이블과 주문테이블의 기본키인 상품번호와 주문번호가 주문상품 테이블의 외래키가 되었다.
  • 그리고 이 두 외래키는 주문상품테이블의 정보를 식별할 수 있는 기본키(2개이상의 컬럼도 기본키로 구성될 수 있다.)의 역할도 하게된다. 이러한 관계를 식별관계라고한다.

 

식별관계에 대해 정리를 해보자면

  • 부모테이블(상품, 주문테이블) 기본키(PK)가 자식 테이블(주문_상품)의 외래키이자 기본키로 사용되는 관계이다.
  • 자식 테이블의 행(정보)를 추가할 때 부모테이블의 참조 행(상품번호 또는 주문번호)이 없다면 자식테이블의 행을 추가 할 수 없다.
    : 주문_상품테이블은 상품번호와 주문번호 중 하나라도 없다면 기본키를 만들 수 없게 되고(두개의 외래키가 합쳐 기본키가 되므로) 기본키가 없어 정보를 식별할 수 없으므로 데이터를 넣을 수 없다.
    : 예를 들면 게시판의 작성글과 댓글의 관계를 식별관계라고 할 수 있다.(작성글이 없다면 댓글도 없다)

 

비식별관계 : 비식별관계는 점선으로 표시한다.

 

  • 부모 테이블을 참조한 테이블에서 참조된 외래키가 기본키가 아닌 일반속성(컬럼)으로 참조되었을 때를 말한다.
  • 위의 그림의 주문_상품테이블에 정보를 식별할 수 있는 기본키를 추가하면 다음과 같다.
  • 주문상품번호라는 기본키를 추가하였다. 주문상품번호로 주문_상품테이블의 정보들을 식별할 수 있게 되고 외래키(상품번호와 주문번호)는 테이블의 일반속성이 되었다.

 

 

비식별관계에 대해 정리하면

  • 부모 테이블(상품, 주문테이블) 기본키가 자식 테이블(주문_상품테이블)의 일반컬럼이나 외래키(Foreign Key) 컬럼에 저장되는 관계이다.
  • 자식 테이블의 행(정보)를 추가할 때 부모테이블의 참조 행(상품번호 또는 주문번호)이 없어도 자식테이블의 행을 추가 할 수가 있다.
    : 예를 들면 회사의 부서와 사원의 관계를 비식별관계라고 할 수 있다. (사원이 부서가 배정되지 않을 수도 있으므로)

여기서 하나 참고할 부분에 대해 말하자면 위의 그림에서 비식별관계는 주문상품번호라는 기본키를 임의로 추가하여 만들었다. 이렇게 추가한 키를 인조키라고 하는데 기본키를 인조키로 설정하는 것이 권장된다.
이유는 식별관계를 나타내는 그림에서 보면 상품번호와 주문번호 두개의 키가 주문상품테이블의 기본키로 되어있다. 기본키는 최대한 변하지 않는 값이어야하는데 어떤이유에서 상품번호 또는 주문번호가 변경이 된다던지 사용을 할 수 없게 된다면 데이터 구조를 다시 만들어야하는 경우가 발생하기 때문이다.

 

[참고 자료]

'Coding > Spring' 카테고리의 다른 글

[26] OAuth / 소셜 로그인  (0) 2022.12.14
[25] JPA 다양한 연관관계 매핑  (0) 2022.12.13
[23] Spring Security  (0) 2022.12.13
[22] 항해99 주특기 숙련주차 시험 Spring  (0) 2022.12.08
[21] ORM, JPA, Spring Data JPA  (0) 2022.12.08

Spring Security

① Spring Security 란?

'Spring Security' 프레임워크는 스프링 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어 준다. 마치 '스프링' 프레임워크가 웹 서버 구현에 편의를 제공해 주는 것과 같다.

더보기

Spring Boot automatically:

  • Enables Spring Security’s default configuration, which creates a servlet Filter as a bean named springSecurityFilterChain. This bean is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the login form, and so on) within your application.
  • Creates a UserDetailsService bean with a username of user and a randomly generated password that is logged to the console.
  • Registers the Filter with a bean named springSecurityFilterChain with the Servlet container for every request.

 

② 스프링 시큐리티 적용하는 방법

  • build.gradle에 스프링 시큐리티 프레임워크 추가
// 스프링 시큐리티
implementation 'org.springframework.boot:spring-boot-starter-security'
  • WebSecurityConfig (springboot 2.7이상) 파일로 스프링 시큐리티 활성화 하기
package com.sparta.springsecurity.config;


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.web.SecurityFilterChain;

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

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

        // 로그인 사용
        http.formLogin();
        
        return http.build();
    }

}

 

③ CSRF(사이트 간 요청 위조, Cross-site request forgery)

  • 공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것
  • CSRF 설정이 되어있는 경우 html 에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 가능
  • 쿠키 기반의 취약점을 이용한 공격 이기 때문에 REST 방식의 API에서는 disable 가능
  • POST 요청마다 처리해 주는 대신 CSRF protection 을 disable 

 

Spring Security 주요 컴포넌트

① Spring Security 와 Filter

  •  Spring Security는 요청이 들어오면 Servlet FilterChain을 자동으로 구성한 후 거치게 한다.
  • FilterChain은 여러 Filter를 chain형태로 묶어놓은 것을 의미
  • 여기서 Filter 란, 톰캣과 같은 웹 컨테이너에서 관리되는 서블릿의 기술이다.
  • Filter는 Client 요청이 전달되기 전후의 URL 패턴에 맞는 모든 요청에 필터링을 해준다. CSRF, XSS 등의 보안 검사를 통해 올바른 요청이 아닐 경우 이를 차단해 준다. 따라서 Spring Security는 이런한 기능을 활용하기위해 Filter를 사용하여 인증/인가를 구현하고 있다.

② SecurityFilterChain

  • session, jwt 등의 인증방식들을 사용하는데에 필요한 설정을 완전히 분리할 수 있는 환경을 제공한다.

 

③ AbstractAuthenticationProcessingFilter : 사용자의 credential을 인증하기 위한 베이스 Filter

 

 

④ UsernamePasswordAuthenticationFilter

  • UsernamePasswordAuthenticationFilter 는 AbstractAuthenticationProcessingFilter를 상속한 Filter다.
  • 기본적으로 아래와 같은 Form Login 기반을 사용할 때 username 과 password 확인하여 인증한다.
  • Form Login 기반은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인페이지를 반환하는 형태이다.

 

⑤ SecurityContextHolder

 

  • SecurityContextHolder 에는 스프링 시큐리티로 인증을 한 사용자의 상세 정보를 저장한다.
  • SecurityContext 란? SecurityContextHolder 로 접근할 수 있으며 Authentication 객체를 가지고 있다.

Authentication

  • 현재 인증된 사용자를 나타내며 SecurityContext 에서 가져올 수 있다.
  • principal : 사용자를 식별한다. Username/Password 방식으로 인증할 때 보통 UserDetails 인스턴스다.
  • credentials : 주로 비밀번호, 대부분 사용자 인증에 사용하고 다음 비운다.
  • authorities : 사용자에게 부여한 권한을 GrantedAuthority 로 추상화하여 사용한다.
  • UsernamePasswordAuthenticationToken는 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용된다.

UserDetailsService : username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환한다. Custom하여 Bean으로 등록 후 사용 가능하다.

 

검증된 UserDetails : UsernamePasswordAuthenticationToken 타입의 Authentication를 만들 때 사용되며 해당 인증객체는 SecurityContextHolder에 세팅된다. Custom하여 사용가능하다.

 

 

Spring 다들 너무 열심히 하는거 아니냐구요 ~_~ ㅎㅎ

 

 

 

1. 어려웠던 부분  : 이번주의 키워드는 인증 인가에 대한 개념과 연관관계였다. JWT 토큰을 이용해 게시글 수정과 삭제하는 기능 구현까지는 어찌저찌 됐는데, 게시글에 댓글까지 추가기능으로 넣으면서 연관관계까지 생각해야 하는 부분이 어려웠다. 반 사람들의 깃헙을 보며 다들 어떻게 코드를 짰는지 봤는데, 사람마다 각기 다른 코드를 구현하는게 신기하면서도 부럽기도하고, 난 아직도 참조변수가 어쩌고 저쩌고 매개변수가 어쩌고 저쩌고를 잘 이해하고 있지 않는 것 같아서 다시 기본기부터 시작해야 할 것 같다는 생각이 들었다.

 

2. 느낀 점 : 아직 스프링을 배운지 2주밖에 되지 않았으니, 모든게 어려운게 당연하다. 우리반에서 내 기준 잘하시는 분들이 더 늦게까지 열심히 공부하시는 모습을 보고 뭔가 반성하게되고 동기부여도 되는 한주였다. 이제 진짜 마지막주차밖에 안남았으니 이번주는 최대한 잡담을 줄이고 공부에 매진해야겠다.

 

3. 새로 알게 된 내용 : 인증과 인가의 차이점, 그리고 쿠키/세션과 JWT 차이점, 테이블 연관관계 맺는 방법, 의존성주입과 제어의 역전에 대한 내용을 공부한 한 주 였다. 정규식에 대한 내용도 찍먹해봤지만 고 부분은 그냥 그때 그때 다시 공부해야 할 것 같다. 김민지 기술매니저님의 블로그 글 덕분에 생성자 자동완성 어노테이션 세가지도 개념이 더 정리된 것 같다.

 

4. 셀프칭찬 (이번주 잘한 일) : 갑자기 난이도가 껑충 뛴 느낌이다. 직접 코드를 작성하진 못했지만, 그래도 여러 사람의 코드를 하나씩 다 뜯어보고 조합해서 내가 이해할 수 있는 나만의 코드로 다시 작성해 과제2를 구현한 부분을 칭찬하고 싶다. 언젠간 나도 다른분들처럼 스스로 코드를 작성할 수 있는 날이 오기를.

 

5. 이번주 할 일 : 스프링 시큐리티 개념 정리 + 과제 구현, JAVA 언어스터디, 연관관계 다시 공부하기. 

 


[이번주 공부한 부분 링크 정리]

 

<Spring>

[10] Spring Boot 어노테이션 정리

[11] Database 와 SQL

[12] 정규식(regex, rational expression)

[13] @Valid, @Validated (작성중. 수정필요)

[14] JPA (1)

[15] JPA (2) 심화

[16] IntelliJ 단축키 모음

[17] 숙련주차 과제 (개념 부분 - 키워드 정리)

[18] 인증과 인가 (1) 세션/쿠키, JWT

[19] 스프링 프레임워크

[20] 의존성 주입 DI(Dependency Injection)

[21] ORM, JPA, Spring Data JPA

[22] 항해99 주특기 숙련주차 시험 Spring

 

<JAVA>

[24] JAVA 타입 변환과 다형성

[25] JAVA 중첩 클래스/ 중첩 인터페이스

[26] JAVA 익명 객체 (Anonymous)

 

<기타>

이번주 내로 끝내야할 필수 개념들 ( 정리하고 갈게요 )

[07] 미니프로젝트 사용 함수, 새 개념 정리

+ Recent posts