Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- K-nearest neighbor
- image_picker
- CS231n
- ModalBottomSheet
- 뮤직플레이어
- Firebase
- 국방오픈소스아카데미
- 고연전
- Dijkstra
- text recognition
- 앱 개발
- loss function
- optimization
- KUsic
- 백준
- 해커톤
- 앱
- 이미지 분류
- 응원가
- 고려대학교 응원가
- 다익스트라
- 더보기창
- linear classifier
- 고려대학교
- image classification
- flutter
- google_ml_kit
- 알고리즘
- 앱 출시
- OSAM
Archives
- Today
- Total
영주머니의 개발주머니
ArgumentResolver 종류 및 사용 예시 본문
@RequestParam
- 1개의 HTTP 요청 파라미터를 받기 위해 사용한다.
@ModelAttribute
- 클라이언트가 전송하는 폼(Form) 형태의 HTTP Body와 요청 파라미터들을 생성자나 Setter로 바인딩하기 위해 사용된다.
- @ModelAttribute에는 매핑시키는 파라미터의 타입이 객체의 타입과 일치하는지 등을 포함한 다양한 검증(Validation) 작업이 추가적으로 진행된다.
@RequestBody
- 클라이언트가 전송하는 Json 형태의 HTTP Body를 Java 객체로 변환해주는 역할을 한다.
- @RequestBody로 받는 데이터는 Spring에서 관리하는 MessageConverter들 중 하나인 MappingJackson2HttpMessageConverter를 통해 Java 객체로 변환되는데, 이는 ObjectMapper라는 클래스를 사용한다.
사용 예시
- 테스트를 위해 아래와 같은 User 객체가 있다고 하자.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Enumerated(EnumType.STRING)
private UserRole role;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setRole(UserRole role) {
this.role = role;
}
public UserRole getRole() {
return role;
}
}
@RequestParam 사용 예시
- Controller
@PostMapping("/signup")
public String signup(@RequestParam("name") String name,
@RequestParam("role") UserRole role) {
User user = new User();
user.setName(name);
user.setRole(role);
User savedUser = userService.signUp(user);
session.setAttribute(SessionConstant.CURRENT_USER, savedUser);
return new CouponResponse<>("회원가입이 완료되었습니다.");
}
- 요청 형태(1) : URL 쿼리 파라미터
POST /signup?name=홍길동&role=USER
- 요청 형태(2): application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
name=홍길동&role=USER
- 요청 처리 과정
- @RequestParam을 보고 요청 파라미터 중 name, role 값을 찾아서 해당 메서드 파라미터에 바인딩한다.
@ModelAttribute 사용 예시
- Controller
@PostMapping("/signup")
public CouponResponse<Void> signup(@ModelAttribute User user, HttpSession session) {
User savedUser = userService.signUp(user);
session.setAttribute(SessionConstant.CURRENT_USER, savedUser);
return new CouponResponse<>("회원가입이 완료되었습니다.");
}
- 요청 형태(1) : HTML form
<form action="/signup" method="post">
<input type="text" name="name" />
<select name="role">
<option value="USER">USER</option>
<option value="ADMIN">ADMIN</option>
</select>
<button type="submit">가입</button>
</form>
- 요청 형태(2): application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
name=홍길동&role=USER
@RequestBody 사용 예시
- Controller
@PostMapping("/signup")
public CouponResponse<Void> signup(@RequestBody User user, HttpSession session) {
User savedUser = userService.signUp(user);
session.setAttribute(SessionConstant.CURRENT_USER, savedUser);
return new CouponResponse<>("회원가입이 완료되었습니다.");
}
- 요청 형태 : JSON Body
POST /signup
Content-Type: application/json
{
"name": "홍길동",
"role": "USER"
}
- 요청 처리 과정
- 클라이언트가 JSON 전송
- @RequestBody는 클라이언트가 보낸 JSON 데이터를 읽어서 내부적으로 Jackson 라이브러리가 JSON 데이터를 User라는 자바 객체로 역직렬화(deserialize) 해준다.
- 컨트롤러에서는 이걸 User 자바 객체로 받아서 사용한다.
- 따라서, user.getName(), user.getRole() 등 자바 코드로 접근이 가능하다.
커스텀 ArgumentResolver
- 공통 파라미터를 컨트롤러에서 반복적으로 사용해야 하는 경우 HandlerMethodArgumentResolver를 구현하여 반복되는 파라미터 처리 로직을 추상화하고 깔끔하게 관리할 수 있다.
- 예를 들어, 아래 코드와 같이 로그인한 사용자 정보를 매번 세션에서 꺼내야 하는 상황을 생각해보자.
@GetMapping("/myCoupons")
public CouponResponse<List<CouponIssuance>> showMyCoupons(HttpServletRequest request) {
HttpSession session = request.getSession(false);
User user = (User) session.getAttribute(SessionConstant.CURRENT_USER);
Long userId = user.getId();
List<CouponIssuance> myCouponList = couponService.getMyCoupons(userId);
return new CouponResponse<>("내 쿠폰 목록 조회에 성공했습니다.", myCouponList);
}
- 반복되는 로직을 모든 컨트롤러에 쓰면 중복이 발생하고 실수가 유발되기 쉽다.
- 중복되는 세션 접근 로직을 제거하기 위해 @LoginUser 어노테이션과 커스텀 ArgumentResolver를 구현하여, 컨트롤러에서 로그인 유저 객체를 자동 주입받을 수 있도록 구현할 수 있다.
구현 방법
- @LoginUser 어노테이션 정의
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginUser {
}
- ArgumentResolver 구현
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// @LoginUser가 붙고, 타입이 User인 경우만 처리
return parameter.hasParameterAnnotation(LoginUser.class)
&& User.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpSession session = webRequest.getNativeRequest(HttpServletRequest.class).getSession();
return session.getAttribute(SessionConstant.CURRENT_USER);
}
}
- supportsParameter( … )
- 이 파라미터를 해당 Resolver가 처리할 대상인지 판단하는 메서드이다.
- true를 반환하면, 이 파라미터는 해당 Resolver가 처리하게 된다.
- resolveArgument( … )
- 파라미터에 실제로 어떤 값을 넣을 결정하는 메서드이다.
- 위의 예시에서는 세션에서 로그인된 사용자(User 객체)를 꺼내서 반환한다.
- WebMvcConfigurer에 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginUserArgumentResolver loginUserArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserArgumentResolver);
}
}
- Spring MVC는 요청이 들어오면 각 파라미터를 처리할 HandlerMethodArgumentResolver를 찾는다.
- Spring MVC에 우리가 만든 LoginUserArgumentResolver를 등록함으로써, 컨트롤러 메서드에서 @LoginUser 어노테이션 붙은 파라미터가 있을 때 해당 Resolver가 동작하여 세션에서 로그인된 사용자 정보를 자동으로 주입해준다.
Controller 적용 예시
@GetMapping("/myCoupons")
public CouponResponse<List<CouponIssuance>> showMyCoupons(@LoginUser User user) {
Long userId = user.getId();
List<CouponIssuance> myCouponList = couponService.getMyCoupons(userId);
return new CouponResponse<>("내 쿠폰 목록 조회에 성공했습니다.", myCouponList);
}
ArgumentResolver 동작 과정

- RequestMappingHandlerAdapter가 등록된 ArgumentResolver를 순서대로 순회하면서 supportsParameter(methodParameter)를 물어보고 true를 반환하는 최초의 HandlerMethodArgumentResolver를 선택해 resolveArgument를 호출한다.
- 만약 @RequestBody 같이 JSON을 자바 객체로 변환해야 하는 경우에 resolveArgument 내부에서 HttpMessageConverter를 HTTP 요청 바디(JSON 등)를 자바 객체로 역직렬화하여 반환해준다.
- 모든 파라미터가 준비되면 컨트롤러를 호출한다.
'Spring' 카테고리의 다른 글
| 필터(Filter) vs 인터셉터(Interceptor) (0) | 2025.05.04 |
|---|
Comments