1. 오버로딩 (Overloading)

오버로딩은 같은 이름의 메서드를 여러 개 정의하는 것을 의미한다.

메서드의 이름은 같지만 매개변수의 수나 타입이 달라야 한다. 오버로딩은 메서드의 서명을 다르게 하여, 메서드를 호출할 때 전달된 인자에 맞는 메서드를 자동으로 선택할 수 있게 한다.

  • 메서드 서명 다름: 메서드 이름은 같지만 매개변수의 수, 타입, 순서가 달라야 한다.
  • 컴파일 타임 다형성: 컴파일 타임에 어떤 메서드가 호출될지 결정된다.
  • 반환 타입은 영향 없음: 반환 타입만으로는 오버로딩을 구분할 수 없다. 매개변수의 차이만로 구분된다.
public class Calculator {
    
    // 정수 두 개를 더하는 메서드
    public int add(int a, int b) {
        return a + b;
    }
    
    // 실수 두 개를 더하는 메서드
    public double add(double a, double b) {
        return a + b;
    }
    
    // 정수 세 개를 더하는 메서드
    public int add(int a, int b, int c) {
        return a + b + c;
    }
}

 

오버라이딩 (Overriding)

오버라이딩은 상속받은 클래스에서 부모 클래스의 메서드를 재정의하는 것을 의미한다

오버라이딩을 통해 자식 클래스에서 부모 클래스의 메서드를 자신에게 맞게 구현할 수 있다

  • 메서드 서명 동일: 부모 클래스와 자식 클래스의 메서드는 이름, 반환 타입, 매개변수 리스트가 모두 동일해야 한다.
  • 런타임 다형성: 런타임에 어떤 메서드가 호출될지 결정된다.
  • @Override 어노테이션 사용: 메서드가 오버라이딩되고 있음을 명시하기 위해
  • @Override 어노테이션을 사용할 수 있다
 
public class Animal {
    // 부모 클래스 메서드
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

public class Dog extends Animal {
    // 부모 클래스의 메서드를 오버라이딩
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound(); // "Dog barks" 출력
    }
}

비교

오버로딩 (Overloading)오버라이딩 (Overriding)

정의 같은 이름의 메서드를 매개변수 목록을 다르게 정의 부모 클래스의 메서드를 자식 클래스에서 재정의
메서드 서명 다름 (매개변수의 수/타입/순서) 동일 (메서드 이름, 반환 타입, 매개변수 리스트)
다형성 컴파일 타임 다형성 (메서드 선택은 컴파일 시 결정) 런타임 다형성 (메서드 선택은 실행 시 결정)
목적 메서드의 이름 재사용 및 여러 버전 제공 상속받은 메서드를 자식 클래스에 맞게 변경
사용 예 같은 작업을 다양한 데이터 타입으로 처리 부모 클래스의 기본 동작을 자식 클래스에서 수정

'CS > JAVA' 카테고리의 다른 글

세션의 값을 저장하고 꺼내는 법  (0) 2024.08.14
추상클래스와 인터페이스  (0) 2024.08.13
Model1과 Model2 아키텍처  (0) 2024.08.13
private 생성자 사용 이유  (0) 2024.07.23
Map  (0) 2024.07.08

Model1Model2 아키텍처는 웹 애플리케이션의 구조를 정의하는 디자인 패턴이다.

주로 JSP(JavaServer Pages)와 서블릿(Servlet) 기반의 웹 애플리케이션에서 사용되며

각각의 아키텍처는 웹 애플리케이션의 구성 방식과 책임 분리에 차이가 있다.

Model1 아키텍처

Model1 아키텍처는 간단한 구조를 갖추고 있으며

웹 애플리케이션의 모든 처리가 하나의 컴포넌트에서 이루어진다.

JSP 페이지나 서블릿이 데이터 처리와 사용자 인터페이스를 모두 담당한다

 

단일 컴포넌트

  • 데이터 처리와 사용자 인터페이스 로직이 같은 JSP 페이지나 서블릿에 포함되어 있다.
  • 하나의 컴포넌트가 모든 작업을 처리한다
  • 단순한 구조로 간단한 웹 애플리케이션이나 작은 프로젝트에서 빠르게 개발할 수 있다
  • 코드가 혼합되어 있어 유지보수와 확장성이 떨어진다.
  • 애플리케이션의 규모가 커질수록 코드의 복잡도가 증가하며 코드가 길어진다
