프론트, 백엔드 코드는 대충 짰다.
config: environments: local: target: 'http://localhost:3334' phases: - duration: 30 arrivalRate: 1 name: Warm up defaults: User-Agent: 'Artiilery' payload: path: 'users.csv' fields: - 'username' - 'password' scenarios: - name: '회원가입' flow: - post: url: '/api/sign-up' json: username: '{{username}}' password: '{{password}}' ```

..왜 400이 생기는가. 도랏니? 왜 400이 뜨고 난리니?
config: environments: local: target: 'http://localhost:3334' phases: - duration: 30 arrivalRate: 1 name: Warm up defaults: User-Agent: 'Artiilery' payload: path: 'users.csv' fields: - 'username' - 'password' scenarios: - name: '로그인' flow: - post: url: '/api/sign-in' json: username: '{{username}}' password: '{{password}}'```

config: environments: local: target: 'http://localhost:3334' phases: - duration: 30 arrivalRate: 1 name: Warm up defaults: User-Agent: 'Artiilery' payload: path: 'users.csv' fields: - 'username' - 'password' scenarios: - name: '공연 목록 조회' flow: - get: url: '/api/reservation'```

config: environments: local: target: 'http://localhost:3334' phases: - duration: 30 arrivalRate: 1 name: Warm up defaults: User-Agent: 'Artillery' payload: path: 'users.csv' fields: - 'username' - 'password' scenarios: - name: '공연 상세 조회' flow: - get: url: '/api/reservation/1' - get: url: '/api/reservation/2' - get: url: '/api/reservation/3'

config: environments: local: target: 'http://localhost:3334' phases: - duration: 30 arrivalRate: 1 name: Warm up defaults: User-Agent: 'Artillery' payload: path: 'users.csv' fields: - 'username' - 'password' scenarios: - name: '공연 예매' flow: # 공연 예약 - post: url: '/api/reservation/2' headers: authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIxLCJpYXQiOjE3MDA2MTMxNzJ9.r5_zty3Q_6W2Q0bKHWU9mxdE6suy4NNQyAgur8xLVKw'
- 예매전
예매후

여기서 http.codes.400이 뜨는 이유는 사용자의 credit은 300,000원이 있고, 공연의 price가 90,000원이기때문에 3번밖에 결제가 안되기때문임.
그렇다면 reservation 테이블에도 3개만 들어가있어야 말이된다.
... 말이 안된다.
/** 공연 예매 **/ router.post('/reservation/:showId', authMiddleware, async (req, res, next) => { let transaction; try { const { showId } = req.params; const { userId } = req.user; const show = await prisma.shows.findFirst({ where: { showId: +showId }, }); if (!show) { return res.status(400).json({ message: '찾는 공연이 없습니다.' }); } const user = await prisma.users.findFirst({ where: { userId: +userId }, }); transaction = await prisma.$transaction(async (tx) => { await tx.reservation.create({ data: { UserId: user.userId, ShowId: show.showId }, }); //예매한다면, show의 quantity 하나 줄이기 if (show.quantity > 0) { await tx.shows.update({ where: { showId: +showId }, data: { quantity: --show.quantity }, }); } else { return res.status(400).json({ message: '예매 수량이 부족합니다.' }); } //계속해서 user의 credit도 줄어들기 if (user.credit > show.price) { await tx.users.update({ where: { userId: +userId }, data: { credit: user.credit - show.price }, }); } else { return res.status(400).json({ message: '보유한 credit이 부족합니다.' }); } return res.status(200).json({ message: '좌석 예매가 완료되었습니다.' }); }); } catch (error) { console.log(error); if (transaction) { await prisma.$executeRaw`ROLLBACK`; } next(error); } });
위의 코드에서 create되는 코드를 수정해줬다. 트랜잭션 안에 있어서 상관이 없다고 생각했는데 우선 shows, users의 내용을 업데이트를 한 후에 create해주는게 맞았나보다. 아래와 같이 코드를 수정후에 credit이 부족할때 reservation에 데이터가 입력이 되지않는다.
/** 공연 예매 **/ router.post('/reservation/:showId', authMiddleware, async (req, res, next) => { let transaction; try { const { showId } = req.params; const { userId } = req.user; const show = await prisma.shows.findFirst({ where: { showId: +showId }, }); if (!show) { return res.status(400).json({ message: '찾는 공연이 없습니다.' }); } const user = await prisma.users.findFirst({ where: { userId: +userId }, }); transaction = await prisma.$transaction(async (tx) => { //예매한다면, show의 quantity 하나 줄이기 if (show.quantity > 0) { await tx.shows.update({ where: { showId: +showId }, data: { quantity: --show.quantity }, }); } else { return res.status(400).json({ message: '예매 수량이 부족합니다.' }); } //계속해서 user의 credit도 줄어들기 if (user.credit > show.price) { await tx.users.update({ where: { userId: +userId }, data: { credit: user.credit - show.price }, }); } else { return res.status(400).json({ message: '보유한 credit이 부족합니다.' }); } await tx.reservation.create({ data: { UserId: user.userId, ShowId: show.showId }, }); return res.status(200).json({ message: '좌석 예매가 완료되었습니다.' }); }); } catch (error) { console.log(error); if (transaction) { await prisma.$executeRaw`ROLLBACK`; } next(error); } });

smoke test 끝~!
이제 진짜 load test를 해보자.