인프런 워밍업 클럽 2기 - 백엔드 프로젝트 (Spring, Kotlin)  1주차 발자국

인프런 워밍업 클럽 2기 - 백엔드 프로젝트 (Spring, Kotlin) 1주차 발자국

일주일간 학습한 내용 요약

웹 개발 기본과 프로젝트 준비

웹 서비스를 구성하는 요소

클라이언트(브라우저, 서버컴 중 요청쪽 등) - 서버(응답주체, CRUD작업, 서버컴퓨터 집합인 클러스터를 구성) - DB(DBMS)

DBMS 서버의 IP주소는 인터넷 세팅을 할때 등록해서 컴퓨터에 알려줘야 한다.

웹 프레임워크와 Spring

웹 프레임워크: 동적 웹 서비스 개발을 편리하게 만들어주는 도구

  • 백엔드 : (Java, Kotlin - Spring), (JavaScript, TypeScript - Express.js, Nest.js), (Python - Django), (Rudy - Rudy On Rails)

  • 프론트엔드 : (JavaScript - React(라이브러리), Angular, Vue.js)

     

프레임워크 vs 라이브러리 -> 제어의 주도권 차이

프레임워크: DIY 가구 키트 - 사용자가 틀 안에서 주어진 것을 활용하여 원하는 것을 만드는 것

라이브러리: 공구 상자 - 사용자가 주도권을 가지고 원하는 것을 만듦

Spring Framework: Java기반의 웹 프레임워크, 웹 서버 개발의 상당 부분을 편리하게 모듈화 해놓음

  • MVC 패턴: 요청 처리, 데이터, 화면 간의 결합도를 낮춰 유지보수 용이하게 함

View: 사용자와 상호작용

Controller: 요청받아 작업을 수행

Model: 데이터 담는다. View는 데이터를 꺼내고, Controller는 데이터를 넣는다.

 디자인 패턴? 경험적으로 특정 문제 상황을 해결하기에 최적이라고 생각되는 설계, 방법론.

코드의 가독성, 유지보수성, 결합도, 응집도 등을 고민 하며 최적화된 코드를 작성하는 자세가 중요

  • 레이어드 아키텍처: 데이터를 컨트롤러에서 받아서 모델에 넣기 전까지 처리하는 과정을 이해하기 쉽고 관리하기 쉽게 구조화하는 방법 중 하나.

     

    입력받은 데이터에 이상은 없는지 검증하고, 한번 가공해서 받은 데이터 기반으로 다른 데이터를 조회하는 등을 할 수 있다.

MVC의 컨트롤러와 분리

Controller(Presentation) - Service(Business) - Repository(Data Access) 각 레이어 별 역할 분리
컨트롤러: 사용자와 상호작용
서비스: 주요 로직 처리
레파지토리: DB와의 상호작용

  • 스프링 Bean과 의존성 주입(Dependency Injection)

스프링Bean: 스프링에서 관리하는 인스턴스

어플리케이션 동작에 필요한 클래스들을 개발자가 직접 만들지 않고 스프링이 만들어서 관리하도록 위임한다. "제어의 역전 IoC(Inversion of Control)" 제어의 주체가 개발자가 아닌 프레임 워크가 되었다.

스프링부트에서는 어노테이션으로 간단하게 스프링 빈을 정의해서 스프링이 그 인스턴스를 만들게 할 수 있다. (컨트롤러,서비스,레파지토리,컴포넌트 등의 어노테이션)

스프링 실행 - 컴포넌트 스캔 - 클래스들을 하나하나 살피면서 어노테이션이 있으면 Bean으로 만듦(인스턴스를 만들어 빈으로 등록)

의존성 주입(DI)는 역제어(IoC)의 한 형태
레퍼지토리를 서비스에 넣어주고, 서비스를 컨트롤러에 넣어주고..의존성 주입