<%@ page import="java.sql.*" %>
<html>
<head><title>Model1 Example</title></head>
<body>
<%
    // Database connection and query execution
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db", "user", "password");
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM users");
%>
<h1>Users List</h1>
<ul>
<%
    while (rs.next()) {
        String name = rs.getString("name");
%>
    <li><%= name %></li>
<%
    }
    conn.close();
%>
</ul>
</body>
</html>

Model2 아키텍처 (MVC 패턴)

Model2 아키텍처는 MVC(Model-View-Controller) 디자인 패턴을 따른다.

이 아키텍처는 웹 애플리케이션의 책임을 세 가지 주요 컴포넌트로 분리하여 관리한다.

구성 요소:

  1. Model:
    • 설명: 데이터와 비즈니스 로직을 처리하는 컴포넌트이다.
    • 데이터베이스와의 상호작용, 비즈니스 로직의 처리를 담당한다.
    • 예시: VO, DAO(Data Access Object) 클래스 등.
  2. View:
    • 설명: 사용자 인터페이스를 담당하는 컴포넌트이다.
    • 사용자에게 데이터를 표시하고, 입력을 받아서 Controller로 전달한다.
    • 예시: JSP 페이지, HTML 템플릿 등.
  3. Controller:
    • view에서 요청을 받고, 필요한 비즈니스 로직을 Service에 연결하는 연결 역할을 한다.
    • 예시: 서블릿, Spring의 Controller 클래스 등.
  • 데이터 처리와 사용자 인터페이스가 분리되어 있어 코드의 유지보수가 용이하다.
  • 각 컴포넌트를 독립적으로 수정할 수 있어, 애플리케이션의 확장성과 유연성이 높다.
  • 중간에서 대규모 웹 애플리케이션 및 복잡한 시스템에 적합하다.

