79
RESTful API (including Mobile) with Spring 3.1 윤윤윤 (@exnis)

Ksug 세미나 (윤성준) (20121208)

Embed Size (px)

Citation preview

Page 1: Ksug 세미나 (윤성준) (20121208)

RESTful API (including Mobile)

with Spring 3.1

윤성준 (@exnis)

Page 2: Ksug 세미나 (윤성준) (20121208)

소 개

‘ 이음’ 이라는 스타트업에서 일하는 ,올해로 4 년차인 자바 개발자

Page 3: Ksug 세미나 (윤성준) (20121208)

• RESTful 의 R 도 모르고 API 의 A 도 모르던 한 개발자가 RESTful API 를 만들기 위해 고민하고 삽질한 과정 공유함으로써 ,

• RESTful 이 무엇인지 , 이를 스프링에서 어떻게 구현할 수 있는지 간략하게나마알아볼 수 있는 시간이 되었으면 ..

들어가기 앞서

Page 4: Ksug 세미나 (윤성준) (20121208)

목 차

• RESTful API with Spring 3.1

• API Exception Handling

• API Security

• API Test

Page 5: Ksug 세미나 (윤성준) (20121208)

REST?

Page 6: Ksug 세미나 (윤성준) (20121208)
Page 7: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

Page 8: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

• 표현 (Representational) - REST 리소스는 XML, JSON, 심지어 HTML 을 포함하여 리소스 사용자에게 가장 적합한 , 사실상 거의 모든 형식으로 표현할 수 있다

• 상태 (State) - REST 와 작업할 경우 리소스에 대해 취할 수 있는 액션보다 리소스의 상태에 대해 더 많은 관심을 둔다

• 전달 (Transfer) - REST 는 한 애플리케이션에서 다른 애플리케이션으로 어떤 표현 형식으로 리소스 데이터 전달을 포함한다

- 스프링 인 액션 제 3 판 中 -

Page 9: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

표현 (Representational) - REST 리소스는 XML, JSON, 심지어 HTML 을 포함하여 리소스 사용자에게 가장 적합한 , 사실상 거의 모든 형식으로 표현할 수 있다

Page 10: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

상태 (State) - REST 와 작업할 경우 리소스에 대해 취할 수 있는 액션보다 리소스의 상태에 대해 더 많은 관심을 둔다

Page 11: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

전달 (Transfer) - REST 는 한 애플리케이션에서 다른 애플리케이션으로 어떤 표현 형식으로 리소스 데이터 전달을 포함한다

Page 12: Ksug 세미나 (윤성준) (20121208)

REST(Representational State Transfer)

• 리소스 지향적이고 ,

• 애플리케이션을 표현하는 객체와 명사를 강조하며 ,

• 가장 적합한 형식이 무엇이든 간에 서버에서 클라이언트로 ( 또는 그 반대로 ) 리소스의 상태를 전달함

Page 13: Ksug 세미나 (윤성준) (20121208)

REST-ful?

Page 14: Ksug 세미나 (윤성준) (20121208)

REST is not a standard; it's a style. 

http://www.xfront.com/REST-Web-Services.html

RESTfu

l!

Page 15: Ksug 세미나 (윤성준) (20121208)

API?

Page 16: Ksug 세미나 (윤성준) (20121208)

API!....OTL

Page 17: Ksug 세미나 (윤성준) (20121208)

RESTful API?

Page 18: Ksug 세미나 (윤성준) (20121208)

RESTless : https://api.dropbox.com/getAccountInfo?id=1RESTful : https://api.dropbox.com/1/account/info [GET]

RESTless : https://api.dropbox.com/deleteFile?id=1RESTful : https://api.dropbox.com/1/fileops/delete [POST]

RESTful API!

Page 19: Ksug 세미나 (윤성준) (20121208)

• 평범한 HTTP URL 을 통해 호출됨

• URL 이 계층적이라 , 왼쪽에서 오른쪽으로 읽다 보면 광범위한 개념에서 정확한 개념으로 이동함

• 쿼리 파라미터를 이용해 리소스를 식별하는 대신에 전체 기본 URL 이 리소스를 식별함

