제네릭(Generic), 아작스(Ajax)

Generic,Ajax
홍윤's avatar
Sep 06, 2024
제네릭(Generic), 아작스(Ajax)
 

1. 제네릭(Generic)

💡
제네릭(Generic)은 타입을 미리 고정하지 않고 다양한 타입을 처리할 수 있는 코드를 작성하는 방식입니다. 제네릭을 사용하면, 클래스나 메소드를 정의할 때 타입을 구체적으로 지정하지 않고, 나중에 사용할 때 개발자가 원하는 타입을 결정할 수 있게 됩니다. 이는 코드의 재사용성을 높이고, 타입 안전성을 보장하는 중요한 개념입니다.

제네릭은 무엇인가?

제네릭은 타입에 의존하지 않는 코드를 작성하는 방법입니다. 예를 들어, 어떤 클래스나 메소드가 Integer, String, Double 등 여러 타입에 대해 동일한 동작을 수행해야 할 때, 제네릭을 사용하면 하나의 코드로 모든 타입을 처리할 수 있습니다. 이렇게 하면 코드를 여러 번 중복해서 작성할 필요가 없으며, 잘못된 타입을 사용하는 실수를 줄일 수 있습니다.

제네릭의 기본 구조

제네릭은 보통 타입 파라미터를 사용해 정의됩니다. 이 타입 파라미터는 클래스나 메소드 정의에서 사용되며, 그 타입은 나중에 개발자가 이 클래스를 사용할 때 결정됩니다.
 
이 코드를 통해 제네릭(Generic)의 동작 방식과 개발자가 타입을 결정하는 방법에 대해 설명드리겠습니다.

코드 분석

1. Box<T> 클래스

class Box<T> { T data; }
Box<T>제네릭 클래스로, T라는 타입 파라미터를 사용하여 data라는 필드를 선언합니다. 이 T는 타입이 아직 결정되지 않았으며, 클래스를 사용할 때 개발자가 타입을 지정하게 됩니다. 즉, Box<T>는 어떤 타입이든 처리할 수 있는 유연한 클래스입니다.

2. test 메소드

public static <B> Box<?> test(B data) { Box<B> b = new Box(); b.data = data; return b; }
  • 이 메소드는 제네릭 메소드로, <B>라는 제네릭 타입 파라미터를 선언했습니다. 이는 메소드를 호출할 때 B가 어떤 타입인지를 개발자가 결정하게 됩니다.
  • test 메소드는 Box<B>라는 제네릭 객체를 생성하고, B 타입의 데이터를 받아서 Box<B>data 필드에 저장한 후, Box<?> 타입으로 반환합니다.
  • *Box<?>*는 와일드카드(?)로, 반환되는 Box의 구체적인 타입이 무엇인지 명시하지 않고, 어떤 타입이든 받아들일 수 있음을 의미합니다. 즉, 이 메소드는 어떤 타입의 데이터를 담는 Box라도 반환할 수 있지만, 반환된 후 그 안에 들어간 타입이 무엇인지 모른다는 의미입니다.

3. main 메소드