"주입"은 의존성(서비스)를 사용하려는 객체(클라이언트)로 전달하는 것.
어떤 서비스를 호출하려는 클라이언트는 그 서비스가 어떻게 구성되었는지 알지 못해야 한다.
의존성 주입의 의도는 객체의 생성과 사용의 관심을 분리하는 것. 이는 가독성과 코드 재사용을 높혀줌.
클래스는 더 이상 객체 생성에 대한 책임이 없음.
라이언트의 생성에 대한 의존성을 클라이언트의 행위로부터 분리
"매개변수 전달"과 동일하게 동작한다. 주입으로써 "파라미터 전달"은 클라이언트를 세부 사항과 분리하기 위해 수행되고 있는 부가적인 의미를 전달

의존성 주입은 네 가지 역할을 담당하는 객체 및 인터페이스를 전제로 한다.

  • 사용될 서비스 객체

  • 사용하는 서비스에 의존하는 클라이언트 객체

  • 클라이언트의 서비스 사용 방법을 정의하는 인터페이스

  • 서비스를 생성하고 클라이언트로 주입하는 책임을 갖는 주입자

비유하자면,

  • 서비스 - 전기, 가스, 하이브리드 또는 디젤 자동차

  • 클라이언트 - 엔진에 상관 없이 동일하게 차를 사용하는 운전자

  • 인터페이스 - 운전자가 기어와 같은 엔진의 세부 사항을 이해할 필요가 없도록 보장해주는 자동변속기

  • 주입자 - 아이에게 어떤 차를 사줄지 결정하고 구매해준 부모

사용될 수 있는 모든 객체는 서비스로 여겨진다. 다른 객체를 사용하는 모든 객체는 클라이언트 여겨진다.

[위키백과]


  1. 생성자(costructor) 주입

  2. 수정자(setter) 주입

  3. 필드(Field) 주입

추가 공부 필요 - 이해가 안됨

생성자 주입 방식을 권장

  • 의존성이 바뀌는 것을 방지할 수 있다

  • 순환참조 시 컴파일 오류가 발생해, 런타임 단계에서의 메소드가 서로 호출하는 스택오버플로우 에러 방지한다.

  • 의존하는 빈이 누락되면 컴파일 오류가 난다.

HTTP와 REST API

HTTP: 네트워크로 통신하는 두 컴포넌트 간 통신규약

HTTP 요청/응답

  • Request: Start Line(HTTP 메서드, URL, HTTP 버전), Header(키/밸류 형태 메타데이터, 컨텐츠의 길이/유형, 클라이언트 정보), Body(본문, JSON 포맷)

  • Response: Start Line(HTTP 상태코드 - 아래 있음)

HTTP 요청메서드

  • GET: 서버 자원을 조회하고 가져온다. 브라우저 주소창은 항상 GET 메서드로 요청,

  • POST: 리소스를 생성메소드(CREATE)

  • PUT, PATCH, DELETE

HTTP 상태 코드

  • 200 OK: 요청이 정상처리됨

  • 300 Multiple Choices(Redirection): 사파리에서 네이버 입력 시, 네이버 서버가 300번대 코드와 m.naver... 주소를 주면 사파리가 다시 m.naver...으로 요청하고 m.naver..서버가 200번대 코드와 html 파일을 사파리에 준다

     

  • 400 Bad Request: 클라이언트의 오류

  • 500 Internal Server Error: 서버의 오류(DB 다운 등)

--> 응답코드는 서버 개발자가 정한다.

Http는 규약이지만 자유도가 높은 규약이다.

REST API: URL도 개발자가 정하기 나름이지만, 일종의 표준처럼 사용하는 아키텍처(기억 장치의 주소 방식)로 REST API를 사용한다.
* 아키텍처: 기능 면에서 본 컴퓨터의 구성 방식. 기억 장치의 주소 방식, 입출력 장치의 채널 구조 따위

  • REST 원칙을 알면 새로운 API를 봐도 어떤 API인지 직관적인 추측이 가능해진다. -> 개발자 간의 커뮤니케이션 비용이 줄어든다.

REST API의 핵심

  • URL 이용한 자원 표현: URL만 보고 어떤 요청인지 이해 가능

  • HTTP 메서드 이용한 행위의 표현: 의미에 맞는 적절한 메서드 사용

  • HATEOAS(헤이티어스) 준수: 응답에 링크 포함해 클라이언트의 다음 행동을 가이드

     