• URL 은 리소스로 무엇을 수행할 지가 아니라 리소스를 식별할 뿐 . 따라서 리소스를 식별하는 URL 은 GET 하거나 PUT 하거나 에 상관없이 모두 동일함

• 리소스로 무엇을 할지는 HTTP 메소드가 결정할 문제임

RESTful API!

Page 20: Ksug 세미나 (윤성준) (20121208)

RESTful API!

http://localhost:8080/articles [GET] : 글 목록을 가져옴

http://localhost:8080/articles/123 [GET] : id 가 123 인

글을 가져옴

http://localhost:8080/articles/123 [PUT] : id 가 123 인

글을 작성

http://localhost:8080/articles/123 [DELETE] : id 가 123

인 글을 삭제

“ 동일한 URL 인 /articles/123 으로 요청을 처리함”

Page 21: Ksug 세미나 (윤성준) (20121208)

메소드 설명 안전 ?(safety)

멱등적 ?(idempo-tency)

GET 서버에서 리소스를 조회한다 . 리소스는 요청 URL 에 의해 식별된다 .

O O

POST 요청 URL 을 리스닝하는 프로세서에 의해 처리되도록 서버에 데이터를 전송한다 .

X X

PUT 요청 URL 에 있는 서버에 리소스를 둔다 . X O

DELETE 요청 URL 에 의해 식별되는 서버의 리소스를 삭제한다 . X O• 안전 (safe)? : 메소드가 리소스의 상태를 변경하지 않는 것• 멱등적 (idempotent)? : 반복되는 요청이 첫 번째 요청 이후에 발생할 수 있는

어떠한 부작용도 일으키지 않는다 . ( 상태를 변경할 수도 변경하지 않을 수도 있음 )

RESTful API!

Page 22: Ksug 세미나 (윤성준) (20121208)

“ 실제로는 GET, POST 만 사용”

Page 23: Ksug 세미나 (윤성준) (20121208)

PUT 을 사용하지 않은 이유

• 클라이언트가 URI 구조를 미리 알아야 함: 그러기 위해서는 id 를 클라이언트에 알려줘야 하고 , 쓸데없는 정보가 노출됨

http://localhost:8080/articles/123 [PUT]

http://localhost:8080/articles/write

[POST]

Page 24: Ksug 세미나 (윤성준) (20121208)

DELETE 을 사용하지 않은 이유

• 리소스를 삭제할 일이 없음

Page 25: Ksug 세미나 (윤성준) (20121208)

RESTful API! - Tip• 동사 대신 명사를 사용하도록 권장 : getDogs (x) dogs (O)

• 단수명사 보다는 복수명사 : /dog (X) /dogs (O)

• 추상적인 명사가 아닌 시나리오에 맞는 구체적인 명사 사용

• : /photos 와 같은 추상적인 명사가 아닌 /profilePhotos 와 같이 명확한 목적을 알 수 있는 명사를 사용

• /resource/identifier/resource : /owners/5678/dogs (5678 번 주인의 dogs): Identifier 는 변경되지 않는 값

• /dogs ( 전체 dog), /dogs/1 (1 번 dog)

• 출력 결과 형식을 지정 : /dogs ( 기본은 json 이며 /dogs.json 과 동일함 ), /dogs.xml 은 xml 형식으로 출력

• 특정 범위의 값을 가져 올 때는 파라미터 사용 : /dogs?limit=25&offset=50

• 결과를 받기 원하는 항목 선택 : /dogs?fields=name,color,location

Page 26: Ksug 세미나 (윤성준) (20121208)

RESTful API with Spring

3.1?

Page 27: Ksug 세미나 (윤성준) (20121208)

스프링이 REST 를 지원하는 방법

• 컨트롤러는 REST 의 네 가지 주요 메소드인 GET, PUT, DELETE, POST 를 포함하여 모든 HTTP 메소드에 대한 요청을 처리할 수 있음

• @PathVariable 에너테이션은 컨트롤러가 파라미터화된 URL( 경로의 일부분에 변수 입력이 있는 URL) 에 대한 요청을 처리할 수 있도록 함