Model (DAO 클래스):

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class UserDAO {
    public List<String> getUsers() throws SQLException {
        List<String> users = new ArrayList<>();
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db", "user", "password");
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT name FROM users");
        while (rs.next()) {
            users.add(rs.getString("name"));
        }
        conn.close();
        return users;
    }
 
 
View (JSP 페이지)
 
<!-- user.jsp -->
<html>
<head><title>User Information</title></head>
<body>
<h1>User Details</h1>
<p>Name: ${user.name}</p>
<p>Age: ${user.age}</p>
</body>
</html>
 

Controller (Servlet):

@WebServlet("/user")
public class UserController extends HttpServlet {
    private UserService userService = new UserService();
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int userId = Integer.parseInt(request.getParameter("id"));
        User user = userService.getUserById(userId);
        request.setAttribute("user", user);
        RequestDispatcher dispatcher = request.getRequestDispatcher("/user.jsp");
        dispatcher.forward(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 사용자 정보 업데이트 로직
        User user = new User();
        user.setName(request.getParameter("name"));
        user.setAge(Integer.parseInt(request.getParameter("age")));
        userService.updateUser(user);
        response.sendRedirect("/user");
    }
}

 

Service:

public class UserService {
    public User getUserById(int id) {
        // 데이터베이스에서 사용자 정보를 조회하고 반환
        // 예를 들어, UserDAO를 사용하여 데이터베이스 쿼리
        User user = userDAO.findById(id);
        return user;
    }
    
    public void updateUser(User user) {
        // 사용자 정보를 업데이트
        userDAO.update(user);
    }
}

'CS > JAVA' 카테고리의 다른 글

추상클래스와 인터페이스  (0) 2024.08.13
오버로딩과 오버라이딩  (0) 2024.08.13
private 생성자 사용 이유  (0) 2024.07.23
Map  (0) 2024.07.08
컨트롤러 어노테이션  (0) 2024.06.29

필드를 만들때 왜 public이 아니라 private를 쓸까?

private 생성자는 해당 클래스의 인스턴스를 제한하는데 사용된다.

이를 통해 클래스의 인스턴스화를 제어하고 객체의 불변성을 보장한다.

 

1. 클래스의 싱글톤 패턴을 구현

 

싱글톤 패턴은 애플리케이션 내에 특정 클래스의 인스턴스가 하나만 존재하도록 보장하는 패턴이다.

이 패턴을 구현할 때 private 생성자를 사용하여 외부에서 객체를 생성할 수 없도록 한다.

 

전역적 접근 제어: 인스턴스 생성을 방지하여 상태가 공유되는 것을 제어할 수 있다.

일관성 유지: 하나의 인스턴스를 사용하므로 객체의 일관성을 유지한다.

 

2. 인스턴스 생성을 막고 정적 메서드만을 제공

 

일관성 있는 사용 패턴: 정적 메서드를 통해 일관된 사용 패턴을 제공하며

객체의 상태 변화에 따른 부작용을 방지한다.

 

3. 상속을 방지하여 클래스의 불변성과 안정성을 보장할 수 있다.

 

상속을 사용하면 부모 클래스와 자식 클래스 사이에 강한 결합도가 생길 수 있다.

부모 클래스가 변경되면 이를 상속받은 모든 자식 클래스에 해당 변경을 반영해야 한다.

 

스레드 안전성: 불변 객체는 여러 스레드에 동시 접근해도 안전하게 사용될 수 있다.

참조 불변성: 불변 객체는 다른 객체가 자신을 변경할 수 없기 때문에 의도한대로 동작함.

 

 

결론: 필드를 만들때 private 로 선언하자

 

'CS > JAVA' 카테고리의 다른 글

오버로딩과 오버라이딩  (0) 2024.08.13
Model1과 Model2 아키텍처  (0) 2024.08.13
Map  (0) 2024.07.08
컨트롤러 어노테이션  (0) 2024.06.29
Getter/Setter  (0) 2024.06.26

java의 Map은 key-value 쌍으로 데이터를 저장하는 자료 구조이다.

 

주요 특징

Key-Value구조 Map은 각 요소가 key와 그에 대응하는 value로 구성된다.
유일한 Key Map은 각 key가 유일해야 한다. 1:1 구조를 가진다
다양한 구현 클래스 java에서 Map 인터페이스의 구현체는 HashMap, TreeMap, LinkedHashMap 이 있다.

 

주요 메서드

A put(K key, V value) 지정된 key와 value를 매핑하여 Map에 추가한다
V get(Object key) 지정된 key에 매핑된 value 반환. key가 존재하지 않으면 null을 반환한
boolean containsKey
(object Key)
지정된 key가 Map에 있는가
boolean containsValue(object value) 지정된 value가 Map에 있는가
V remove(object key) 지정된 key와 그에 매핑된 value를 Map에서 제거하여 value 반환
int size() Map에 저장된 key-value 쌍의 개수 반환
void clear() Map의 모든 요소 제거

 

주요 구현 클래스

HashMap<K, V>

해시 테이블을 기반으로 key-value쌍 저장. O(1)의 시간 복잡도를 가진다

 

import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        // HashMap 생성
        Map<String, Integer> hashMap = new HashMap<>();

        // 요소 추가
        hashMap.put("apple", 10);
        hashMap.put("banana", 20);
        hashMap.put("cherry", 15);

        // 요소 접근
        System.out.println("Value of apple: " + hashMap.get("apple")); // 10

        // 요소 수정
        hashMap.put("banana", 25); // banana의 value를 25로 수정

        // 요소 제거
        hashMap.remove("cherry");

        // 모든 key와 value 출력
        System.out.println("HashMap:");
        for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        // HashMap 크기 확인
        System.out.println("Size of HashMap: " + hashMap.size());
    }
}
Value of apple: 10
HashMap:
Key: apple, Value: 10
Key: banana, Value: 25
Size of HashMap: 2

 

TreeMap<K, V>

Red-Black 트리를 사용하여 key-value 쌍을 정렬된 상태로 저장
key에 대해 정렬된 순서를 유지하며 O(log n)의 시간 복잡도를 가짐

 

import java.util.Map;
import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        // TreeMap 생성
        Map<String, Integer> treeMap = new TreeMap<>();

        // 요소 추가
        treeMap.put("apple", 10);
        treeMap.put("banana", 20);
        treeMap.put("cherry", 15);

        // 요소 접근
        System.out.println("Value of banana: " + treeMap.get("banana")); // 20

        // 요소 수정
        treeMap.put("banana", 25); // banana의 value를 25로 수정

        // 요소 제거
        treeMap.remove("cherry");

        // 모든 key와 value 출력
        System.out.println("TreeMap:");
        for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        // TreeMap 크기 확인
        System.out.println("Size of TreeMap: " + treeMap.size());
    }
}
Value of banana: 20
TreeMap:
Key: apple, Value: 10 //사전 순으로 정렬된다
Key: banana, Value: 25
Size of TreeMap: 2

 

Hashtable<K, V>

해시맵을 기반으로 인덱스를 주어 빠른 검색속도를 보장한다. 평균 시간복잡도는 O(1) 이다.

 

import java.util.Hashtable;
import java.util.Map;