public static void main(String[] args) { Box b = test(1);
여기서 main 메소드에서 test 메소드를 호출하고 있습니다.
  • test(1)1이라는 int 값을 전달하므로, 컴파일러는 BInteger로 결정합니다. 즉, BInteger 타입이 되고, Box<Integer>가 생성됩니다.
  • 하지만 test 메소드는 **Box<?>*를 반환하기 때문에, 반환된 값은 타입 정보가 사라진 상태로 다루어집니다. 즉, 반환된 BoxBox<Integer>라는 타입 정보를 가지고 있지만, <?>로 인해 그 타입이 명시되지 않습니다.

제네릭과 개발자의 역할

이 코드에서 개발자가 타입을 결정하는 과정을 다시 설명하겠습니다.
  1. Box<T> 클래스는 제네릭 타입 T를 사용합니다. 하지만 이때 T는 아직 구체적인 타입이 결정되지 않았습니다. 개발자가 이 클래스를 사용할 때 타입을 결정하게 됩니다.
  1. test 메소드에서는 제네릭 타입 B를 사용합니다. 이 B 역시 호출 시점에 결정됩니다. test(1)이라고 호출했을 때, 컴파일러는 BInteger로 추론합니다. 즉, 개발자가 호출할 때 전달하는 값의 타입에 따라 B가 결정됩니다.
  1. *와일드카드 Box<?>*는 반환될 때 타입을 제한하지 않기 때문에, 반환된 Box의 타입을 정확히 알 수 없게 됩니다. 이는 제네릭에서 타입 정보를 숨기기 위한 방식 중 하나입니다. 즉, 개발자는 타입을 결정할 수 있지만, 특정 상황에서는 그 타입을 숨기거나 모호하게 처리할 수 있습니다.

중요한 개념들

1. 제네릭 타입 파라미터 <T>, <B>

제네릭 클래스나 메소드에서 TB와 같은 타입 파라미터는 코드 작성 시점에 구체적인 타입을 명시하지 않고 유연하게 처리할 수 있도록 합니다. 이 타입 파라미터는 클래스나 메소드가 호출될 때 결정됩니다.

2. 와일드카드 <?>

와일드카드 <?>모든 타입을 수용할 수 있지만, 구체적인 타입을 알 수 없게 만듭니다. 이 경우에는 해당 타입의 값을 읽을 수는 있지만, 추가적인 타입 체크나 타입 캐스팅을 해야 할 수 있습니다.
Box<?> b = test(1); // 와일드카드를 사용하여 반환된 타입을 명시하지 않음
위 코드에서는 반환된 Box의 내부 타입이 무엇인지 모르는 상태로 다루기 때문에, Box<Integer>라고 명시적으로 선언하지 않은 상태에서 타입 정보를 숨긴 셈입니다.

3. 개발자의 타입 결정권

이 코드에서 중요한 점은 개발자가 test 메소드를 호출할 때 전달하는 값에 따라 제네릭 타입이 결정된다는 것입니다. test(1)을 호출하면 BInteger로 결정되고, test("Hello")를 호출하면 BString으로 결정됩니다. 제네릭 코드는 동일하지만, 구체적인 타입은 개발자가 사용하는 상황에 맞게 결정됩니다.

결론

이 코드는 제네릭을 사용해 타입을 일반화하는 예시입니다. 제네릭을 사용하면 코드가 타입에 종속되지 않으며, 개발자가 사용하는 시점에서 타입을 결정할 수 있게 됩니다. 또한, 와일드카드(<?>)를 통해 타입을 유연하게 다루면서도, 반환된 타입의 정보를 숨기거나 제약을 걸 수 있습니다. 이로 인해 유연성과 타입 안전성을 동시에 유지할 수 있게 되는 것이 제네릭의 장점입니다.
 

2. 아작스(Ajax)

💡
Ajax(Asynchronous JavaScript and XML)는 웹 개발에서 비동기적인 통신을 가능하게 하는 기술입니다. Ajax를 사용하면 페이지를 새로 고침하지 않고 웹 서버와 데이터를 주고받을 수 있습니다. 이로 인해 사용자 경험이 더 향상되며, 빠르고 동적인 웹 페이지를 만들 수 있게 됩니다.

Ajax의 핵심 개념

  • Asynchronous (비동기적): Ajax 요청은 웹 페이지를 다시 로드하지 않고 서버와 통신합니다. 즉, 페이지의 특정 부분만 서버와 통신하여 변경할 수 있습니다. 이로 인해 사용자 인터페이스가 중단되지 않고 더 빠르고 매끄럽게 동작합니다.
  • JavaScript: Ajax는 JavaScript를 기반으로 동작합니다. JavaScript를 사용하여 HTTP 요청을 보내고, 서버로부터 받은 데이터를 처리합니다.
  • XML/JSON: 처음에는 XML 형식을 많이 사용했으나, JSON(JavaScript Object Notation)이 더 가볍고 처리하기 쉬워서 현재는 주로 JSON을 사용합니다.

Ajax의 동작 방식

Ajax는 웹 페이지가 서버와 비동기적으로 데이터를 주고받을 수 있도록 합니다. 이 과정을 단계별로 설명하면 다음과 같습니다.
  1. 사용자의 요청: 사용자가 페이지에서 특정 동작(버튼 클릭 등)을 수행하면, JavaScript가 Ajax 요청을 생성합니다.
  1. Ajax 요청 생성: JavaScript는 XMLHttpRequest 객체 또는 fetch API를 사용하여 서버에 HTTP 요청을 보냅니다. 이 요청은 동기적이거나 비동기적으로 처리할 수 있지만, 보통 비동기적으로 사용됩니다.
  1. 서버 처리: 서버는 클라이언트로부터 요청을 받아 필요한 처리를 한 후, 결과 데이터를 클라이언트로 응답합니다. 이 데이터는 주로 JSON이나 XML 형식입니다.
  1. 응답 처리: JavaScript는 서버로부터 받은 데이터를 처리하고, 웹 페이지의 일부를 업데이트하거나 사용자에게 결과를 보여줍니다.
  1. 페이지 재로딩 없음: 전체 페이지를 새로고침하지 않고, 필요한 부분만 변경됩니다.

간단한 Ajax 예시 (JavaScript)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Ajax Example</title> </head> <body> <h1>Ajax Example</h1> <button id="loadDataBtn">Load Data</button> <div id="result"></div> <script> document.getElementById("loadDataBtn").addEventListener("click", function() { var xhr = new XMLHttpRequest(); xhr.open("GET", "<https://jsonplaceholder.typicode.com/posts/1>", true); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { document.getElementById("result").innerHTML = xhr.responseText; } }; xhr.send(); }); </script> </body> </html>

