아래는 경로가 없는 미들웨어 함수이기 때문에 이 함수는 모든 경로, 모든 HTTP 메서드 요청에 대해서 실행된다
const myLogger = (req, res, next) => {
console.log("LOGGED");
next(); // 다음 미들웨어 또는 라우트 핸들러로 제어를 넘김
}
**app.use**(myLogger);
/* ----> 위에 두 개의 코드를 하나로 합친 것이다.
app.use((req, res, next) => {
console.log("LOGGED");
next();
});
*/
'/' 경로로 들어오는 모든 HTTP 요청에 대해 실행되는 미들웨어 함수는 app.use()와 '/'를 이용한다.
**app.use('/'**, (req, res, next) => {
console.log('Request Type:', req.method)
next();
});
'/' 경로로 들어오는 GET 요청에 대해 실행되는 미들웨어 함수는 app.get() 과 '/' 를 이용한다.
app.get('/', (req, res) => {
console.log("/");
res.send("Hello UMC!");
}
next() 는 다음 미들웨어 함수 or 해당 라우트 핸들러로 제어를 넘기는 함수이다. 따라서 next()를 호출하지 않으면 요청이 다음 단계로 진행되지 않는다.
const myLogger = (req, res, next) => {
console.log("LOGGED");
// next();
}
app.use(myLogger);
app.get('/', (req, res) => {
console.log("/");
res.send("Hello UMC!");
});
app.get('/hello', (req, res) => {
console.log('/hello');
res.send('Hello world!');
});
next() 를 주석처리 했더니 '/' 경로로 요청을 해도 LOGGED만 출력되고 '/hello' 경로로 요청을 해도 LOGGED만 출력되는 것을 확인했다.
즉, app.use(myLogger)미들웨어만 실행되고 이후에 실행되어야 할 라우트 핸들러는 실행되지 않는 것이다. 이렇게 되면 res.send() 코드가 실행되지 않아 응답이 전송되지 않고 이로 인해 무한 로딩 상태 or 타임 아웃으로 끝난다.

export const handleMemberSignUp = async (req, res, next) => {
console.log("회원가입을 요청했습니다!");
console.log("[MemberController] request body:", req.body); // 값이 잘 들어오나 확인하기 위한 테스트용
const member = await memberSignUp(bodyToMember(req.body));
// res.status(StatusCodes.OK).json({
// resultType: "SUCCESS",
// error: null,
// success: member,
// });
res.status(StatusCodes.OK).success(member);
};
member.service.js
member 저장 + preference 저장 두 db 작업을 트랜잭션을 사용하여 하나로 묶었다.
해당 트랜잭션 함수를 repository 계층으로 분리하는 작업은 이후에 리팩토링 할 예정이다.
export const memberSignUp = async (data) => {
try{
const result = await prisma.$transaction(async (tx) => {
// 1. 이메일 중복 검사
const existing = await tx.member.findFirst({where:{email:data.email}});
if(existing)
throw new error("이미 존재하는 이메일입니다.");
// 2. member 생성
const created = await tx.member.create({
data:{
email: data.email,
name: data.name,
gender: data.gender,
age: data.age,
address: data.address,
specAddress: data.specAddress,
phoneNumber: data.phoneNumber,
}
});
const memberId = created.id;
// 3. member_prefer 생성
for (const categoryId of data.preferences) {
await tx.memberPrefer.create({
data: {
memberId: memberId,
categoryId: categoryId,
createdAt: new Date(),
updatedAt: new Date(),
},
});
}
// 4. member + member_prefer 정보 조회
const member = await tx.member.findUnique({ where: { id: memberId } });
const preferences = await tx.memberPrefer.findMany({
where: { memberId },
orderBy: { categoryId: 'asc' },
select: { categoryId: true }
});
return responseFromMember({ member, preferences });
});
return result;
} catch(error) {
// rollback
console.error("회원가입 실패: ", error.message);
throw error;
}
