Backend/Spring

Spring 복습 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

둉이 2021. 8. 28. 22:05
이 글은 야매로 스프링을 배운 블로그 주인이 스프링 복습 겸 스프링 부트 학습을 위해 인프런 강의를 듣고 정리한 내용을 적은 글입니다.

 

학습 영상

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

 

[무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., 스프링 학습 첫 길잡이! 개발 공부의 길을 잃지 않도록 도와드립니다. 📣 확인해주세

www.inflearn.com

 

학습 기간

2021.08.27 ~ 2021.08.28

 


프로젝트 환경 설정

요새는 그냥 스프링을 잘 안 쓰고 스프링 부트를 쓰는 추세

maven 안 쓰고 gradle을 주로 사용하는 추세

스프링 부트 프로젝트 생성은 https://start.spring.io/ 에서 아주 간단하게 생성 가능

 

m1, m2나 snapshot이 뒤에 붙은 버전들은 정식 버전이 아니므로 주의

src는 java 파일, resources는 java 파일을 제외한 html, css 파일 등이 위치

src - main - java - 내 패키지... - ~SpringApplication 파일의 main 클래스를 run 해주면 spring boot 프로젝트 실행 가능

→ 기본 접속 포트는 8080

 

- build.gradle

: plugin, jdk 버전, repositories 및 dependencies 정보를 저장하는 설정 파일

 

- External Libraries에는 현재 프로젝트에서 사용되는 외부 라이브러리가 저장됨

=> build.gradle에 등록한 라이브러리 의존성

gradle(혹은 maven)이 라이브러리 의존 관계를 관리해주기 때문에 자동으로 필요한 라이브러리를 추가해주기 때문!

(*)으로 중복된 라이브러리 제외

 

예전에는 was, web 서버를 따로 설치하여 설정한 후에 war 파일을 밀어 넣어서 실행하는 방식을 사용했지만 요새는 was 자체를 프로젝트 내에 내장(embeded)시켜서 사용하기 때문에 따로 서버 설정이 필요 없음

 

- 스프링 부트 라이브러리

sout로 디버깅 하면 X → logging을 사용해야 함(slf4j, logback)

 

- 테스트 라이브러리

junit(v5)으로 테스트, mockito(객체 목업 라이브러리)로 모킹, assertj(테스트 코드 작성 도우미) 사용

src - resources - static에 index.html 파일을 생성하여 welcome-page 설정 가능

→ welcome-page란? root path로 접근했을 때 뜨는 페이지

 

- 템플릿 엔진

: FreeMarker, Groovy, Thymeleaf, Mustache 등을 사용

→ 스프링과는 달리 jsp 사용을 권장하지 않음

// thymeleaf 예시
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title>메인 페이지</title>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   </head>
   <body>
      <p th:text="'안녕하세요 ' + ${data}"></p>
   </body>
</html>

 

- 스프링 부트 폴더 관리

src - main - java 내에 패키지로 controller, dao, service 등을 분리하여 관리

resources - templete 내에 view 파일들을 관리(html)

 

- 만약 컨트롤러에 매핑된 주소로 접근이 안된다면?

SpringApplication 내에 @ComponentScan(basePackages = {"패키지명"}) annotation 추가

 

스프링에서의 MVC 동작 환경

컨트롤러는 다음과 같은 형태를 띔

 

- @GetMapping annotation을 사용하여 주소 라우팅

- 문자열을 반환하는 경우, viewResolver에 의해 resources - templetes에 있는 파일명을 자동으로 찾아서 뷰를 그려줌

 

 

- 직접 빌드(jar)하는 방법

① gradlew build (linux에서는 ./gradlew build 실행)

② cd build/libs 이동

java -jar 파일명.jar 으로 was 실행

 

 


스프링 웹 개발 기초

웹 개발 방식은 크게 3가지로 나뉨 → 정적 컨텐츠, MVC와 템플릿 엔진, API

 

① 정적 컨텐츠

: 파일 그대로 사용하므로 프로그래밍 불가능

  resources - static 내에 위치 → [웹사이트 주소]/파일명.html 형태로 접근 가능

  컨트롤러에 파일명.html이라는 주소를 갖는 라우터가 존재하지 않으므로 static 폴더에서 정적 파일을 찾아 뷰에 그려줌

 

② 템플릿 엔진

: 웹 개발에 주로 사용됨 / jsp, php 등 포함

  viewResolver가 templetes 폴더에 있는 html 파일을 찾아서 변환(템플릿 엔진 문법 변환) 후 뷰에 그려줌

  매개변수를 받는 경우에는 @RequestParam 사용

@RequestParam(value = "", defaultValue = "", required = false)
// 1. value : 파라미터 이름(name) 설정, 이것만 사용하는 경우 value 생략해도 됨
// 2. defaultValue : 기본값 설정
// 3. required : 필수 여부(기본값 true)

 

 

③ API

: 주로 JSON 형태로 클라이언트에게 응답을 보내줌 or 서버끼리의 통신 형태

  @RequestBody 어노테이션을 꼭 붙여줘야 함

  → 요청에 대한 응답의 body에 해당 결과를 넣어준 후 반환한다는 의미

 

  viewResolver를 사용하지 않고 HttpMessageConverter가 동작

  → 기본 문자 처리는 StringHttpMessageConverter, 기본 객체 처리는 MappingJackson2HttpMessageConverter가 담당

 

  문자열이 아닌 객체 반환 시, JSON 형태로 변환되어 반환

 

 


회원 관리 예제 - 백엔드 개발

프로젝트 진행 과정

1. 비즈니스 요구사항 정리

2. 회원 도메인과 repo 만들기

3. 회원 repo test case 작성

4. 회원 서비스 개발

5. 회원 서비스 테스트(Junit)

 

- 일반적인 웹 어플리케이션 계층 구조

① controller : 웹 MVC의 컨트롤러

② service : 핵심 비즈니스 로직 구현

③ repository : DB에 접근, 도메인 객체를 DB에 저장하고 관리(=DAO)

④ domain : 비즈니스 도메인 객체(=VO, DTO, entity의 모음)

 

프로젝트 초기 단계에 DB가 확정되지 않은 경우에는 메모리 기반의 데이터 저장소를 DB처럼 사용

 

- Optional 클래스

Optional.ofNullable()로 감싸서 리턴

 

- ConcurrnetHashMap

: 동시성을 지원하므로 멀티 스레드 환경에서 사용 가능

 

- AtomicLong

..

 

- Junit을 통한 테스트 코드 작성 및 실행

test 폴더에서 main에 있는 패키지명과 동일 + 파일 이름 뒤에는 Test를 붙여서 테스트 파일 생성

각 메소드에 @Test 어노테이션을 붙여서 테스트 코드 작성

Assertj 라이브러리의 Assertions 객체를 사용하여 테스트 결과 비교 가능

테스트 코드는 실제 빌드 파일에 포함되지 않음

 

코드 예시

class MemoryMemberRepoTest {
   MemoryMemberRepo repo = new MemoryMemberRepo();
   @Test
   public void testcase1() {
      Member member = new Member();
      member.setName("mjkim");
      repo.save(member);
      Member result = repo.findById(member.getId()).get();
      Assertions.assertThat(result).isEqualTo(member);
   }
}

 

- AfterEach

: 각 테스트 케이스가 실행된 후 실행되는 메소드

  @AfterEach 어노테이션을 사용하여 메소드 선언

// afterEach 예시
@AfterEach
public void afterEach() {
   repo.clearStore();
}

 

- 테스트 케이스 작성 팁

: given / when / then 구성으로 작성하는 것이 좋음

 

service 파일의 메소드명은 비즈니스에 맞게 작성
ctrl + shift + t를 누르면 자동으로 테스트를 생성할 수 있음