반응형

↓↓↓ 이전내용

2024.01.05 - [Web Application/Backend] - [REST API] Spring Boot로 REST API CRUD 간단 구현 (7) - JUnit TEST service 계층 test 예제

 

[REST API] Spring Boot로 REST API CRUD 간단 구현 (7) - JUnit TEST service 계층 test 예제

↓↓↓ 이전 내용 2023.12.30 - [Web Application/Backend] - [REST API] Spring Boot로 REST API CRUD 간단 구현 (6) - JUnit TEST 기본 설정 및 repository 계층 test 예제 [REST API] Spring Boot로 REST API CRUD 간단 구현 (6) - JUnit TEST

im-gonna.tistory.com

 

이전 내용에 이어서 이번에는 최상단 layer인 Controller의 test를 진행해보자.

 

main에 있는 controller class 이름에 ctrl+shift+t를 눌러서 test 클래스를 자동 생성해준다.

 

💡 Controller test class

 

import 되어있는 jupiter assertion은 제거한다. (이전에 설명했지만 기본 assertion 사용!)

 

  • 클래스 어노테이션 추가

외부 data와 직접 상호작용하는 계층이기 때문에 test class에 어노테이션을 추가해준다.

 

그리고 컨트롤러 클래스를 인자로 가져온다.

 

  • mockMvc 주입

 

web layer url test이기 때문에, 모의 MVC가 필요하다.

따라서 MockMvc 객체를 하나 선언하여 사용한다.

 

  • 필요한 객체 선언

controller 레이어는 service 레이어와 통신하기 때문에 모의 service를 만들어주어야 한다.

그리고 cloudvendor 인스턴스 2개를 각각 만들어 주고, 이들을 담을 리스트로 하나 선언해준다.

 

  • setUp 메서드

 cloudVendorOne 인스턴스와 cloudVendorTwo 인스턴스를 생성해주고, list에 담아준다.

 

 

  • getCloudVendorDetails()의 test 메서드

  • controller에 정의된 getCloudVendorDetails()의 로직을 보면, cloudVendorService의 getCloudVendor()를 호출한 결과를 반환한다.
  • 따라서 cloudVendorService의 getCloudVendor()에 cloudVendorId가 1로 전달하며, 이 메서드를 호출하면 cloudVendorOne을 return하여 성공적으로 보이도록 한다.
  • 그리고 mockMvc의 perform메서드를 통해 get 동작을 수행하도록 하고 url은 controller에서 지정한대로 cloudVendorId에 따라 달라지므로, /cloudvendor/1 로 가져오도록 한다.
  • andDo(print()): 이 메서드는 테스트 결과를 출력한다. 테스트가 실행될 때 컨트롤러가 반환하는 HTTP 응답 등의 정보를 콘솔에 출력하여 디버깅이나 테스트 결과 확인을 도와준다.
  • andExpect(status().isOk()): 이 메서드는 특정한 조건을 검증하는데, 여기서는 HTTP 응답의 상태 코드가 "200 OK"인지 확인한다. 만약 상태 코드가 200이 아니면 테스트는 실패하는 것이다.
  • 여기까지하면, perform get에서 빨간 줄이 쳐질 것이다. 예외처리가 필요하다. 메서드에 throws Exception을 추가해주자.

getCloudVendorDetails test 결과

 

테스트 결과 성공이다.

getCloudVendorDetails()의 test를 위해 모의(mock) http 서블릿 요청이 제대로 구축되는 것을 확인할 수 있다.

(이는 마치 레포지토리 레이어에서 내장된 데이터베이스 h2를 사용하는 것과 유사한 상황이다)

