[Spring] Device

Device

스프링에서 데스크탑 브라우저와 모바일 디바이스에 대한 요청을 다르게 처리할 때 사용한다


Dependency

1
2
3
4
5
<dependency>
<groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId>
<version>${org.springframework.mobile-version}</version>
</dependency>



DeviceResolverHandlerInterceptor

스프링 모바일에서 핸들러 인터셉터를 통해 인터셉터 레이어에서 디바이스 정보를 감지할 수 있다
요청은 currentDevice라는 request Attribute내에 색인된다
DeviceUtils를 통해 디바이스 정보를 가져올 수 있다

1
2
3
4
5
6
7
8
9
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
}



DeviceResolverRequestFilter

필터레이어에서 디바이스 정보를 감지할 수 있다

1
2
3
4
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>

디바이스 정보는 컨트롤러에서 다음과 같이 받을 수 있다

1
Device currentDevice = DeviceUtils.getCurrentDevice(servletRequest);



DeviceHandlerMethodArgumentResolver

Device 를 컨트롤러의 파라미터로 받을 수 있도록 도와준다

1
2
3
4
5
6
7
8
9
@Bean
public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
return new DeviceHandlerMethodArgumentResolver();
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(deviceHandlerMethodArgumentResolver());
}



LiteDeviceResolver

DeviceResolver의 구현체인 LiteDeviceResolver는 모바일 태블릿 등 디바이스의 존재를 감지한다
디폴트로 등록되나 별도의 설정을 통해 추가적인 constructor argument설정 정보를 넣을 수 있다

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
32
33
34
35
36
@Bean
public LiteDeviceResolver liteDeviceResolver() {
List<String> keywords = new ArrayList<String>();
keywords.add("iphone");
keywords.add("android");
return new LiteDeviceResolver(keywords);
}

@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor(liteDeviceResolver());
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
}
```
위 경우 iphone과 android는 더이상 mobile에 속하지 않게 된다
<br><br>


## Site preference management
모바일 환경에서 접속시 모바일에 관련된 페이지를 노출하나, PC버전 페이지를 보고싶을 때 다음과 같은 기능을 활성화 하면 된다
선호 페이지 정보는 Site preference storage에 저장시키며 사용자의 요청은 쿠키에 저장된다

```JAVA
@Bean
public SitePreferenceHandlerInterceptor sitePreferenceHandlerInterceptor() {
return new SitePreferenceHandlerInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sitePreferenceHandlerInterceptor());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Controller
public class HomeController {

@RequestMapping("/")
public String home(SitePreference sitePreference, Model model) {
if (sitePreference == SitePreference.NORMAL) {
logger.info("Site preference is normal");
return "home";
} else if (sitePreference == SitePreference.MOBILE) {
logger.info("Site preference is mobile");
return "home-mobile";
} else if (sitePreference == SitePreference.TABLET) {
logger.info("Site preference is tablet");
return "home-tablet";
} else {
logger.info("no site preference");
return "home";
}
}
}



Site Switching

모바일 사이트를 기본 도메인과 다른 도메인으로 사용하고 싶을 때 사용한다

mDot SiteSwitcher

mDot은 모바일 유저를 m.${server.nave}으로 리다이렉트 시킨다
테블릿은 기본적으로 기본 사이트를 바라보게 되지만 설정을 통해 모바일로 변경 가능하다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
//두번째 아규먼트가 true가 되면서 테블릿은 모바일을 바라보게 된다
return SiteSwitcherHandlerInterceptor.mDot("myapp.com", true);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}


dotMobi SiteSwitcher

dotMobi는 모바일 유저를 ${serverName - lastDomain}.mobi로 리다이렉트 시킨다
mDot과 동일하게 테블릿은 기본 사이트를 바라보게 되지만 설정을 통해 모바일로 변경 가능하다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
return SiteSwitcherHandlerInterceptor.dotMobi("myapp.com", true);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}


Standard SiteSwitcher

모바일 테블릿 웹 브라우저의 페이지를 모두 나누고 싶을 때 사용한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
return SiteSwitcherHandlerInterceptor.standard("app.com",
"mobile.app.com", "tablet.app.com", ".app.com");
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}


urlPath SiteSwitcher

urlPath SiteSwitcher로 설정하게 되면 모바일 유저를 어플리케이션 경로 내 지정한 다른 사이트로 리다이렉트 시킨다
mDot이나 dotMobi와는 달리 다른 DNS 엔트리를 설정할 필요가 없다

Mobile Path

${serverName}/${mobilePath}로 모바일 사용자를 리다이렉트 시킨다
다음과 같이 설정할 경우 myapp.com/m/ 으로 리다이렉트 된다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
//url Path 설정
return SiteSwitcherHandlerInterceptor.urlPath("/m");
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}

Mobile Path and Root Path

urlPath에서 Root path를 명시할 수 있다
${serverName}/${rootPath}/${mobilePath}로 사용자를 리다이렉트 시킨다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
//이 때 주소는 myapp.com/showcase/m/이 된다
return SiteSwitcherHandlerInterceptor.urlPath("/m", "/showcase");
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}

Mobile Path, Tablet Path, and Root Path

urlPath에서 모바일과 테블릿을 다른 사이트로 리다이렉트 시켜준다
모바일은 ${serverName}/${rootPath}/${mobilePath}로 테블릿은 ${serverName}/${rootPath}/${tabletPath}로 리다이렉트 시킨다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}

@Bean
public SiteSwitcherHandlerInterceptor siteSwitcherHandlerInterceptor() {
return SiteSwitcherHandlerInterceptor.urlPath("/m", "/t", "/showcase");
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
registry.addInterceptor(siteSwitcherHandlerInterceptor());
}



Device aware view management

서로 다른 디바이스 타입들에 대한 뷰를 리턴하기 위해 사용된다

LiteDeviceDelegatingViewResolver

LiteDeviceDelegatingViewResolver를 사용해서 웹 브라우저, 모바일, 테블릿에 대한 suffix와 prefix를 지정할 수 있다
사이트 전역에 유지된다

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public LiteDeviceDelegatingViewResolver liteDeviceAwareViewResolver() {
InternalResourceViewResolver delegate = new InternalResourceViewResolver();
delegate.setPrefix("/WEB-INF/views/");
delegate.setSuffix(".jsp");
LiteDeviceDelegatingViewResolver resolver = new LiteDeviceDelegatingViewResolver(delegate);
//모바일 설정
resolver.setMobilePrefix("mobile/");
//테블릿 설정
resolver.setTabletPrefix("tablet/");
/* 모바일과 테블릿 모두 별도의 suffix도 설정 가능하다 */
return resolver;
}

Fallback resolution

사이트 전역에 뷰 네임 전략이 적용되는 LiteDeviceDelegatingViewResolver이 되는데 몇몇 뷰는 모바일, 웹, 테블릿 환경에 종속적일 필요가 없는 경우가 있다
그럴 때 Fallback resolution을 통해 기본 뷰를 리턴하도록 할 수 있다
레퍼런스에 따르면 모바일 테블릿 환경에서 요구되는 뷰 이름이 존재하지 않을시 null이 리턴되는데 이 때 viewResolver가 기본 웹 페이지에 대한 리턴을 돌려주는거라고 명시되있는거 같다

1
2
3
4
5
6
7
@Bean
public LiteDeviceDelegatingViewResolver liteDeviceAwareViewResolver() {
...
resolver.setEnableFallback(true);
...
return resolver;
}

참고

https://mybatis.org/mybatis-3/

Author: Song Hayoung
Link: https://songhayoung.github.io/2020/06/28/Spring/Spring-mobile/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.