Weekly devIL 5

임선용·2022년 6월 12일
0

Lombok, DTO

Lombok

어노테이션을 통해 코드를 줄일 수 있다

ex) getter, setter생성 / 기본생성자 자동생성 / 매개변수 자동선언

// 생성자를 통해, Service 클래스를 만들 때 꼭 Repository를 넣어주도록 스프링에게 알려줌
public BoardService(BoardRepository boardRepository){
    this.boardRepository = boardRepository;
}

@RequiredArgsConstructor // 자동으로 위의 과정 실행

DTO

== VO (Value Object)

DTO(Data Transfer Object)는 프로젝트 전반에서 해당 클래스의 데이터를 가지고 다니는 오브젝트이다
특히 DTO로 Http 요청과 응답시 Body의 Json을 직병렬화하여 쉽게 주고 받을 수 있다

API

👉 클라이언트 - 서버 간의 약속입니다.
클라이언트가 정한대로 서버에게 요청(Request)을 보내면, 서버가 요구사항을 처리하여 응답(Response)을 반환합니다.

Rest

👉 REST란, 주소에 명사, 요청 방식에 동사를 사용함으로써 의도를 명확히 드러냄을 의미합니다.

  • 여기에 쓰이는 동사는 우리가 JPA 시간에 배운 CRUD를 지칭합니다.
  • 즉 A에 대해 생성(POST)/조회(GET)/수정(PUT)/삭제(DELETE) 요청을 하는 것이죠.
  • 예시
    • GET /courses → 강의 전체 목록 조회 요청
    • GET /courses/1 → ID가 1번인 녀석 조회 요청
    • POST /courses → 강의 생성 요청
    • PUT /courses/3 → ID가 3번인 녀석 수정 요청
    • DELETE /courses/2 → ID 2번인 녀석 삭제 요청

Rest API 설계 규칙

https://duckgugong.tistory.com/301

GET

@GetMapping("/api/boards")
    public List<Board> getBoards(){
        return boardRepository.findAll();
    }

POST

@RequestBody POST의 특성 상 url에 데이터가 담기는 것이 아니라 body에 담긴다

@PostMapping("/api/boards")
public Board createBoard(@RequestBody BoardDTO boardDTO) {
    // BoardDTO 는, 생성 요청을 의미합니다.
    // 강의 정보를 만들기 위해서는 강의 제목과 튜터 이름이 필요하잖아요?
    // 그 정보를 가져오는 녀석입니다.

    // 저장하는 것은 DTO가 아니라 Board이니, DTO의 정보를 Board에 담아야 합니다.
    // 잠시 뒤 새로운 생성자를 만듭니다.
    Board board = new Board(boardDTO);

    // JPA를 이용하여 DB에 저장하고, 그 결과를 반환합니다.
    return boardRepository.save(board);
}

PUT

@PathVariable로 url의 변수와 이름이 같은 변수를 할당한다

@PutMapping("/api/boards/{id}")
public Long updateBoard(@PathVariable Long id, @RequestBody BoardDTO boardDTO){
    return boardService.update(id, boardDTO);
}

DELETE

@DeleteMapping("/api/boards/{id}")
public void deleteBoard(@PathVariable Long id){
    boardRepository.deleteById(id);
}

JPA - 연관관계 설정

https://velog.io/@devsh/JPA-연관-관계-매핑-OneToMany-ManyToOne-OneToOne-ManyToMany
https://ict-nroo.tistory.com/122
https://cjw-awdsd.tistory.com/47
https://www.youtube.com/watch?v=brE0tYOV9jQ - 백기선 강사님 영상1
https://www.youtube.com/watch?v=hsSc5epPXDs - 백기선 강사님 영상2

방향(Direction) : [단방향, 양방향]이 있다.
예를 들어 회원과 팀이 관계가 있을 때 회원 -> 팀 또는 팀 -> 회원 둘 중 한 쪽만 참조하는 것을 단방향 관계라 하고, 회원 -> 팀, 팀 -> 회원 양쪽 모두 서로 참조하는 것을 양방향 관계라 한다. 방향은 객체관계에만 존재하고 테이블 관계는 항상 양방향이다.