파라미터와 헤더는 아무것도 필요로 하지 않았다.

 

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = {"data":{"vendorId":"1","vendorName":"Amazon","vendorAddress":"USA","vendorPhoneNumber":"xxxxx"},"httpStatus":"OK","message":"Requested Vendor Details are given here"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

그 아래 더 내려서 response 부분을 보면, status는 200, 에러 사항 없음, body data에 controller에서 반환하는 CloudVendorOne에 대한 data가 담겨져 있는 것을 확인할 수 있다.

 

 

  • getAllCloudVendorDetails()의 test 메서드

  • 앞의 get메서드와 로직은 유사하나, service 메서드를 getAll로 수정해주고, 가져오는 단위가 list이기 때문에, 초기에 설정해주었던 cloudVendorList를 return하도록 한다.
  • 모든 cloudVendor를 가져올 때에는 기본 url을 사용하기 때문에, /cloudvendor로 mapping되도록 한다. 

getAllCloudVendorDetails test 결과

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = [{"vendorId":"1","vendorName":"Amazon","vendorAddress":"USA","vendorPhoneNumber":"xxxxx"},{"vendorId":"2","vendorName":"GCP","vendorAddress":"UK","vendorPhoneNumber":"yyyyy"}]
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

body를 보면 one, tow 모두 값을 가져오는 것을 확인할 수 있다.

 

 

  • deleteCloudVendorDetails()의 test 메서드

  • controller의 delete 메서드 로직을 보면, service의 delete메서드를 호출하고, 이 안에서는 Success 메시지를 반환하도록 되어있다.
  • 따라서 cloudvendorId가 1인 cloudvendor를 delete하도록 service 메서드가 호출되면, Success를 return하도록 하여, service의 delete 메서드 호출을 성공적으로 보이게 한다.
  • 그리고 mockMvc의 perform을 통해 delete mapping시 url은 /cloudvendor/1에 매핑되도록 한다.

deleteCloudVendorDetails test 결과

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
     Content type = text/plain;charset=UTF-8
             Body = Cloud Vendor Deleted Successfully
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

response의 body를 보면 controller의 해당 메서드에서 반환하는 값인 메시지를 반환하는 것을 확인할 수 있다.

 

 

  • createCloudVendorDetails()의 test 메서드

 

  • controller에서 create메서드 로직을 살펴보면, cloudVendorService의 create메서드를 호출한다. 그 메서드 안에서는 success를 return한다.
  • 따라서 create메서드가 호출되면 Sucess를 return하도록 한다.
  • perform의 post mapping 시 /cloudvendor url과 mapping되도록 한다.
  • 그런데, 내용으로 전달되는 data를 json형식으로 전달하여야 하기 때문에, contentType을 json으로 지정해준다.
  • 그런데, cloudvendor는 entity이기 때문에, json형식으로 바꾸어주기 위해 위 코드를 작성해준다.
  • json 형식의 cloudvendor를 requestJson에 저장해주고, requestJson을 content에 넣는다.

createCloudVendorDetails test 결과

 

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
     Content type = text/plain;charset=UTF-8
             Body = Cloud Vendor Created Successfully
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

response의 body를 보면 controller의 해당 메서드에서 반환하는 값인 메시지를 반환하는 것을 확인할 수 있다.

 

 

  • updateCloudVendorDetails()의 test 메서드

  • 앞의 create 메서드와 로직이 유사하기 때문에, service 메서드의 create를 update로 변경하고, perform메서드는 post를 put으로 변경한다.

updateCloudVendorDetails test 결과

 

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"33"]
     Content type = text/plain;charset=UTF-8
             Body = Cloud Vendor Updated Successfully
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

역시 response의 body에는 controller의 해당 메서드에서 반환하는 값인 메시지를 담고 있다.

 

모든 unit test를 마쳤으므로, 전체 test class의 test coverage를 확인해보자.

 

controller의 test coverage 결과

test coverage가 100% 인것을 확인하였다.

 

summery

 

 

↓↓↓ 다음 내용

2024.01.25 - [Web Application/Backend] - [REST API] Spring Boot로 REST API 프로젝트 (9) - Swagger로 api document 생성하기

 

[REST API] Spring Boot로 REST API 프로젝트 (9) - Swagger로 api document 생성하기

↓↓↓이전내용 2024.01.10 - [Web Application/Backend] - [REST API] Spring Boot로 REST API 프로젝트 (8) - JUnit TEST controller 계층 test 예제 [REST API] Spring Boot로 REST API 프로젝트 (8) - JUnit TEST controller 계층 test 예제 ↓

im-gonna.tistory.com

반응형
반응형
REST : 웹(HTTP)의 장점을 활용한 아키텍쳐

 