• 리소스는 XML, JSON, Atom 그리고 RSS 같은 데이털 모델 랜더링을 위한 새로운 뷰 구현을 포함하여 스프링의 뷰와 뷰 리졸버를 이용해 클라이언트에 가장 적합한 형태로 리소스의 뒤에서 데이터를 표현할 수 있음

• 뷰 기반의 응답의 경우 , ContentNegotiatingViewResolver 는 클라이언트가 원하는 컨텐츠 타입을 만족시키는 몇 가지 뷰 리졸버에서 생성한 최적의 뷰를 선택할 수 있음

• 컨트롤러 핸들러 메소드에 @ResponseBody 애너테이션을 적용하여 뷰 처리를 완전히 무시하고 , 몇 가지 메시지 변환기 중 하나로 변환된 값을 클라이언트에 대한 응답으로 변환

• 마찬가지로 새로운 @RequestBody 애너테이션은 HttpMethodConverter 구현체와 함께 인바운드 HTTP 데이터를 컨트롤러의 핸들러 메소드에 전달하는 자바 객체로 변환할 수 있음

- 스프링 인 액션 제 3 판 中 -

Page 28: Ksug 세미나 (윤성준) (20121208)

@Controller

@RequestMapping

@PathVariable

@RequestParam

@ResponseBody

사실 , 스프링 MVC 에서 다 쓰던 것들 ..

Page 29: Ksug 세미나 (윤성준) (20121208)

@RequestMapping

@PathVariable

@RequestMapping(value = "/files", method = Request-Method.GET)@ResponseBodypublic void getFile(@RequestParam(“id") Integer id) {

File file = fileService.getFile(id);}

@RequestMapping(value = "/files/{id}", method = Re-questMethod.GET)@ResponseBodypublic void getFile(@PathVariable(“id") Integer id) {

File file = fileService.getFile(id);}

http://localhost:8080/files?id=1

http://localhost:8080/files/1

Page 30: Ksug 세미나 (윤성준) (20121208)

“ 예를 하나 들어보겠습니다”

Page 31: Ksug 세미나 (윤성준) (20121208)

아이디 ( 이메일 ) 과 비밀번호를 입력하고로그인 버튼을 누르면 ,

http://api.i-um.com/authentication/loginemail : [email protected] : ########## “POST 방식으로 호출”

{ "status":"SUCCESS", "result": {"accessToken": “28as9dyhd923!3e2" }, "error": "NULL"

}

“JSON 으로 리턴”

Page 32: Ksug 세미나 (윤성준) (20121208)

@RequestMapping(value = "/login", method = Request-Method.POST,produces = "application/json")@ResponseBodypublic ApiResult login(

@RequestParam("email") String email, @RequestParam("password") String password

) { … }

@RequestMapping("/authentica-tion")@Controllerpublic class Authentication-ApiController {

}

http://api.i-um.com/authentication/loginemail : [email protected] : ##########mobileType : IPHONE / ANDROID

“POST 방식으로 호출”

예 ) 로그인 - Annotation 사용

Page 33: Ksug 세미나 (윤성준) (20121208)

@RequestMapping(value = "/login", method = Request-Method.POST, produces = "application/json")@ResponseBodypublic ApiResult login(

@RequestParam("email") String email, @RequestParam("password") String password

) { … }

@RequestMapping("/api/authen-tication")@Controllerpublic class Authentication-ApiController {

}

http://api.i-um.com/authentication/loginemail : [email protected] : ##########mobileType : IPHONE / ANDROID

“POST 방식으로 호출”

예 ) 로그인 - Annotation 사용

Page 34: Ksug 세미나 (윤성준) (20121208)

@RequestMapping(value = "/login", method = Request-Method.POST, produces = "application/json")@ResponseBodypublic ApiResult login(

@RequestParam("email") String email, @RequestParam("password") String password

) { … }

@RequestMapping("/api/authen-tication")@Controllerpublic class Authentication-ApiController {

}

{ "status": "SUCCESS", "result": { "accessToken": “28as9dyhd923!3e2" }, "error": "NULL"

}

“JSON 으로 리턴”

예 ) 로그인 - Annotation 사용

Page 35: Ksug 세미나 (윤성준) (20121208)

“JSON 으로 결과값을 리턴하기 위해서는 ?”

1.MappingJacksonHttpMessageConverter 사용

2. MappingJacksonJsonView (JSON 지원 View 이용 ) & ContentNegotiatingViewResolver 사용 (JSON 외 XML 등 다른 format 의 view 제공하고 싶을 때 )

예 ) 로그인 – JSON 으로 리턴

