인프런 워밍업 클럽 2기 - 백엔드 프로젝트(Kotlin, Spring) / 1주차 발자국
⭐ 1주 동안 배운 내용을 정리하고 회고하는 시간을 가져보자.
복습한다고 생각하고 간단하게 요약하며 정리해보자. ╰(°▽°)╯
1일차 - 웹 기본 개념 이해하기
웹 서비스의 구성 요소
클라이언트 [요청하는 주체] ↔ 서버 [응답하는 주체] ↔ 데이터베이스 [데이터 집합]
클라이언트는 요청하는 주체이며, 사용자 혹은 고객이라고도 표현한다.
서버는 응답하는 주체이며, 요청받은 결과를 클라이언트 측으로 응답한다.
데이터베이스는 데이터의 집합이며 이를 관리하는 DBMS를 일반적으로 DB라고 부른다.
브라우저에 주소를 입력하면 벌어지는 일
클라이언트가 브라우저에 https://www.google.com
을 입력하면 어떻게 될까?
클라이언트가 보낸 주소를 DNS 서버에서 IP로 변환하여 알려준다.
클라이언트는 해당 IP 주소로 서버에 요청을 하며, 서버는 요청 데이터를 처리한다.
처리 완료된 응답 데이터를 다시 클라이언트 측에 전달한다.
DNS? (Domain Name System)
DNS는 사용자가 흔히 보는 www.google.com
과 같은 도메인 이름을 IP로 변환하는 시스템이다.
DNS 서버는 이러한 변환 역할을 대신 수행해주는 서버이며, KT, SKT, LG, Google 등이 이러한 서버를 제공한다.
웹 프레임워크
Framework, 프레임워크?
프레임워크는 공통적으로 요구되는 기능들을 보다 편리하게 만들 수 있도록 해주는 뼈대, 구조이다.
제어의 주도권을 프레임워크가 가지고 있으며, 틀 안에서 주어진 것을 활용해야한다.
Library, 라이브러리?
라이브러리는 활용 가능한 도구들의 집합으로 제어의 주도권을 사용자가 가지고 있으며 정해진 틀 없이 사용자가 원하는 것을 만들 수 있다.
Spring Framework
MVC 패턴 (Model-View-Controller)
소프트웨어 아키텍쳐 디자인 패턴으로 Model, View, Controller로 각 역할을 분담하여 결합도를 낮추고 유지보수를 용이하게 할 수 있다.
Model - 데이터 처리
View - 보여지는 화면 처리
Controller - 클라이언트 요청 처리
레이어드 아키텍처 (Controller-Service-Repository)
가장 대중적인 소프트웨어 아키텍처로 Controller, Service, Repository로 구분하여 사용한다.
Controller - 클라이언트 요청 처리
Service - 비즈니스 로직 (핵심 로직) 처리
Repository - 데이터베이스 접근 처리
Spring Bean과 의존성 주입
Spring Bean은 스프링에서 관리되는 객체를 뜻한다.
이는 스프링 컨테이너가 직접 관리하기에 제어의 역전(Inversion of Control; IOC)라고 부르며 스프링에서 의존성을 주입해주어 객체를 사용할 수 있다.
생성자 주입, 수정자 주입, 필드 주입의 방법이 있지만, 런타임 시 수정자를 통해 의존성이 바뀌거나 의존하는 Bean을 누락했을 시 컴파일 단에서 오류를 잡아낼 수 있기 때문에 생성자 주입을 추천한다.
생성자 주입
@Service
class PresentationService (private val presentationRepository: PresentationRepository) { ... }
수정자 주입
private lateinit var presentationRepository: PresentationRepository
@Autowired
fun setPresentationRepository(presentationRepository: PresentationRepository) {
this.presentationRepository = presentationRepository
}
필드 주입
@Autowired
private lateinit var presentationRepository: PresentationRepository
HTTP와 REST API
HTTP (Hyper Text Transfer Protocol) 는 서버와 클라이언트 간 어떻게 데이터를 교환할지를 정해놓은 통신 규약이다.
HTTP 요청 메서드
GET - 읽기 작업을 처리할 때 사용됨
POST - 쓰기 작업(생성)을 처리할 때 사용됨
PUT (전체 수정) / PATCH (부분 수정) - 쓰기 작업(업데이트)를 처리할 때 사용 됨
DELETE - 삭제 작업을 처리할 때 사용 됨
HTTP 상태 코드
2xx : 정상 처리
3xx : 리다이렉션 - 페이지 이동이 이루어져야 함
4xx : Bad Request - 클라이언트 측 요청 오류
5xx : Internal Server Error - 서버 측 오류
REST API
클라이언트와 서버 간 인터넷을 통해 정보를 안전하게 교환하기 위해 사용하는 규칙이다.
RESTful 하게 API를 작성하려면 URL만으로 어떤 자원에 대해 어떻게 처리할 건지 파악할 수 있어야 한다.
POST /members ⇒ O, Post는 생성을 처리할 때 사용 / member 생성하기 위한 요청임을 알 수 있다.
POST /createNewMember ⇒ X, RESTful 하지 않음
2일차 - 데이터베이스 기본 개념
데이터베이스
1일차에 소개했던 것 처럼 데이터의 집합이다.
이를 관리하는 툴을 DBMS (Database Management System)이라고 부른다.
RDBMS, 관계형 데이터베이스
행과 열로 이루어진 표의 형태로 저장되는 데이터베이스
하나의 행은 데이터, 열은 각 데이터의 특징이라고 할 수 있으며 이것들이 모여 하나의 테이블(표)이 된다.
각 테이블을 조인하여 정보 간의 관계나 링크를 설정할 수 있는 기능이 있으며, 이를 통해 여러 데이터 간의 관계를 설정할 수 있기에 관계형 데이터베이스라고 부른다.
⇒ Oracle, MySQL, PostgreSQL 등이 이에 해당된다.
NoSQL, 비관계형 데이터베이스
관계형 데이터베이스를 제외한 모든 종류의 데이터베이스를 비관계형 데이터베이스로 분류한다.
⇒ MongoDB, Redis 등이 이에 해당된다.
JPA
JPA (Java Persistence API)는 자바 진영 ORM 기술의 표준이다.
ORM (Object Relational Mapping)은 객체 관계를 매핑해주는 기술로 객체지향 프로그래밍의 객체와 데이터베이스를 매핑해주는 역할을 한다.
장점
특정 DB에 대한 의존성을 줄일 수 있음
쿼리를 직접 작성하지 않아도 됨
데이터에 객체지향적인 관점에서 접근이 가능함
단점
ORM 만으로는 한계가 있기에, 복잡한 쿼리의 경우 네이티브 쿼리를 작성해야 함
JPA에 대한 충분한 학습이 이루어진 후 사용해야 함.
영속성 컨텍스트
JPA에서 Entity를 관리하는 저장공간이다.
애플리케이션과 데이터베이스 사이에서 Entity를 보관하는 가상 데이터베이스 역할을 한다.
아래에선 이 영속성 컨텍스트의 3가지의 특징을 소개하려고 한다.
1차 캐시
영속성 컨텍스트 내부의 캐시를 1차 캐시라고 부른다.
조회한 결과를 캐시 공간에서 먼저 찾아보고 쿼리를 수행 할지 결정한다.
더티 체킹
영속성 컨텍스트 내에서 Entity의 변화가 감지됬을 경우 이를 데이터베이스에 자동으로 적용하는 기능을 더티 체킹 또는 변경 감지라고 부른다.
최초로 데이터를 조회할 때의 스냅샷을 보관해두고 이를 트랜잭션 종료 시점과 비교하여 변경된 내용을 적용하는 것이다.
쓰기 지연
쓰기 작업을 즉시 수행하지 않고, 영속성 컨텍스트 내에 모아두었다가 트랜잭션이 종료될 때 한 번에 수행한다.
트랜잭션
트랜잭션은 데이터베이스에 적용할 여러 작업을 하나로 묶어주는 논리적 단위이다.
커밋, Commit : 트랜잭션으로 묶인 모든 작업을 데이터베이스에 영구히 반영하는 작업
롤백, Rollback : 트랜잭션으로 묶인 모든 작업을 원상복구 하는 작업
3일차 ~ 5일차 (실습)
이번 실습 내용에서는 기존에 알고 있던 내용은 제외하고 실습을 진행하면서 알게 된 Kotlin 문법에 대해서 조금 정리해볼까 한다.
@Entity
class Achievement( // 여기가 생성자
title: String,
description: String,
achievedDate: LocalDate?, // null 허용 (=일 수도 있다.) / 반대로 !!는 null이 아니다를 표현함
host: String,
isActive: Boolean
) : BaseEntity() { // BaseEntity 상속
// 생략
var isActive: Boolean = isActive
}
위는 실습 중에 작성한 Entity의 일부이다.
Java와는 다르게 Class명 옆에서 생성자를 정의할 수 있고, 변수명: 타입
과 같은 구조를 가지고 있다.
타 클래스 상속을 위해서 : BaseEntity()
와 같이 사용한 부분을 볼 수 있다.
변수를 선언할 때는 var 또는 val을 쓴다.
var ⇒ 읽기/쓰기가 가능한 일반 변수
val ⇒ 읽기만 가능한 final 변수
nullable을 표현할 수 있다.
? ⇒ null 일 수도 있다
fun getEndYearMonth(): String {
if (endYear == null || endMonth == null) {
return "Present"
}
return "${endYear}.${endMonth}"
}
이어서 함수 부분이다.
Java와는 다르게 메서드를 정의할 때 fun
을 통해 선언하며, String을 반환할 때 프론트에서 사용하던 것 처럼 ${}
사이에 변수를 넣어 처리를 할 수 있었다.
번외 - 서브 미션 과제
워밍업 클럽 2기 - 백엔드(Kotlin, Spring) 과정에서는 서브 미션을 수행하도록 과제가 주어진다.
현재 기획한 내용은 음악 플레이리스트를 만들 수 있는 미니 프로젝트를 기획하고 테이블 설계까지 완료 하였다.
단순하게 요즘 듣는 음악 리스트를 공유하기 위한 프로젝트로 기획하게 되었으며, 설계한 테이블은 아래와 같다.
User 별로 플레이리스트를 생성하여 음악 목록을 만들 수 있게 해두었고, 목록을 관리하기 위해 각 테이블을 분리하였다.
미션 내용이 단순히 CRUD 까지 밖에 없어서 임의로 데이터를 추가하거나, 향후 시간이 난다면 실제 데이터를 불러와서 이용할 수 있게 해볼까 한다.
총 회고
오랜만에 기초부터 복습하는 느낌이 들어 면접 준비한다는 느낌으로 중요한 내용만 추려서 정리해보았다.
아직 1주차라서 많은 내용을 다뤄보지는 못한 것 같고, 앞으로 실습 면에서 Kotlin 문법을 기억 속에서 되찾으며 여러모로 부족한 부분을 찾아가며 배워보면서 즐겨 볼 생각이다.
모두 화이팅! (o゚v゚)ノ
댓글을 작성해보세요.