클라이언트에서 서버로 데이터 전달 방법

  • Query Parameter: URL에 있다. ((get) inflearn.com/roadmaps?terms=5&page=1) -->'?'뒤 내용이 쿼리파라미터이다.

  • HTTP Request Body: Http 메시지 안에 들어있기 때문에 Post등을 쓰지 않는 이상 눈으로 보기 어렵다.

  • Path Variable(경로변수): URL에 있다.

코딩 컨벤션: 코딩을 하는 프로그래머 사이의 규칙 규약, 읽고 관리하기 쉬운 코드 작성을 위한 코딩 스타일 규약

데이터베이스란

DBMS: 데이터를 체계적으로 관리하기 위한 프로그램

  • 관계형/비관계형 데이터베이스로 나뉜다

관계형 DB(RDBMS): 행과 열로 이루어진 표의 형태

  • 후보키: 유일성(중복x) 최소성(최소한의 컬럼조합 사용)

  • 기본키PK: 후보키 중 하나

  • 학과와 학생은 1:N의 관계

  • 복수전공시

  • 학생 join 학과를 하면 학번의 유일성이 깨진다

  • 때문에 중간에 맵핑 역할을 하는 테이블 필요 "학생전공"테이블 학생전공ID(기본키)

  • 학과와 학생이 N:M 관계 가능해짐

  • 학생전공 join 학생 join 학과

  • DB는 프로젝트의 골격과도 같기 때문에 서비스 운영 중 DB구조를 바꾸는 것은 매우 어렵다. 프로젝트 설계가 중요하다.

  • 오라클(유료), MySQL(유/무료),PostgreSQL(꾸준히 점유율 올라가는 오픈소스DB, 플러그인 확장성이 좋다.)

비관계형 DB: 관계형DB를 제외한 모든 종류의 DB(키-값형, 문서형 등)

  • 개발하려는 서비스에 따라 비관계형DB도 공부 필요

  • MongoDB: 문서형, 데이터를 비정형적으로 저장가능

  • Redis: 키-값, 주로 캐시 용도로 사용(자주 조회된 데이터를 레디스에 저장해서 사용-빠르다)

     

 

JPA란

JAP: Java Persistence API, 자바 ORM 기술의 표준 인터페이스, Java의 객체관계형DB의 테이블로 또는 그 반대로 변환해주는 기능/맵핑을 해주는 라이브러리

  • 서비스를 좀더 객체지향적인 관점에서 설계 및 유지보수할 수 있게 도와주고

  • 개발자가 직접 작성해야하는 코드를 줄여준다.

ORM: Object Relational Mapping, 객체 관계 매핑, 객체지향 프로그래밍의 인스턴스관계형DB를 매핑해주는 기술

  • 학생, 학과 테이블 -> 클래스 (class Project)

  • 각 컬럼들 -> 클래스에 있는 필드 (val title)

  • 각 레코드 -> 클래스로 만들어진 인스턴스

  • 여러 레코드 -> 클래스의 리스트 (List<ExperienceDetail>)

  • 이렇게 테이블에 매핑되는 자바 클래스를 엔티티라고 한다. (class Project)

  • DB엔티티에 해당하는 자바 클래스 = JPA 엔티티

  • ORM은 테이블들이 갖는 관계까지 이용해 DB를 좀 더 쉽게 다룰 수 있는 기능을 제공

ORM의 장점

  • 원래 자바로 DB를 다루려면 SQL문을 개발자가 직접 작성해서 DB로 보내야한다.

  • JPA는 개발자가 정의해둔 엔티티의 필드들과 연관관계를 통해서 테이블 구조를 이해하고 있고 이를 바탕으로 대신 SQL을 작성함 => 개발 생산성 증가

  • 엔티티라고 부르는 Java 객체를 기반으로 쿼리 작성하기 때문에 데이터를 객체지향적으로 관점에서 접근 가능

  • 스프링과 구체적인 RDBMS(오라클, MySQL 등)에 대한 종속성을 끊어 의존성이 줄어든다. -> DB를 쉽게 변경 가능하다(ex. 오라클에서 MySQL로)

     

