김다정, React.js, 스프링 부트, AWS로 배우는 웹 개발 101
JSON | 오브젝트를 표현하기 위한 문자열 | |
---|---|---|
오브젝트 | 메모리 상의 자료구조. 스프링에서의 Bean | |
직렬화 Serialization | 서로 언어 또는 아키텍처가 다른 오브젝트를 변환 또는 전송을 위해 다른 형태로 변환하는 작업. 그 다른 형태가 JSON | |
서버 | 네트워크 오퍼레이션을 수행하는 프로그램 | |
정적 웹 서버 Static- | HTTP 서버 종류 중 하나. 리소스 파일을 반환하는 서버 React 등 |
|
동적 웹 서버 Dynamic- | 요청값에 따라 응답 바디가 달라지는 서버 이 구현은 비즈니스 요구사항에 따라 모두 달라짐 모든 걸 개발자가 다 짤 필요는 없고, 서블릿 엔진(톰캣 등)의 도움을 받으면 됨 |
|
서블릿 컨테이너(=서블릿 엔진) | 서블릿 엔진의 도움을 받으려면 클래스 파일을 Javax.servlet.httpHttpServlet 서브 클래스를 작성해야 됨 그 클래스의 상속 및 구현은 스프링 부트가 해 줌 |
2.1
스프링 | 오픈 소스의 경량 프레임워크 | |
---|---|---|
프레임워크 | 개발자들이 확장해서 사용할 수 있는 코드 | |
확장? | 1. 프레임워크가 제공하는 클래스나 라이브러리를 사용 2. 프레임워크가 제공하는 클래스나 인터페이스를 상속 및 구현해 우리 코드를 프레임워크의 일부로 실행하는 것 |
|
스프링 프레임워크 | 의존성 주입, 스프링 AOP, 스프링 ORM, 스프링Web 등… 의존성 주입 컨테이너 중 하나 오브젝트 간의 의존성을 명시하면 스프링의 IoC 컨테이너가 오브젝트를 관리해 줌 스프링을 쓰면 Servlet을 상속받지 않아도 되고 doGet을 오버라이드 하지 않아도 되고 ServletRequest를 직접 파싱하지 않아도 되고 ServletResponse를 직접 작성하지 않아도 되고 비즈니스 로직만 짜면 되기 때문에 쓰는 거임. |
|
의존성 주입 | 의존? 특정 클래스에 의존하는 필드. 그 필드는 그 클래스가 존재해야 쓸 수 있다는 얘기임. 그런데 1) 그 클래스를 바꾸고 싶을 수도 있고 2) 그 클래스가 100개쯤 있을 수 있음. 그러면 그걸 다 치고 바꾸고 싶으면 그걸 다 바꿔야 함. 3) 단위 테스트하기가 힘듦. 단위 테스트를 할 때는 껍데기만 있는 클래스(=Mock 클래스)를 만들어서 쓰는데 이것도 어려움. 그래서 의존성을 외부에서 주입하려고 하는 거임. 어떻게 하냐면 1) 생성자를 쓰거나 2) Setter를 쓰는 거다. |
|
@SpringBootApplication | 이 클래스가 스프링부트 설정 클래스임을 의미 @Component, @ComponentScan 어노테이션 포함 |
|
@Component | 이 클래스를 자바 빈으로 등록시키라고 알려주는 어노테이션 | |
@ComponentScan | 이게 특정 클래스에 달려 있어야 @Component가 달려 있는 곳을 빈으로 등록할 수 있음 | |
@Bean | 로컬에서만 쓰이거나 엔터프라이즈 어플리케이션이거나 스프링기반이 아니라서 @Component를 못 쓸 때 @Bean을 이용해서 등록 | |
@Autowired | 스프링이 이게 달려있는 오브젝트를 찾아서 알아서 컨트롤러에 등록 | |
REST API | URI Unified Resource Identifier, HTTP 메서드, 요청 바디로 구성 |
2.2
레이어드 아키텍처 패턴 | 애플리케이션을 구성하는 요소들을 수평으로 나눠 관리하는 것 |
---|---|
수평? | |
계층 | |
엔티티 클래스 | |
롬복 | @Builder |
@NoArgsConstuctor, @AllArgsConstructor | |
@Data | |
DTO 쓰는 이유 | 캡슐화 |
클라이언트가 필요한 정보를 모델이 전부 가지고 있지 않은 경우가 있음 | |
REST | Representational State Transfer |
RESTful API | |
Client-Server | |
Cacheable | |
Layered System | |
Uniform Interface | |
Stateless | |
Code-On-Demand |
@RestController | http 관련된 코드 및 매핑을 알아서 해 주는 어노테이션 |
---|---|
@PathVariable | 매개변수를 넘겨받는 방법 1 |
@RequestParam | 매개변수를 넘겨받는 방법 2 |
@RequestBody | 오브젝트처럼 복잡한 자료형을 넘겨받고 싶을 때 쓰는 어노테이션 |
서비스 레이어 | 컨트롤러와 퍼시스턴스 사이에서 비즈니스 로직을 수행 1. HTTP와 긴밀히 연관된 컨트롤러에서 분리되어 있음 2. DB와 긴밀히 연관된 퍼시스턴스에서 분리되어 있음 집중하고 싶은 비즈니스 로직을 구현하기 좋음 |
JPA 쓰는 이유 | ORM 하기 귀찮아서. ORM(Object-Relation Mapping)이 뭐냐면 JDBC 깔아서 Connection으로 DB에 연결하고 쿼리 실행해서 ResultSet에 담고 While문 내에서 원하는 정보를 뽑아서 원하는 오브젝트로 바꾸는 것,. 그거를 좀 더 편하게 해 주는 게 Hibernate, JPA. |
스프링 데이터 JPA | JPA 편하게 쓰게 해 주는 거. 그 중 하나가 그게 저번에도 써 봤던 JPA provider 중 하나인 JpaRepository. |
JPA 설정 | yaml이나 application.properties에서 해 주는거. Database, show-sql, database-platform: -.MySQL8Dialect Hibernate: ddl-auto: update Datasource 설정: url, username, password |
@Entity | JPA를 쓸 때 Entity 클래스에 달아 줌 |
@Table | 테이블 이름 바꾸고 싶을 때 이용. 안 쓰면 1. @Entity, 2. 클래스의 이름을 테이블 이름으로 간주 |
@Id | 기본 키에 달아 준다 |
@GeneratedValue | Id를 자동으로 생성하겠다는 뜻. 기본 Generator에 Incremental, Sequence, Identity 등이 있음 |
@GenericGenerator | 커스텀 Generator를 사용하고 싶을 때 이용 |
JpaRepository<T, ID> | T: 테이블에 매핑할 엔티티 클래스 ID: 그 엔티티의 기본 키 타입 |
@Query | JpaRepository가 제공하는 기본 쿼리 외에 다른 쿼리를 쓸 때는 국룰대로 메서드를 써 주면 됨. 국룰 주소: https://docs.spring.io/spring-data/jpa.docs/current/reference/html/#jpa.query-methods.query-creation 그것보다 더 복잡한 쿼리는 @Query를 이용 |
2.3
Logger 설정 | @Slf4j 로그계의 JPA |
---|---|
Create | Validate 메서드로 검증하고 Save()로 엔티티를 저장 findByUserId로 엔티티를 검색해서 리턴 |
Retrieve | JpaRepository에서 국룰대로 만든 findByUserId() 메서드를 이용 |
Update | findById로 가져온 다음 setter로 하나씩 바꿈 그 다음 save()로 저장 |
Delete | Delete() 메서드로 삭제 |
3.1
프론트엔드 | 사용자의 바로 앞에서 앱 로직을 수행하고 백엔드로 요청을 전달하는 역할 |
---|---|
Node.js | JS를 브라우저 밖에서 실행할 수 있게 하는 프로그램. (=JS 런타임 환경) V8 JS 엔진 실행 이게 무슨 얘기냐면 JS로 서버를 만들 수 있다는 얘기임 |
Npm Node Package Manager | Gradle/Maven같은 거. |
Package.json | 프로젝트의 메타데이터, 사용할 node.js 패키지 목록 등을 포함 |
Package-lock.json | 어느 환경에서든 같은 버전의 패키지가 설치되도록 각 패키지가 사용할 버전을 고정하는 파일 |
파싱 | 렌더링을 하기 위한 전처리 단계 1. HTML을 트리 자료구조의 형태인 DOM Document Object Model 트리로 변환 2. 리소스를 다운로드(image, css, script 등) 2-1. CSS의 경우 다운로드 하고 CSSOM CSS Object Mode 트리로 변환 3. 다운로드안 JS를 인터프리트, 컴파일, 파싱, 실행 |
렌더링 | 한마디로 말하면 화면에 보여주는 거. 파싱 이후 단계 1. DOM 트리와 CSSOM 트리를 합쳐 렌더 트리를 만듦. 2. 레이아웃을 정함: 브라우저 상 트리의 위치 및 크기를 정하는 것 3. 브라우저 스크린에 렌더트리의 각 노드를 그려줌 그러니까 리액트는 ReactDOM(Virtual DOM)을 가지고 있음. 어찌 됐든 상태(State)가 변하면 ReactDOM이 이를 감지하고 컴포넌트 함수를 다시 호출해서 변경된 부분의 HTML을 바꿔 줌 |
SPA Single Page Application | 한번 웹 페이지를 로딩하면 유저가 임의로 새로고침하지 않는 이상 페이지를 새로 로딩하지 않는 애플리케이션 페이지가 바뀔 때 js 내에서 html이 재구성되므로 서버에 새 html 페이지를 요청하지 않음 이렇게 렌더링 하는 걸 Client-Side Rendering이라고 얘기함 |
JSX | 리액트가 한 파일에서 HTML과 JS를 함께 사용하기 위해 확장한 JS 문법 |
3.2
훅 | 리액트의 상태와 여러가지 기능을 사용할 수 있도록 도와주는 함수. UseState같은 거. |
---|---|
UseState | 함수형 컴포넌트에서 상태 변수를 사용할 수 있게 해 줌 상태변수는 사용자가 무언가를 할 때마다 바뀜. 이를 추적해서 새 상태가 화면에 나타나도록 렌더링 해야 될 거임 이 오브젝트가 상태라고 알려주는 함수가 UseState 함수 배열을 반환: [A, B] 첫 번째는 오브젝트고, 두 번째는 상태를 업데이트할 수 있는 함수 |
상태 변수? | 시간이 지나거나, 컴포넌트의 사용자가 컴포넌트와 상호작용하는 동안 변경되는 변수 |
{} | JS로 된 변수를 JSX에서 쓰려면 변수를 {}로 묶어주면 됨 |
콜백 함수 | 소괄호 안에 들어가는 함수 어떤 사건이 일어났을 때의 상태와 그 사건에 대한 정보를 담고 있음 |
map | Array 자료 개수만큼 함수안의 코드 실행해 줌 변수가 JSON이라면 JSON의 key값을 key={변수.key} 로 뽑아서 쓸 수 있음 |
event.target.value | 매개변수의 값이 담겨 있음 |
스프레드 연산자[…]로 새 배열 만든 이유 | 리액트는 레퍼런스를 기준으로 재렌더링함 근데 배열의 레퍼런스는 배열에 값을 추가하더라도 변하지 않음 근데 값을 바꿨으면 변해야 되니까 아예 배열을 …으로 새로 만든 거(=초기화)임 |
.filter | 조건에 맞는 경우만 필터링 |
3.3
CORS Cross-Origin Resource Sharing | 처음 리소스를 제공한 도메인(=Origin)이 현재 요청하려는 도메인과 다르더라도 요청을 허락해주는 웹 보안 방침 |
---|---|
useEffect | 원래 리액트는 컴포넌트가 변하면 ReactDOM이 이를 감지해서 렌더링을 해 줌. 근데 상태를 업데이트하는 함수가 끼어 들어가면 렌더링을 또 하고, 이게 계속 반복되면 무한루프에 들어가는 거임. 이걸 useEffect로 방지할 수 있음. |
useEffect(콜백함수, 디펜던시 배열) | |
fetch | Promise |
Fetch 말고 XMLHttpRequest 라는 걸 써도 됨 | |
Promise | |
그래서 Fetch가 뭐냐면 | |
onReject / onError |
4.1
인증 | 로그인 요청 및 확인 |
---|---|
인가 | 로그인을 한 유저에게 할 수 있는 자원을 정의하는 것 |
Basic 인증 | 모든 HTTP 요청에 아이디와 비밀번호를 같이 보내는 것 아이디와 비밀번호를 콜론으로 이어 붙인 후 Base64로 인코딩한 문자열을 함께 보냄 단점: 1. 디코더만 있으면 바로 뚫림 2. MITM(Manipulator in the Middle) 공격에 취약함 2-1. 무슨 얘기냐면 무조건 HTTPS를 써야 한다는 뜻임 - 중간에 HTTP 요청을 가로채 문자열을 디코딩하는 것 3. 유저를 로그아웃 시킬 수 없음 4. 인증 서버 및 인증 DB에 과부하가 걸릴 확률이 높음 5. 서비스를 2개로 쪼갠다 그러자. 서비스 1에서 인증하고 서비스 2에서도 인증해야 됨 6. 인증 서버가 단일 장애점이 됨 |
토큰 기반 인증 | 토큰 |
장점 | |
단점 | |
JWT | 전자서명된 토큰 중 하나 |
Header | |
Payload | |
Signature | |
작동 원리 | |
장점 | |
4.3
스프링 시큐리티 | 서블릿 필터의 집합 | |
---|---|---|
서블릿 필터 | 서블릿 실행 전에 실행되는 클래스 HttpFilter 또는 Filter를 상속해서 doFilter 메서드를 오버라이딩함 DispatcherServlet 실행 전에 실행됨 이 필터를 통해서 원치 않는 HTTP 요청을 거절할 수 있음 이 필터를 여러 개 깔아서 순서대로 실행시킬 수도 있음(FilterChain) |
|
OncePerRequestFilter | 서블릿 필터 중 하나. 한 요청당 반드시 한 번만 실행됨 |
|
@AuthenticationPrincipal | HttpSecurity를 구현한 클래스에서 UsernamePasswordAuthenticationToken를 생성했을 때 생성자의 첫 번째 매개변수. | |
Salting | 값에 의미없는 값을 더해서 암호화하는 것 값이 매번 달라지기 때문에 spring의 BcryptPasswordEncoder에서는 matches() 메서드로 두 값을 비교함 |
5.1
Server-Side Routing | 특정 주소에 주소를 요청하면 그 때 웹 페이지를 렌더링하고 그 웹 페이지를 새로고침하는 것 | |
---|---|---|
Client-Side Routing | 서버로 어떤 요청도 날리지 않는 라우팅 JS가 모든 라우팅을 해 줌 처음 주소에 들어가면 모든 리소스를 다 받아 옴 |
|
React-router-dom | 클라이언트 사이드 라우팅 라이브러리 중 하나 | |
오래된 버전의 클라이언트 사이드 라우팅의 경우 브라우저 히스토리 문제로 기능 구현이 제대로 되지 않는 경우가 있음 그 히스토리를 사용해서 브라우저-리액트 간 URL을 동기화하는 컴포넌트 |
||
여러 개의 를 관리하고 가장 적합한 를 찾아주는 컴포넌트 |
5.3
웹 스토리지 | 데이터를 key, value형태로 저장 | |
---|---|---|
세션 스토리지 | 브라우저를 닫으면 사라짐 | |
로컬 스토리지 | 브라우저 닫아도 값 남아 있음 |
6.1
EC2 Elastic Compute Cloud | 서버 |
---|---|
도메인 이름 Domain Name | IP를 대신하는 이름 |
DNS Domain Name System | 도메인 이름과 주소를 매핑해 놓은 시스템 |
Route 53 | DNS 중 하나 |
Virtual IP | 두 인스턴스가 공유하는 IP |
Application Load Balancer | 트래픽을 적절히 분배해주는 하드웨어 또는 소프트웨어 |
Target Group | AWS에서, 로드 밸런서에 연결되어 있는 인스턴스. |
Auto Scaling Group ASG | 인스턴스가 죽었을 때, ASG가 적정 인스턴스 수만큼 인스턴스를 실행시킴. 최소, 최대, 적정 인스턴스 수는 정할 수 있음 알아서 scale in, scale out하도록 설정할 수도 있고. |
VPC Virtual Private Cloud | AWS 전용 가상 네트워크 |
가상 네트워크 | EC2밖에서 VPC 내부로 접근하지 못함 |
AWS 일래스틱 빈스톡 ElasticBeanStalk | 얘가 위 표에 있는 여러 인프라를 알아서 처리해줌 이 과제에서는 RDS, 로드 밸런서, ASG, EC2, 타깃 그룹을 설정해 줌 |
AWS Cloudformation | JSON 또는 YML 파일을 이용해 리소스 및 관계를 표시 |
IaC Infrastructure as Code | 파일을 바탕으로 인프라를 구축하는 것 |
6.5
Route 53 | MITM 공격은 Basic / Token / JWT 만으로 막을 수 없음 HTTPS 인증서가 필요 |
|
---|---|---|
인증서 | 를 쓰려면 일단 자신의 도메인이 있어야 됨. 그걸 해주는 서비스가 Route 53 | |
Host Zone | DNS 영역 파일 | |
DNS 영역(=DNS Namespace) 니가 만든 도메인이 관리할 영역 여러 개의 레코드를 한 곳에서 관리하려고 만듦 |
||
레코드 | SOA Start Of Authority 레코드 이 영역을 관리하는 관리자의 정보 NS 레코드 해당 도메인 A 레코드 해당 도메인의 서브 도메인이나 특정 IP로 연결하는 레코드 |
|
6.6
인증서:
Aws console > certificate manager에서 인증서 만들고
Elastic beanstalk에서 https 포트만 활성화
이 이후로는 당연히 그냥 http 도메인으로 접속 불가
Ec2 프론트엔드에서 80포트를 443포트로 redirect