public class HashtableExample {
    public static void main(String[] args) {
        // Hashtable 생성
        Map<String, Integer> hashtable = new Hashtable<>();

        // 요소 추가
        hashtable.put("apple", 10);
        hashtable.put("banana", 20);
        hashtable.put("cherry", 15);

        // 요소 접근
        System.out.println("Value of banana: " + hashtable.get("banana")); // 20

        // 요소 수정
        hashtable.put("banana", 25); // banana의 value를 25로 수정

        // 요소 제거
        hashtable.remove("cherry");

        // 모든 key와 value 출력
        System.out.println("Hashtable:");
        for (Map.Entry<String, Integer> entry : hashtable.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        // Hashtable 크기 확인
        System.out.println("Size of Hashtable: " + hashtable.size());
    }
}
Value of banana: 20
Hashtable:
Key: banana, Value: 25
Key: apple, Value: 10
Size of Hashtable: 2

'CS > JAVA' 카테고리의 다른 글

Model1과 Model2 아키텍처  (0) 2024.08.13
private 생성자 사용 이유  (0) 2024.07.23
컨트롤러 어노테이션  (0) 2024.06.29
Getter/Setter  (0) 2024.06.26
참조변수와 일반변수에 대하여  (1) 2024.03.07

Controller 어노테이션은 @Component를 구체화하여 만든 어노테이션을

IoC컨테이너에 Bean으로 등록해주며 이 클래스가 Controller로 사용된다는 것을 알려준다.

 

@Controller
public class HomeController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("message", "Welcome to the home page!");
        return "home"; // "home"은 View의 이름을 나타냅니다.
    }
}

 

1. 구체화된 @Component

  • Component는 스프링에서 관리하는 컴포넌트를 나타내는 어노테이션으로 해당 클래스가 스프링 IOC 컨테이너에서 관리되어야 함을 정의한다.
  • @Controller는 @Component의 구체화된 형태로 스프링 MVC에서 웹 어플리케이션의 요청을 처리하는 컨트롤러 역할이다.

2. Bean으로 등록

  • 스프링 IOC 컨테이너는 애플리케이션을 구성하는 여러 객체들을 관리하고 이를 Bean이라고 한다.
  • @Controller 어노테이션이 붙은 클래스는 컨트롤러로 사용될 것임을 명시하며, 이를 스프링에 등록하여 관리하도록 요청한다.

3. Controller로 사용

  • Controller로 지정된 클래스 웹 애플리케이션에서 HTTP 요청을 처리하고 응답을 반환하는 역할을 한다. 주로 HTML 뷰를 렌더링 하거나 JSON 형태의 데이터를 반환하는데 사용된다.
  • 그 종류에는 View를 리턴하는 @Controller와 Json 데이터를 리턴하는 @RestController가 있다.

@Controller

@Controller 어노테이션은 스프링 MVC 패턴에서 사용되며  주로 View 기반의 애플리케이션에서 요청을 처리하고

화면을 반환한다.

 

@Controller
public class HomeController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("message", "Welcome to the home page!");
        return "home"; // "home"은 View의 이름을 나타냅니다.
    }
}

 

/home 경로로 들어오는 Get 요청을 처리하고 home 문자열을 반환하여

View Resolver가 실제 View를 찾아 렌더링한다.

 

즉, @Controller로 지정된 클래스의 메서드들은 HTML 페이지를 반환하거나

View의 값을 지정하여 이를 랜더링하는 역할을 수행한다.

 

@RestController

  • @RestController 어노테이션은 @Controller의 확장 형태이다.
  • JSON 또는 XML 형식의 데이터를 반환하는 RESTful 서비스의 컨트롤러에 사용된다.
  • @RestController로 지정된 클래스의 모든 메서드는 @ResponseBody가 적용된 것으로 간주된다.
  • 메서드가 반환하는 객체를 문자열 형태로 변환하여 클라이언트에게 전송한다.
@RestController
@RequestMapping("/api")
public class ProductController {

    @GetMapping("/products/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        // id에 해당하는 제품 정보를 조회하여 반환
        Product product = productService.getProductById(id);
        
        if (product != null) {
            return ResponseEntity.ok(product);
        } else {
            return ResponseEntity.notFound().build();
        }
    }
}

 

/api/products/{id} 경로로 들어오는 GET 요청을 처리하고

Product 객체를 JSON 형식으로 변환하여 클라이언트에게 반환한다.

컨트롤러에 사용되는 Mapping 어노테이션 (HTTP 요청)

 

@RequestMapping

 

