웬만하면 모든 api는 아래 순서로 구현하는게 편하다
DTO -> service -> controller -> router
update는 model의 findByIdAndUpdate() 메소드를 사용해주면 된다
// UserUpdateDto
import { SchoolInfo } from "../school/SchoolInfo";
export interface UserUpdateDto {
name?: string;
phone?: string;
email?: string;
age?: string;
school?: SchoolInfo;
}
update의 경우 각각의 필드가 요청으로 들어올 수도 안 들어올 수도 있기 때문에 ?를 붙여줘서 널값을 허용해준다
// UserService
const updateUser = async (userId: string, userUpdateDto: UserUpdateDto) => { // String 안됨
try{
await User.findByIdAndUpdate(userId, userUpdateDto);
} catch (error){
console.log(error);
throw error;
}
}
유저를 찾아서 해당 유저를 업데이트하기 위해서는 조회를 위한 userId와 업데이트할 데이터 값인 userUpdateDto를 아규먼트로 받아야한다 이건 controller에서 넘겨줄거임
반환값은 딱히 없다
// UserControlller
const updateUser = async (req: Request, res: Response) => {
const { userId } = req.params; // 대괄호 없으면 오류남
const userUpdateDto: UserUpdateDto = req.body;
try{
await UserService.updateUser(userId, userUpdateDto);
res.status(statusCode.NO_CONTENT).send();
} catch(error) {
console.log(error)
res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));
}
}
controller다 어려운 부분은 없다 그런데 req에서 param을 받아올 때 대괄호가 없으면 오류가 난다 왜..?
// UserRouter
router.put("/:userId", UserController.updateUser); // UserRouter 파일에 추가해주면 된다
조회의 경우 다른 수정, 생성, 삭제 api와는 다르게 ResponseDto, 즉 반환할 때 일정한 형태를 정해주어야 한다 요청을 받을 때는 해당 객체의 id만 받아오면 되지만 응답을 반환할 때는 정해진 ResponseDto에 맞춰서 보내야 한다는 뜻
// UserResponseDto
import { UserCreateDto } from "./userCreateDto";
export interface UserResponseDto extends UserCreateDto {
}
여기서는 create용 dto랑 read용 dto가 같아서 그냥 상속을 통해 구현하였다
// UserService
const findByUserId = async (userId: string) => {
try{
const user: UserResponseDto | null = await User.findById(userId);
return user;
} catch(error) {
console.log(error);
throw error;
}
}
User 모델의 findById() 메소드를 통해 구현한다 여기서 찾으면 해당 객체가, 못찾으면 null값이 반환되어 controller로 넘어간다
// UserController
const findByUserId = async (req: Request, res: Response) => {
const { userId } = req.params
try{
const data: UserResponseDto | null = await UserService.findByUserId(userId);
if (!data){
res.status(statusCode.NOT_FOUND).send(util.fail(statusCode.NOT_FOUND, message.NOT_FOUND));
} else {
res.status(statusCode.OK).send(util.success(statusCode.OK, message.READ_USER_SUCCESS, data));
}
} catch(error){
console.log(error)
res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));
}
}
service에서 받아온 data가 null이면 유저를 찾지 못했다는 메시지와 함께 응답을 보내준다 찾았으면 UserResponseDto 형식의 데이터를 응답과 함께 보내주고, 에러가 터지면 다른 api처럼 에러 응답 메시지를 보내준다
// UserRouter
router.get("/:userId", UserController.findById) // 라우터에 추가
delete는 별다른 dto가 필요하지 않다 삭제할 객체의 id만 요청에서 받아와서 삭제를 진행하고 반환값도 크게 필요하지 않는다
// UserService
const deleteUser = async (userId: string) => {
try {
await User.findByIdAndDelete(userId);
} catch (error) {
console.log(error);
throw error;
}
}
삭제는 findByIdAndDelete() 메소드를 사용한다
// UserController
const deleteUser = async (req: Request, res: Response) => {
const { userId } = req.params;
try {
await UserService.deleteUser(userId);
res.status(statusCode.NO_CONTENT).send(util.success(statusCode.NO_CONTENT, message.DELETE_USER_SUCCESS));
} catch (error) {
console.log(error)
res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));
}
}
controller 로직이다 크게 어려운 건 없음
// UserRouter
router.delete("/:userId", UserController.deleteUser);
끝!