[Spring Boot] 3. 간단한 GET API를 만든다(2/3)

0. 목표

 

[Mission 03] feat: add @RequestParam GET API by ssoyeong · Pull Request #7 · ssoyeong/spring-boot-study

미션 간단한 GET API를 만든다. 만든 API를 로컬 환경에서 테스트해본다. 스펙 GET localhost:8080/test/greeting?name={NAME} 예시 # 요청 GET localhost:8080/test/greeting?name=ssoyeong # 응답 Hello, ssoyeong! 세부 내용 GET API

github.com

아래 API를 개발하자

 

스펙

GET localhost:8080/test/greeting?name={NAME}

예시

# 요청
GET localhost:8080/test/greeting?name=ssoyeong

# 응답
Hello, ssoyeong!

 

1. Query String이란?

1.1. 개념

- URL 끝에 '?' 문자로 시작하고 각 파라미터는 'key=value' 형태로 쓰이며 여러 개의 파라미터는 '&'로 연결됨

ex) http://example.com/page?name=ssoyeong&age=22

 

1.2. 특징

가시성 및 편의성: URL에 직접 포함되어 있어 사용자에게 보여지고, 간단하고 쉽게 데이터를 전달할 수 있음

길이 제한: 특정 브라우저나 웹 서버는 URL 길이에 제한을 두어, 매우 긴 쿼리 스트링은 문제를 일으킬 수 있음

(URL 절단, 400에러, 500에러 등)

 

1.3. 사용 용도

데이터 전달: 주로 GET 요청에서 클라이언트에서 서버로 데이터를 전달하기 위해 사용됨

필터링 및 검색: 웹 애플리케이션에서 데이터를 필터링하거나 검색하는 데 사용됨

 

1.4. 다루기 좋은 데이터

검색 조건

검색어, 카테고리, 태그 등과 같이 검색 조건을 전달

ex) ?q=search_keyword&category=books

 

필터링 조건

리스트를 필터링할 때 필터링 조건을 전달

ex) ?minPrice=100&maxPrice=500

 

정렬 조건

정렬 방법이나 기준을 전달

?sortBy=date&order=asc

 

페이징 정보

페이지 번호, 페이지당 항목 수와 같이 페이징 정보를 전달

?page=1&pageSize=10

 

단일 값 데이터

?id=123

단일 값을 전달

 

1.5. 주의 사항

URL Encoding

- URL에 특수 문자(&, ?, =, %, #) 등이 포함된 경우, 다국어 문자가 포함된 경우 해당 문자를 인코딩하여 전달해야 함

- 공백은 '%20'으로 인코딩

 

민감한 정보 노출 금지

- 비밀번호, 개인정보 등의 민감한 정보는 노출시키지 않아야 함

- 이런 경우 보안을 위해 POST 요청을 사용하는 것이 좋음

 

길이 제한 고려

- URL에는 길이 제한이 있으므로 너무 긴 데이터는 POST 요청을 사용하는 것이 좋음

 

SQL Injection, XSS 등 방어

SQL Injection

입력값이 데이터베이스 쿼리에 삽입될 때 SQL Injection 공격에 대응해야 함

 

ex) 공격자는 아래와 같이 원래의 쿼리를 왜곡시켜 모든 사용자의 정보를 반환하도록 만들 수 있음

 

원래 SQL 쿼리

SELECT * FROM users WHERE username='입력한_사용자_이름';

SQL Injection 공격

SELECT * FROM users WHERE username='admin' OR '1'='1';

 

대응하기 위해 Prepared Statements 사용

SQL 쿼리에 사용되는 변수들을 파라미터화하여 쿼리를 실행함

String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, inputUsername);
preparedStatement.setString(2, inputPassword);
ResultSet resultSet = preparedStatement.executeQuery();

 

Cross-Site-Scripting

악의적인 스크립트를 웹 페이지에 삽입해 사용자의 브라우저에서 실행되게 하는 공격에 대응해야 함

 

XSS 공격 예시

<script>alert('XSS 공격');</script>

대응하기 위해 입력값 예외 처리

사용자로부터 입력받은 데이터를 HTML 태그로 해석되지 않도록 이스케이프 처리하여 특수 문자를 변환함

const userInput = "<script>alert('XSS attack');</script>";
const escapedInput = escapeHtml(userInput);

function escapeHtml(input) {
    return input.replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

 

2. Spring에서 Query String을 다루는 방법

'http://localhost:8080/test/greeting?name=ssoyeong'의 형태로 들어오는 URL은 @RequestParam 어노테이션을 사용한다.

@RequestParam은 Spring에서 HTTP 요청 파라미터를 메서드의 인자로 전달받을 때 사용하는 어노테이션이다.

 

2.1. 기본 사용

@GetMapping("/endpoint")
public String handleRequest(@RequestParam("paramName") String paramValue) {
    // paramName이라는 이름의 요청 파라미터 값을 paramValue에 매핑
    // 사용할 로직
    return "viewName";  // 적절한 뷰 이름으로 반환
}

2.2. 파라미터 이름과 메서드 파라미터 이름이 동일한 경우

@GetMapping("/endpoint")
public String handleRequest(@RequestParam String paramName) {
    // 요청 파라미터명과 메소드 파라미터명이 동일하다면 파라미터 값을 매핑
    // 사용할 로직
    return "viewName";  // 적절한 뷰 이름으로 반환
}

2.3. 필수 파라미터

@GetMapping("/endpoint")
public String handleRequest(@RequestParam(name = "paramName", required = true) String paramValue) {
    // 필수 요청 파라미터로 설정
    // 사용할 로직
    return "viewName";  // 적절한 뷰 이름으로 반환
}

2.4. 기본값 지정

@GetMapping("/endpoint")
public String handleRequest(@RequestParam(name = "paramName", defaultValue = "default_value") String paramValue) {
    // 요청 파라미터가 없을 경우 기본값 "default_value"로 설정
    // 사용할 로직
    return "viewName";  // 적절한 뷰 이름으로 반환
}

2.5. 여러 파라미터 받기

@GetMapping("/endpoint")
public String handleRequest(@RequestParam Map<String, String> params) {
    // 모든 요청 파라미터를 Map으로 받을 수 있음
    // 사용할 로직
    return "viewName";  // 적절한 뷰 이름으로 반환
}

 

3. 코드

package com.ssoyeong.studyapplication.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/test/hello")
    public String getHello() {
        return "Hello world!";
    }

    @GetMapping("/test/greeting")
    public String getGreeting(@RequestParam(defaultValue = "이름") String name) {
        return "Hello, " + name + "!";
    }
}

조금 심심해서 defaultValue를 추가해봤다.

 

4. HTTP 요청을 테스트해볼 수 있는 도구

4.1. Postman

API 개발, 테스트, 공유 및 문서화하는 데 사용되는 API 클라이언트

API 엔드포인트 URL을 입력하는 테스트에 사용되며, 서버로 요청을 보내고 서버에서 응답을 받아 API가 잘 동작하는지 확인할 수 있음

 

4.2. cURL

command line에서 서버와 통신할 수 있는 명령어

다양한 프로토콜을 지원한다는 장점(HTTP, FTP, SMTP 등)

근데 마지막에 %는 왜 붙는지 모르겠다...에러 같은데 해결책 못찾음.......

 

4.3. 인텔리제이 HTTP Client 플러그인

.http 파일을 기반으로 RESTful API를 개발하고 테스트하기 위한 도구

 

참고자료

 

아직도 postman 쓰세요? Intellij http를 통해 api를 테스트해보자!

들어가며

sihyung92.oopy.io