우선 트랜잭션에 대한 자세한 개념 공부 이후 실제 코드로 실습을 진행했다.
개념 포스팅 보러가기 👉[Database] 트랜잭션과 무결성·정합성, 면접 질문
트랜잭션 적용(좋아요 기능)한 프로젝트 보러가기 👉 GitHub Source
1. 사용 목적
'좋아요' 기능을 개발할 때 여러 유저가 동시에 좋아요를 누르는 경우가 발생한다.
이때 데이터 정합성 보장을 목적으로 모두 완벽하게 처리(Commit)하거나 또는 처리하지 못할 경우에는 원 상태로 복구(Rollback)해서 작업의 일부만 적용되는 현상이 발생하지 않게 구현하고자 했다.
2. 구현
index.js
const db = mongoose.connection;
export { db }
like.js - 좋아요 스키마
const likeSchema = new Schema({
giveUserId: {
type: Schema.Types.ObjectId,
ref: "User",
},
getCocktailId: {
type: Schema.Types.ObjectId,
ref: "Cocktail",
},
name: {
type: String,
}
});
likeService.js - 서비스 계층
static addLike = async ({ giveUserId, getCocktailId }) => {
const session = await db.startSession();
try {
session.startTransaction();
const name = await CocktailModel.findById({ getCocktailId });
const newLike = await LikeModel.addLike({
name: name.name,
giveUserId,
getCocktailId,
});
await CocktailModel.likeCocktail({ getCocktailId });
await session.commitTransaction();
return newLike;
} catch (e) {
await session.abortTransaction();
const errorMessage = "좋아요를 생성하는 데 실패했습니다.";
return { errorMessage };
} finally {
session.endSession();
}
};
Transaction은 MongoDB sessions에 구성되어 있다고 한다.
그래서 다음과 같은 방식으로 구현하였다.
- db.startSession() 으로 호출한 다음
- session.startTransaction() 으로 함수를 선언한다.
- 이때 try - catch 문을 사용하여
- '성공 = session.commitTransaction()'으로 모든 커밋을 저장
- '실패 = session.abortTransaction()'으로 트랜젝션내의 모든 작업을 rollback
- '최종 = session.endSession()'으로 세션 종료
초반에는 예외처리를 해주지 않아 불안정한 서비스였지만 리팩토링을 통해 예외처리를 추가해주었다.
JAVA에서의 트랜잭션 구현
@Service
@Transactional(readOnly = true)
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
Spring 프레임워크에서는 @Transactional 애너테이션을 통해 트랜잭션 설정
3. 아쉬운 점
- 현재 상태에서는 오버엔지니어링이라서 구현되어 있지 않지만
- 차후 프로젝트 확장을 고려했을 때 파티셔닝이 필요하다고 생각했다.
- 현재의 방식은 좋아요 하는 user_id와 좋아요를 받은 cocktail_id로 저장하고 있지만 인스타그램과 같은 서비스를 생각해보았을 때 이 방식은 확장성 있는 코드가 아니라고 판단된다.
- 소규모 서비스를 만든다는 생각에서 벗어나서 좀 더 대규모 서비스를 초점으로 코드 구현이 필요할 것 같다.
- 파티션 키를 유저로 잡고 구현이 필요하다!!
📌 Reference
반응형
'프로젝트 개발 기록 > [개발] trouble shooting' 카테고리의 다른 글
[Error: TS(2339)] Express Request 확장하기 (0) | 2022.06.09 |
---|---|
Swagger를 활용한 API 명세와 개발 협업 2탄 (0) | 2022.06.04 |
[TDD] 테스트 코드 작성 (0) | 2022.05.19 |
Swagger를 활용한 API 명세와 개발 협업 (0) | 2022.04.20 |
댓글