1. REST (REpresentational State Transfer) 기본

  • REST의 요소
  • method
method 의미 idemptent
POST Create No
GET Select Yes
PUT Update Yes
DELETE Delete Yes

 

** idempotent : 한 번 수행하냐, 여러 번 수행했을 때 결과가 같나?

 

  • Resource
    ✔ http://myweb/users와 같은 URI
    ✔ 모든 것을 Resource (명사)로 표현하고, 세부 Resource에는 id를 붙임

  • Message
    ✔ 메시지 포맷이 존재
    : JSON, XML 과 같은 형태가 있음 (최근에는 JSON 을 씀)
HTTP POST, http://myweb/users/
{
	"users" : {
		"name" : "terry"
	}
}

 

  • REST 특징
  • Uniform Interface (일관된 인터페이스)
    • HTTP 표준을 기반으로 하며, 특정 언어나 기술에 종속되지 않음.
    • 예를 들어, REST API가 HTTP와 JSON을 사용하여 정의되었다면, 어떤 플랫폼이든 해당 API에 접근 가능.
  • Self-Descriptive Messages (자기 서술적 메시지)
    • API 메시지 자체만으로도 그 의미를 이해할 수 있도록 설계해야 함.
    • 메시지를 보고도 어떤 리소스에 어떤 동작을 수행하는지 직관적으로 이해할 수 있어야 함.
  • HATEOAS (Hypermedia As The Engine Of Application State)
    • 응답에는 현재의 상태를 나타내는 하이퍼링크가 포함되어야 함.
    • 클라이언트는 이 링크를 통해 다음에 수행 가능한 작업을 이해하고 진행할 수 있음.
  • Statelessness (무상태성)
    • 각각의 요청은 독립적이며, 서버는 클라이언트의 상태를 저장하지 않음.
    • 이로써 서버는 간단해지고, 확장성이 높아짐.
  • Resource 지향 아키텍처 (ROA)
    • 자원(리소스)을 중심으로 하는 아키텍처
    • 각 리소스는 고유한 URI(Uniform Resource Identifier)를 가지며, 명사 형태로 정의됨.
  • Client-Server Architecture (클라이언트-서버 아키텍처)
    • 시스템을 클라이언트와 서버로 분리함으로써 각각의 역할을 명확하게.
  • Cache Ability (캐시 사용 가능)
    • 응답은 캐싱될 수 있어서, 동일한 요청에 대한 반복적인 처리를 최소화
  • Layered System (계층화 구조)
    • 시스템은 계층화될 수 있어서, 각 계층은 독립적으로 구현

  • Code On Demand (선택적 코드 전송)
    • 서버로부터 클라이언트가 실행 가능한 코드를 전송할 수 있습니다. 이는 선택 사항이며, 일반적으로는 사용되지 않음

=> REST는 자원을 중심으로 하며, 간단하고 일관된 인터페이스를 통해 클라이언트와 서버 간의 통신을 단순화하고 효율적으로 만들기 위한 웹 아키텍처

 

 

***참고
https://gyoogle.dev/blog/web-knowledge/REST%20API.html

반응형

'Web Application' 카테고리의 다른 글

HTTP status code (HTTP 상태 코드)  (0) 2023.12.28
HTTP Request Methods  (0) 2023.12.23
쿠키(cookie)와 세션(session)의 차이  (1) 2023.12.22
브라우저 동작 방법  (0) 2023.12.20
[Node.js] Node.js와 Javascript의 개념  (0) 2023.09.13
반응형
API ?

"API 만들어 본 적 있어?"

친구의 질문으로 시작된 본격 API 파헤치기.. 

여기서 API는 [ Application Programming Interface ]의 약자로, 서로 다른 애플리케이션 사이에서 데이터를 주고 받을 수 있게 해주는 중간 다리 역할 이라고 생각하면 된다.

 

API에는 RESTful API, SOAP API, JPA... 등등 여러 종류가 있다.

 