클라이언트의 HTTP 요청 (URL)이 올 때 어떤 메소드로 처리할지 연결하는 어노테이션이다.

주로 컨트롤러 클래스나 메서드 위에 붙여서 사용되며  옵션을 설정해 주소나 매핑의 방식을 정할 수 있다.

 

옵션 설명
value 연결할 URL을 설정한다. 다른 옵션이 없다면 생략 가능하다.
method RequestMethod를 통해 사용되는데 주로 GET, POST, PUT, DELETE를 많이 사용한다.
params 클라이언트에게 받은 데이터를 전달받기 위해 사용
headers header의 정보를 전달해주는 옵션이다

 

자세한 내용은 

https://tecoble.techcourse.co.kr/post/2021-06-18-spring-request-mapping/ 참고.

동작 방식과 옵션들에 대해 자세하게 설명되어 있다.

 

메서드의 경우 각각에 맞는 메서드 옵션이 적용된 어노테이션이 존재해 생략 가능하다.

 

params는 api url은 /examle?id=1&password=2와 같이 전달하고 싶을 때 사용하는 것으로 

param에 전달한 것과 일치하는 param이 붙으면 이 메서드로 매핑해준다. 

 @RequestMapping(method = RequestMethod.GET, value = "/example", params = {"id", "password"})
    public ResponseEntity<Example> getExample(@RequestParam("id") int paramId, @RequestParam("password") String password) {
      Example example = new Example("example" + paramId + password);
      return ResponseEntity.ok(example);
    }

 

header

    @PostMapping(value = "/example/{text}", headers = "content-type=text/plain")
    public ResponseEntity<Example> getExample3(@PathVariable("text") String text) {
      Example example = new Example("example" + text);
      return ResponseEntity.ok(example);
    }

 

와 같이 content-type을 지정해준 경우

 

 

위와 같이 헤더가 들어온다. (예시는 블로그 참조)

@Controller
@RequestMapping("/products")
public class ProductController {

    @RequestMapping(method = RequestMethod.GET)
    public String getAllProducts(Model model) {
        // 처리 로직
        return "products";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String getProductById(@PathVariable("id") Long id, Model model) {
        // 처리 로직
        return "productDetail";
    }
}

 

 

@RequestMapping의 경우 같은 value 값으로 GET, POST를 만들때 메서드를 따로 만들어줘야 한다는 단점이 있다.

url은 class에 requestMapping으로 설정을 해주고

그 안의 메서드들에게 Get, post, put, delete 어노테이션을 붙여 간결하게 생략한다.

뒤에 추가적으로 url을 붙이고 싶다면 어노테이션뒤에 추가적인 url을 작성한다.

 

@RestController
@RequestMapping(value = "/hello")
public class HelloController {

    @GetMapping()
    public String helloGet(...) {
        ...
    }

    @PostMapping()
    public String helloPost(...) {
        ...
    }

    @PutMapping()
    public String helloPut(...) {
        ...
    }

    @DeleteMapping()
    public String helloDelete(...) {
        ...
    }
}
@RestController
@RequestMapping(value = "/hello")
public class HelloController {    
    @GetMapping("/hi")
    public String helloGetHi(...) {
        ...
    }
}

 

@GetMapping 데이터를 가져올 때 사용된다. Get 방식을 사용한다
@PostMapping 데이터를 입력할 때 사용된다. Post 방식을 사용한다.
@PutMapping 데이터를 수정할 떄 사용한다. Put 방식을 사용한다.
@DeleteMapping 데이터를 삭제할때 사용한다. Delete 방식을 사용한다.

.

Spring mvc 패턴에서 수정과 삭제는 일반적으로 서버에서 처리하기 때문에 

get, post만 자주 사용된다고 보면 된다.

 

컨트롤러에서 Parameter 받기

@RequestParam

@RequestParam 어노테이션은 스프링 MVC에서 클라이언트가 요청한 URL의 쿼리 스트링에서

파라미터 값을 추출하여 메서드의 매개변수에 할당한다.

쿼리 스트링: URL의 끝 부분에 위치하며 ? 문자로 시작하여 키와 값의 쌍으로 구성된 데이터를 포함한다.

주로 웹에서 GET방식의 요청 시 데이터를 전달하는 데 사용된다.

 

예를 들어 클라이언트가 http://localhost:8080/api/user?username=johndoe&password=12345
와 같은 쿼리 스트링을 포함하는 요청을 보낼 때

 

메서드는 username=johndoe와 password=12345를 @RequestParam 어노테이션을 통해 받는다.

 

쿼리문의 파라미터 이름과 메소드에 적힌 이름이 같다면 굳이 어노테이션을 적어주지 않아도 된다.

 

@RequestBody

HTTP POST 요청의 본문(body) 데이터를 자바 객체로 변환하여 받을 때 사용되는 어노테이션이다. 

 

주로 JSON이나 plain text형식의 데이터를 컨트롤러에서 처리할 때 사용된다.

이 어노테이션을 사용하면 클라이언트가 전송한 데이터를 자바 객체로 변환하는 과정을 자동으로 처리할 수 있다.

 

HTTP POST 요청 처리

