back-end/Spring

1~3장. 스프링 부트 및 기초 지식

림가이드 2023. 4. 26. 14:19

< 스프링 프레임워크 >

: 자바 기반의 application framework로 엔터프라이즈급 application을 개발하기 위한 다양한 기능을 제공함

(vs library?)

: 라이브러리는 내 코드가 라이브러리를 호출해서 사용하는 것.

프레임워크는 내 코드를 호출하는 것.

 

why? : application 개발에 필요한 기반을 제공해서 개발자가 비즈니스 로직 구현에만 집중하도록 하기 위해 존재

- 넓은 컨테이너(판때기, ApplicationContext) 위에 내가 만드는 클래스(ApplicationConfig.class)만 얹으면 개발 가능

- 스프링 bean(클래스를 활용하는 bean을 만듬)에 맞춰 만들면 서로서로 사용 쉬움

- 너무 자유롭지는 않아서 좋음

 

 

 

1. spring project 생성

1) spring application 부팅

- new SpringApplication()

- SpringApplication.run() : main()에서 이미 존재하는 SpringApplication 클래스의 run() 메서드를 호출하는 방식

(vs Java) : 이용할 class를 생성하고 static void main()에서 생성한 클래스를 선언하고 이용해서 실행

2) SpringBootApplication 어노테이션

(나중에..........)

 

 

2. 스프링 코어

- DI, IoC, container : 스프링의 근간을 이루고 전체 application을 통제하는데 활용

- resource, AOP, validation, SpEL : 많은 application에서 공통적으로 활용하기 좋은 기능

 

 

3. 스프링 Web MVC

: http 요청/응답 처리 (Web MVC는 계속 application이 요청이 올때까지 대기를 하고 있다가 요청이 오면 바로 처리하여 응답

- 필터, 인터셉터 : 웹에서 들어오는 요청을 필터링/공통적 처리 기술

- 예외처리 : 웹에서 들어온 처리를 하던 중 오류 발생시 안전하게 처리할 수 있도록

 

 


< DI, IoC, container >

 

1. IoC (inversion of control)

: 사용자가 직접 클래스를 생성하지 않고 프레임워크(spring)가 제어하도록 하는 것

 

 

2. DI (dependency injection 의존성 주입)

: 사용할 객체를 직접 만들지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 방식

- A가 B를 사용한다.

ex) '결제서비스(A)가 머니어댑터(B)와 편의점 할인(B)을 사용한다.'는 것을 application context(spring)이 서비스(A)가 어떤 객체(B)를 사용할지를 정해줌.

 

- 방법: Bean : 사용할 클래스로 객체를 생성하여 반환하는 것

① XML을 통한 Bean(사용할 클래스로 객체를 생성하여 반환하는 것) 등록 → 번거로움

② XML ComponentScan을 통한 Bean 등록

(어노테이션 : @Controller, @RestController, @Service, @Component, @Repository 등)

③ JavaConfig을 통한 Bean 등록       → 편의점 결제 서비스

(@Configuration)

④ JavaConfig ComponeneScan을 통한 Bean 등록 : ② + ③

(@Configuration, @ComponentScan(어디부터 싹 다), @Component... 이용)

@SpringBootApplication으로 프로젝트 생성하면 바로 생김

 

+ 추가 설명

1. Bean의 구현체가 여러개이면?

이게 무슨 말인가?!?!

할인적용 방법이 두가지가 있다. 편의점에 따른 할인이냐, 지불방법에 따른 할인이냐.

이 두가지 할인정책의 각 클래스는 둘 다 bean으로 등록되어 있다. 그래서 한 가지 결정을 해야하는 상황

 

이때 사용하는 것이 @Primary.

우선적용을 뜻하는 것으로 편의점할인 클래스에 붙여주면 인터페이스에서 자동으로 먼저 편의점으로 할인을 적용시키도록 하고, 반대이면 반대로 적용된다.

 

BUT! 구현체가 2개보다 훨씬 많은 것이라면...? @Qualifier(BeanName).

인터페이스를 사용하는 구간(편의점 서비스)에 @Qualifer(bean이름)을 전줄에 붙인다.

 

2. Bean의 생성 정의 @Scope("방법")

1) 싱글톤 : 재활용

2) prototype : 매번 새로 만듬

- request에 따라, session에 따라

 

 3. spring 환경설정 : @Profile("환경이름")

- 실무에서는 환경을 다양하게 하기 때문에 해당 환경에서만 동작하는 Bean을 만드는 것이 중요

- 환경이름?