지금껏 내가 해왔던 프로젝트는 클라이언트와 서버간의 상호작용에 있어서는 전통적인 자바 애플리케이션 @controller를 사용했다. 즉, HTTP 메서드인 GET, POST, PUT, DELETE (소위 CRUD라고 함)를 활용해서 조작하지 않고, @Getmapping, @Postmapping으로 url을 잡고 사용해왔다.

이런 방식은 사실 상 서버 사이드 렌더링을 통해서 웹 페이지를 생성하고 제공하는데에 사용되기 때문에, 서버랑 클라이언트가 강력하게 결합되어 있어서 서버-클라이언트 간의 독립성은 떨어진다. (한 마디로 정말 간단한 웹 서비스 개발..)

[서버사이드 렌더링이 뭐고] ↴

더보기

서버 사이드 렌더링이 무슨말이냐구요?

 

서버 사이드 렌더링(Server-Side Rendering, SSR)은 웹 애플리케이션의 사용자 인터페이스(UI)를 서버에서 생성하고 초기 로드 시에 클라이언트에게 완전한 HTML 페이지를 제공하는 웹 개발 기술입니다. 이것은 클라이언트 사이드 렌더링(Client-Side Rendering, CSR)과 대조적입니다.

SSR의 작동 방식은 다음과 같습니다:

  1. 클라이언트에서 웹 페이지 요청을 서버로 보냅니다.
  2. 서버는 요청을 받아 해당 요청에 필요한 데이터를 데이터베이스에서 가져오거나 다른 외부 소스로부터 데이터를 가져옵니다.
  3. 서버는 서버 사이드 렌더링 엔진을 사용하여 사용자 인터페이스(UI) 템플릿을 렌더링하고, 데이터를 포함한 HTML 페이지를 생성합니다.
  4. 서버는 완전한 HTML 페이지를 클라이언트에게 반환합니다.
  5. 클라이언트는 받은 HTML을 렌더링하고 페이지를 화면에 표시합니다.

하지만 요즘 대부분의 서비스는 여러 형태의 클라이언트 플랫폼과 서버간의 통신이 이루어지는 방식이기 때문에, 서버와 클라이언트가 독립적이면서도 잘 통신할 수 있도록 하는 방식이 선호된다.

 

그런 방식이 대표적으로 RESTful API라고 할 수 있다.

 

그럼 RESTful API는 뭐야???

 

RESTful API?

RESTfult API는 [ Representational State Transferful Application Programming Interface ]의 약자로, URI에 자원의 정보를 나타내도록 하고, HTTP 메서드( GET, POST, PUT, DELETE  )를 사용해서 자원을 조작하는 것이다.

 

자원?? URI??? 조작???

 

한가지 예를 들어보자.

회원(회원정보)이 있고, 상품(상품정보)이 있다고 가정하자. 각각은 자원이라고 부른다. 

회원 정보에 대해서 조회(GET)를 할수 있고, 새로운 회원 정보를 생성(POST)할 수 있고, 회원 정보를 수정(PUT)할 수 있고, 회원 정보를 삭제(DELETE)할 수 있다.

mapping할 때마다 우리는 URI를 적었다. 그 URI를 자원에 따라서 패턴화 하고, 적절한 HTTP 메서드를 사용함으로써 동작을 정의할 수있다.

  

즉 이와 같이 쓸 수 있다.

  • GET /members: 모든 회원 목록 조회.
  • GET /members/{id}: 특정 회원 조회.
  • POST /members: 새로운 회원 생성.
  • PUT /members/{id}: 특정 회원 수정.
  • DELETE /members/{id}: 특정 회원 삭제.
  • GET /products: 모든 상품 목록 조회.
  • GET /products /{id}: 특정 상품 조회.
  • POST /products : 새로운 상품 생성.
  • PUT /products /{id}: 특정 상품 수정.
  • DELETE /products /{id}: 특정 상품 삭제.

 이렇게 한 자원에 대해서 '/자원'으로 패턴화 하는 과정을 거치고, 그 안의 세부 동작이나 자원에 대해서는 /이하에 붙여서 URI를 통해 자원의 상태를 나타내어 가독성을 높혀주는 것이다.

 

특징을 보면 자원이 모두 복수명사 형태로 표현된 것을 확인 할 수 있다.