다중성(Multiplicity) : [다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)] 다중성이다. 예를 들어 회원과 팀이 관계가 있을 때 여러 회원은 한 팀에 속하므로 회원과 팀은 다대일 관계다. 반대로 한 팀에 여러 회원이 소속될 수 있으므로 팀과 회원은 일대다 관계다.

연관관계의 주인(Owner) : 객체를 양방향 연관관계로 만들면 연관관계의 주인을 정해야 한다.

- 양방향 매핑시 가장 많이 하는 실수

  1. 연관관계의 주인에 값을 입력하지 않음.
  2. mappedBy 에 필드 값을 수정하는 것.
  3. 이 필드는 읽기 전용이 되는 것을 꼭 명심해야 함.
  4. 양방향 매핑시에 무한 루프 조심, toString, lombok, JSON 생성 라이브러리
  5. 스프링 부트는 컨트롤러 레이어에서 유저로 데이터를 반환할 때 @ResponseBody 로 반환하는 경우 Json 파싱을 하게 되는데 이 때 Jackson 라이브러리를 사용합니다. 만약 엔티티를 컨트롤러에서 사용하게 되면 무한 참조가 발생하게 됩니다. 처리하는 방법은 @JsonIgnore 나 엔티티를 사용하지 않는 방식이나 일반적으로 엔티티를 사용하지 않고 DTO 로 변환해서 사용하는 것이 매우 매우 매우 권장됩니다.

@ManyToOne

N:1 관계를 표현하는 어노테이션이다. @ManyToOne이 붙은 엔티티가 N이고 반대 엔티티가 1이다.

@OneToMany

1:N 관계를 표현하는 어노테이션이다. @OneToMany가 붙은 엔티티가 1이고 반대 엔티티가 M이다.

@OneToMany 속성

  • mappedBy = "반대쪽 매핑의 필드 이름값"
    • 양방향 매핑일 때 사용한다

mappedBy의 필요성

양방향 매핑에서 객체는 서로 다른 단방향 2개로 이루어져있기 때문에, 2개의 연관관계 ID가 필요하게 된다.
즉, 외래키 2개를 관리해야 하는 상황에 관계형 데이터베이스는 외래키 1개를 가지고 관리하기 때문에,
JPA는 두개의 연관관계중 하나를 고르게 하기 위해 mappedBy를 설정한다.
여기서 관리되는 연관관계를 연관관계의 주인이라 한다.
다시 말해 mappedBy가 없는 엔티티(외래키가 생성되는 엔티티, @ManyToOne 어노테이션이 붙은 엔티티)가 연관관계의 주인이다.

연관관계주인 방향에서 데이터를 입력하면 연관관계 주인이 아닌 엔티티에 데이터를 넣지 않아도 데이터베이스에는 정상적으로 들어간다. (mappedBy로 매핑되어 알아서 데이터가 들어가기때문에, 연관관계 주인인 엔티티에만 데이터를 넣어주면 된다)

@JoinColumn(name="")

외래키를 정의하는 어노테이션이다.

Cascade 옵션

https://velog.io/@max9106/JPA엔티티-상태-Cascade

Entity의 상태

  1. Transient: 객체를 생성하고, 값을 주어도 JPA나 hibernate가 그 객체에 관해 아무것도 모르는 상태. 즉, 데이터베이스와 매핑된 것이 아무것도 없다.
  2. Persistent: 저장을 하고나서, JPA가 아는 상태(관리하는 상태)가 된다. 그러나 .save()를 했다고 해서, 이 순간 바로 DB에 이 객체에 대한 데이터가 들어가는 것은 아니다. JPA가 persistent 상태로 관리하고 있다가, 후에 데이터를 저장한다.(1차 캐시, Dirty Checking(변경사항 감지), Write Behind(최대한 늦게, 필요한 시점에 DB에 적용) 등의 기능을 제공한다)
  3. Detached: JPA가 더이상 관리하지 않는 상태. JPA가 제공해주는 기능들을 사용하고 싶다면, 다시 persistent 상태로 돌아가야한다.
  4. Removed: JPA가 관리하는 상태이긴 하지만, 실제 commit이 일어날 때, 삭제가 일어난다.

