GlobalExceptionHandler와 CustomException으로 전역 예외 처리하기 Spring을 사용해서 웹 애플리케이션 개발을 하다 보면, 예외가 발생했을 때 예외 종류에 따라 클라이언트 측에 다른 응답을 보내줘야 한다. 이때, 일일히 Controller마다 예외 처리해서 Response를 던져주는 작업을 하게 되면 서비스가 커질수록 중복 코드가 늘어나고 유지보수가 힘들어진다. 이를 해결하기 위해 Exception Handling을 전역적으로 관리할 수 있는 방법을 알아보자 ErrorCode Enum 에러에 대해서 Response를 전달할 때, 에러 메시지를 같이 전달하게 되는데 이 때 메시지를 String 값으로 하드 코딩하게 되면 관리가 힘들어진다. 그러므로 Http 상태 코드와 메시지..
👀BCryptPasswordEncoder란? BCryptPasswordEncoder는 Spring Security 프레임워크에서 제공하는 클래스로 비밀번호를 암호화(해시)하는 데에 사용한다. 해시 함수에는 MD5나 SHA 등의 종류가 있지만 BCrypt는 단순히 입력을 1회 해시시키는 것이 아니라 솔트(salt)를 부여하여 여러번 해싱하므로 더 안전하게 암호를 관리할 수 있다. BCrypt는 같은 비밀번호를 암호화하더라도 해시 값은 매번 다른 값이 도출된다. 따라서 BCryptPasswordEncoder에서는 사용자가 제출된 비밀번호와 암호화되어 저장된 비밀번호의 일치 여부를 확인하는 메소드가 제공된다. BCryptPasswordEncoder는 BCrypt의 로그 라운드라고도 하는 강도(strength)..
Spring DTO 파일 깔끔하게 관리하기 Spring Boot를 사용해서 Restful API를 개발하다 보니 DTO 파일이 어느새 중구난방 하게 많아져 있는 모습이 찜찜했었는데, 다른 사람들은 이런 경우에 어떻게 파일을 관리하나 찾아보던 중 좋은 글을 발견해서 적용해 보았다. DTO 파일이 많아지는 이유 예를 들어 쇼핑몰에서 상품에 대한 Entity가 있을 때, 이에 대한 DTO를 만든다고 하면, Request에 대한 DTO, Response에 대한 DTO 등 하나의 Entity에 대해서도 여러 개의 DTO가 생기게 되고 이게 각각의 클래스로 만들다 보면 DTO 파일이 많아질 수밖에 없다. 해결 방안 이렇게 많아지는 Product 도메인에 대한 DTO 클래스를 하나의 ProductDto 클래스 안에서..
Redis로 JWT RefreshToken 관리하기 JWT를 사용하여 유저 인증을 구현할 때, RefreshToken은 데이터베이스에 저장해두고 사용자가 토큰 재발급을 요청할 때 검사해야 한다. 그러나 RefreshToken에도 유효기간이 있기 때문에, RDBMS에 저장하면 배치를 이용하여 주기적으로 삭제를 해줘야 하는 번거로움이 생기는데 이럴 때 Redis를 사용하면 생성할 때 유효기간을 정해두고 따로 작업이 필요 없이 만료된 토큰은 삭제된다. JWT 구현 부분은 생략하고 Redis 연동하는 부분만 설명하도록 하겠다. (redis 설치가 된 후의 진행과정) 1. bulid.gradle에 redis 의존성 추가 implementation 'org.springframework.boot:spring-boot..
JPA를 사용한 카테고리 (하위메뉴) 구현 오픈마켓 프로젝트에서 상품들을 카테고리 별로 분류하기 위해 카테고리 기능을 구현하게 됐다. 카테고리는 depth가 있기 때문에, 하위 메뉴까지 가져올 수 있도록 구현해야 한다. 테이블 계층형 구조를 위해 category 테이블에 자신의 PK를 부모로 삼는 parent 외래키를 넣어줬다. Entity 도메인 @Entity @Getter @Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") priva..
프론트엔드와 백엔드를 분리한 API 서버를 개발하면서 외부에서 접속이 잘 되는지 확인하기 위해 포트포워딩 설정하고, 방화벽 인바운드 규칙에 8080포트 열어주고 서버 실행시킨다음에 노트북으로 접속해보려고 하니까 mysql 3306이나 redis 6379 포트는 ping이 잘 가는데 8080 포트에는 접속이 안되는 문제가 생겼다. 근데 또 스프링 내장 톰캣말고 따로 설치했던 톰캣을 실행하면 접속이 되는걸 확인하면서 포트 문제가 아니라 스프링 설정에 문제가 있을 거라는 추측이 가능했다. mysql 외부 접속이 안될 때 포트포워딩이랑 인바운드 규칙 설정 후에 잘되는 걸 확인했었는데, 이번에도 똑같은 방법으로 했는데 안되니까 뭐가 문제인지 찾는데 몇시간은 걸린 것 같다. 그래서 찾은 문제는 application..
IoC(Inversion of Control) 기존의 프로그램은 클라이언트 구현 객체가 스스로 필요한 서버 구현 객체를 생성하고, 연결, 실행하므로써 구현 객체가 프로그램의 제어 흐름을 스스로 조종했다. (객체를 생성하고, 객체 간의 의존성을 만들어주고, 초기화하고 객체를 호출하는 등) 그러나 IoC은 제어의 역전이라는 의미로 프로그램의 제어 흐름을 개발자가 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전(IoC)이라고 한다. Spring에서 IoC는 객체의 대한 제어권이 스프링 컨테이너로 역전되기 때문에 xml 파일이나 어노테이션 방식으로 스프링 컨테이너에 Bean(객체)를 등록하면, 스프링 컨테이너에서 Bean의 생명주기(생성, 의존성 설정, 초기화, 소멸)를 모두 관리한다. IoC를 ..
게시판의 게시글을 가져오는 api를 작업하고 있는데, 작업이 끝난 후에 Postman으로 확인을 해보면 리스트 안의 내용이 텅텅 비어있는 문제가 생겼다. 에러가 뜨는 것도 아니라서 우선 Serivce에서 Mapper로 DB의 게시글 목록 잘 가져오는 것 확인하고, 문제가 없길래 DTO에 값이 잘 안들어가나 하고 Controller에서 리턴해줄 때 body 값을 확인했는데 body에도 값이 정상적으로 다 들어가 있길래 정말 당황스러웠다. 그래서 온갖 검색어로 다 찾아보면서 삽질하고 있었는데, 겨우겨우 stackoverflow에서 답을 찾을 수 있었다. 해당 질문 링크 Spring REST Controller returns empty JSON. Iterable data structure. Why? I rea..