Page 36: Ksug 세미나 (윤성준) (20121208)

예 ) 로그인 – JSON 으로 리턴

Controller가

리턴하는 오브젝트

클라이언트가 원하는리소스

HttpMes-sageCon-verter

• MappingJacksonHttpMessageConverter : JSON

• MarshallingHttpMessageConverter : XML

• RssChannelHttpMessageConverter : RSS

.

.

.

“MappingJacksonHttpMessageConverter?”

Page 37: Ksug 세미나 (윤성준) (20121208)

1.Servlet-context.xml 에 bean 선언 추가

<bean class="org.springframework.web.servlet.mvc.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <value>application/json;charset=UTF-8</beans:value> </property> </bean> </list> </property></bean>

2. JSON 으로 return 하고자 하는 Controller 에 @ResponseBody 를 붙여줌

ResponseBody 를 통해 반환되는 값에 한글이 있을 경우 깨지는 현상을 방지하기 위해 넣어줌

“MappingJacksonHttpMessageConverter 를 사용하려면 ?”

@RequestMapping(value = "/login", method = RequestMethod.-POST)@ResponseBodypublic ApiResult login(

예 ) 로그인 – JSON 으로 리턴

Page 38: Ksug 세미나 (윤성준) (20121208)

로그인public class ApiResult {

private SuccessFail status;: SuccessFail 은 SUCCESS / FAIL 의 enum type

private Object result;: API 를 호출한 쪽에 전달되어야 할 값 ( 값이 없으면 NULL)

private ExceptionReason error;: error 가 발생하면 error 에 대한 정보 (code) 를 넣어줌

private String msg; (error 가 NULL 이 아닌 경우에만 보이도록 함 )

: error 가 발생했을 때 클라이언트가 뿌려줘야 할 메시지

…} {

"status":"SUCCESS", "result":{"accessToken":"28as9dyhd923!3e2"}, "error":"NULL"

}

“JSON 으로 변환”

Page 39: Ksug 세미나 (윤성준) (20121208)

“ 다른 예를 들어보겠습니다”

Page 40: Ksug 세미나 (윤성준) (20121208)
Page 41: Ksug 세미나 (윤성준) (20121208)

예 ) 배지 – RequestMapping 전략

@RequestMapping(value = "/badges", method = RequestMethod.GET)@ResponseBodypublic ApiResult getBadges(…) { … }

1) 배지 목록 가져오기

Page 42: Ksug 세미나 (윤성준) (20121208)

@RequestMapping(value = "/badges/{badgeId}", method = RequestMethod-.GET)@ResponseBodypublic ApiResult getBadge(@PathVariable Long badgeId) { … }

예 ) 배지 – RequestMapping 전략

2) badgeId 에 해당하는 배지 가져오기

Page 43: Ksug 세미나 (윤성준) (20121208)

@RequestMapping(value = "/badges/{badgeId}/photos", method = Request-Method.GET)@ResponseBodypublic ApiResult getBadgePhotos(@PathVariable Long badgeId) { … }

예 ) 배지 – RequestMapping 전략

3) badgeId 에 해당하는 배지의 사진들 가져오기

Page 44: Ksug 세미나 (윤성준) (20121208)

배지

@RequestMapping(value = "/badges/{badgeId}/photos/{slotNum}", method = RequestMethod.GET)@ResponseBodypublic ApiResult getBadgePhoto(@PathVariable Long badgeId, @PathVariable(“slotNum”) Integer slotNum) { … }

4) badgeId 에 해당하는 배지의 {slotNum} 번째 사진 가져오기

Page 45: Ksug 세미나 (윤성준) (20121208)

배지

@RequestMapping(value = "/badges/{badgeId}/photos/{slotNum}/upload", method = RequestMethod.POST)public ApiResult uploadBadgePhoto(@PathVariable Long badgeId,@PathVariable(“photoOrder”) Integer photoOrder) { … }