리소스 명은 동사보다는 명사를 사용하도록 하는 것이 바람직한 표현 방식이다.

 

따라서 명심하자.

 

GET /members/delete/1  //잘못된 표현

이와 같이 동작을 나타내는 delete를 리소스에 작성하는 것이 아니다.

 

DELETE /members/1  //옳게 수정된 표현

 자원은 명사로만 두고, 동작은 HTTP 메서드로 표현하는 것이다.

 

(URI 설계의 자세한 내용은 아래의 블로그를 참고하자.)

 

 

개발 초보를 위한 RESTful API 설계 가이드

초보자를 위한 RESTful API 설계 가이드를 작성해보았습니다.

velog.io

 

스프링부트에서 코드 상 어떻게 쓰이는지 살펴보자.

@RestController
@RequestMapping("/api/members")
public class MemberRestController {
    // 멤버 API 정의
    
    @GetMapping
    public ResponseEntity<List<MemberDTO>> getAllMembers() {
        // 모든 멤버 목록 조회 로직
        List<MemberDTO> members = memberService.getAllMembers();
        return new ResponseEntity<>(members, HttpStatus.OK);
    }

    @GetMapping("/{id}")
    public ResponseEntity<MemberDTO> getMember(@PathVariable Long id) {
        // 특정 멤버 조회 로직
        MemberDTO member = memberService.getMemberById(id);
        return new ResponseEntity<>(member, HttpStatus.OK);
    }

    @PostMapping
    public ResponseEntity<MemberDTO> createMember(@RequestBody MemberDTO memberDTO) {
        // 새로운 멤버 생성 로직
        MemberDTO createdMember = memberService.createMember(memberDTO);
        return new ResponseEntity<>(createdMember, HttpStatus.CREATED);
    }

