본문 바로가기

📕 Spring Framework57

2022.06.07 「프로젝트 중간 점검」 이번 4일 간 프로젝트를 집중 있게 하느라 블로그 글 작성도 못하고 코테 준비도 제대로 못했다 ㅜㅜ 프로젝트 초기에는 속도에 대한 반성을 많이 했었는데, 시간이 지나고 프로젝트의 틀이 잡힐수록 그 반성은 큰 오산이라는 것을 알게 되었다. 퀄리티 있고, 클린 한 코드를 작성하려면 꽤나 공들이며 시간을 투자해야 한다는 것을 깨달았다. 즉, 더 효율적인 시간 분배가 관건이다. 이제 프로젝트에서 계획한 기능은 거의 구성이 된 상황이다. 거진 1달이 걸렸다. 계획한 것에 비해 늦었다고 생각하지만 본격적인 리팩터링을 적용해볼 생각이다. 처음으로 혼자서 제대로 된 프로젝트를 하기 때문에 더 애착이 가기도 한다. 이제 반도 안 왔고, 갈 길이 험난할 테지만 이뤄보자~ 지난 4일 간 구현 목록 카카오 페이 REST AP.. 2022. 6. 7.
2022.06.02 「DB 동시성 문제」 자바 기반 웹 프로그램은 기본적으로 멀티스레딩을 기반으로 하기 때문에, 동시성 관련 문제를 잘 해결해야 한다고 들었다. 이번에 내가 하는 쇼핑몰 프로젝트에서도 그 이슈가 딱 터졌다. 예를 들어 몇 만 명이 한정된 재고의 상품을 주문하려고 할 때? 수많은 멀티스레드는 데이터의 재고량을 조회하며 재고가 떨어졌으면 예외를 발생시키면 된다. 하지만 동시에 접근하면? 이거 난감하다. 이 문제에 대한 고찰을 작성하겠다. DB 동시성 문제 동시에 DB를 조회할 때가 문제이다. 내가 사용하는 DBMS는 Mysql Mysql은 기본적으로 트랜잭션의 격리 수준으로 Level 2 Repeatable Read를 사용하고 있다. 언두 영역을 통한 다양한 버전 별 MVCC를 통해 버전에 맞는 값을 조회할 수 있다. 하지만 모든 .. 2022. 6. 2.
2022.06.01 「결제 API - Ver.2」 지난번 포스팅에 이어 작성하겠다! https://sweeeetgoguma.tistory.com/entry/20220529-%E3%80%8C%EA%B2%B0%EC%A0%9C-API%E3%80%8D 2022.05.29 「결제 API」 장바구니 crud 작업한 것을 수정 및 테스트를 이번 주에 끝내고 나서, 뒤늦게 결제 API를 설계하기 시작했다. 카카오 페이 API를 사용해서 해보려고 하는데, 생각만큼 쉽지 않았다. 어디서 본 건데 sweeeetgoguma.tistory.com 카카오페이 Rest API를 이용해 결제 준비에 필요한 객체를 설계하는 것까지 완료했다. 카카오 페이 프로세스에 따라 준비와 결제 및 승인을 위한 통신 객체를 생성해야 한다. 이 과정 속에서 수많은 삽질이 있었다. 사실 삽질이라기보다.. 2022. 6. 1.
2022.05.29 「결제 API」 장바구니 crud 작업한 것을 수정 및 테스트를 이번 주에 끝내고 나서, 뒤늦게 결제 API를 설계하기 시작했다. 카카오 페이 API를 사용해서 해보려고 하는데, 생각만큼 쉽지 않았다. 어디서 본 건데 만들어진 API를 가져와서 쓰는 것도 능력이라고..ㅋㅋ 그래도 해야지 어쩌겠나. 카카오 페이 API 문서를 보니 되게 다양한 API를 소개해 놓았다. 결제 요청도 보안상 서버를 통해 요청을 해야 된다고 한다. 그리고 넘겨 주고 받는 파라미터도 굉장히 많다. 실거래를 위해 만들어진 API라 확실히 다르긴 하다. 개인적인 프로젝트 수준에서 테스트 결제를 위해 필요한 데이터를 추리는 작업은 참 골치 아픈 일인 것 같다. 일단 결제 요청 부터 시작하기로 결정했다. 내가 설계한 프로젝트에서는 크게 보면 두 가지 종.. 2022. 5. 29.
2022.05.28 「쿠키 수정」 장바구니 API를 처음 구현해보는 쿠키로 힘들게 짰었다. 오늘 주문 API를 구현하려고 카카오페이 관련 API 탐색 및 구상을 하던 도중 장바구니 데이터를 가지고 결제하는 경우를 떠올렸다. 다시 한번 장바구니 API 동작이 잘 되는지 포스트맨으로 확인을 하던 도중 이상한 쿠키 에러가 발생하는 것을 발견할 수 있었다.. 다시 한번 점검을 통해 코드 수정을 하며 단번에 완벽한 코드를 작성한다는 자만심 느꼈던 자신에 반성을 하게 되었다..ㅎㅎ 문제점 장바구니 상품 추가가 되질 않는다 쿠키가 다중으로 생성된다 => 이 두 가지 문제가 제일 컸다 기존 코드 장바구니 쿠키를 수정하여 response 객체에 삽입한다. 문제 새로운 쿠키가 같은 Key를 가진 객체가 생성되어 저장된다. => 내가 원한 건 기존 쿠키를 .. 2022. 5. 28.
2022.05.26 「트래픽이 몰렸을 경우」 이메일을 통해 인증 번호를 전송하는 방식은 매우 느리다. 서버 사용자가 늘어날수록 트래픽이 많이 몰려 인증 번호를 전송하는 시간이 무진장 늘어날 것이다. 이러면 안 된다. 그래서 찾아보았다. 트래픽이 몰렸을 경우에는 어떤 식으로 해결을 하는지? 동기와 비동기 방식이 있다. 동기는 첫 프로세스가 완료되어야 다음 프로세스로 넘어가는 방식이고, 완료 여부와 상관없이 다음 프로세스를 요청하거나 실행하는 것이 비동기 방식이다. 이메일 전송에 이 비동기 방식을 적용해 보고자 한다. Async Config 스프링에서는 @Async를 통해 비동기 방식을 쉽게 구현할 수 있다. configuration을 통해 스레드의 개수를 커스터 마이징 시켰다. Async 적용 비동기 방식으로 동작하길 바라는 메서드에 애노테이션을 적.. 2022. 5. 26.
2022.05.25 「Email 인증」 열심히 프로젝트를 하다가 초기 구상한 wiki를 다시 보게 되었다. 회원가입 시 이메일 api를 사용하기로 했는데 그걸 까먹었다.. 그래서 회원가입을 다시 건드리게 되었다. Java의 MailSender 인터페이스를 사용하여 SMTP 구글 이메일로 이메일 인증 번호를 클라이언트 요청 이메일로 보내주도록 설계하고 인증 번호를 redis DB에 저장하여 비교하고 회원가입을 이루게 할 것이다. Mail Sender // Mail implementation 'org.springframework.boot:spring-boot-starter-mail' 먼저 의존성을 추가했다. Application.yml 지금까지 Properties 파일을 사용하고 있었는데, 이번 기회에 yaml을 사용해보기로 결정했다. 이유는 인.. 2022. 5. 25.
2022.05.24 「코드 리팩토링 Ver.2」 주마다 리팩터링 및 기능 추가하는 브랜치를 따 설계하며 프로젝트를 진행 중이다. 이런 식으로 주마다 리팩터링을 하니까 확실히 코드가 깔끔해지는 걸 느낀다. 오늘 아침부터 진행한 코드 리팩토링은 유지보수성을 따지는 것은 물론이거니와 어려운 듯하면서도 새로운 개념을 도입해서 진행하니 나름 보람찼던 리팩터링이었다. 직면했던 문제들을 나열하며 정리를 한번 해보겠다. 인증 & 인가 책임 분리 나는 인증, 인가를 인터셉터로 구현했다. 인증은 토큰 검증, 인가는 에너테이션 및 토큰 검증으로 구현했다. 기존 코드 : 인터셉터의 preHandle 메서드 안에 두 개의 로직이 동시에 들어있다. 토큰 검증 + 에너테이션 검증 => 책임이 많다 -> 유지보수가 어렵다. 해결 : 인터셉터를 나누어 분리했다. @Override .. 2022. 5. 24.
2022.05.22 「Shopping Cart API [Ver.2]」 어제부터 장바구니 API 구현에 대해 고민을 정말 많이 했다. 당연히 DB를 이용하다 쿠키로 구현해보려는 시도가 처음이라 더 개념이 낯설었다. 추가 및 조회는 끝났는데, 오늘 아침 다시 보니 추가에서 이상한 로직이 있었고, 중복되는 코드가 있어서 수정을 하고 장바구니 수정 및 삭제 API를 작성해보았다. API를 설계하면서 문제점들과 확실히 알게 된 점을 정리해보겠다~ 장바구니 조회 장바구니를 조회한다는 것은 곧 장바구니에 들어있는 상품 목록의 데이터를 얻겠다는 것. 그 상품 목록의 객체를 설계했다. public class CartItemDTO { private final Integer productNo; private Integer productStock; private final String prod.. 2022. 5. 22.
2022.05.21 「 Shopping Cart API 만들기 」 어제부로 인증, 인가 작업이 완료되었다. 진짜 오래 걸렸다. 속도를 좀 더 낼 필요가 있다. 오늘부터는 장바구니를 만들건대 이번에는 DB를 이용하지 않을 것이다. 쿠키를 이용해 볼 생각이다. 쿠키에 장바구니 관련 정보를 넣어서 클라이언트에게 응답하는 것이다. 한 때 장바구니에 들어가는 데이터도 중요하다고 생각을 했는데 보통 장바구니는 쿠키나 로컬 스토리지를 이용한다고 한다. 나는 온전한 API로만 구현을 하고 있기 때문에 쿠키를 통해 구현해볼 생각이다. 장바구니를 어떻게 구현할까? 일단 DB에 저장을 따로 하지 않고 쿠키로 구현을 하기로 결심했다. 주요 기능을 생각해보았다. 기능 1. 상품을 장바구니에 추가 2. 장바구니에 담긴 상품 목록 조회 => 수정과 삭제가 없는 이유는 프런트단에서 할 수 있지 않.. 2022. 5. 21.
2022.05.20 《스프링 부트 권한 처리》 스프링 부트 프로젝트 중이다. jwt를 이용한 인증은 다 끝났고 인가 작업만 남았다. 대부분 스프링 서큐리티를 사용해서 권한 처리를 하는듯하다. 나는 일단 서큐리티를 사용하지 않고 짜고 있기 때문에 고민을 좀 많이 해봤다. 결론을 내리자면 인터셉터를 이용하기로 결심했다. 관리자인지 회원인지 인증이 필요한 작업이든지 중복되는 로직이 너무 많아지므로 이것은 인터셉터에서 컨트롤러로 넘어가기 전에 인가 작업을 해줘야 하는 것이 주된 이유다. 한번 해보자~ => 전반적인 계획 작성 중간 정리 혼자 프로젝트를 해서 인지 속도가 너무 나질 않는다. 생각을 해보았다. 어느 한 기능이든 유지보수가 용이하게 설계하기 때문이라는 생각이 들었다. 가장 시간을 많이 쏟은 부분은 Restful 한 설계 방식과 인증 인가 부분이다.. 2022. 5. 20.
2022.05.18 「Redis DB 적용」 스프링 부트 프로젝트를 하며 로그인 API까지는 jwt 토큰을 전달하는 방식으로 구현을 잘했다. 하지만 문제는 로그아웃이다. jwt 토큰 자체는 클라이언트에서 보관하기 때문에 서버가 자체적으로 삭제시킬 수 없다. 세션을 사용 시 서버가 세션 DB에 저장하고 있기 때문에 세션을 삭제하면 그만이지만 토큰은 그렇게 못 한다. 그래서 Redis DB라는 인메모리 DB를 이용해 보기로 했다. 처음 들어보는데 DB도 여러 가지 종류가 있는데 이 인메모리 DB는 다른 DBMS와 비교하여 어떤 성격을 가지는지 그걸 정리하고 적용해보는 하루를 보내게 될 것 같다. Redis DB Key & Value 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비 관계형 DBMS 캐시, DB 등으로 사용하며 인메모리.. 2022. 5. 18.
2022.05.17 「@Transactional 옵션 및 성능」 스프링 부트 프로젝트를 하던 도중 Service 클래스에서 @Transactional 사용에 옵션을 설정할 수 있다는 것을 처음 알았다. 옵션을 한번 추가해보라는 피드백을 받고 한번 이 에너테이션에 대해 알아보기로 했다. 프로그램 성능에 직접적인 영향을 끼칠 수도 있는 중요한 옵션이기 때문에 한번 정리를 해보겠다. 트랜잭션(Transaction)의 정의 데이터 베이스의 상태를 변경할 때, 한번에 수행되어야 하는 연산 트랜잭션 ACID 성질 원자성(Atomicity) : 트랜잭션이 DB에 모두 반영되거나, 전혀 반영되지 않거나 해야한다. 일관성(Consistency) : 트랜잭션은 일관성 있는 DB 상태를 유지해야한다. 작업 처리의 결과가 항상 일관되어야 함. 독립성(Isolation) : 동시에 실행되는.. 2022. 5. 17.
2022.05.16 「리팩토링」 프로젝트를 진행 중이다. 제대로 신경 써서 하다 보니 너무 오래 걸리는 것 같다. 또 제대로 짰다고 생각한 코드도 리팩터링 할 영역 투성이다. 이러면서 실력이 느는 거겠지..? 진짜 제대로 된 프로젝트 한번 만들어보자 리팩토링 목록 불변 객체 이슈 => setter를 허용한 객체 문제 : 불변성을 띄질 못한다. 해결 : loginDTO 객체는 값을 전달하는게 목적이므로 확실하게 불변성을 지녀야 한다. 따라서 불변객체로 다시 만들자 public class UserLoginDTO { private final String userId; private final String userPw; public UserLoginDTO(String userId, String userPw) { this.userId = use.. 2022. 5. 16.
2022.05.14 「JWT 인증」 인증을 구현하기 위해 기존에 사용하던 Session 로그인이 아닌 JWT를 이용하여 인증을 구현했다. 토큰을 처음 사용했다 보니 알아가는데 너무 오래 걸렸다. 무엇보다 나는 스프링 시큐리티를 사용하지 않고 서블릿 필터나 스프링 인터셉터를 이용해 토큰 유효성 검사를 하려고 했어서 더 쉽지 않았던 것 같다. 이번 프로젝트 인증에서 Session을 사용하지 않은 이유는 서버의 규모가 확장될 때의 인증 문제이기 때문인데 JWT를 이용한 인증도 여러 가지가 있기 때문에 나의 프로젝트에 맞는 단계가 어디인지에 상당히 헷갈렸던 한 주였다. 인증 작업을 하며 문제가 생겼던 부분이나 구현한 부분에 대해 정리를 해보겠다. Rest API를 설계할 때 인증은 session 기반이 아닌 토큰 기반으로 하는 것이 더 restf.. 2022. 5. 14.
반응형