5) badgeId 에 해당하는 배지의 {slotNum} 번째 사진 업로드하기

Page 46: Ksug 세미나 (윤성준) (20121208)

API ExceptionHandling

Page 47: Ksug 세미나 (윤성준) (20121208)

예외처리

“Service 에서 Business Logic 이 실행되다가 Exception 이 발생하면 Controller 에서 catch 해서 에러코드와 메시지를 리턴해줌”

{ "status":"FAIL", "result":"NULL", "error":"INVALID_EMAIL_PASSWORD" "message":" 이메일 또는 비밀번호가 틀렸습니다 "

}

Page 48: Ksug 세미나 (윤성준) (20121208)

Exception

ex-tends

“Exception 을 상속받아 별도의 Exception Class 를 만듦”

A Exception private AExceptionReason exceptionReason;

public enum AExceptionReason {이유 1, 이유 2, 이유 3, 이유 4, …

};

: 예외가 발생한 이유를 enum 형으로 정의함

예외처리

Page 49: Ksug 세미나 (윤성준) (20121208)

AException (class)AExceptionReason (enum)

CException (class)CExceptionReason (enum)

“ 도메인 or 서비스마다 Exception(class) 과 Exception Reason(enum) 이 생김”

BException (class)BExceptionReason (enum)

DException (class)DExceptionReason (enum)

EException (class)EExceptionReason (enum)

Fexception (class)FExceptionReason (enum)

GException (class)GExceptionReason (enum)

IException (class)IExceptionReason (enum)

HException (class)HExceptionReason (enum)

JException (class)JExceptionReason (enum)

.

.

.

예외처리

Page 50: Ksug 세미나 (윤성준) (20121208)

