🔌 SPARTA/Courses

스탠다드반 1회차: MVC & REST API

eunjiom 2026. 2. 2. 21:08

🗒️ 플로우차트

 

  • 팩토리얼


💻 REST API 와 HTTP

1. HTTP : 규격화된 봉투

  • 주소(URL/ULI): 어디로 보낼지(/posts, /members)
  • 우표(Method): 이걸로 뭘 하고 싶은지

2. REST API의 4대 천왕

  • GET(조회)
  • POST(생성)
  • PUT/PATCH(수정)
  • DELETE(삭제)

3. 이름표(Resource)는 명사

  • 동사 사용x
  • 명사, 복수형 사용
  • X: GET/get-all-posts
    O: GET/posts

4. 서버의 대답(status code)

  • 200 ok
  • 201 Created
  • 404 Not Found
  • 500 Internal Server Error

🔌 Controller

1. 안내 데스크(Controller)

  • 홀직원 / 입구
  • 3대 핵심 역할
    • 요청 수신: HTTP 봉투에 담긴 손님의 요청을 받아냄 / 주문
    • 목적지 배정: 알맞은 주방으로 업무 넘김 / 위임
    • 응답 반환: 요리 끝나고 포장(JSON) 후 손님에게 건냄 / 서빙

2. @RestController

  • 안내 데스크 임무 부여하는 어노테이션
  • @Controller: 기본 html
  • @ResponseBody: json 포장
@RestController // 1. "여기는 데이터 안내 데스크입니다!"
public class MemberController {

    @GetMapping("/api/members/welcome")
    public String welcome() {
        return "스탠다드반 여러분, 환영합니다! 드디어 서버가 대답했어요!";
    }
}

 

3. @RequestMapping

  • 주소 명패 달기 / 부서를 나누는 것
  • ("/api/members" )> 주소 공통으로 사용 가능
@RestController
@RequestMapping("/api/members") // 👈 "이 건물 2층은 전부 멤버 관련 부서입니다!"
public class MemberController {

    @GetMapping // 👈 여기는 /api/members 주소 그 자체!
    public String getMemberList() {
        return "전체 회원 목록을 가져오는 중입니다...";
    }
}
  • 코드가 깔끔해짐(중복주소) / 유지보수 쉬움
  • 클래스에선 공통 주소 / 메서드 내에서 세부 주소
  • GetMapping = RequestMethod.GET
  • 메서드가 두 개일때 (put, patch): value = "URL", method {put,patch}

4. Controller 지켜야 할 규칙

 

1) 컨트롤러는 말라깽이(Thin)여야 함

  • 컨트롤러의 일: 손님 왔어? 주문 받아! 주방장 불러!
  • 실제 요리(로직): 주방장(Service)

2) 무상태성 유지

@PathVariable

1. 경로 변수

  • 이전 방식: /api/members/me (항상 나만 나옴)
  • 진화된 방식: /api/members/7, /api/members/100 (숫자에 따라 다른 사람이 나옴)
  • 주소(path) 자체에 변하는 값을 넣는 것 = 경로 변수(PathVariable)

2. @PathVariable 사용법

// {id} 라고 적으면 "이 자리는 변하는 값이 들어올 구멍이야!"라는 뜻입니다.
@GetMapping("/{id}")
public String getMemberProfile(@PathVariable Long id) {
    // @PathVariable이 주소창의 {id} 값을 낚채서 변수 id에 담아줍니다.
    return "요청하신 " + id + "번 회원의 프로필을 조회 중입니다...";
}
  • 변수 이름이 다를 때(주소창은 {userId}인데 자바 변수는 Long id): @PathVariable(name = "userId") Long id 라고 명시
    @GetMapping("/{id}")
    public String getMemberProfile(@PathVariable("id") Long no) {
        int id = 10; // 지역변수
        // @PathVariable이 주소창의 {id} 값을 낚채서 변수 id에 담아줍니다.
        return "요청하신 " + no + "번 회원의 프로필을 조회 중입니다...";
    }

 

3. ID 주소를 넣는 이유

 

1) 리소스 중심 설계

  • 모든 자원(Resource)은 고유한 주소를 가져야 함
  • 7번 회원 = /api/members/7
  • 나중에 캐싱(Caching)하기가 매우 유리

2) 공유하기 좋은 주소

  • /post/12345 처럼 주소에 ID 포함되어야 똑같은 정보 볼 수 있음

4. 게시물 상세 페이지 입구 만들기

미션 목표 힌트
게시물 상세 조회 /api/posts/10 접속 시 "10번 게시물을 보여줍니다." 출력 @GetMapping("/{postId}") 활용
// 힌트 코드 (PostController.java)
@RestController
@RequestMapping("/api/posts")
public class PostController {

    @GetMapping("/{postId}")
    public String getPostDetail(@PathVariable Long postId) {
        // TODO: 여기에 코드를 작성해 보세요!
        return postId + "번 게시물 상세 페이지입니다.";
    }
}

 