cascade는 이러한 상태변화를 전이시키는 것이다.

여러 Entity의 @GeneratedValue

과제 프로젝트를 진행하며 두 개의 Entity를 구성하였고,
두 개의 Entity 모두 Long 타입의 id를 PK로 갖는다

문제

  • 두개의 Entity의 id를 GenerationType.AUTO로 생성해줬더니 생성되는 숫자가 테이블 간에 공유가 됐다
    예를들면, 테이블1에서 1,2,3,4 까지의 id를 생성하고 테이블2에서 id를 생성하면 5부터 생성된다

원인

  • GenerationType.AUTO는 서버에서 생성해 DB에 전달 해주기 때문에, 테이블마다 별개로 인식하지 않는다

      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;

해결

  • 첫 번째 방법은 @SequenceGenerator로 자동으로 하나씩 커지는 숫자를 생성해 주는 것이었다

  • 그리고 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GENERATOR")를 사용하여 생성한 @SequenceGenerator를 사용했다

    @SequenceGenerator(
    name = "BOARD_SEQ_GENERATOR",
    sequenceName = "BOARD_SEQ",
    initialValue = 1,
    allocationSize = 1
    )
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GENERATOR")
    private Long id;

  • 두 번째 방법이 간단하고 효율적이었는데, GenerationType.IDENTITY를 사용하는 것이다

  • GenerationType.IDENTITY는 DB에서 생성하는 것이기 때문에 테이블마다 별개로 생성되어,
    모든 테이블의 id가 1부터 시작하는 값을 갖는다

  • 기술 매니저님의 말로는 현업에서도 GenerationType.IDENTITY를 많이 사용한다고 하셨다

      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;

보안

XSS [ Cross-site Scripting ]

저장형 XSS(Stored Cross Site Scripting) 공격과 방어 - Junhyunny’s Devlogs

반사형 XSS(Reflected Cross Site Scripting) 공격과 방어 - Junhyunny’s Devlogs

DOM 기반 XSS(DOM based Cross Site Scripting) 공격과 방어 - Junhyunny’s Devlogs

주로 다른 웹사이트와 정보를 교환하는 식으로 작동하므로 사이트 간 스크립팅이라고 한다

SQL injection과 함께 웹 상에서 가장 기초적인 취약점 공격 방법의 일종으로, 악의적인 사용자가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽입된 코드를 실행하게 되며, 보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다.

크로스 사이트 스크립팅이란 이름 답게, 자바스크립트를 사용하여 공격하는 경우가 많다. 공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방어 조치를 해두지 않아 공격을 받는 경우가 많다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파된다. 심지어는 닉네임에 코드를 심기도 한다.

주로 CSRF를 하기 위해서 사용되기 때문에 종종 CSRF와 혼동되는 경우가 있으나, XSS는 자바스크립트를 실행시키는 것이고, CSRF는 특정한 행동을 시키는 것이므로 다르다.

Stored XSS (저장형 XSS)

  • 보안이 취약한 서버에 해커가 악성 스크립트를 저장함으로써 발생한다.

Reflected XSS (반사형 XSS)

  • 해커가 보안이 취약한 사이트를 통해서 악성 스크립트를 넣은 URL을 만들어 일반 사용자에게 스팸 메일로 전달한다.

DOM 기반 XSS

  • 보안에 취약한 JavaScript 코드로 DOM 객체를 제어하는 과정에서 발생합니다.

XSS 방어방법

스크립트를 실행시키지 않는 방법을 이용한다

