[Inf-WUP] 1주차 발자국
웹 서비스를 구성하는 요소
클라이언트
요청하는 주체 (브라우저)
서버
응답하는 주체
DB에서 Data의 삽입, 수정, 조회, 삭제 -> 클라이언트에 반환
데이터베이스
데이터의 집합
DBMS : 데이터의 집합을 저장하고 관리하는 역할 (보통 데이터베이스라고 하면 DBMS 의미)
웹 서비스 실행 과정
DNS 서버(전화번호부와 같은 역할. 주소를 다 갖고 있음)에서 도메인 전송
DNS 서버가 도메인에 해당하는 IP 주소 찾아 알려줌
해당 IP로 요청. 일반적으로 HTTP 통신. 이때 서버가 작업 처리를 위한 필요 데이터를 함께 전달
작업 처리 (DB 삽입, 조회, 수정, 삭제 등)
DB는 서버가 요청한 결과 반환
조회 : 조회된 데이터 전달
삽입, 수정, 삭제 : 작업의 성공 여부 응답
서버는 클라이언트에게 작업 수행 결과 응답. 웹 브라우저가 화면으로 표현할 수 있는 HTML 포맷의 데이터 전달, 사전에 클라이언트와 협의된 규격의 데이터 전달
웹 프레임워크와 Spring
웹 프레임워크; 동적 웹 서비스 개발을 편리하게 만들어주는 도구
백엔드
Java, Kotlin : Spring
JavaScript, TypeScript : Express.js, Nest.js
Python : Django
Ruby : Ruby On Rails
프론트엔드
JavaScript : React(라이브러리), Angular, Vue.js
프레임워크 vs 라이브러리; '제어의 주도권'
프레임워크 : 틀 안에서 주어진 것들을 활용해 원하는 것 제작
라이브러리 : 사용자가 주도권을 가지고 원하는 것 제작
Spring Framework; Java 기반의 웹 프레임워크
MVC 패턴(Model-View-Controller)
소프트웨어 아키텍처 디자인 패턴
사용자의 요청을 받아 데이터와 화면을 전달하는 과정에서 각각의 역할 분담
Model : 데이터를 담음.
View : 사용자에게 보여지는 화면을 담당. Model에서 데이터를 꺼내올 수 있음
Controller : 요청을 받아 작업을 수행. 작업의 결과 데이터를 Model에 넣을 수 있음
레이어드 아키텍처(Controller-Service-Repository)
Presentation(Controller) : 클라이언트가 요청할 수 있는 인터페이스 정의. 전달 받은 데이터 검증, Service의 메소드 호출
Business(Service) : 목적에 맞게 데이터 처리. 일반적으로 Repository의 다양한 데이터베이스 처리 메소드 호출 -> 저장, 수정, 조회, 삭제
Data Access(Repository) : 데이터베이스에 접근하여 작업 요청. 다양한 데이터베이스 처리 방법 제공 시 여러 서비스에서 공통적으로 사용 가능
이점 : 별도의 컨벤션이 없다면 역할을 구분할 코드 재사용, 확장성, 협업 커뮤니케이션 등이 더욱 원활
Spring Bean과 의존성 주입(Dependency Injection)
스프링에서 관리되는 객체(Java 클래스의 인스턴스) 의미
제어의 역전 IoC(Inversion of Control) : 스프링 Bean으로 지정된 클래스는 개발자가 직접 인스턴스를 생성, 관리하지 않고 스프링 컨테이너가 주체가 됨
Bean에서 다른 Bean을 사용(의존)하는 경우 -> 스프링 컨테이너에서 의존성 주입
의존성 주입 : 한 객체가 사용하는 다른 객체를 객체 내부에서 직접 만들지 않고, 외부에서 주입받아 사용하는 방법
스프링 실행 -> 컴포넌트 스캔 -> Bean으로 지정된 클래스들의 객체 모두 생성 (한 Bean이 사용하는 다른 Bean이 있다면 그 Bean을 먼저 생성)
스프링부트에서 의존성을 주입받는 방법
생성자(Constructor); 가장 선호하는 방식
의존성 변경 방지
스택오버플로우 에러 방지
NullPointerException 방지
@Service
class PresentationService(
private val presentationRepository: PresentationRepository
){ //생략 }
@Service
class PresentationService{
private val presentationRepository: PresentationRepository
constructor(presentationRepository: PresentationRepository) {
this.presentationRepository = presentationRepository
}
//생략
}
수정자(Setter)
@Service
class PresentationService{
private lateinit var presentationRepository: PresentationRepository
//서비스 인스턴스, 레포지토리 인스턴스를 다 만들어 둠
//이후 실행 시 Autowired 인스턴스 찾아서 행동함
@Autowired
fun sePresentationRepository(presentationRepository: PresentationRepository) {
this.presentationRepository = presentationRepository
}
//생략
}
필드(Field)
@Service
class PresentationService{
@Autowired
private lateinit var presentationRepository: PresentationRepository
//생략
}
HTTP와 REST API
HTTP; HyperText Transfer Protocol 네트워크로 통신하는 두 컴포넌트 간의 통신 규약
HTTP 요청/응답
Request
Start Line : HTTP 메서드, URL, HTTP 버전을 표현
Header : 컨텐츠의 길이나 유형, 클라이언트의 정보 담음
Body : 서버에서 작업 처리를 위해 필요한 실질적인 데이터 담음. 최근에는 JSON 포맷 주로 사용
Response
Start Line : HTTP 버전, 상태 코드 , 상태 메시지를 표현
Header : 컨텐츠의 길이나 유형, 서버의 정보 등을 표현
Body : 응답의 결과 데이터 담음.
서버 사이드 렌더링 방식 : HTML 사용
클라이언트 사이드 렌더링 방식/서버 간의 통신 : JSON 사용
HTTP 요청 메서드
GET
Read 작업을 요청 시 사용
브라우저의 주소창은 항상 GET 메서드로 요청
GET 요청 시 일부 HTTP 라이브러리에서는 Body에 데이터를 담을 수 없음
따라서 데이터를 보내야 할 경우 쿼리 파라미터를 주로 사용
POST
Create 작업 요청 시 사용
브라우저에서는 사용 X, Postman과 같은 별도의 툴을 사용해야함
PUT
Update 작업 요청 시 사용
PATCH
Update 작업 요청 시 사용
DELETE
Delete 작업 요청 시 사용
HTTP 상태 코드; 응답에서 요청의 처리 결과를 표현하는 코드
200 : OK
201 : Created
202 : Accepted
300 : Multiple Choices
400 : Bad Request
401 : Unauthorized
403 : Forbidden
404 : Not Found
405 : Method Not Allowed
415 : Unsupported Media Type
500 : Internal Server Error
502 : Bad Gateway
503 : Service Unavailable
504 : Gateway Timeout
REST API; HTTP 통신으로 동작하는 어플리케이션 기능을 정의하는 컨벤션
※강제성이 없으며 클라이언트와 서버 간에 합의만 있다면 PST 메서드의 처리 결과가 삭제될 수도 있음. URL도 개발자 재량임
REST API 핵심
URL을 이용한 자원의 표현
URL만으로 어떤 자원에 대한 요청인지 이해 가능하게 함
HTTP 메서드를 이용한 행위의 표현
CRUD에 부합하도록 적절한 HTTP 메서드를 사용하여 요청이 어떤 행위를 할 것인지 파악할 수 있게 함
HATEOAS 준수
HTTP 응답에 링크를 포함하여 클라이언트가 다음에 할 행동을 가이드
REST API 예시
회원가입
O : POST /members
X : PST /createNewMember
회원정보 조회(특정 회원)
O : GET /members/1
X : POST /getMemder?memberId=1
가능한 REST를 준수하되, 팀 컨벤션 개설 필요
클라이언트에서 서버로 데이터를 전달하는 방법
Query Paratmeter(=Query String)
컨트롤러에 @RequestParam 어노테이션으로 가져올 수 있음
HTTP Request Body
컨트롤러에 @RequestBody 어노테이션으로 가져올 수 있음
Path Variable(=경로 변수)
URL에 접근하고자 하는 자원의 식별자 표현.
@PathVariable 어노테이션으로 가져올 수 있음
데이터베이스; 데이터의 집합
DBMS(DataBase Management System)
DB를 저장하고 관리할 수 있는 응용 프로그램
보통 웹 개발에서는 데이터베이스 = DBMS임
관계형 데이터베이스
데이터를 행과 열로 이루어진 표의 형태로 저장
행(Recode) : 한 개의 데이터
열(Column) : 데이터의 특성
후보 키 : 유일한 레코드를 식별할 수 있는 컬럼의 최소 조합
기본 키 : 후보 키 중 대표로 지정한 것
대표적인 관계형 데이터베이스
Oracle Database
MySQL
PostgreSQL
비관계형 데이터베이스(NoSQL)
관계형 데이터베이스를 제외한 모든 종류의 데이터 베이스
대표적인 비관계형 데이터베이스
MongDB
문서형 데이터베이스
데이터를 비정형적으로 저장
Redis
Key-Value 스토어 데이터베이스
캐시 용도로 주로 사용
JPA(Java Persistence API)란
;자바 ORM 기술의 표준 인터페이스
ORM(Object Relational Mapping); 객체 관계 매핑
ORM의 장점
개발자가 직접 쿼리를 작성하는 과정이 생략 -> 생산성 향상
데이터에 객체지향적 관점으로 접근 가능
구체적인 DBMS에 대한 의존성 감소
ORM의 단점
JPA로 데이터베이스를 정확히 다루려면 지식 필요
ORM만으로 원하는 기능을 모두 구현하기에는 한계가 있음
트랜잭션
정의
여러 개의 데이터베이스 작업을 하나로 묶어주는 논리적 단위
커밋 : 트랜잭션으로 묶인 모든 작업을 영구히 반영
롤백 : 트랜잭션으로 묶인 모든 작업을 원상복구
영속성 컨텍스트
정의
JPA에서 엔티티를 관리하는 임시 메모리, 버퍼와 같은 개념
실습
Intellij Github 연동
프로젝트 생성
Terminal 창에서 아래 명령어 입력
git init
View -> Tool Window -> Commit
commit 창에서 Changes 선택 후 Ctrl+Alt+L
Github에서 레포지토리 생성
View -> Git -> Manage Remotes
레포지토리 URL 추가
View -> Tool Window -> Git
main 브랜치 push
어노테이션
@Entity : Entity 어노테이션을 달아줘야 JPA에서 테이블과 매핑되는 엔티티 클래스라는 것을 알 수 있음
@GeneratedValue(strategy = GenerationType.IDENTITY) : PK 생성 전략을 정해줌
GenerationType.TABLE : PK를 만들기 위한 테이블을 전용으로 만들어 PK 생성
GenerationType.SEQUENCE : 순서대로 번호를 따지는 기능 MySQL은 사용 불가
GenerationType.IDENTITY : 기본키 생성을 DB에 위임
GenerationType.AUTO : JPA가 내부 알고리즘을 따라 자동으로 전략 결정
@Column(name = "column_name") 이 필드가 어떤 이름을 가진 컬럼과 매핑되는지 개발자가 직접 지정
@Column(nullable = false, updatable = false) : 값이 null일 수 없고 이 필드의 처음 생성된 값이 변경된다면 오류 발생됨
@MappedSuperclass : 이 클래스를 상속 받는 클래스가 안에 있는 필드들을 해당 엔티티에 있는 테이블의 컬럼과 매핑
@CreatedDate : JPA Entity가 생성된 시간 자동으로 세팅
@LastModifiedDate : 마지막으로 수정된 일시는 언제인지
@OneToMany : 현재 클래스와 타겟 엔티티가 1:n 관계
@Enumerated(value = EnumType.STRING) : 자료형이 enum클래스일때 사용하는 어노테이션
EnumType.STRING : 이름을 그대로 넣어줌
fun findAllByIsActive(isActive: Boolean): List<ClassName> : JPA에서 알아서 쿼리 생성함
select * from achievement where is_active = :isActive
@Query("select e from Experience e left join fetch e. details where e.isActive = :isActive") : JPQL, 자바의 객체지향적인 쿼리
fun countAllByCreatedDateTimeBetween(start: LocalDateTime, end: LocalDateTime): Long
시작점으로 넣어준 시간과 종료점으로 넣어준 시간 사이의 모든 데이터를 세서 넣어줌
ex. 오늘 방문자 수를 알아낼 수 있음
회고
워밍업 클럽을 시작하며 가장 먼저 든 생각은 미리미리 해야겠다는 것이다... 대학교에 다니고 있어 미션과 발자국을 수행하며 강의를 병행할 수 있을지 걱정되어 1주차를 미리 들었다. 엔티티, 리포지토리를 직접 개발하며 이전에 배웠던 데이터베이스 내용이 좀 더 와닿았고, 어떤 식으로 구현이 되는지 알아가는 과정이 재미있었다.
미션 회고
우선, ERD를 처음부터 직접 설계하는 것은 처음이라 내 서비스에서 꼭 필요한 데이터가 무엇인지부터 추린 다음 해결하였다.
가이드에 있는 ERD Cloud를 이용하였는데 데이터베이스 ERD 설계에 대한 내용을 다시 되짚어보는 기회가 되었다.
2주차 미션과 강의를 미리 수행하며 1주차 미션을 보니 ERD 설계에서 수정해야할 부분이 눈에 보였다. 강의를 따라가며 차근차근 수정해나가야겠다.
댓글을 작성해보세요.