깨록

@RestController 사용 시 불필요한 속성 포함하는 문제 본문

개발하다/Spring

@RestController 사용 시 불필요한 속성 포함하는 문제

쓰온 2024. 5. 28. 12:53

배경

Spring Boot를 사용해 개발하던 중 Controller 레이어에서 클래스에 @RestController를 추가하고 조회하는 메서드를 작성했을 때 문제가 발생했었습니다. 특정 엔티티를 반환하려고 할 때 필드로 작성하지 않은 값까지 추가되어 반환되는 문제가 발생했습니다.

원인 분석

위와 같은 문제는 Jackson 라이브러리가 엔티티의 모든 getter 메서드를 JSON 속성으로 변환하는 기본 동작으로 인해 발생했던 문제였습니다. 즉, 필드를 이외의 값을 조회하는 메서드에도 get...을 사용하였었고 이것이 Jackson 라이브러리의 동작과 겹쳐져 생긴 문제였습니다.

예를 들어, User 엔티티가 있다고 할 때

public class User {
    private Long id;
    private String username;
    private String password;
    private String additionalInfo;

    // 엔티티에 없는 속성
    public String getSomething() {
        return "Something";
    }

    // getters and setters
}

'getSomething()' 메서드는 실제로 엔티티에 속성이 존재하지 않지만, Jackson은 이를 Json 응답에 포함시킵니다.

해결 방법

1. @JsonIgnore 어노테이션 사용

@JsonIgnore 어노테이션을 사용해 특정 속성 또는 메서드를 JSON 직렬화에서 제외할 수 있습니다. 이를 통해 원치 않는 속성이 포함되지 않도록 합니다.

import com.fasterxml.jackson.annotation.JsonIgnore;

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

    // 엔티티에 없는 속성
    @JsonIgnore
    public String getSomething() {
        return "Something";
    }

    // getters and setters
}

예제 코드에 @JsonIgnore을 사용함으로서 JSON 응답에서 제외됩니다.

2. DTO(Data Transfer Object) 사용

DTO를 사용하면 필요한 속성만을 포함하는 객체를 만들어 전송할 수 있습니다. 이를 통해 엔티티와 JSON 응답을 분리하여 관리할 수 있습니다.

// User 엔티티
public class User {
    private Long id;
    private String username;
    private String password;

    // 엔티티에 없는 속성
    public String getSomething() {
        return "Something";
    }

    // getters and setters
}

// UserDTO 클래스
public class UserDTO {
    private Long id;
    private String username;

    // 생성자
    public UserDTO(User user) {
        this.id = user.getId();
        this.username = user.getUsername();
    }

    // getters and setters
}

// UserController 클래스
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping("/{id}")
    public UserDTO getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return new UserDTO(user);
    }
}

위 예제에서 UserDTO는 User 엔티티의 필요한 속성만 포함하도록 설계되었습니다. Controller는 User 엔티티를 가져와 UserDTO로 변환하여 반환합니다.