Spring 8

spring boot 사이드 프로젝트: DockerFile, docker-compose.yml 작성 및 클라우드 세팅(GCP) 1

프로젝트 작성이 거진 다 끝나고, 테스트와 기능 개선 과제, 그리고 배포 정도의 과제가 남았다. 이제 로컬로 개발서버를 여는 것 뿐 아니라 클라우드 인스턴스에 24시간 배포를 시작해보려 한다. 클라우드 서비스는 가장 대중적인 아마존의 AWS, 마이크로소프트의 Azure, 구글의 GCP 등등 여러가지가 존재하는데, 나는 여기서 GCP를 선택했다. 이유는 단순하게도 무료로 이용이 가능해서(...) 이다. 다른 서비스는 무료를 더 이상 쓸 수 없는 상황.. 당장 복잡한 클라우드 아키텍처를 설계하지는 않았다. 일단 가볍게 다음과 같은 구조를 생각했다. GCP인스턴스 하나를 실행해서 그 안에 도커를 이용해 3개의 컨테이너를 띄운다. 8080으로 요청을 보내면 설정을 통해 스프링 부트 애플리케이션이 실행중인 컨테이..

Project/9uin 2023.10.30

spring boot 사이드 프로젝트 : spring boot + github action을 통해 CI/CD구축

ci/cd란 continuous integration / continuout deploy(delivery) 의 줄임말로, 지속적 통합과 배포를 말한다. 스프링 예제를 하나라도 해보면 알겠지만 서버 코드를 업데이트 했다고 실행중인 애플리케이션에 바로 적용되지는 않고, 서버를 껐다 켜야 업데이트한 코드가 적용된다. 개발서버와 배포 서버를 따로 둔 상황에서 업데이트 내용을 적용하려면 배포 서버에 직접 접속해서 git pull이나 docker pull같은 작업을 거친뒤 다시 서버를 껐다 켜야되는데 서버가 한 두대면 모를까 여러대면 이런건 고역이 따로 없다. ci/cd를 통해 이런 작업을 할 필요 없이, 트리거만 충족되면 배포 서버에도 업데이트한 내용이 바로 적용되고, 다시 배포를 알아서 시작해준다. 프로젝트 마..

Project/9uin 2023.10.29

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

springboot 사이드 프로젝트[9] : controller 작성

사용자와 상호작용을 위한 controller 레이어를 만들었다. 기본적으로, 이 프로젝트에 구현한 대부분의 컨트롤러는 이렇게 crud하는 구조를 가진다. (물론, 특수한 로직을 사용해야하는 경우 추가로 다른 구조로 작성되었다.) 가장 자주 사용되는 게시글 api를 살펴보자. Board controller BoardController.java @RestController @RequestMapping("/boards") @Tag(name = "board", description = "게시글 관련 api") public class BoardController { private BoardService boardService; private static final Logger log = LoggerFactory...

Project/9uin 2023.09.04

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 JPA : 페이징(paging)

보통 게시판 화면을 보면 게시글이 특정 개수 단위로만 띄워진다. 모든 게시글을 한눈에 보이도록 제공하지는 않는다. 그렇게 하면 서버 부하도 심할 것이고, 보는 사용자 입장에서도 가시성이 떨어질 것이다. 그래서 특정 단위로 쪼개서 데이터를 페이지 구분을 하는 방법을 사용하는데, 이것을 페이징이라고 이야기한다. DBMS를 이용해 쿼리를 할 때 개수를 나눠서 쿼리하는 페이지네이션 방법은 다 다르다. 예로 mysql은 offset, limit를 사용하면 가능하다. 문제는 이건 DBMS마다 다르기에, 페이지네이션을 하는 다양한 방법들을 하나의 방법으로 통합해서 추상화하여 제공하는 것을 필요로 한다. 이것을 JPA에서는 dialect(방언) 설정을 통해 처리한다. 이 덕에 개발자들은 SQL을 사용하지 않고 API를..

Backend/spring boot 2023.05.25