백엔드 Back-end

Q. HTTP PUT 메소드와 PATCH 메소드의 차이는?

Tap to restart 2022. 2. 27. 08:00
반응형

A. PUT은 새로운 리소스를 생성하거나 대상 리소스를 나타내는 데이터를 대체, PATCH는 일부 수정할 때 사용한다.

(출처: MDN Web Docs PUT, MDN Web Docs PATCH)

위 설명에서 중요한 건 리소스를 생성도 한다는 점이다. 대상 리소스가 없으면 PUT은 새로 생성한다. 있다면 바꾸고.

PUT은 없으면 Add, 있다면 Replace 교체 느낌이다. PATCH는 수선 고치는 Update 느낌이다.

 

실제 코드에서는 PUT을 PATCH처럼 쓰는 경우를 많이 볼 수 있다.

유명한 개발자들도 그렇게 쓰는 경우도 발견할 수 있다.

PUT을 PATCH처럼 쓰는 예 (출처: full-stack-fastapi-postgresql)

@router.put("/me", response_model=schemas.User)
def update_user_me(
    *,
    db: Session = Depends(deps.get_db),
    password: str = Body(None),
    full_name: str = Body(None),
    email: EmailStr = Body(None),
    current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
    """
    Update own user.
    """
    current_user_data = jsonable_encoder(current_user)
    user_in = schemas.UserUpdate(**current_user_data)
    if password is not None:
        user_in.password = password
    if full_name is not None:
        user_in.full_name = full_name
    if email is not None:
        user_in.email = email
    user = crud.user.update(db, db_obj=current_user, obj_in=user_in)
    return user

 

PUT을 PATCH처럼 쓰는 게 큰 문제가 없을 수도 있지만, 가끔 이상한 현상이 나타날 수 있다.

PUT 메소드로 위 코드 예처럼 email만 변경했는데, is_active가 기본값인 true로 자동 변경되는 현상이다. 실제 그런 사례를 경험한 적이 있다. 되도록 일부 수정인 경우에는 PATCH를 쓰자.

 

보통 API 서버에서 CRUD와 HTTP Method는 아래처럼 대응한다.

CRUD HTTP Method
Create POST
Read GET
Update PATCH
Delete DELETE

PUT을 PATCH처럼 쓰지 않는다면 PUT은 쓸 일이 많지 않다.

 

실제로 NestJS의 CRUD generator를 써보면 PUT이 아예 없다.

코드 출처: NestJS의 CRUD generator

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(+id, updateUserDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
}

 

반응형