@RequestParam

1. 쿼리 파라미터

  • 추가 옵션 요청
  • 예시) 홍씨/20세: /api/members/hong/20

2. 쿼리 스트링(+조건)

  • 형식: 주소?키=값&키=값
  • 예시: /api/members/search?name=홍길동&age=20
    rating=3(별점 3점이상) / listSize=60(상품 60개씩 조회) 등
  • 클라이언트가 요청

3. @RequestParam 사용법

// /api/members/search?name=홍길동 요청이 오면 실행!
@GetMapping("/search")
public String searchMember(@RequestParam String name) {
    // @RequestParam이 주소창의 ?name= 뒤에 있는 값을 name 변수에 담아줍니다.
    return name + "이라는 이름을 가진 회원들을 검색 중입니다...";
}
  • 필수가 아닌 옵션:  @RequestParam(required = false)

4. @PathVariable vs @RequestParam

 

5. 주문 옵션이 너무 많을 때

  • 커맨드 객체 방식 사용: 자바 객체(DTO)를 파라미터로 두면 스프링이 알아서 값을 넣어줌

6. 게시물 검색기 만들기

// PostController.java
@GetMapping
public String getPosts(@RequestParam(required = false, defaultValue = "all") String category) {
    return category + " 카테고리의 게시물 목록입니다.";
}

 

DTO & JSON

1. DTO

  • 데이터 전송용 객체: 서버가 가진 데이터를 외부로 보낼 때 사용하는 전용 상자
  • String(비닐봉지 - 뒤죽박죽), DTO(도시락통 - 칸이 정해져 있음)

2. JSON

  • 자바 스크립트 표기법(공용어)
  • 모든 컴퓨터가 알아들을 수 있는 텍스트 형식인 JSON으로 변환
  • 생김새
{
  "id": 7,
  "nickname": "hong_tutor",
  "email": "hong@sparta.com"
}

 

3. 프로필 도시락 만들기

@GetMapping("/me")
public MemberResponse getMyInfo() {
    // 1. 도시락통(DTO)을 준비합니다.
    // 2. 지금은 DB가 없으니 가짜(Mock) 데이터를 꾹꾹 담아볼게요.
    return new MemberResponse(1L, "hong@sparta.com", "홍튜터");
}

 

4. 엔티티(Entity)를 직접 안 내보내는 이유

  • 보안 사고
  • API 규격의 안정성: DB구조가 바꼈을 때 안정성
  • 성능 최적화: 필요한 데이터만 골라서 보냄

5. 게시물 리스트 포장

// PostController.java
@GetMapping("/{postId}")
public PostResponse getPostDetail(@PathVariable Long postId) {
    // TODO: 1번 게시물, "첫 게시물입니다!", "이미지URL", "작성자닉네임"을 담아 반환하세요.
    return new PostResponse(postId, "오늘 첫 수업 너무 재밌어요!", "[https://image.com/1](https://image.com/1)", "홍튜터");
}

 

PostMapping

1. POST

  • 데이터 처리(생성)
  • 데이터를 HTTP 봉투 본문(Body)에 숨겨서 보냄

2. Request DTO vs Response DTO

 

1) Request DTO

  • 손님이 서버로 보낼 때 사용(예: 비밀번호 포함)
  • 파라미터에서 사용

2) Response DTO

  • 서버가 손님에게 줄 때 사용(예: 비밀번호 제외)

3) 회원가입 신청서(Request) 만들기

// MemberController.java
@PostMapping("/signup")
public String signup(@RequestBody MemberSignupRequest request) {
    // @RequestBody가 JSON '본문'을 자바 객체(Request DTO)로 변환해줍니다.
    System.out.println("가입 요청 이메일: " + request.getEmail());
    return request.getNickname() + "님, 가입 신청이 완료되었습니다!";
}

 

3. curl로 테스트

// PowerShell
curl.exe -X POST http://localhost:8090/api/members/signup `
     -H "Content-Type: application/json" `
     -d '{\"email\": \"test@test.com\", \"password\": \"1234\", \"nickname\": \"SpartaKing\"}'
// postman

POST > Body

{
    "email": "pororo@naver.com",
    "nickname": "뽀로로"
}

 

4. 게시물 작성 API 구현하기

// PostController.java
@PostMapping
public String createPost(@RequestBody PostCreateRequest request) {
    // TODO: 전달받은 게시물 내용(content)을 콘솔에 찍고 성공 메시지를 반환하세요.
    return "게시물이 등록되었습니다: " + request.getContent();
}

 

'🔌 SPARTA > Courses' 카테고리의 다른 글

스탠다드반 3회차: 실전 SQL  (0) 2026.02.09
스탠다드반 2회차: 데이터 베이스 모델링  (0) 2026.02.05
Spring MVC / Data JPA  (0) 2026.01.30
Spring 시작하기  (1) 2026.01.29
배열과 컬렉션  (1) 2026.01.28