설명

  • XMLHttpRequest 객체: Ajax 요청을 보내기 위한 객체입니다. 이 객체를 사용하여 비동기적으로 서버에 데이터를 요청하고, 그 결과를 처리합니다.
  • GET 요청: 이 예시에서는 외부 API에서 데이터를 받아옵니다. 서버에서 데이터를 가져와 #result라는 div 태그에 결과를 표시합니다.
  • 비동기 요청: xhr.open("GET", "URL", true)에서 마지막 true는 비동기적으로 요청을 보내겠다는 의미입니다.

fetch API를 사용한 Ajax (ES6+)

최근에는 fetch API가 도입되어 Ajax 요청을 더 간단하고 직관적으로 처리할 수 있습니다. fetchPromise를 기반으로 하여 더 깔끔한 비동기 처리가 가능합니다.
document.getElementById("loadDataBtn").addEventListener("click", function() { fetch("<https://jsonplaceholder.typicode.com/posts/1>") .then(response => response.json()) .then(data => { document.getElementById("result").innerHTML = JSON.stringify(data); }) .catch(error => console.error('Error:', error)); });

설명

  • fetch API는 HTTP 요청을 쉽게 보낼 수 있게 해주는 최신 JavaScript API입니다. XMLHttpRequest보다 가독성이 좋고, 비동기 처리를 더 간편하게 할 수 있습니다.
  • *then()*과 catch(): fetch는 비동기적으로 데이터를 처리하고, 응답이 성공하면 then()으로 처리하고, 오류가 발생하면 catch()로 처리합니다.

Ajax의 장점

  1. 빠른 데이터 전송: 페이지 전체를 새로 고침하지 않고 필요한 데이터만 서버로부터 받아오기 때문에 응답 속도가 빠릅니다.
  1. 향상된 사용자 경험: 페이지가 중단 없이 동작하므로, 더 매끄럽고 반응성 좋은 UI/UX를 제공합니다.
  1. 서버 부하 감소: 페이지 전체를 다시 로드하지 않기 때문에 불필요한 서버 요청이 줄어듭니다.

