SpringBoot 기초 강의 feat.인프런 part1

김하진·2023년 7월 3일
0

java 공부를 시작하면서 Spring Boot 강의를 듣기 시작했다. 김영한님 강의는 볼수록 여러가지 배울것이 많아서 도움이 많이 된다.

Spring 이란?

Spring 은 자바 기반의 웹 어플리케이션을 만들 수 있는 프레임 워크이다.

스프링 프레임워크는 현대 자바 기반의 엔터프라이즈 어플리케이션을 위한 프로그래밍 및 Configuration Model 제공한다'라고 언급하고 있다.

유명한 MVC의 패턴이 사용되며, DI와 AOP 의 특징이 있다. 이것에 관해서는 나중에 따로 정리할 예정이다. 한국에서 사용자가 많은 만큼 방대한 양의 오픈소스와 안정성을 가질 수 있다.

스프링 프레임워크의 특징

  • POJO 기반의 구성
  • 의존성 주입(DI)를 통한 객체 간의 관계 구성
  • AOP(Aspect-Oriented-Programming) 지원
  • 편리한 MVC 구조
  • WAS의 종속적이지 않은 개발 환경
  • 단위 테스트 JUnit지원

현재까지 flask, django, fast-api, node.js , nest.js .. 등등 여라가지 프레임워크를 써보았지만 Spring은 깊게 공부해볼 생각이다.

SpringBoot란 무엇인가

SpringBoot는 Spring framework 기반 프로젝트를 복잡한 설정없이 간편하고 빠르게 만들어 주는 라이브러리 이다.
원래 Spring 개발 환경 셋팅을 할때 XML 설정 파ㅣ일이라고 web.xml, rootContext.xml, ServletContext.xml 등을 작성하고, 일일이 개발자가 설정을 해주었다면, SpringBoot를 이용하면 보다 쉽고 빠르게 사용할 수 있다. tomcat 같은 was 서버도 자동으로 셋팅이 된다.

Spring boot 장점

  1. 라이브러리 관리 자동화.

스프링부트의 Starter 라이브러리를 등록해서 라이브러리 의존성을 간단히 관리할 수 있다.

  1. 라이브러리 버전 자동관리
    기존 스프링 라이브러리는 버전을 직접 입력해야 했지만, 스프링 부트는 pom.xml에 스프링 부트 버전을 입력해놓으면 spring 라이브러리 뿐만 아니라 third party라이브러리들도 호환되는 버전으로 알아서 다운로드 및 관리해준다.
  1. 설정 자동화
    스프링 부트는 @EnableAutoConfiguration 어노테이션을 선언해서 스프링에서 자주 사용했던 설정들을 알아서 등록해준다. 이 기능이 스프링 부트의 마법이라고 불린다고 한다.
  1. 내장Tomcat.
    스프링 부트는 WAS인 Tomcat을 내장하고 있다. @SpringBootApplication 어노테이션이 선언되어 있는 클래스의 mail()메소드를 실행하는 것만으로 서버를 구동시킬 수 있다.
    내장 톰캣을 사용하기 위한 별도 설정없이 web starter 의존성만 추가해주면 된다.
  1. 독립적으로 실행가능함 JAR
    웹 프로젝트라면 war파일로 패키징 해야하는데 스프링 부트는 내장 톰캩ㅅ을 지원하기 때문에 jar 파일로 패키징해서 웹 애플리케이션을 실행시킬 수 있다

시작하기.

SpringStarter 를 통해서 Spring 을 셋팅하고 파일을 생성할 수 있다.

이파일을 통해서 Intellij 를 통해 실행 시키면 된다.

그전에 JDK 를 설치하여 버전에 맞게 세팅을 해야한다 이부분은 생략하도록 하겠다.

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

main 메서드이다. java 는 main 메서드가 있어야 실행이 된다.

package spring.basic.spring.basic.domain;

public class Member {