  • @RequestBody 어노테이션은 POST 요청의 본문(body)에 포함된 데이터를 읽어와서 자바 객체로 변환한다.
  • 주로 JSON 형식의 데이터를 자바 객체로 변환하여 컨트롤러에서 사용할 수 있도록 한다.
  • 메서드 전체를 문자열 형식으로 읽기 때문에 때문에 redirect시 클라이언트에서 처리해주어야 한다.

MessageConverter

  • 스프링은 @RequestBody 어노테이션이 적용된 메서드에 대해 HttpMessageConverter 인터페이스를 사용하여 HTTP 요청의 본문을 자바 객체로 변환한다.
  • 예를 들어, JSON 데이터를 처리하기 위해 MappingJackson2HttpMessageConverter가 사용되는데 이 Converter는 JSON 데이터를 자바 객체로 변환할 수 있다.

지원하는 데이터 타입

  • 주로 text/plain 또는 application/json 타입의 데이터를 처리할 때 사용된다.
  • text/plain은 단순한 문자열 형식의 데이터를 받을 때 사용된다.
  • application/json은 JSON 형식의 데이터를 받을 때 주로 사용된다.

Ajax 통신과의 관련

  • Ajax를 통해 JSON 형식으로 데이터를 서버에 전송할 때 @RequestBody 어노테이션이 주로 사용된다.
  • 클라이언트 측 JavaScript에서 JSON 형식으로 데이터를 생성하여 POST 요청을 보내면, 스프링 MVC는 @RequestBody를 통해 이 데이터를 자바 객체로 변환하여 컨트롤러에서 사용할 수 있다.
@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/user")
    public ResponseEntity<String> createUser(@RequestBody User user) {
        // @RequestBody를 통해 전송된 JSON 데이터가 User 객체로 자동 변환됩니다.
        // User 객체를 이용한 로직 처리 (예시에서는 단순히 사용자 정보 출력)
        String response = "Received user: " + user.toString();
        return ResponseEntity.ok(response);
    }
}

 

위 예시에서 /api/user 경로로 POST 요청이 들어오면 createUser 메서드가 실행된다.

이 메서드의 매개변수 @RequestBody User user는 클라이언트가 전송한 JSON 데이터를

자동으로 User 객체로 변환하여 받는다.

 

@PathVariable

URL 경로에서 변수 값을 추출하여 메서드의 매개변수로 전달받을 때 사용된다.

주로 RESTful 웹 서비스에서 URL 경로에 동적인 값을 넣어 요청을 처리할 때 활용된다.

 

URL 경로에서 변수 값 추출

  • @PathVariable 어노테이션은 URL 경로에 포함된 {변수이름} 부분의 값을 추출하여 메서드의 매개변수로 전달받는다.
  • 예를 들어, /api/user/{userId}와 같은 경로에서 userId라는 변수 값을 추출할 수 있다.

 

  • 변수 이름 매칭:
    • 기본적으로 {변수이름}과 메서드의 매개변수 이름이 동일해야한다. 이 경우 스프링은 자동으로 경로 변수 값을 매핑한다.
    • 예를 들어, /api/user/{userId}라는 경로에서 userId라는 매개변수를 가진 메서드가 있으면, 스프링은 {userId}의 값을 userId 매개변수에 할당한다.
  • 변수 이름 지정:
    • 경우에 따라 URL 경로 변수의 이름과 메서드의 매개변수 이름이 다를 수 있다. 이 때는 @PathVariable("변수이름")과 같이 명시적으로 변수 이름을 지정한다.
    • 예를 들어, /api/user/{id}라는 경로에서 메서드의 매개변수 이름이 userId일 경우 @PathVariable("id")로 명시하여 매핑할 수 있다.