저장형 XSS 방어

  1. 사용자 입력 검증 및 변경

    • 사용자가 입력한 값을 그대로 저장하지 않습니다.

    • 태그를 만들 때 사용하는 <, >을 HTML에서 사용하는 특수 문자로 변경합니다.

  2. 문자열 그대로 출력 (스크립트가 실행되지 않음)

반사형 XSS 방어

  1. 입력 값 제한
    • 브라우저에서 사용자 입력 시 특수 문자를 제한합니다.
  2. 입력 값 치환
    • 악성 스크립트를 만들 수 있는 특수 문자들을 치환합니다. 모든 요청에 대해 치환을 적용할 수 있도록 필터를 만들어 이를 적용합니다.
  3. 문자열 그대로 출력 (스크립트가 실행되지 않음)

CSRF [ Cross-Site Request Forgery ]

CSRF(Cross-Site Request Forgery) 공격과 방어 - Junhyunny’s Devlogs

웹 애플리케이션 취약점 중 하나로 인터넷 사용자(희생자)가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격 방법이다. 공격의 난이도가 높지 않아 흔히 사용된다

CSRF를 통해 해커는 희생자의 권한을 도용하여 중요 기능을 실행하는 것이 가능합니다. CSRF는 해커가 사용자의 컴퓨터를 감염시키거나 페이스북 서버를 해킹을 해서 이뤄지는 공격은 아니고, 클라이언트의 세션과 쿠키에 저장된 회원정보를 탈취하여 악용하는 것이다.

그래서 CSRF 공격이 이뤄지려면 다음 조건이 만족되어야 합니다.

  1. 위조 요청을 전송하는 서비스(페이스북)에 희생자가 로그인 상태
    (=> Stateful 한 서비스를 제공하기 위해 인증된 사용자 정보를 세션에 저장하고, 세션 ID가 쿠키에 저장되기 때문에 문제가 발생)

  2. 희생자가 해커가 만든 피싱 사이트에 접속

또한 희생자가 해커가 만든 피싱 사이트를 하지 않더라도 해커가 XSS 공격을 성공한 정상 사이트를 통해 CSRF 공격이 수행 될 수 도 있습니다.

CSRF 방어방법

탈취된 개인 정보인지 아닌지 확인하는 방법을 사용한다 (보낸 사람의 개인 정보가 맞는지 확인)

일반적으로 CSRF 공격 방어는 조회성(HTTP GET Method) 데이터에는 방어 대상에 두지 않고, 쓰기/변경이 가능한 POST, PATCH, DELETE Method에만 적용하면 됩니다.

  1. Referrer 검증

    • 서버에서 사용자가 요청한 헤더 정보에서 Referrer 확인 (host와 Referrer값이 같은지 확인)

    • Back-end 단에서 request의 referrer를 확인하여 domain이 일치하는지 검증하는 방법이다. 일반적으로 referrer 검증만으로 대부분의 CSRF 공격을 방어 할 수 있지만, 같은 도메인 내의 페이지에 XSS 취약점이 있는 경우 CSRF 공격에 취약해 질 수 있다. 이때는 domain 단위 검증에서 좀 더 세밀하게 페이지 단위까지 일치하는지 검증을 하면 도메인 내의 타 페이지에서의 XSS 취약점에 대한 CSRF 공격을 방어할 수 있다.

  2. CSRF 토큰 검증

    • 임의의 CSRF 토큰을 만들어 세션에 저장합니다. 요청하는 페이지에 hidden 타입 input 태그를 이용해 토큰 값을 함께 전달합니다. 이후 서버에서 세션에 저장된 CSRF 토큰 값과 요청 파라미터에 담긴 토큰 값을 비교합니다.

과제 제출

XSS, CSRF란 무엇이며, 어떻게 해결할 수 있는지 설명해주세요.