ORM의 단점

  • 충분한 학습이 없으면 의도와 다르게 쿼리가 동작할 수 있음

     

    ex: (n+1) 직접 쿼리를 작성했을 때는 한번만 쿼리가 전송됨, JPA를 사용하면 쿼리가 여러번 전송됨. => 해결법은 있지만 별도로 공부가 필요

  • 간단한 쿼리작성에는 효과적, 복잡한 쿼리에서는 한계점이 있어 불가피하게 구체적인 RDBMS에 종송적인 네이티브 쿼리 작성 => 의존성을 줄이는 장점이 사라짐

트랜잭션: 데이터베이스의 개념, 여러 DB 작업을 하나로 묶는 논리적 단위(계좌이체 예시)

  • 커밋: 트랜잭션으로 묶인 모든 작업을 DB에 영구히 반영하는 작업

  • 롤백: 트랜잭션으로 묶인 모든 작업을 원상복구 하는 작업

영속성 컨텍스트: 어플리케이션의 로직과 DB 사이에 있는 임시 메모리 또는 버퍼 공간

  • 개발자가 java코드로 CRUD 명령을 수행할 때 JPA는 이 영속성 컨텍스트를 거쳐 DB와 상호작용

  • 트랜잭션과 주기가 같다. 하나의 트랜잭션의 DB 작업들을 영속성 컨텍스트를 거쳐 좀 더 효율적으로 처리

     

영속성 컨텍스트 처리과정

  1. 데이터 조회시 1차 캐시라는 곳에서 해당 데이터가 있는지 먼저 확인 -> 데이터 없으면 DB로 조회쿼리 날림

  2. 1차 캐시(엔티티1)에 조회한 데이터를 저장 -> 엔티티1 상태를 스냅샷 저장

  3. 그 후 또 같은 엔티티 조회시 DB까지 쿼리가 날라가지 않고 1차 캐시에 있는 데이터를 그대로 가져감(쿼리 날리는 과정이 생략)

영속성 컨텍스트 더티체킹(변경감지)

  1. 데이터 처음 조회 시 처음 상태를 스냅샷 저장 후 영속성 컨텍스트가 종료될 때 현재 있는 엔티티1와 엔티티1스냅샷을 비교

  2. 두개가 다를 경우 업데이트가 있다고 JPA가 판단하고 알아서 쿼리를 작성해 DB에 전송함.

영속성 컨텍스트 쓰기 지원

  1. 한 트랜잭션 안에서 for문을 가지고 1~100까지 데이터를 insert할 때,

  2. for문 반복이 수행될 때마다 DB로 insert 쿼리를 전송하지 않고, 영속성 컨텍스트에 저장할 데이터를 넣어 뒀다가 트랜잭션 종료될 시점에 한번에 모든 쿼리를 날림

  3. 때문에 JPA로 insert를 날린 시점과 log에서 insert, update 쿼리가 찍히는 시점이 차이가 날 수 있다.

영속성 컨텍스트 플러시(Flush)

  • 개발자가 원하는 시점에 DB에 쿼리 전송 가능

패키지 구조

[패키지 구조]

패키지: 연관된 자바파일들을 묶어주는 디렉토리(폴더)

  • 다른 개발자들이 프로젝트 구조를 이해하는데 도움이 된다

  • 다양한 방법론이 있다.

  • presentation(방문자), admin(관리자), domain(프로젝트가 공통으로 가진 뼈대(코어)가 되는 기능들이 모인 패키지, DB 접근 기능 등)

  • 도메인 패키지가 베이스가 되고 그 위에 방문자, 관리자 패키지를 병렬로 쌍은 느낌의 구조

     