Ajax의 단점

  1. SEO 문제: Ajax로 로딩된 콘텐츠는 초기 HTML에 포함되지 않기 때문에, 검색 엔진에서 인덱싱이 어려울 수 있습니다.
  1. 브라우저 호환성: 최신 브라우저에서는 대부분 지원되지만, 매우 구버전 브라우저에서는 제대로 작동하지 않을 수 있습니다.
  1. 복잡한 디버깅: 비동기 요청과 콜백 함수로 인해 디버깅이 복잡할 수 있습니다.

Ajax의 사용 사례

  1. 실시간 검색: 검색창에 입력할 때마다 결과를 서버에서 비동기적으로 가져오는 기능.
  1. 무한 스크롤: 스크롤할 때마다 서버에서 데이터를 받아와서 페이지에 추가하는 기능.
  1. 양방향 채팅: 페이지를 새로 고침하지 않고 서버와 주고받는 실시간 메시지 서비스.

Ajax는 현대 웹 개발에서 동적이고 빠른 웹 페이지를 만들기 위한 핵심 기술로, 전체 페이지가 아닌 필요한 데이터만 서버와 주고받아 사용자 경험을 크게 개선할 수 있는 도구입니다.

3. 아작스 오류

  • 아작스 요청이 잘못 됐을때 이걸 사용한다.
notion image
  • GlobalApiExceptionHandler 코드 설명
💡
public ResponseEntity<?> ex400(Exception e) { //프론트앤드 개발자가 알기 쉽게 해주기 위해(배려) return new ResponseEntity<>(Resp.fail(400, e.getMessage()), HttpStatus.BAD_REQUEST); }
  • ResponseEntity<?>: Spring의 ResponseEntity는 HTTP 응답을 표현하는 객체입니다. 이 객체는 응답 본문(body), 상태 코드(status), 헤더(headers)를 설정할 수 있습니다.
    • <?>: 제네릭으로 사용되었으며, 반환하는 데이터 타입에 제한을 두지 않겠다는 의미입니다. 즉, 어떤 타입의 응답이든 보낼 수 있습니다.
  • ex400(Exception e): 이 메소드는 Exception 객체를 매개변수로 받아 처리합니다. e는 발생한 예외에 대한 정보를 담고 있으며, 예외의 메시지(e.getMessage())를 통해 오류 내용을 확인할 수 있습니다.
  • new ResponseEntity<>(...): ResponseEntity 객체를 생성하여 반환합니다. 여기서 반환하는 내용은 클라이언트로 전송될 HTTP 응답입니다.
    • Resp.fail(400, e.getMessage()): Resp.fail() 메소드를 호출하여 응답 본문(body)를 생성합니다.
      • 400: HTTP 상태 코드 **400 (Bad Request)**를 나타냅니다. 이는 클라이언트의 잘못된 요청을 의미합니다.
      • e.getMessage(): 예외의 상세 메시지를 가져와서 응답 본문에 포함시킵니다. 이 메시지는 예외 발생 원인에 대한 설명입니다.
    • HttpStatus.BAD_REQUEST: 응답의 HTTP 상태 코드를 설정합니다. 여기서는 400 Bad Request 상태 코드를 나타냅니다. 이는 클라이언트의 요청이 잘못되었을 때 반환하는 코드입니다.

요약:

이 메소드는 클라이언트가 잘못된 요청을 보냈을 때(예: 유효성 검사 실패) 이를 처리하여, HTTP 400 상태 코드와 함께 예외 메시지를 포함한 응답을 반환합니다. 이때 프론트엔드 개발자가 쉽게 이해할 수 있도록 상태 코드와 메시지를 명확하게 제공합니다.
 
 
Share article

Uni