일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 비용함수
- 딥러닝공부
- unsupervised learning
- 효묘블로그
- 머신러닝 강의
- Gradient Descent
- 딥러닝
- c언어 오목
- feature scaling
- 머신러닝 강좌
- 자바시작하기
- 파이썬강의
- 자바강좌
- supervised learning
- 자바
- 경사하강법
- 머신러닝
- 지도학습
- 파이썬강좌
- JAVA강좌
- python강좌
- C언어
- 인공지능
- java
- 비지도학습
- 백준 알고리즘
- 머신러닝공부
- acmicpc.net
- 선형회귀
- Python강의
- Today
- Total
컴공과컴맹효묘의블로그
[Spring Boot Session] 1주차 RESTFul API 본문
- INDEX
1. 웹 서버
웹은 어떤 원리로 동작할까?
사용자가 브라우저를 키고 url에 google.com을 입력하고 엔터를 누르면 구글에 접속할 수 있다. 그리고 구글 검색차에 검색어를 입력하고 엔터를 누르면 수십만가지의 검색 결과가 나온다. 이 동작을 할 수 있게 해주는 것이 웹 서버이다.
웹이 정상적으로 동작하려면 최소한 두 대의 컴퓨터가 필요하다. 하나는 사용자가 사용할 컴퓨터, 하나는 사용자 컴퓨터에 정보를 보내줄 컴퓨터다. 사용자가 사용하는 컴퓨터는 클라이언트라고 부르고, 사용자에게 정보를 주는 컴퓨터는 서버라고 부른다. 우리가 흔히 IT에서 사용하는 용어와 일치한다. Front-end, Back-end와는 다른 개념이다.
웹 서버(Web Server)는 일반적인 용어이다. 사용자가 웹 페이지에 접속할때 필요한 파일들을 제공해주는 역할이다. 보통 Apache, Nginx등이 이에 속한다. 웹 서버는 정적인 콘텐츠만을 제공한다.
웹 어플리케이션 서버(Web Application Server / WAS)는 웹 서버와는 달리 동적인 콘텐츠를 처리한다. 스프링 부트처럼 복잡한 로직을 수행해야하는 경우 이에 해당한다. Tomcat, Node.js가 WAS에 속한다.
벡엔드는 웹 어플리케이션 개발에 해당한다.
Spring Framework는 WAS가 아니다. 통합 어플리케이션 개발 도구이다.
Web Server, WAS
웹 서버 동작 방식
웹 어플리케이션 서버(WAS) 동작 방식
웹 동작 더 자세히
일반적으로 웹(HTTP)은 다음과 같은 순서로 동작한다.
- URL을 입력한다. 이 행위를 요청(Request)이라고 한다.
- 서버가 클라이언트에게 정보를 준다. 이 행위를 응답(Reponse)이라고 한다.
- 브라우저가 응답을 받아 화면에 렌더링한다.
- 사용자는 페이지와 상호작용한다.
벡엔드 서버는 위 동작에서 클라이언트의 요청을 처리하여 응답하는 역할을 한다.
그럼 웹(HTTP)는 어떤 요청이 있는지 알아보자.
2. HTTP Methods
HTTP request methods - HTTP | MDN
메서드 | 목적 | 데이터 변경 여부 | Idempotent 여부 | 응답에 본문 포함 |
---|---|---|---|---|
GET | 서버에서 데이터를 가져옴 | X | O | O |
POST | 서버에 데이터를 제출하고, 리소스를 생성 | O | X | O |
PUT | 리소스를 대체하거나 새로 생성 | O | O | O |
PATCH | 리소스의 일부를 수정 | O | O (서버에 따라 다름) | O |
DELETE | 리소스를 삭제 | O | O | O (응답에 따라 다름) |
HEAD | 리소스의 헤더 정보만 가져옴 | X | O | X |
OPTIONS | 서버가 지원하는 메서드를 확인 | X | O | X |
TRACE | 경로 디버깅 | X | O | O |
CONNECT | 터널링 설정 | X | X | O |
여기서 GET, POST, PUT, DELETE는 CRUD(Create, Read, Update, Delete)와 밀접한 관계가 있다. 본 세션에서도 이 메서드만 이용할것이다.
3. RESTfulAPI
REST
REST(Representational State Transfer)는 자원을 이름으로 구분하여 해당 자원의 상태 정보를 주고받는 모든 것을 의미한다.
자원이란 문서, 사진, 데이터 등을 의미한다.
자원의 표현이란 해당 자원을 표기하기위한 이름이다. 예를 들어 학생 데이터는 “student”로 표현한다.
REST는 기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 사용하기 때문에 웹의 장점을 최대한 활용할 수 있는 아키텍쳐이다.
좀 더 자세히 이야기하면,
HTTP URI를 이용하여 자원의 위치를 명시하고, HTTP Methods를 이용하여 자원에 대한 CRUD를 수행하는 것이다.
HTTP URI가 자원, HTTP Methods가 행위라고 생각하면 된다. 그리고 이에 대한 응답은 표현이라고 한다.
예를 들어보자.
id가 3인 학생 정보를 가져오고싶다.
여기서 자원은 “id가 3인 학생 정보”이고, 행위는 “가져오다” 이다.
가져오다에 해당하는 HTTP Methods는 GET이라고 할 수 있다.
그리고 자원에 해당하는 HTTP URI는 다음과 같이 표현할 수 있다.
/student/3
위 요청을 보내면 해당하는 응답(표현)에는 다음과 같이 예상할 수 있다.
{
"id": 3,
"name": "홍윤기",
"stduent_no": "201904128"
}
왜 REST를 사용하나?
REST를 이용하는 이유중 하나는 다양한 플랫폼이 생겼기 때문이다. 2010년 이전에는 인터넷을 사용하는 디바이스는 컴퓨터 외에는 거의 없었지만, 스마트폰 등장의 이후로 안드로이드, 아이폰과 같은 디바이스에서도 통신을 할 수 있어야하기 때문이다. 이 문제를 해결하기 위해 모색한 방법중 하나가 바로 REST이다.
REST의 구성 요소
- 자원(Resource): URI
- 모든 자원은 고유한 ID가 존재하고, 이 자원은 서버에 존재한다.
- 자원을 구별하는 방법은 URI이다. (예:
/student/3
) - Client는 URI를 이용해서 자원을 지정하고 해당 자원의 상태정보를 조작한다.
- 행위(Verb): HTTP Methods
- 자원에 대한 행위는 HTTP Method를 사용한다.
- HTTP Method는 GET, POST, PUT, DELETE 등이 있다.
- 표현(Represetation of Resource)
- 요청된 정보에 의해 서버는 이에 대한 응답을 해야한다.
- REST에서 하나의 자원은 JSON, XML 등 여러 형태의 Representaion으로 나타내어진다.
- 보통 JSON 혹은 XML로 표현한다.
REST 특징
- Server-Client
- 자원이 있는 쪽이 서버, 자원을 요청하는 쪽이 Client
- Stateless
- Client의 context를 Server에 저장하지 않는다.
- 즉, 세션과 쿠기와 같은 context정보를 신경쓰지 않아도 된다.
- Server는 각각의 요청을 완전히 별개의 것으로 인식하고 처리한다.
- 즉 API서버는 단순히 Client의 요청을 처리한다.
- 이전 요청이 다음 요청의 처리에 연관되어서는 안된다.
- 단, DB 수정에 의한 정보 변경은 허용한다.
- Server의 처리 방식에 일관성을 부여하고 부담이 줄어들며 서비스의 자유도가 높아진다.
- Client의 context를 Server에 저장하지 않는다.
- Cacheable
- 웹 표준 HTTP 프로토콜을 그대로 사용하므로 웹에서 사용하는 기존의 인프라를 그대로 활용할 수 있다.
- HTTP의 캐싱을 사용할 수 있다.
- HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.
- 대량의 요청을 효율적으로 처리하기 위해 캐시가 요구된다.
- 캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답 시간, 성능, 서버 자원 이용률을 향상시킬 수 있다.
- 웹 표준 HTTP 프로토콜을 그대로 사용하므로 웹에서 사용하는 기존의 인프라를 그대로 활용할 수 있다.
- Layered System
- Client는 REST API Server만 호출한다.
- API Server는 순수 비지니스 로직을 수행하고 그 앞단에 보안, 로드밸런싱, 암호화, 사용자 인증 등을 추가하여 구조상의 유연성을 줄 수 있다.
- 로그밸런싱, 공유 캐시 등을 통해 확장성과 보안성을 향상시킬 수 있다.
- PROXY, Gateway같은 네트워크 기반의 중간 매체를 사용할 수 있다.
- Client는 REST API Server만 호출한다.
- Code-On-Demand(optional)
- Server로부터 Script를 받아서 Client에서 실행한다.
- 필수 조건은 아니다.
- Uniform Interface
- URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행한다.
- HTTP Protocol을 사용하는 모든 플랫폼에서 사용이 가능한다.
- 특정 언어나 기술에 종속되지 않는다.
REST API 설계 원칙
- 슬래시 구분자(/ )는 계층 관계를 나타내는데 사용한다.
- URI 마지막 문자로 슬래시(/ )를 포함하지 않는다.
- URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라져야 한다.
- REST API는 분명한 URI를 만들어 통신을 해야 하기 때문에 혼동을 주지 않도록 URI 경로의 마지막에는 슬래시(/)를 사용하지 않는다.
- Ex) http://restapi.example.com/houses/apartments/ (X)
- 하이픈(- )은 URI 가독성을 높이는데 사용
- 불가피하게 긴 URI경로를 사용하게 된다면 하이픈을 사용해 가독성을 높인다.
- 밑줄(_ )은 URI에 사용하지 않는다.
- 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 하므로 가독성을 위해 밑줄은 사용하지 않는다.
- URI 경로에는 소문자가 적합하다.
- URI 경로에 대문자 사용은 피하도록 한다.
- RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문
- 파일확장자는 URI에 포함하지 않는다.
- REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다.
- Accept header를 사용한다.
- Ex) http://restapi.example.com/members/soccer/345/photo.jpg (X)
- Ex) GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg (O)
- 리소스 간에는 연관 관계가 있는 경우
- /리소스명/리소스 ID/관계가 있는 다른 리소스명
Ex) GET : /users/{userid}/devices (일반적으로 소유 ‘has’의 관계를 표현할 때)
- /리소스명/리소스 ID/관계가 있는 다른 리소스명
4. Spring 동작 원리
Bean
Spring Bean은 스프링 컨테이너에 의해 생성되고 관리되는 객체입니다. 보통 자바 클래스들이 스프링 IoC 컨테이너에 의해 관리되는 객체들인데, 이 객체들은 자동으로 관리된다.
보통 @Controller
, @Service
, @Repository
, @Component
등 어노테이션으로 Bean 객체를 만들 수 있습니다. 이들은 서버에서 처리되는 여러가지 복잡한 일들을 신경쓰지 않고 구현해야할 것에 집중할 수 있게 해준다.
IoC (Inversion Of Control)
IoC는 컴포넌트 의존관계 설정(Component dependency resolution), 설정(Configuration), 및 생명주기(Life Cycle)을 해결하기 위한 디자인 패턴(Design Pattern)이다.
코드로 예들 들겠습니다.
스워치로 램프를 조작한다 → 램프가 스위치를 조작한다.
제어의 역전
Controller가 Spring을 조작한다 → Spring이 Controller를 조작한다.
에 비유 가능
public class Lamp {
boolean light = false;
public void lightOn() {
light = true;
}
public void lightOff() {
light = false;
}
}
public class Switch {
Lamp lamp = new Lamp();
boolean isOn = false;
public void toggle() {
if(isOn) {
isOn = false;
lamp.lightOff();
} else {
isOn = true;
lamp.lightOn();
}
}
}
이 떄 Switch는 Lamp에 의존적이다. Lamp가 바뀌면 Switch가 바뀌어야한다.
또한 Lamp가 아닌 Engine을 조작하는 Switch를 만드려면 Lamp에 의존적인 Switch는 재사용할 수 없다.
interface SwitchButtonInterface {
void on();
void off();
}
class Lamp implements SwitchButtonInterface {
public void on() {
System.out.println("Lamp on");
}
public void off() {
System.out.println("Lamp off");
}
}
class SwitchButton {
SwitchButtonInterface switchButton;
boolean isOn = false;
public SwitchButton(SwitchButtonInterface sb) {
switchButton = sb;
}
public void toggle() {
if(isOn) {
switchButton.off();
} else {
switchButton.on();
}
isOn = !isOn;
}
}
class Container {
Lamp lamp = new Lamp();
SwitchButton button = new SwitchButton(lamp);
public void controlLamp() {
// ...
button.toggle();
// ...
}
}
SwitchButtonInterface
는 스위치 기능을 추상화한다. 그리고 Lamp
는 SwitchButtonInterface
를 구현한다. SwitchButton
은 SwitchButtonInterface
인스턴스를 생성자 매개변수로 받아서 사용한다.
이렇게 하면 SwitchButtonInterface
를 구현한 객체는 SwitchButton
의 매개변수로 사용할 수 있다.
즉, EngineButton
을 따로 구현할 필요 없이 Engine
이 SwitchButtonInterface
를 구현하기만 하면 된다.
Container
는 Injection을 담당한다. 필요한 객체를 생성하여 SwitchButton
에 넘겨주고, 직접 조작하는 역할을 한다. 이 부분이 바로 Spring의 IoC Container 역할이다. 물론 아주 간소화 한 것이다. 이는 DI가 아니기 때문이다.
Dependency Injecion
DI(Dependency Injection)이란, 의존성 주입이라는 뜻으로 객체의 생성 및 주입을 프로그래머가 아닌 프레임워크가 담당한다는 의미이다. 이게 스프링 프레임워크에서의 @Autowired
에 해당한다. 더보기
주입하는 형태에 따라서 Constructor Injection, Setter Injection, Field Injection등으로 나뉜다.
Autowired는 스프링 프레임워크에서 스프링 IoC Container가 DI를 해준다.
Constructor Injection
객체를 생성자를 통해 의존성을 주입받는다.
public class MemberService {
private MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
Setter Injection
Setter Method 정의를 통해 의존성을 주입받는다.
public class MemberService {
private MemberRepository memberRepository;
@Autowired
public setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
Field Injection
Field에 직접 의존성을 주입받는다.
public class MemberService {
@Autowired
private MemberRepository memberRepository;
}
다음주차에는 Spring Boot를 미리 설치해와서 실제로 서비스를 구현하면서 스프링 부트 프레임워크를 사용하는 방법을 배워본다.
'쓰고싶은 것 > 글' 카테고리의 다른 글
[42 Seoul 온라인 테스트 후기] (0) | 2020.01.24 |
---|---|
머신러닝 공부 시작했슴다.. (0) | 2019.06.15 |