XSS는 저장형 XSS와 반사형 XSS가 있다.
 저장형 XSS는 보안이 취약한 서버에 해커가 악성 스크립트를 저장함으로써 발생하고, 반사형 XSS는 해커가 보안이 취약한 사이트를 통해서 악성 스크립트를 넣은 URL을 만들어 일반 사용자에게 스팸 메일로 전달하는 방식으로 작동한다.
 XSS의 방어는 "악성 스크립트를 실행시키지 않는" 방법으로 진행되는데, 스크립트에 필수적인 태그나 특수 문자들을 치환하여 저장하고 특수 문자 입력을 제한하는 등의 방법을 사용한다.

CSRF는 클라이언트의 세션과 쿠키에 저장된 회원 정보를 탈취하여 악용하는 것이다.
 세션과 쿠키에 중요한 정보가 있는 상태에서 피싱 사이트 등의 공격으로 정보를 탈취당하면,
해커는 탈취한 정보를 바탕으로 클라이언트나 서버를 공격할 수 있게 된다.
 CSRF의 방어는 "탈취 된 정보인지 아닌지 확인하는 방법을 사용한다"(보낸 사람의 개인 정보가 맞는지 확인). 이러한 방법으로는 헤더의 host와 Referrer이 같은지 확인하는 방법과, CSRF 토큰을 사용하는 방법이 있다.

CORS

Reverse Proxy & Port Forwarding

Proxy (Forward, Reverse), CORS — Duck9s' (tistory.com)

Access Token (Refresh Token)

[인증] Access Token, Refresh Token — Today Sangmin Learned (tistory.com)

팀 과제

  1. JPA가 무엇인가요?
  • JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준이며, JAVA 어플리케이션과 JDBC 사이에서 동작한다.
  • 여기서 ORM(Object-Relational Mapping)은 객체와 테이블을 매핑해서 패러다임의 불일치 문제를 개발자 대신 해결해주는 프레임워크이다.
  1. Controller, Service, Repository 가 무엇인가요?
  1. Controller
    • 사용자의 요청을 받고, 클라이언트에게 응답하는 계층.
    • 요청에 대한 처리는 서비스에게 전담한다.
  2. Service
    • 전반적인 비즈니스 로직을 수행하는 계층.
    • 사용자의 요구사항을 처리한다.
    • DB의 정보가 필요할 때는 Repositroy에게 전담한다.
  3. Repository
    • DB 관리(연결, 해제, 자원 관리)를 어떻게 할 것인지를 정의해주는 계층
  1. 우리가 브라우저에서 구매한 도메인 주소를 입력하면 만들어 놓은 aws EC2 서버까지 전달이 되어서 해당 서버에게 요청을 보낼 수 있습니다. 이 과정이 상세하게 어떻게 진행되는지 그림으로 한번 그려볼까요?

  1. 스프링 프레임워크는 어떤 특징 혹은 장점을 가지고 있나요? (3가지 이상)

스프링은 내부적으로 별도의 API를 사용하지 않고, 일반적인 Java 코드를 이용하여 객체를 구성한다. 따라서, 이 프레임워크에서는 개발자가 특정한 라이브러리나 컨테이너의 기술에 종속되지 않는다. 또한, 프레임워크이기 때문에, 개발자의 수준과 실력에 상관없이 빠른 구현과 일정 수준의 품질을 기대할 수 있다. 담당자 혹은 개발자가 도중에 바뀌더라도, 유지보수에 관한 리스크를 줄일 수 있다.

  1. 스프링에서 DI (의존성 주입) 를 사용하는 이유가 무엇인가요? 예를 통해 설명 해 보세요?

의존 관계 주입(Dependency Injection)이란 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는게 아니라, 주입 받아 사용하는 방법이다. (new 연산자를 이용해서 객체를 생성하는 것이라고 생각하면 된다)

제어의 역전 (Inversion of Control)은 IoC Container에게 모든 관계 설정에 대한 책임을 위임하는 것이다

#제어의 역전을 한마디로 표현
"Don't call us, we'll call you"