    @PutMapping("/{id}")
    public ResponseEntity<MemberDTO> updateMember(@PathVariable Long id, @RequestBody MemberDTO memberDTO) {
        // 특정 멤버 수정 로직
        MemberDTO updatedMember = memberService.updateMember(id, memberDTO);
        return new ResponseEntity<>(updatedMember, HttpStatus.OK);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteMember(@PathVariable Long id) {
        // 특정 멤버 삭제 로직
        memberService.deleteMember(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

각 객체의 CRUD를 위해서 하나의 RESTController로 정의되는 것을 확인할 수 있다.

어노테이션에 주목하자.

@RestController
@RequestMapping("/api/members")

@RestController를 통해서 RESTful API를 사용하겠다는 것을 나타내고 있다.

@RequestMapping을 통해서 URI 패턴을 정의하기 시작했다. 회원에 대해서는 /api/members가 기본 URI로 동작할 것이다.

그리고 각각의 CRUD 동작에 맞추어서 @Getmapping @Postmapping @Putmapping @Deletemapping을 사용하고 있는 것을 확인할 수 있다.

 

여기서 또 중요한 점!!!

 

기존 프로젝트에서는 CRUD결과 html 페이지(main.html 이런 파일 자체)를 반환했었는데에 반해(그래서 더욱 결합이 된 것일지도..), RESTful API 방식에서는 ResponseEntity를 반환하고 있다!!!??

 

ResponseEntity ?

ResponseEntity는 Spring Framework에서 제공하는 클래스로, HTTP 응답을 나타내는 객체이다. 이 클래스를 사용하여 클라이언트에게 HTTP 응답을 구성하고 전달할 수 있다.

 

왜 이 객체를 반환하는 것일까?

 

그건 바로 RESTful API 방식에서의 HTTP 응답 형식은 JSON이나 XML같은 데이터 형식을 사용함으로써 클라이언트에 응답하기 때문이다. 따라서 반드시 반환 형태를 JSON 또는 XML형태의 데이터로 주어야 한다.

 

ResponseEntity는 다음과 같은 기능을 제공한다. 

  1. HTTP 응답 상태 코드 설정
  2. HTTP 응답 헤더 설정
  3. 응답 본문 데이터 설정
  4. 응답 타입 설정

 

이것도 코드를 통해서 쓰임을 살펴보자.

 

@GetMapping
    public ResponseEntity<List<MemberDTO>> getAllMembers() {
        // 모든 멤버 목록 조회 로직
        List<MemberDTO> members = memberService.getAllMembers();
        return new ResponseEntity<>(members, HttpStatus.OK);
    }

 매핑 결과 ResponseEntity 객체를 new로 생성해서 members의 정보와 함께 HttpStatus.OK라는 것을 담아 반환하고 있다.

members는 조회 결과를 담은 데이터를 반환해 준 것일테고, HttpStatus.OK가 조금 생소하다.

 

HttpStatus.OK가 바로 ResponseEntity의 기능 1번인 HTTP 응답 상태 코드를 나타내는데, 의미는 200 OK 상태를 나타내는 코드이다.=말 그대로 OK= 요청이 성공적으로 처리되었음

HttpStatus.NOT_FOUND라는 코드는 404 not found 상태를 반환하라는 의미이다.= 요청한 리소스를 찾을 수 없음

(상태별로 코드가 정리된 표도 위 참고 블로그에 있으니 참고하자.)

 

상태 정보를 넘기는 이유가 뭘까?

상태코드 ?

상태 코드는 서버가 클라이언트에게 요청을 처리한 결과를 전달하는 수단이다. 클라이언트는 상태 코드를 통해 요청이 성공했는지, 실패했는지, 어떤 종류의 오류가 발생했는지 등을 파악할 수 있다.

 

클라이언트는 상태 코드를 기반으로 다음 단계를 결정할 수 있다. 예를 들어, 성공적인 응답(예: 200 OK)일 경우 데이터를 표시하고, 오류 응답(예: 404 Not Found)일 경우 오류 메시지를 표시하거나 다른 조치를 취할 수 있다.

 

이 외에도 다양한 이유가 있지만, 서버와 클라이언트 간의 정확하고 원활한 상호작용을 위해서가 중점이라고 할 수 있겠다.

 

 

마지막으로 한가지 더 잡고 넘어가야 할 부분이 있다.

 

바로 '세션' 문제인데, 기존의 프로젝트 코드(전통적인 웹 애플리케이션 방식)에서는 @HttpSession을 통해서 로그인 상태를 세션을 통해 유지할 수 있었다.

근데 RESTful API방식은 상태를 관리하지 않는 stateless 방식을 따른다. 각 요청이 독립적이고, 서버는 클라이언트의 상태를 유지하지 않기 때문에, 클라이언트는 요청을 할 때 요청 정보를 함께 제공해 주는 과정이 필요하다!!

 

예를 들어서 인증 정보는 요청 헤더에 토큰 또는 인증 정보를 포함하여 전송할 수 있다. 토큰 기반 인증을 사용해 사용자 인증을 하고 상태 관리를 할 수 있는 것이다.

 

RESTful API에서의 토큰 기반 인증:

  1. 사용자가 서버에 로그인하면 서버는 사용자에게 액세스 토큰(access token)을 발급합니다.
  2. 클라이언트는 액세스 토큰을 안전한 방식으로 저장하고 각 요청에 포함시켜 서버로 보냅니다. 일반적으로 요청의 헤더에 포함됩니다.
  3. 서버는 액세스 토큰을 검증하고, 유효한 토큰인 경우 해당 사용자를 식별하고 요청을 처리합니다.

요청의 헤더가 어디일까..~

 

일반적으로 사용되는 토큰 기반 인증 방식 중에는 OAuth 2.0 및 JWT(Json Web Token)가 있습니다. 이러한 인증 방식을 사용하여 RESTful API에서 사용자 인증 및 세션 관리를 구현할 수 있습니다.

 

OAuth...!!! 이번 정처기 실기에 나왔던 개념인데, 이걸 먼저 공부했더라면 맞힐 수 있었을텐데..

 

토큰 관련해서는 좀 더 공부가 필요할 것으로 보인다. 과거에 express랑 node.js로 개발했을 때 로그인에서 한번 쓴 것 같기도 한데(토큰 유효 시간 설정하고 그랬었음), 기억이 잘 나지 않은 것 보니.. RESTful API로 한번 프로젝트 파서 직접 해봐야겠다!!!

 

할거 +1됨.

 

 

 

반응형

+ Recent posts