try {…} catch (Exception e) { ApiError apiError = null; if (e instanceof AException) { apiResult.setError((((AException)e).getAExceptionReason()); } else if(e instanceof BException) {

apiResult.setError((((BException)e).getBExceptionReason()); } else if(e instanceof CException) {

apiResult.setError((((CException)e).getCExceptionReason()); } else { apiResult.setError(UNKNOWN_EXCEPTION); }

apiResult.setMessage(e.getMessage());}

return apiResult;

코드의 중복이 발생 !

Exception 개수만큼 조건문 늘어남 !!

예외처리

Page 51: Ksug 세미나 (윤성준) (20121208)

ExceptionReason(interface)

AExceptionReason(enum)

implements

BExceptionReason(enum)

CExceptionReason(enum)

Enum 은 extend 가 안되어서 ,interface 만든 후 implements 하도록 처리 !

예외처리 : 개선 후

Page 52: Ksug 세미나 (윤성준) (20121208)

FrontModuleExcep-tion (abstract

class)

Exception (class)

AException (class)

public abstract ExceptionReason getExceptionRea-son();

ex-tends

ex-tends

BException(class)

@Overridepublic ExceptionReason getException-Reason() { return aExceptionReason;}

@Overridepublic ExceptionReason getExceptionReason() { return bExceptionReason;}

private AExceptionReasonaExceptionReason;

private BExceptionReasonbExceptionReason;

예외처리 : 개선 후

Page 53: Ksug 세미나 (윤성준) (20121208)

try {…} catch (FrontModuleException e) { apiResult.setError(e.getExceptionReason()); apiResult.setMessage(e.getMessage());}

return apiResult;

Exception 개수가 많아도 하나로 처리 !

예외처리 : 개선 후

But 여전히 코드의 중복이 발생 !

Page 54: Ksug 세미나 (윤성준) (20121208)

예외처리 : 다른 개선방안

ExceptionResolver

ResponseEntity<?>ContentNegotiat-ingViewResolver

http://dev.anyframejava.org/docs/anyframe/plugin/springrest/1.0.2/reference/html/ch10.html

Page 55: Ksug 세미나 (윤성준) (20121208)

API Security

Page 56: Ksug 세미나 (윤성준) (20121208)

“3rd Party 나 개발자에게 공개된 API” (pub-

lic)

“ 클라이언트 (앱 ) 와 통신하는 API” ( 반만 public)

“ 회사 내부에서만 사용되는 API”(private)

API Security

아래에 해당할수록 어플리케이션 레벨의 보안에 신경써야 !

적당히

꼼꼼히

Page 57: Ksug 세미나 (윤성준) (20121208)

API Security

ID(Identity): 누가 API request 를 요청했는지 확인

인증 (Authentication): 주체의 신원을 주체가 주장하는 신원과 대비해 검증하는 과정 (A 가 정말로 A 가 맞는지 확인 )

허가 (Authorization): 인증된 사용자에게 권한들을 승인하는 과정 (A 가 어떤 액션을 하려고 할 때 , 그 액션을 하도록 허용되었는지 확인 )

API 에서 이 3 가지를 모두 요구하지는 않는다 !

Page 58: Ksug 세미나 (윤성준) (20121208)

ID(Identity) 만 요구 - Google Maps API: API key 만 알면 API 사용 가능

API Security

Page 59: Ksug 세미나 (윤성준) (20121208)

ID(Identity), 인증 (Authentication) 요구– Twit-ter API: username / password 를 입력해서 인증해야 함

API Security

Page 60: Ksug 세미나 (윤성준) (20121208)

ID(Identity), 인증 (Authentication), 허가(Authorization) 요구– Facebook API: email / password 입력한 후 , 특정 action 에 대한 허가를 요구함

API Security

Page 61: Ksug 세미나 (윤성준) (20121208)

“ 이렇게 했습니다”

Page 62: Ksug 세미나 (윤성준) (20121208)

API Security

• Oauth

• OpenID

• SAML

• HTTP authentication

• WS-Security

• Basic API Key

Page 63: Ksug 세미나 (윤성준) (20121208)

• 로그인 이후 모든 API 호출 시 , 액세스 토큰 (Access To-ken) 을 파라미터로 같이 넘겨 매번 인증 (Authentication)함

• 액세스 토큰은 DB 에 저장되어 있음 ( 세션에 저장하지 않음 )

• 스프링에서 제공하는 http basic 이나 remember-me au-thenticaiton 을 사용하지 않았음

• 액세스 토큰이 다시 생성되어 업데이트 및 , 클라이언트에게 리턴 되는 경우

1. 로그아웃 후 , 다시 로그인2. 다른 기기에 설치되어 있는 앱으로 로그인

API Security

Page 64: Ksug 세미나 (윤성준) (20121208)

{ "status": "SUCCESS", "result": { "accessToken": “28as9dyhd923!3e2" }, "error": "NULL"

}

“ 로그인 성공”

ApiResult abc(@RequestParam("accessToken") String accessToken, …) {

accessToken 을 authentication 하는 로직 }

ApiResult def(@RequestParam("accessToken") String accessToken, …) {

accessToken 을 authentication 하는 로직}

ApiResult xyz(@RequestParam("accessToken") String accessToken, …) {

accessToken 을 authentication 하는 로직} 코드의 중복이 발생 !

API Security

Page 65: Ksug 세미나 (윤성준) (20121208)

public class MobileAuthenticationInterceptor extends HandlerInterceptorAdapter {

@Override public boolean preHandle(HttpServletRequest request,

HttpServletResponse response, Object handler) throws Exception {

accessToken 을 authentication 하는 로직 }}

AccessToken 을 인증하는 로직을 Interceptor 로 분리해서Controller 메소드가 실행되기 전 호출되도록 처리함

API Security

Page 66: Ksug 세미나 (윤성준) (20121208)

API Security

• 보안 인터셉터 엘리먼트를 통한 메서드 보호

• 포인트컷을 활용한 메서드 보호

• 애너테이션을 활용한 메소드 보호

장점 : 호출 보호하고자 하는 메서드 위에 애너테이션만 붙이면 된다 .단점 : 나중에 어디에 애너테이션을 적용했는지 잊어버려 검색해봐야 한다 .

“ 특정유저 (슈퍼유저 ) 만 호출가능한 메서드를 만들고 싶을 때”

- 스프링 3 레시피 中 -

메서드 호출 보호 (Spring Security)

Page 67: Ksug 세미나 (윤성준) (20121208)

API Security

@Secured("ADMIN_USER") <!-- 스프링에서 제공 -->@RolesAllowed(“ADMIN_USER”) <!-- JSR-250 -->@PreAuthorize(“hasRole(‘ADMIN_USER’)”) <!-- 스프링에서 제공 -->public void deleteAccount(Long seqId) { 계정을 삭제하는 로직 (for 가입 테스트 ) …}

@Secured 를 사용하려면 ? <global-method-security secured-annotations=“enabled”/>

@RolesAllowed 를 사용하려면 ? <global-method-security jsr250-annotations=“enabled” />

@PreAuthorize 를 사용하려면 ? <global-method-security pre-post-annotations=“enabled” />

Page 68: Ksug 세미나 (윤성준) (20121208)

• 클라이언트에 정보를 딱 필요한 만큼만 준다 .

• 민감한 정보는 절대 넘겨주지 않는다 .

( 예 : 유저의 seq_id, 주민번호 등 )

API Security - 잊지 말아야 할 것 !

Page 69: Ksug 세미나 (윤성준) (20121208)

API TEST

Page 70: Ksug 세미나 (윤성준) (20121208)

API(Analytical Profile Index) TEST?

출처 : http://www.biologyreference.com/Ar-Bi/Bacterial-Genetics.html

Page 71: Ksug 세미나 (윤성준) (20121208)

클라이언트 (앱 ) 개발자나 기획자가쉽고 편하게 API 를 테스트하게 하려면 ?

Page 72: Ksug 세미나 (윤성준) (20121208)

API TEST

REST Client 이용 (Firefox, Chrome 확장 플러그인 설치 )?

장점 : 설치 및 사용이 쉽다 . 단점 : 테스트해야 할 API 들이 많은 경우 , 매번 HTTP URL 을

입력하기 번거롭다 . 개발자에게만 친숙한 환경이다 .

Page 73: Ksug 세미나 (윤성준) (20121208)

“ 이렇게 했습니다”

Page 74: Ksug 세미나 (윤성준) (20121208)

API TEST

웹 테스트 페이지

Page 75: Ksug 세미나 (윤성준) (20121208)

http://swagger.wordnik.com/

API TEST

http://twitter.github.com/bootstrap/

Page 76: Ksug 세미나 (윤성준) (20121208)

Component scan 으로 모든 Controller 클래스를 스캔한 후(@Controller 에너테이션으로 스캔 가능 ), 클래스의 methods() 를 사용해 모든 method 를 가져올 수 있음

API TEST

• @PathVariable 로 들어오는 값과 @RequestParam 으로 들어오는 값을 따로 처리해야 함

• 메소드 추가 , 삭제가 불편함 ( 일괄적으로 처리하기 때문 )• 유연하게 카테고리를 나누기 힘듬

메소드가 생길 때마다 URL, 메소드 타입 , 파라미터는개발자가 직접 입력하자 !

Page 77: Ksug 세미나 (윤성준) (20121208)

API TEST

public enum ApiTestEnum {

// A. 로딩페이지IntroGate("A. 로딩페이지 ", "/intro", "GET", "gate"),

// B. 로그인Login("B. 로그인 ", "/authentication/login", "POST", "login"),FindPassword("B. 로그인 ", "/authentication/password/find", "POST", "findPassword"),

// C. 가입IsVaildEmail("C. 가입 ", "/authentication/email/check", "POST", "is-ValidEmail"),AuthorizeName("C. 가입 ", "/authentication/name", "POST", "autho-rizeName"),... private String apiCategory; private String apiUrl; private String methodType; private String name;}

카테고리 URL HTTP메소드

메소드명

ApiTestEnum ApiTestCon-troller

ApiTestMan-ager

ApiTestView(swagger, boot-

strap)

Page 78: Ksug 세미나 (윤성준) (20121208)

References

1. http://apigee.com/about/api-best-practices/all/ebook2. [Book] 웹 개발자를 위한 웹을 지탱하는 기술3. [Book] 스프링 인 액션 제 3 판4. [Book] 스프링 3 레시피5. [Book] 스프링 시큐리티 3

Page 79: Ksug 세미나 (윤성준) (20121208)

Thank you for Listening!