@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/user/{userId}")
    public ResponseEntity<String> getUserInfo(@PathVariable Long userId) {
        // @PathVariable을 통해 {userId} 값이 Long 타입으로 자동 변환되어 매개변수 userId에 전달됩니다.
        // userId를 이용한 사용자 정보 조회 로직 (예시에서는 단순히 userId 출력)
        String response = "User ID: " + userId;
        return ResponseEntity.ok(response);
    }
}

 

 

위 예시에서 /api/user/{userId} 경로로 GET 요청이 들어오면, getUserInfo 메서드가 실행된다.

{userId}는 클라이언트가 전송한 실제 사용자 ID 값으로 대체되고,

이 값을 @PathVariable Long userId를 통해 자동으로 userId 매개변수로 받아서 사용할 수 있다.

 

@ModelAttribute

클라이언트가 전달한 파라미터를 자바 객체의 필드에 할당한다. 

주로 HTML 폼에서 입력된 데이터를 컨트롤러로 전송할 때 활용되며

여러 개의 파라미터를 한 번에 객체로 받아올 수 있다.

 

 

  • 클라이언트 데이터 바인딩:
    • @ModelAttribute 어노테이션을 사용하면 클라이언트가 전송한 파라미터를 자바 객체에 할당한다.
    • 클라이언트가 전송한 데이터는 자동으로 해당 객체의 Setter를 통해 필드에 설정된다. 생성자를 통해 초기화도 가능하다.
  • HTML 폼 데이터 처리
    • 주로 HTML 폼에서 사용자가 입력한 데이터를 서버로 전송할 때 사용된다. 폼의 각 입력 필드의 이름과 자바 객체의 필드 이름이 일치해야 자동으로 할당된다.
  • @RequestParam과의 차이점
    • @RequestParam은 URL 쿼리 스트링이나 POST 요청의 특정 파라미터 값을 매개변수로 받아온다.
    • @ModelAttribute는 여러 개의 파라미터를 하나의 객체로 받아올 수 있다. 주로 HTML 폼에서 여러 입력 값을 한 번에 받아와야 할 때 유용하다.
  • Setter 메서드와 생성자 필요
    • @ModelAttribute를 사용할 때는 해당 객체에 값을 설정할 수 있는 Setter 메서드가 필요하다. 생성자도 있으면 좋다.
    • 스프링은 Setter 메서드를 통해 입력된 데이터를 객체에 할당한다.
@Controller
@RequestMapping("/user")
public class UserController {

    @PostMapping("/add")
    public String addUser(@ModelAttribute UserForm userForm, Model model) {
        // @ModelAttribute를 통해 userForm 객체에 클라이언트가 전송한 데이터가 자동으로 바인딩됩니다.
        // UserForm 클래스는 폼에서 전송된 데이터를 받기 위한 DTO(Data Transfer Object)입니다.
        
        // 예시에서는 받은 데이터를 모델에 추가하여 뷰로 전달합니다.
        model.addAttribute("userForm", userForm);
        
        return "userDetail"; // userDetail이라는 뷰를 반환
    }
}

 

 

UserForm은 HTML 폼에서 입력된 데이터를 받기 위한 클래스이다.

 

@ModelAttribute 어노테이션을 사용하여

addUser메서드의 매개변수로 UserForm 객체를 받아와 클라이언트가 입력한 데이터를 자동으로 설정한다.

 

리다이렉션

클라이언트의 요청을 다른 URL로 전환한다. 

스프링 MVC에서는 redirect:/주소 형식을 사용하여 리다이렉션을 수행할 수 있다.

이를 통해 다른 메서드나 경로를 재사용하고 클라이언트를 다른 페이지로 보낼 수 있다.

 

  • HTTP 상태 코드: 리다이렉션은 클라이언트에게 HTTP 상태 코드 302를 반환하여 임시적으로 리소스가 이동되었음을 알려준다. 

리다이렉션 과정

  1. 리다이렉션 요청: 클라이언트가 요청한 작업이 완료되었을 때, 그 결과를 보여주기 위해 다른 페이지로 이동시키고 싶을 때 사용한다.
  2. redirect:/주소지 형식: redirect: 다음에는 이동할 URL을 지정한다. 이 URL은 애플리케이션의 상대 경로일 수도 있고, 절대 경로일 수도 있다. 보통은 상대 경로를 사용하여 다른 컨트롤러 메서드나 정적 리소스 경로로 이동한다.
@Controller
public class LoginController {

    @Autowired
    private UserService userService;
    