각 패키지의 하위 패키지 => 다양한 방법론 중 하나의 구조다.

  • domain:

     4개의 하위 패키지

    • configuration(암호와 관련된 설정 클래스 들어갈 패키지),

    • constant(도메인 패키지에 사용되는 상수들),

    • entity(DB의 테이블에 대응하는 java객체들이 들어갈 패키지) ,

    • repository(각 엔티티 별 DB에서 CRUD를 수행할 객체들)

  • presentation:  5개의 하위 패키지

    • controller,

    • dto(화면에서 필요로 하는 데이터를 담는 클래스),

    • interceptor(컨트롤러까지 요청이 들어가기 전에 그 모든 컨트롤러에 대해 공통 처리를 해주는 클래스, 인터셉터에서 각 화면을 조회할 때 그 요청에 대한 정보를 따로 DB에 저장하는 기능 개발),

    • repository(DB와 직접 상호작용을 하지 않고 도메인의 레퍼지토리 패키지를 활용해서 프레젠테이션 레이어에서 필요로 하는 DB작업을 쉽게 할 수 있도록 중간에 랩핑 해주는 기능, 디자인패턴 중 Facade 패턴),
      => 퍼사드(Facade) 패턴: 복잡한 시스템을 보다 쉽게 사용 가능하도록 단순화된 인터페이스를 제공. 시스템의 복잡성 숨기고, 사용자 친화정 인터페이스로 시스템 접근을 용이하게 함.

    • service

    => 도메인과 프레젠테이션 패키지를 결합한 것도 하나의 프로젝트로 볼 수 있다. 나중에 확장 될때, 도메인과 어드민을 또 따로 결합해 사용할 수 있도록 만들어진 구성

     

  • admin:

    • advice(컨트롤러 어드바이스, 예외를 처리하는 클래스),

    • context(

      • 데이터베이스에 만들 테이블들 별로 context 패키지 안에 하위 패키지들이 있다.

      • 각 테이블 별로 화면 조회부터 데이터 추가/수정/삭제 기능들을 분리해 넣을 예정

      • ex) achievement(이 안에 각각 controller, service=view,form 하위 패키지가 또 있다), dashboard, experience, ...etc),
        => 새로운 테이블이 추가되고 관리할 기능이 필요하다면, 컨텍스트 하위에다가 새로운 패키지를 만들어 기존 기능에 대해 영향이 없이 확장성있게 개발 가능하게 구성됨

    • data(API 공통 응답 포맷, 입력 폼 정보, 테이블 정보 등을 담는 클래스),

    • exception(어드민 레이어에서 따로 커스터마이징한 예외들 들어갈 패키지),

    • interceptor(화면에서 보여지는 사이드바를 초기화 하는 클래스),

    • security(로그인 관련된 기능들)

테이블 설계(명세)

메인페이지(=index page) 사용 테이블

  • introduction 테이블 (소개글 등)
    created_date_time, updated_date_time 컬럼은 메타 데이터 타입으로 데이터의 생성과 수정을 추적하기 위한 목적이다.

  • link 테이블 (링크 아이콘 등)
    name을 기반으로 이미지

     

Resume 페이지 사용 테이블

  • experience(학력, 경력, 한줄 요약 등)

  • experience_detail(어떤 경험에 대한 내용인지, 설명 등)

  • => experience와 experience_detail은 1:N으로 묶인 테이블

  • achievement(수상, 자격증 등)

  • skill(사용할 줄 아는 기술들)

Projects 페이지 사용 테이블

  • project

  • project_detail(url 컬럼이 추가로 있다)

  • project_skill(프로젝트와 skill을 맵핑해주는 테이블)

  • => 프로젝트와 스킬은 N:M의 관계

기타

  • http_interface(
    사용자가 페이지 조회를 한번 할 때마다 사용자의 브라우저에서 서버로 요청이 들어올 때 요청의 정보를 저장하는 테이블.
    조회수, 일자별 조회수 통계, ip주소를 통한 중복방문제거, 모바일/데스크탑 방문 통계 등이 가능하다)


    => interceptor를 사용해 보기 위해 넣었다.

개발 환경 구성

윈도우 사용자는 이 강의를 스킵하고 강의자료로 진행

  • Homebrew(Mac Only)

  • JDK(zulu): 버전 17로

  • IntelliJ IDEA

  • H2 Database

  • DBeaver

  • Docker

댓글을 작성해보세요.

채널톡 아이콘