Spring 비동기로 이메일 전송하기
·
Spring
✅ 개요스프링 부트에서는 이메일 전송을 쉽게 구현할 수 있습니다. 여기에 추가로 `@Async`를 활용한 비동기 처리로 성능 개선 과정을 정리하고자 합니다. ✅ Before먼저 기존 코드는 다음과 같습니다. 사용자는 이메일로 받은 링크를 클릭하면 이메일 인증 처리가 되는 구조로 설계되어 있습니다.public void sendEmail(Long guestId) { Guest guest = guestRepository.findById(guestId) .orElseThrow(() -> new EntityNotFoundException("Guest with id " + guestId + "cannot be found")); String toke..
쿠키 Samesite 설정으로 이슈 해결하기
·
트러블슈팅
✅ 개요로컬 개발 환경에서는 프론트엔드와 백엔드 간의 쿠키 전달에 문제가 없었지만, 배포 환경에서는 문제가 발생해 해결 과정을 기록하고자 합니다. ✅ 문제 상황프로젝트에서 다음과 같이 로그인 인증 이후 헤더와 쿠키로 각각 JWT 액세스 토큰과 리프레시 토큰을 전달하고 있습니다.private TokenResponse getTokenResponse(HttpServletResponse response, Guest guest, String principalName) { String accessToken = jwtProvider.generateAccessToken(guest, principalName); String refreshToken = jwtProvider.generateRefreshToken(..
Spring OAuth AccessToken 제대로 추출하기
·
트러블슈팅
✅ 개요사용자가 OAuth로 인증한 상태에서 로그아웃 요청을 받으면 서버에서 JWT 처리(만료 쿠키, 블랙리스트 처리 등) 외 추가적으로 OAuth에 토큰 삭제 요청 API를 사용하려고 할 때 발생한 문제와 해결방법을 기록하고자 합니다. ✅ 문제 상황OAuth 토큰 삭제 요청 API는 반드시 삭제 대상 액세스 토큰(JWT 아님)을 전달해야 합니다. 그리고 토큰은 `OAuth2AuthorizedClientService`를 통해 얻을 수 있으며, 토큰을 얻기 위해 필요한 메서드는 `loadAuthorizedClient`로 두 개의 인자를 받습니다.`clientRegistrationId`는 kakao, google같은 값으로 DB에 잘 저장했다면 어렵지 않게 얻을 수 있습니다. 그리고 `principalNam..
JpaRepository에서 default 키워드를 사용할 때 주의점
·
트러블슈팅
✅ 개요Spring Data Jpa 인터페이스에서 default 키워드를 사용할 때의 발생하는 문제점과 해결 방법을 기록하고자 합니다. ✅ 문제 상황평소와 같이 `JpaRepository`를 사용하여 편리하게 JPA를 사용할 때 default 키워드를 사용하면 서비스 로직에서 더 편리하게 사용할 수 있을 것 같아서 다음과 같이 작성했습니다.public interface MemberRepository extends JpaRepository { default Member getMemberById(Long id) { return findById(id).orElseThrow(() -> new EntityNotFoundException("Cannot be found Member for id: "..
JPA HikariCP autoCommit=false로 설정하는 이유
·
JPA
✅ 개요팀 프로젝트 진행 중 한 팀원분이 `autoCommit: false` 설정을 언급해 주셨습니다. 이에 대한 내용을 전혀 모르고 있다가 다른 글들을 보니 이 설정 하나로 성능 최적화를 할 수 있었다고 해서 꽤 흥미로운 내용인 것 같아 제가 이해한 내용을 정리해보려고 합니다. ✅ autoCommit=false 설정스프링 부트에서는 다음과 같이 설정 파일로 간단하게 autoCommit을 설정할 수 있습니다.spring: datasource: hikari: auto-commit: false 그렇다면 이 설정 하나로 어떻게 성능 최적화가 가능한지 디버깅해 보았습니다.1️⃣ LogicalConnectionManagedImpl - begin()먼저 직접 설정하거나 또는 `JpaRepositor..
Spring AbstractRequestLoggingFilter로 RequestBody 로깅 찍기
·
Spring
✅ 개요인터셉터를 사용해 엔드포인트, 메서드, 실행 시간 등의 로깅을 남기기 위해 여러 다른 글들과 스프링 클래스들을 살펴보던 도중 `AbstractRequestLoggingFilter`이라는 클래스를 발견하였습니다. 이 필터를 사용해 정상적으로 로그를 출력하기 위한 과정을 정리하고자 합니다. ✅ ApiLoggingFilter 구현먼저 `AbstractRequestLoggingFilter`는 `org.springframework.web.filter` 패키지로 스프링 시큐리티 필터를 모두 거친 다음에 동작하는 필터입니다. 이 필터 클래스에서 `getBeforeMessage()`와 `getAfterMessage()` 메서드만 직접 만들면 원하는 형태로 로그를 출력할 수 있을 것으로 예상하고 다음과 같이 구성..
[데브코스] Spring + Toss payments로 결제 기능 개발하기
·
Spring
✅ 개요팀 프로젝트에서 결제 기능을 맡게 되었습니다. 스프링 개발 환경에서 어떤 식으로 결제 기능을 구현했는지 공유하고자 합니다. ✅ Toss Payments를 선택한 이유먼저 어떤 API로 결제 기능을 구현할지 카카오페이, 포트원, 토스 등 여러 서비스의 가이드를 한 번씩 훑어보았습니다. 이 중 토스를 선택한 이유는 가장 먼저 가독성 때문이었습니다. 일단 다른 서비스에 비해 UI도 마음에 들었고, API 사용 가이드가 이해하기 쉽게 구성되어 있던 것 같습니다. 또 다른 이유는 샘플 코드와 테스트 환경을 제공해 주기 때문이었습니다. 프론트와 백엔드 각각 샘플 코드를 제공해 주어 가이드대로 따라 하기 매우 수월했습니다. ✅ Toss Payments 결제창 이해Toss Payments 결제 서비스 연동에는 ..
[프로그래머스 SQL] Lv.3 - 있었는데요 없었습니다
·
SQL/JOIN
https://school.programmers.co.kr/learn/courses/30/lessons/59043 프로그래머스SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프programmers.co.kr문제 풀이ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블을 아이디를 기준으로 조인한다.ANIMAL_INS의 보호 시작일보다 ANIMAL_OUTS의 입양일이 빠른 행을 필터링한다.아이디와 이름을 조회한다.보호 시작일을 기준으로 오름차순 정렬한다.SELECT A.ANIMAL_ID, A.NAMEFROM ANIMAL_INS AS A JOIN ANIMAL_OUTS AS B ON A.ANIMAL_ID = B.ANIMAL_..
[프로그래머스 SQL] Lv.3 - 없어진 기록 찾기
·
SQL/JOIN
https://school.programmers.co.kr/learn/courses/30/lessons/59042 프로그래머스SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프programmers.co.kr문제 풀이ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블을 동물 ID를 기준으로 조인한다. 이때 RIGHT JOIN으로 ANIMAL_INS 테이블에는 없는 ANIMAL_OUTS 테이블의 데이터가 NULL로 조회되도록 한다.ANIMAL_INS 테이블의 동물 ID가 NULL인 행을 필터링한다.ANIMAL_OUTS 테이블의 동물 ID와 이름을 조회한다.동물 ID를 기준으로 오름차순 정렬한다.SELECT B.ANIMAL_ID, B.NAM..
[프로그래머스 SQL] Lv.2 - 상품별 오프라인 매출 구하기
·
SQL/JOIN
https://school.programmers.co.kr/learn/courses/30/lessons/131533 프로그래머스SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프programmers.co.kr문제 풀이PRODUCT 테이블과 OFFLINE_SALE 테이블을 상품 ID를 기준으로 조인한다.상품코드를 기준으로 그룹핑한다.상품 코드와 SUM 키워드로 상품 코드별 매출액의 합계를 조회한다.매출액을 기준으로 내림차순 정렬, 상품 코드를 기준으로 오름차순 정렬한다.SELECT P.PRODUCT_CODE, SUM(P.PRICE * O.SALES_AMOUNT) AS SALESFROM PRODUCT P JOIN OFFLINE_SA..