즉, 각 객체간의 의존성을 스프링 컨테이너(Spring Container)가 자동으로 연결해주는 것으로, 개발자가 빈(Bean) 설정파일에 의존관계가 필요한 정보를 추가해주면, 스프링 컨테이너가 자동적으로 연결해 준다 의존성이란 한 객체가 다른 객체를 사용할 때 의존성이 있다고 한다.

  • DI와 IOC를 적용하지 않았을 때의 객체 관계

  • DI와 IOC를 적용했을 때의 객체 관계

  1. 스프링 시큐리티를 사용해 회원관리하는 방법을 순서도를 통해 정리해 보세요.

회원관리의 흐름

스프링 시큐리티
  • Client 의 요청은 모두 Spring Security 를 거침
  • Spring Security 역할
    • 인증/인가
      1. 성공 시: Controller 로 Client 요청 전달
        Client 요청 + 사용자 정보 (UserDetails)
      2. 실패 시: Controller 로 Client 요청 전달되지 않음
        Client 에게 Error Response 보냄
  1. 개발자 테스트 코드 작성 시 장/단점과 테스트 종류 별 (단위 테스트, 통합 테스트, E2E 테스트) 로 특징은?
  1. 테스트 코드의 장단점
    • 장점: 예상 동작과 실제 동작을 비교하여 빠르고 정확한 테스트가 가능하기 때문에 초기 개발의 디버깅이 쉬워진다.
    • 단점: 테스트 코드까지 작성해야 하기 때문에 개발 시간이 오래 걸린다.
  2. 단위 테스트
    • 단위 테스트는 응용 프로그램에서 테스트 가능한 가장 작은 소프트웨어를 실행하여 예상대로 동작하는지 확인하는 테스트이다.
    • 일반적으로 클래스 또는 메소드 수준의 단위로 테스트한다.
    • 단위 테스트는 TDD와 함께 할 때 특히 더 강력해진다.
  3. 통합 테스트
    • 통합 테스트는 단위 테스트보다 더 큰 동작을 달성하기 위해 여러 모듈들을 모아 이들이 의도대로 협력하는지 확인하는 테스트이다.
    • 단위 테스트와 달리 개발자가 변경할 수 없는 부분(외부 라이브러리 등) 까지 묶어 검증할 때 사용한다.
    • 스프링부트 에서는 @SpringBootTest
  4. E2E 테스트
    • E2E(End to End)테스트는 개발물을 사용자 관점에서 테스트하는 방법이다.
    • 다양한 시스템, DB 등 앱의 올바른 작동을 사용자 관점에서 확인한다.
    • 다양한 앱의 의존관계가 정확히 작동하는지 확인한다.
  1. ORM, JPA, Spring Data JPA 를 구분해서 설명해 보세요.

ORM(Object-Relational Mapping) - 자바 객체와 RDBMS의 데이터를 자동으로 매핑해주는 것을 의미

  • 자바의 객체 지향 기술과 관계형 DataBase를 서로 연결 해주는 추상화된 기술
  • ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치 해결
  • Object 필드와 데이터 베이스 데이터를 서로 매핑
  • 객체를 사용하여 갖접적으로 데이터베이스 데이터를 다루는 개념
  • 데이터 영속성을 위한 API(Persistant API)의 한 종류

JPA(Java Persistence API) - Java를 이용하여 데이터 관리/유지 기법을 정리해 놓은 표준 Spec

  • 데이터 베이스 관련 작업을 대신 처리해주는 추상화된 계층의 구현 스펙
  • Java의 ORM 기술에 대한 인터페이스의 모음

Spring Data JPA는 스프링 프레임워크에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트이고, 데이터 접근 계층을 개발할 때 지루하게 반복되는 CRUD 문제를 해결해준다.

  • CRUD를 처리하기 위한 공통 인터페이스를 제공한다.
  • Repository를 개발할 때 인터페이스만 작성하면 실행 시점에 구현 객체를 동적으로 생성해서 주입해준다.
  • 따라서, 구현 클래스 없이 인터페이스만 작성해도 개발을 완료할 수 있다.
profile
백엔드 개발 공부중

0개의 댓글