    @GetMapping("/loginForm")
    public String loginForm() {
        return "loginForm"; // 로그인 폼을 보여주는 뷰 이름
    }
    
    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password, HttpSession session) {
        // 로그인 로직 처리
        boolean isAuthenticated = userService.authenticate(username, password);
        
        if (isAuthenticated) {
            session.setAttribute("username", username);
            return "redirect:/home"; // 로그인 성공 후 /home으로 리다이렉션
        } else {
            return "redirect:/loginForm?error=true"; // 로그인 실패 시 다시 로그인 폼으로 리다이렉션
        }
    }
    
    @GetMapping("/home")
    public String home() {
        return "home"; // 홈 페이지 뷰 이름
    }
}

 

 

1. /loginForm 경로에서는 로그인 폼을 보여주는 loginForm 뷰를 반환한다.

2. /login 경로에서는 POST 요청을 받아 로그인 정보를 검증하고, 성공 시 redirect:/home으로 홈 페이지로 리다이렉션한다.

3. 로그인 실패 시 redirect:/loginForm?error=true으로 다시 로그인 폼으로 리다이렉션하며, error=true 쿼리 파라미터를 추가하여 실패 상태를 알려준다.

4. /home 경로에서는 로그인 성공 후 리다이렉션되어 보여질 홈 페이지를 나타내는 home 뷰를 반환한다.

 

'CS > JAVA' 카테고리의 다른 글

private 생성자 사용 이유  (0) 2024.07.23
Map  (0) 2024.07.08
Getter/Setter  (0) 2024.06.26
참조변수와 일반변수에 대하여  (1) 2024.03.07
클래스 설정  (0) 2024.01.23

자바 웹 프로그래밍

 

데이터베이스에서 데이터를 가져올 때 특정 테이블과 매핑되어 데이터를 가져오는 역할을 하는 클래스를 만든 후

Getter Setter는 데이터 클래스에서 데이터를 읽고 쓰는 역할을 한다.

 

Getter/Setter의 사용 예시

1. 데이터베이스의 특정 테이블에 대응되는 클래스를 만든다

예를 들어, 사용자 정보를 관리하는 User 클래스를 만든다고 가정한다.

public class User {
    private Long id;
    private String username;
    private String email;

    // Getter for id
    public Long getId() {
        return id;
    }

    // Setter for id
    public void setId(Long id) {
        this.id = id;
    }

    // Getter for username
    public String getUsername() {
        return username;
    }

    // Setter for username
    public void setUsername(String username) {
        this.username = username;
    }

    // Getter for email
    public String getEmail() {
        return email;
    }

    // Setter for email
    public void setEmail(String email) {
        this.email = email;
    }
}

 

user 클래스는 사용자의 id, username, email을 나타내는 변수를 가지고 있다.

각 변수에 getter setter 메소드가 정의되어 있어 이 클래스의 데이터를 읽고 쓸 수 있다.

Setter를 사용하여 데이터 설정 및 가공

Setter 메소드를 사용하여 객체의 데이터를 설정하거나 가공할 수 있다.

Setter을 호출하여 객체의 상태를 변경한다.

 

예를 들어, User 객체의 setEmail 메소드를 사용하여 이메일을 설정할 수 있다.

 

public class UserController {

    // ... (다른 필드와 메소드는 생략)

    public void updateUserEmail(Long userId, String newEmail) {
        User user = userService.getUserById(userId);
        if (user != null) {
            // 예: 이메일 형식 검사
            if (isValidEmail(newEmail)) {
                user.setEmail(newEmail); // Setter를 통해 이메일 설정
                userService.updateUser(user); // 사용자 정보 업데이트
            } else {
                throw new IllegalArgumentException("유효하지 않은 이메일 형식입니다.");
            }
        } else {
            throw new IllegalArgumentException("해당 ID에 해당하는 사용자가 없습니다.");
        }
    }

    private boolean isValidEmail(String email) {
        // 이메일 형식 검사 로직 (정규 표현식 등)
        return email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    }
}

 

1. userService.getUserById(userId) 를 통해 주어진 userId에 해당하는 User객체를 가져온다

2. 가져온 user 객체가 null이 아닐 경우 새로운 이메일 주소인 newEmail을 user.setEmail(newEmail)을 통해 할당한다

3.userService.updateUser(user)을 호출하여 변경된 사용자 정보를 DB에 업데이트 한다

 

'CS > JAVA' 카테고리의 다른 글

Map  (0) 2024.07.08
컨트롤러 어노테이션  (0) 2024.06.29
참조변수와 일반변수에 대하여  (1) 2024.03.07
클래스 설정  (0) 2024.01.23
지역변수의 특징  (0) 2024.01.18

+ Recent posts