스프링 프레임워크(영어: Spring Framework)는 자바 플랫폼을 위한 오픈 소스애플리케이션 프레임워크로서 간단히 스프링
(Spring)이라고도 한다. 동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공하고 있다. 대한민국 공공기관
의 웹 서비스 개발 시 사용을 권장하고 있는 전자정부 표준프레임워크의 기반 기술로서 쓰이고 있다.
java 기본값이 17인데 실수로 11로 변경하는 것을 놓쳐서 나중에 기본 예제를 실행하는데 계속 에러가 나서 고생하다 나중에 버전 문제인 것을 알고 다시 프로젝트를 GENERATE했다.
src/main/java/hello/hellospring/HelloSpringApplication을 실행하면
이렇게 뜨면 성공한 것이다.
Gradle, Maven은 의존성 관리를 해주어서 의존관계가 있는 라이브러리를 함께 다운로드한다.
즉, 특정 라이브러리를 사용하기 위해 필요한 다른 라이브러리를 같이 다운 받는다는 뜻이다.
프로젝트를 진행하면서 사용하는 수많은 라이브러리들을 관리해주는 도구입니다.
여기서 메이븐의 특징적인 점은 그 라이브러리들과 연관된 라이브러리들까지 거미줄처럼 모두 연동이 되서 관리가 된다는 점입니다.
즉, 메이븐은 네트워크를 통해 연관된 라이브러리까지 같이 업데이트를 해주기 때문에 사용이 편리합니다.
1. 스크립트 길이와 가독성 면에서 gradle이 우세하다.
2. 빌드와 테스트 실행 결과 gradle이 더 빠르다. (gradle은 캐시를 사용하기 때문에 테스트 반복 시 차이가 더 커진다.)
3. 의존성이 늘어날 수록 성능과 스크립트 품질의 차이가 심해질 것이다.
maven은 프로젝트가 커질수록 빌드 스크립트의 내용이 길어지고 가독성이 떨어집니다.
반면에 gradle은 훨씬 적은 양의 스크립트로 짧고 간결하게 작성할 수 있습니다.
maven이 정적인 형태의 XML 기반으로 작성되어 동적인 빌드를 적용할 경우 어려움이 많다면,
gradle은 Groovy를 사용하기 때문에 동적인 빌드는 Groovy 스크립트로 플러그인을 호출하거나 직접 코드를 짜면 됩니다.
출처: https://dev-coco.tistory.com/65 [슬기로운 개발생활:티스토리]
출처: https://dev-coco.tistory.com/65 [슬기로운 개발생활:티스토리]
템플릿 양식(html)과 데이터 모델(DB)에 따른 입력 자료를 결합해서 문서를 출력하는 소프트웨어를 템플릿 엔진이라고 한다.
그리고 두가지의 종류로 나뉘는데
서버에서 가져온 데이터를 미리 만들어진 템플릿에 넣어서 html을 완성시키고 클라이언트에게 전달한다.
브라우저 위에서 html 형태로 화면을 생성하고, 서버에서 받은 json, xml형식의 데이터를
여기서 동적인 화면으로 만드는 것이며 예로는 React나 Vue.js가 있다.
그리고 현직에서는 jsp를 많이 사용하지 않는다고 하는데 왜냐하면 스프링에서 자동 설정을 지원하지 않기 때문이라고 합니다!!
그렇다면, Spring에서 자동 설정을 지원하는 템플릿 엔진에는 무엇이 있을까?
FreeMarker, Groovy, Thymeleaf, Mustache가 있다.
그 중 가장 인기가 많은 Thymeleaf가 인기가 가장 많다고 합니다.
Thymeleaf는 스프링부트와 굉장히 궁합이 잘 맞기에 권장하는 템플릿 엔진인 것 같다. Thymeleaf를 사용하기 위해서는 의존성을 추가해주고 view에서 html 언어를 추가해서 문법을 적용시키면 됩니다.
@GetMapping("hello-mvc")
)를 확인하고 return 해줄 때 이름을 hello-template으로 하고 model의 name값을 spring으로 viewResolver로 넘겨줍니다. 그러면 viewResolver는 해당 html을 찾아 반영합니다.회원객체
package hello.hellospring.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;
}
}
회원 리포지토리 인터페이스
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
회원 리포지토리 메모리 구현체
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
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();
}
}
회원 리포지토리 메모리 구현체 테스트
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() {
repository.clearStore();
}
@Test
public void save() {
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get();
assertThat(result).isEqualTo(member);
}
@Test
public void findByName() {
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
Member result = repository.findByName("spring1").get();
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll() {
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
회원 서비스
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import java.util.List;import java.util.Optional;
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// 회원가입
public Long join(Member member) {
validateDuplicateMember(member); //중복 회원 검증
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
//전체 회원 조회
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
회원 서비스 테스트
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach
public void beforeEach() {
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach
public void afterEach() {
memberRepository.clearStore();
}
@Test
public void 회원가입() throws Exception {
//given
Member member = new Member();
member.setName("hello");
//when
Long saveId = memberService.join(member);
//then
Member findMember = memberRepository.findById(saveId).get();
assertEquals(member.getName(), findMember.getName());
}
@Test
public void 중복_회원_예외() throws Exception {
//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("이미 존재하는 회원입니다.");
}
}