    private  Long id;
    private  String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

강의 내용중 domain 이라는 패키지를 만들어서, Member라는 class 를 만들어서 getter, setter 하는 내용이다. 기본적인 class 의 구조를 따르고 있다.

public class MemoryMemberRepository implements MemberRepository {
    private  static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;

    @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }
    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }

    public void clearStore() {
        store.clear();
    }
}

여기서 볼만한 점은 Optional 이다. 개발을 하다보면 많은 예외 처리를 하는데, Optional을 사용하면 NPE 를 방지할 수 있고. 그러다 보니 로직이 좀더 직관적으로 변할 수 있다.

  • Optional.empty() - 값이 Null인 경우
  • Optional.of() - 값이 Null이 아닌 경우
  • Optional.ofNullbale() - 값이 Null일수도, 아닐수도 있는 경우
public interface MemberRepository {
    Member save(Member member);
    Optional<Member> findById(Long id);
    Optional<Member> findByName(String name);
    List<Member> findAll();
}

java 의 interface 이다. 기본적인 구조는 TypeScript 에서 쓰던
interface 와 유사하다고 볼 수 있다.

다만 추상클래스와 인터페이스의 차이가 있는데 짚고 가자면

추상클래스는 일반 클래스와 별 다를 것이 없다. 단지, 추상 메서드를 선언하여 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스, 그래서 미완성 설계도라고도 표현한다. 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없다.

class 앞에 "abstract" 예약어를 사용하여 상속을 통해서 구현해야한다는 것을 알려주고 선언부만 작성하는 추상메서드를 선언할 수 있다

인터페이스는 추상클래스가 미완성 설계도라면 인터페이스는 기본 설계도라고 할 수 있다. 인터페이스도 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 작성하고 클래스와 다르게 다중상속(구현)이 가능합니다.

Repository 를 사용하는 방식도 기존 Nest에서 사용하던 구조와 비슷하다. 강의에서는 db연결없이 memory 를 사용했지만, 실제 db 를 이용하여 구현할때는 많이 달라질것으로 보이지만 사용하는 느낌은 알 것 같다.

TEST!

가장 중요한 TEST 이다. 우선 이부분은 통째로 가지고 오겠다.

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);

        /*
        같은 Memory Repository 를 사용하기 위해 DI를 사용
        DI(Dependency Injection)란 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로
        객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다.
        DI(의존성 주입)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.
         */

    }

    @AfterEach
    public void afterEach() {
        memberRepository.clearStore();
    }

    @Test
    void 회원가입() {
        //given
        Member member = new Member();
        member.setName("spring");

        //when
        Long saveId = memberService.join(member);

        //then
        Member findMember = memberService.findOne(saveId).get();
        assertThat(member.getName()).isEqualTo(findMember.getName());

    }

    @Test
    void 중복_회원_예외(){
        //given

        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));

        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다");

    }

    @Test
    void findOne() {
    }
}

우선 TEST에 AfterEach, BeforeEach 와 같이 테스트 시작전, 후로 사용하는 메서드 들이 존재한다. 상황에 맞게 적절히 사용하면 될 것 같다(ex 데이터의 초기화)

spring 에는 junit 이라는 테스트 라이브러리가 있다고 하였는데, 실제 코딩을 하다보면 junit 말고도 한가지다 더 존재해서 상황에 맞게 사용하면 될 것 같다.

Test 의 기본 검증은 given, when, then 의 절차를 따르는게 좋고,

Assertions.assertThat(member).isEqualTo(result); static import 하면 아래처럼 변환가능 alt + enter

static import 를 통해 간단하게 쓸수도 있다.

또한 Intellij 를 쓰면서 많은 단축키 들이 존재하는데 유용한 것들이 만은 것 같다.

getter,setter 를 자동으로 해준다거나, 특정 로직을 Method 로 바꿔준다거나, 해당 class 의 test 기본 구조를 짜준다거나 이런것들이 강의에 많이 포함되어 있어서 좋은거 같다.

현재 절반정도 수강한거 같은데 나머지도 듣고 좀더 정리해볼 예정이다.

profile
진킴

0개의 댓글