πŸ”™λ’€λ‘œκ°€κΈ°

@RestController μ–΄λ…Έν…Œμ΄μ…˜

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	@AliasFor(annotation = Controller.class)
	String value() default "";

}

@Controller와 @ResponsBodyλ₯Ό ν•©μΉœ 것이닀.

V1 νšŒμ› 등둝 API - μ—”ν‹°ν‹°λ₯Ό RequestBody에 직접 λ§€ν•‘

package jpabook2.jpashop2.domain.api;

import jpabook2.jpashop2.domain.Member;
import jpabook2.jpashop2.domain.service.MemberService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequiredArgsConstructor
public class MemberApiController {
    private final MemberService memberService;
    /*
    등둝 V1 : μš”μ²­ κ°’μœΌλ‘œ Member μ—”ν‹°ν‹°λ₯Ό 직접 λ°›λŠ”λ‹€.
     */
    @PostMapping("/api/v1/members")
    public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member){
        Long id = memberService.join(member);
        return new CreateMemberResponse(id);
    }

    @Data
    static class CreateMemberRequest{
        private String name;
    }
    @Data
    static class CreateMemberResponse {
        private Long id;

        public CreateMemberResponse(Long id) {
            this.id = id;
        }
    }
}

V1의 문제점

  1. 엔티티와 APIκ°€ 1:1둜 λ§€ν•‘λœ μƒνƒœ β‡’ μ—”ν‹°ν‹° μŠ€νŽ™ λ³€κ²½ μ‹œ API의 μŠ€νŽ™ μžμ²΄κ°€ λ°”λ€Œμ–΄λ²„λ¦°λ‹€.
  2. μ—”ν‹°ν‹°μ˜ μ½”λ“œκ°€ 지저뢄해짐 β‡’ 엔티티에 ν”„λ ˆμ  ν…Œμ΄μ…˜ 계측을 μœ„ν•œ 둜직이 μΆ”κ°€λœλ‹€. β‡’ 엔티티에 @NotEmpty λ“± API 검증을 μœ„ν•œ 둜직이 μΆ”κ°€λœλ‹€.
  3. ν•˜λ‚˜μ˜ 엔티티에 λͺ¨λ“  APIλ₯Ό μœ„ν•œ μŠ€νŽ™μ„ 담을 μˆ˜λŠ” μ—†λ‹€. β‡’ μ‹€λ¬΄μ—μ„œλŠ” νšŒμ› μ—”ν‹°ν‹°λ₯Ό μœ„ν•œ API만 해도 λ‹€μ–‘ν•˜κ²Œ λ§Œλ“€μ–΄μ§
  4. μ—”ν‹°ν‹°λŠ” νŒŒλΌλ―Έν„°λ‘œ 무엇이 λ„˜μ–΄μ˜¬μ§€ λͺ¨λ₯Έλ‹€. β‡’ 개발자 μž…μž₯μ—μ„œλŠ” API μŠ€νŽ™ λͺ…μ„Έλ₯Ό κΉŒλ³΄μ§€ μ•ŠλŠ” ν•œ μ–΄λŠ λ°μ΄ν„°κΉŒμ§€ λ„˜μ–΄μ˜€λŠ”μ§€ νŒλ‹¨ν•  μˆ˜κ°€ μ—†λ‹€.

κ²°λ‘ 

μ—”ν‹°ν‹°λ₯Ό νŒŒλΌλ―Έν„°λ‘œ 받지도 말고, 외뢀에 λ…ΈμΆœμ‹œν‚€μ§€λ„ 말자.

ν•΄κ²°μ±…

V2 νšŒμ› 등둝 API - μ—”ν‹°ν‹° λŒ€μ‹  DTOλ₯Ό RequestBody에 λ§€ν•‘

/*
등둝 V2 : μš”μ²­ κ°’μœΌλ‘œ Member μ—”ν‹°ν‹° λŒ€μ‹  λ³„λ„μ˜ DTOλ₯Ό λ°›λŠ”λ‹€.
*/
@PostMapping("/api/v2/members")
    public CreateMemberResponse saveMemberV2(@RequestBody @Valid 
																						CreateMemberRequest request) {
        Member member = new Member();
        member.setName(request.getName());
        Long id = memberService.join(member);

        return new CreateMemberResponse(id);
    }

@Data
    static class CreateMemberRequest {
        private String name;
    }