실행시, 환경변수 설정

- (!, &, |) 로 사용가능.

@Profile("!환경변수이름") : 환경변수가 아닐때 적용

 

1) class 단위

@Configuration / @Component

@Profile("환경이름")

2) 메서드 단위

@Bean

@Profile("환경이름")

3) 여러개

: -Dspring.profiles.active = 환경이름들 콤마로 나열

 


< resource, AOP, validation, SpEL >

 

1. resource : 외부자원(http, 이미지, 파일 등) 가져오기

- resource 인터페이스 (spring에서 제공)

public interface Resource extends InputStreamSource {
    boolean exists();
    boolean isReadable();
    boolean isOpen();
    boolean isFile();
    URL getURL() throws IOException;
    URI getURI() throws IOException;
    File getFile() throws IOException;
    ReadableByteChannel readableChannel() throws IOException;
    long contentLength() throws IOException;
    long lastModified() throws IOException;
    Resource createRelative(String relativePath) throws IOException;
    String getFilename();
    String getDescription();
}

- resource 목록들

: UrlResource, ClassPathResource, FileSystemResource, SevletContextResource, InputStreamResource 등 존재

 

- ResourceLoader 인터페이스 : 프로젝트 내의 resource를 로딩할 때 사용

public interface ResourceLoader {
    Resource getResource(String location);
    ClassLoader getClassLoader();
}

- ResourcePatternResolver

등등등등등...

 

자세한 내용은 프로젝트 하면서 더 알아보고 추가해보기 :)

 

 

 

2. AOP (관점지향 프로그래밍) : 여러 메서드에서 동일한 코드가 반복될 때 사용

- 로깅 :  요청의 내용은? 어떤 요청이 들어왔는데 실제로 나가는 응답은 무엇인가? or 요청이 들어온 시간과 응답한 시간? 등의 정보를 기록하는 행위

- 트랜잭션 : DB의 상태를 변화시키는 작업 단위로 일련의 작업이 동시에 모두 다 성공 및 실패. (송금 : 돈을 보내면 상대방이 돈을 받는 것. 중간에 에러가 나면 돈을 보낸 것과 받는 것 둘 다 실패로 적용시키는 것)

- 인증, 캐쉬

 

이것들이 반복된다고?

상품 정보를 등록하는 것과 상품 정보를 조회하는 두 가지 작업이 있다.

어쨌든 이 두 작업 모두 DB를 접근해야하는 상황이 발생. 즉, 같은 트랜잭션 영역에서 수행한다.

또한 로깅 마찬가지로 기록하는 행위는 같다.

 

자세한 내용은 또 공부하면서 추가하기 :)

 

 

 

3. Validation, data binding : data를 믿고 쓰기, 데이터를 원하는 형식으로 받고 싶을 때

1) validation

: 다른 서버에서 요청이 날라올 때 그 내용이 잘못된 내용인지 확인하는 것

- 종류?

: 데이터 검증 - 필수data 존재?, 문자열길이/숫자범위 괜찮은지, 데이터의 형식에 맞춘 데이터인지?

: 비즈니스 검증 - 서비스 정책에 따른 데이터 확인 (배달앱에서 배달 요청할 때 주문건이 결제완료상태인가?

 

- Spring에서 validation 방법?

① Java Bean을 통한 검증

public class MemberCreationRequest { 
    @NotBlank(message="이름을 입력해주세요.") 
    @Size(max=64, message="이름의 최대 길이는 64자 입니다.") 
    private String name;
    
    @Min(0, "나이는 0보다 커야 합니다.")
    private int age;
    
    @Email("이메일 형식이 잘못됐습니다.")
    private int email;
}

ㄴ dto에 어노테이션으로 명시

@PostMapping(value = "/member")
public MemeberCreationResponse createMember(
  @Valid @RequestBody final MemeberCreationRequest memeberCreationRequest) {
  // 검증 성공 후 실행될 것들
}

ㄴ 웹에서 요청을 받는 말단에서

 

② Spring validator 인터페이스 구현을 통한 검증

public class Person {
    private String name;
    private int age;
}

ㄴ 클래스 생성

public class PersonValidator implements Validator {
    /**
     * 이 validator은 Person 객체에 대해서만 검증 가능
     */
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz);
}
    public void validate(Object obj, Errors e) {
        ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
        Person p = (Person) obj;
        if (p.getAge() < 0) {
            e.rejectValue("age", "negativevalue");
        } else if (p.getAge() > 110) {
            e.rejectValue("age", "too.darn.old");
        }
} }

