Backend 11

spring boot : entity <-> dto 변환 방법에 대한 고민( MapStruct 에 대해)

개요프로젝트를 진행하며 여러 layer사이에 데이터를 전달할 때, dto, entity 간 변경이 자주 일어나는 상황에 변환하는 코드를 일일이 적어넣는 것이 불편했습니다.   예시로 보면, member  한 명을 생성하는 post api는 다음처럼 작성되어 있었습니다.  @Controller@RequiredArgsConstructorclass MemberController { private final MemberService memberService; @PostMapping() public Member createMember(@RequestBody MemberDto memberDto){ //dto 사용 Member member = memberService.createM..

Backend/spring boot 2024.10.09

spring security : refresh 토큰 구현(redis 활용)

jwt 토큰을 통해 로그인을 구현하면 세션에 비해 서버에 부담이 적고, 확장하기도 편리하다는 장점이 있다. 하지만 온전히 사용자가 보내는 http 메시지에 담긴 토큰을 기반으로 서버가 유저를 판단하기 때문에, 이 토큰이 탈취당하면 탈취자를 사용자로 오인하게 되어 매우 위험하다. 프로젝트에서 이를 극복하기 위해 refresh 토큰을 도입했다. Refresh Token 이란? 이전에 작성한 jwt토큰을 이용한 로그인 방식은 엄밀히 보면 access를 위한 토큰이라 볼 수 있다. 그래서 사람들은 보통 이 토큰을 access token이라 지정하는 경우도 많다. 문제는 이 토큰이 탈취당하면 리스크가 크다는 점인데, 이는 access 토큰의 유효시간을 짧게 설정해서 보완할 수 있다. 유효시간이 짧다면 공격하는 사..

spring security : jwt를 이용한 로그인 구현[2]

이전 과정을 거쳤다면 다음으로 accessDeniedHandler와 authenticationEntryPoint를 커스터마이징하는 것이다. 기본적으로 제공되지만 인증, 인가가 실패했을 때 서버와 클라이언트에서 더 명확하게 판단할 필요가 있었기에 직접 작성해야했다. 먼저 CustomAccessDeniedHandler이다. CustomAccessDeniedHandler.java @Component public class CustomAccessDeniedHandler implements AccessDeniedHandler { private final Logger log = LoggerFactory.getLogger(CustomAccessDeniedHandler.class); @Override public vo..

spring security : jwt를 이용한 로그인 구현[1]

프로젝트를 하면서, 로그인을 구현해야하는 단계에 왔을 때, sns로그인을 이용해 간단하게 넘길지 아니면 직접 구현할지 팀원과 의논했다. spring security는 강의에서도 생각보다 자세하게 다루지 않아, 깊게 공부하려면 아예 따로 spring security강의를 찾거나 레퍼런스를 뒤지면서 처음부터 공부해야했다. 그래도 이왕 하는 김에, 처음부터 머리박으면서 구현해보는게 좋겠다는 생각으로 뛰어들었다. 로그인을 구현할 때, 먼저 세션과 토큰 방식 중 선택해야했다. 두 방식의 차이점은 크게 보면 세션은 유저 정보가 서버에 저장되고, 토큰은 유저 정보를 클라이언트에서 보낸다는 점이다. 우리는 토큰 방식을 선택했는데, 이는 다음과 같은 이유에서 였다. 1. 세션같은 경우, 유저 정보를 서버가 저장한다. 유..

spring boot jpa : soft delete 구현 (delete 후 데이터 복원)

데이터를 삭제할 때 DB에서 완전히 삭제되는 방식은 사실 프로젝트를 운영해 나갈 때 좋은 방식이 아니다. 누군가 데이터를 실수로 삭제했을 때 복구하려면 DB에 어떤 방식이든 데이터를 남겨둬야 했다. 그렇기에 데이터를 복구하는 방법을 찾아보니, soft delete라는 방식을 통해 데이터 삭제를 하는 방법이 있었다. soft delete란? 데이터를 삭제할 때 두 가지 방식 중 하나다. hard delete, soft delete가 있다. hard delete : 실제로 db에 delete쿼리를 날려 데이터를 삭제하는 것. soft delete : 실제로 삭제하는 것이 아니라, 테이블에 deleted_check 같은 필드를 추가해서 그 데이터가 삭제처리 되면 삭제가 아니라 deleted_check만 바꿔주..

Backend/spring boot 2023.09.06

spring boot jpa : hibernate delete 쿼리가 실행되지 않는 현상

프로젝트를 하면서, 게시글이나 유저 정보를 delete해야 하는 경우가 있었다. delete 자체는 jpa를 이용하면 간단하게 구현했었고 테스트도 항상 통과했었는데, 문제가 생겼다. 다음은 게시글 삭제를 위한 boardService의 deleteBoard 메서드이다. @Override @Transactional // @PreAuthorize("hasAuthority('ADMIN') or #board.author.username == authentication.principal.username") //hasAuthority를 사용해야 함.여기서 hasRole은 단지 문자열 비교로 public void deleteBoard(Long id, HttpServletRequest request) { //권한을 확인..

Backend/spring boot 2023.08.31

spring boot에서 DTO를 엔티티로 변환할 때 연관관계에 있는 엔티티와 연결하기

서비스 레이어로 request요청한 dto를 가져올 때 마주친 문제가 있었다. 예시로 가져온 이 클래스는 댓글관련 요청을 위한 RequestCommentDto이다. @Data @Builder @NoArgsConstructor @AllArgsConstructor @ToString public class RequestCommentDto { private Long user_id; private Long board_id; private String text; public Comment toEntity(){ return Comment.builder .text(text) //문제의 부분. .build(); } public RequestCommentDto(Comment comment){ this.user_id = c..

Backend/spring boot 2023.08.15

외부에서 spring boot 서버에 접속 해보기(접속 안 될 때 이슈, sk 브로드밴드 포트포워딩)

프로젝트를 진행하던 중, 프론트 팀원으로부터 한 번 열린 서버를 통해 테스트해보려 한다는 이야기를 듣고 외부에서 접속을 위한 준비를 했다. 포트포워딩을 하는 과정과, 그 과정에서 발생한 이슈들을 이야기 하려한다. 내 로컬 컴퓨터에서 실행되는 애플리케이션 서버에 접속하기 위해서는 당연히 내 컴퓨터의 주소를 알아야 할 것이고, 주소를 알고 pc로 찾아왔다면 그 다음에는 spring이 실행 중인 애플리케이션 포트 위치를 알아야 할 것이다. 먼저 아이피 확인을 위해 cmd창을 켜 ipconfig/all을 입력했다. ipv4 부분을 내 컴퓨터가 할당받은 내부 ip로, 이를 이용해 포트포워딩을 진행하려 한다. 우리집 공유기는 sk 브로드밴드를 사용하고 있다. 포트포워딩을 위해 기본 게이트 웨이 ip를 이용해 브라우..

Backend/spring boot 2023.08.11

spring boot 사이드 프로젝트 : service 테스트

이번에는 service 레이어를 테스트했던 방법을 작성해봤다. 1. Entity @Entity @Builder @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Table(name = "board") //테이블과 매핑 public class Board extends BaseEntity { @Column(nullable = false) private String type; @Column(nullable = false) private String title; @Column(nullable = false) private String text; @Column(nullable = false) private String proceed_method; //진행 방식 @..

Backend/spring boot 2023.07.12

spring boot JPA : 컬렉션 형태의 데이터를 저장하기(@ElementCollection)

데이터베이스에 단일값이 아닌 컬렉션 형태(list 같은) 값을 넣는 것은 RDB에서 허용되지 않는다. 이 때문에 컬렉션 형태의 값이 필요하다면, 추가적인 테이블을 만든 뒤 그 테이블과 연관관계를 형성하는 방법을 사용해야 한다. 이 때 사용되는 방법이 @ElementCollection을 사용하는 것이다. @ElementCollection public class Post extends BaseEntity { @Column(nullable = false) private String type; @Column(nullable = false) private String title; @Column(nullable = false) private String text; @Column private String proce..

Backend/spring boot 2023.06.17