이동봉사 공고마다 하나의 신청만을 허용하는 프로젝트에서, 여러 요청이 동시에 들어왔을 때 처음 들어온 요청만 허용하도록 하기 위한 과정을 거쳤다! 여러 가지 해결책 중 프로젝트에 가장 적합하다고 생각하는 해결책을 적용해 보았다. 1. synchronized 사용 - (X) Java의 synchronized는 모니터 방식으로 구현되어, 메서드가 실행되는 시점에 모니터를 소유하고, 실행이 끝난 후 release하는 방식으로 진행된다. 하지만 이 방법은 멀티 스레드에서 트랜잭션이 시작되는 시점이 동일할 때, 모니터를 소유하고 비즈니스 로직을 수행한 후 release를 하더라도 Transaction Commit이 진행되기 이전에 공고에 접근하여 신청한다면 한 공고에 여러 개의 신청이 들어갈 수 있어 문제가 될 ..
이동봉사 중개 공고 등록 시 PostImage를 save하는 쿼리가 여러 번 나가는 성능 문제가 생긴다 ,, ! 분명 PostImage의 List를 만들어 한 번에 saveAll을 했지만 쿼리가 PostImage의 개수만큼 나간다 ! 벌크 연산을 적용하기 위해 batch size를 설정하여 한 번에 할 수 있는 작업을 늘렸다. 하지만 batch size를 설정한 후에도 쿼리가 나가는 횟수는 동일했다. 어떤 게 문제일까? 문제는 바로 ,,, Id 채번 방식 (데이터베이스나 시스템에서 고유한 식별자(ID)를 생성하는 방식)이 GenerationType.IDENTITY이면 batch insert가 불가능하다는 것이었다!! GenerationType.SEQUENCE 또는 GenerationType.TABLE로 ..
이동봉사 중개 공고 등록 API 구현 중 S3에 이미지를 올리는 과정에서 warn 로그 발생 S3 warning: "No content length specified for stream data" AWS 공식 문서에 나와 있는 설명 ↓ metadata 콘텐츠 길이를 정해 해결! ObjectMetadata metadata = new ObjectMetadata(); try (InputStream inputStream = multipartFile.getInputStream()) { metadata.setContentLength(multipartFile.getSize());// metadata ContentLength 설정 amazonS3Client.putObject(bucketName, savedFileNam..
이번 이동봉사 중개 서비스를 구현하는 데 있어서 고민되는 부분이 있었다! 게시글에 여러 이미지가 들어갈 수 있기 때문에 게시글 테이블과 이미지 테이블을 분리했다. 그런데 게시글에는 대표 이미지가 따로 있어서 대표 이미지를 어떻게 넣을까 고민하다가 처음에는 아래와 같이 String 타입의 mainImage 컬럼을 만들어서 해당 컬럼에 이미지 url 값을 저장하면 되겠다! 라고 생각했다. (그러면 join해서 가져오지 않아도 게시글 목록을 불러올 때 대표 이미지를 더 빠르게 불러올 수 있을 것이라 생각했다.) 하지만 . . 다시 생각해 보니 정규화가 되지 않았다는 것을 알 수 있었다. 게시글 테이블에 이미지 url이 들어가는 것은 잘못된 설계라는 것을 깨달았다. 이미지에는 이미지만 따로 들어가야 하지만 공고..
RDBMS 데이터 타입과 제약을 통해 데이터의 정확성 보장 SQL이라는 RDBMS의 데이터를 관리하기 위해 설계된 프로그래밍 언어를 사용한 질의문을 통해 데이터를 다룸 데이터의 update가 빠름 데이터 처리에 대한 부하 발생 시 처리가 어려움 하나의 정보를 만들기 위해 여러 테이블로 쿼리를 사용하게 되며, 트랜잭션 처리를 중요시함 장점 정해진 스키마에 따라 데이터를 저장해야 하므로 명확한 데이터 구조 보장 각 데이터를 중복없이 한 번만 저장 가능 단점 테이블 간 관계를 맺고 있어 시스템이 커질 경우 join문이 많은 복잡한 쿼리가 만들어질 수 있다. 성능 향상을 위해서는 Scale-Up 만을 지원해 비용 문제가 있을 수 있다. 스키마로 인해 데이터가 유연하지 못하다. 스키마가 변경될 경우 번거롭고 어렵..
이번 프로젝트를 진행하면서 JWT와 관련해 팀원들과 논의한 내용을 기록해 보고자 한다! 안드로이드와 협업하는 과정에서 나누었던 이야기를 크게 3가지로 정리해 보면 다음과 같다. 1. 소셜 로그인에서의 역할 분배 2. 토큰 전달 방식(http only cookie 등), 프론트의 토큰 저장 방식 3. JWT 토큰 재발급 1. 소셜 로그인에서의 역할 분배 지난 프로젝트에서 안드로이드 앱을 출시했을 때, 소셜 로그인은 안드로이드가 처리한 후 서버는 해당 유저의 정보를 받아 저장하는 형식으로 프로젝트를 진행하였다. 이후, 웹 프로젝트를 진행하면서 소셜 로그인에 대해 알아보면서 이번에 구현하고자 했던 소셜 로그인 플로우는 다음과 같았다. 카카오를 예를 들어 설명하면, 1. 프론트가 소셜 로그인을 클릭시 서버로 리..
AWS + Docker + Github Actions를 이용한 CI/CD 개발 환경 Docker AWS EC2 Ubuntu Github Actions Spring boot Java 17 Gradle 인텔리제이에서 코드를 작성 후, Github로 Push. Github에서 조건을 만족할 경우, Github Actions 실행. (develop branch에 코드가 Push, Pull Request될 경 koeyhk.tistory.com 이전 글의 과정에서 AWS + Docker + Github Actions를 이용한 CI/CD를 구축하는 데 있어 생긴 오류들을 모아봤다! 1. make application-dev.yml # application-dev.yml 생성 - name: make applicatio..
프로젝트에서 필요한 DELETE 쿼리를 만들기 위해, 다음과 같이 쿼리를 따로 작성하여 테스트하기 위해 @Query로 쿼리를 생성하고 @Transactional 어노테이션을 붙여 해당 작업을 트랜잭션 안에서 관리해주면 된다고 생각했다! 그래서 나는 벌크연산을 이용해 하나의 쿼리로 많은 데이터를 변경할 수 있도록 작성하였다. @Transactional @Query(value = "DELETE FROM BoardStorage bs \n" + "WHERE bs.user.id = :user_id and bs.board.id in " + "(SELECT b.id FROM Board b where b.user.id = :block_user_id)") void deleteAllByUser_Id(@Param("user..
Spring Boot 프로젝트의 배포 자동화를 설정하기 위해 아래 블로그를 순차적으로 따라가다 문제가 발생하였다! ! Github Actions CD: AWS EC2 에 Spring Boot 배포하기 Overview 애플리케이션을 개발하면 외부에서도 접근 가능하도록 클라우드 환경에 배포합니다. 이전에 포스팅 했던 AWS 1편에서는 마지막에 scp 명령어로 로컬에 존재하는 빌드 파일을 EC2 인스턴스 bcp0109.tistory.com 모든 설정을 마치고 코드를 변경하여 github repository에 올렸을 때, 처음 발생한 Error는 다음과 같았다. Error: Error: Gradle script '/home/runner/work/modugarden-server/modugarden-server/g..