ㄴ Person 객체에 대한 validator

 

 

2) data binding

: validation 후, 그 data를 특정 도메인 객체에 저장해서 우리 프로그램에 Request에 담아주는 것

- 방법?

① Converter<Source,Target> Interface

: S라는 타입을 받아서 T라는 타입으로 변환해주는 인터페이스

package org.springframework.core.convert.converter;
public interface Converter<S, T> {
    T convert(S source);
}

ㄴ 인터페이스 모양

// 요청
GET /user-info
x-auth-user : {"id":123, "name":"Paul"}

// 유저 객체
public class XAuthUser {
    private int id;
    private String name;
}

@GetMapping("/user-info")
public UserInfoResponse getUserInfo(
  @RequestHeader("x-auth-user") XAuthUser xAuthUser){
  // get User Info logic here...
}

 

@Component
public class XAuthUserConverter implements Converter<String, XAuthUser> {
  @Override
  public XAuthUser convert(String source) {
    return objectMapper.readValue(source, XAuthUser.class);
  }
}

ㄴ json을 특정 dto에 담는 내용 (string을 XAuthUser로)

 

② Formatter

: 특정객체 ↔ String 변환

package org.springframework.format.datetime;
@Component
public final class DateFormatter implements Formatter<Date> {
    public String print(Date date, Locale locale) {
        return getDateFormat(locale).format(date);
}
    public Date parse(String formatted, Locale locale) throws ParseException {
        return getDateFormat(locale).parse(formatted);
}
}

ㄴ Date ↔ String

 

 

 

 

4. SpEL : Spring의 모든 영역에서 사용 가능한 표현언어


< Spring MVC > : 웹 개발 기술

 

- model : 이동하는 데이터들

- view : 화면

- controller : 모델/뷰를 응답

 

자세한 건 뒤에서...

 


< 기초 지식 >

 

- 서버 간 통신 : 클라이언트 ↔ 서버 (HTTP/HTTPS)

1. spring boot 동작

참고(책) : spring boot 핵심 가이드

- 서블릿 : client의 요청 처리 및 응답하는 자바 웹 프로그래밍

- 서블릿 컨테이너 : 서블릿 객체 생성 및 관리

(1) : DS(dispatcher servlet)에 요청이 들어오면 DS는 핸들러(=controller) 매핑을 통해 요청 URI에 매핑된 핸들러를 탐색

(2) : 핸들러 어댑터로 컨트롤러를 호출

(3) : 핸들러 어댑터에 컨트롤러의 응답이 들어오면 ModelAndView로 응답을 가공해 반환

(4) : 뷰 형식으로 리턴하는 controller를 사용할 때는 뷰 리졸버를 통해 뷰를 받아 리턴

 

2. 레이어드 구조 (Spring MVC)

: application의 component를 유사한 기준으로 레이어로 묶어 수평적으로 구성한 구조

참고(책) : spring boot 핵심 가이드

- 프레젠테이션 : 클라이언트의 요청을 해석/응답 (View, Controller)

- 비즈니스 : application이 제공하는 기능을 정의 (Model)

- 데이터 접근 : DB에 접근 (Model)

 

 

참고(책) : spring boot 핵심 가이드

1) 프레젠테이션

- UI

- client로부터 data/request 받고 response 전달

2) 비즈니스

- Service

- transaction 처리, validation

3) 데이터 접근

- Persistence

- DB 접근

 

3. 디자인 패턴

: 소웨를 설계할 때 발생하는 문제에 대한 해결책

1) 종류

- GoF : 생성, 구조, 행위 (자세한 내용은 인터넷 참고)

 

4. REST API : 애플리케이션 인터페이스(client가 서버에 접근하고 자원 조작 가능)

- REST? : WWW과 같이 주고받는 resource에 이름을 규정하고, URI에 명시해 HTTP(get, post, put, delete)를 통해 해당 자원 상태를 주고받는 것.

1) 특징

- 유니폼 인터페이스 : HTTP 규약 따름. 많은 곳에서 호환 가능

- 무상태성 : 서버에 상태 정보를 따로 보관X -> request를 개별적으로 처리

- 캐시 가능성 : 같은 요청에 대해서 이전의 데이터 가져옴 (=서버 transaction 부하↓)

- 레이어 시스템

- 클라이언트/서버 구조 : 의존성↓

2) URI 설계 규칙

- URI 마지막 '/' 안붙임 ex) http://localhost:8080

- 언더바X.

- URL에는 동사X 명사O

- URL는 소문자로 작성