클라이언트의 요청에 대해 서버에 미리 저장된 파일(HTML, CSS, JS 등)을 그대로 응답으로 제공하는 방식
localhost:8080/hello-static.html 수신@GetMapping("/hello.html")이 있는 Controller가 있다면 → 이 메서드가 실행/resources/static 디렉터리에서 정적 파일을 찾아 클라이언트에게 반환💡 모든 클라이언트 요청에 대해 동일한 결과를 반환한다.
Model: 데이터와 비즈니스 로직을 담당
View: 클라이언트에게 표시되는 사용자 인터페이스를 생성
Controller: 클라이언트 요청을 처리하고 Model과 View를 연결
🖥️ Controller
@Controller
public class HelloController {
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
}
🖥️ View
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
/hello 요청 → Controller가 요청을 처리서버와 클라이언트 간 데이터를 교환하기 위한 인터페이스
html파일 자체가 아니라 @RestController와 JSON 형식을 사용해 클라이언트에게 전달
🖥️ @ResponseBody 문자 반환
@Controller
public class HelloController {
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
}
🖥️ @ResponseBody 객체 반환
@Controller
public class HelloController {
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
static class Hello {
private String name;
public String getName() {
return name;
}
public String setName(String name) {
this.name =name;
}
}
}
자바의 main 메서드나 웹 애플리케이션의 컨트롤러를 통해 해당 기능을 실행하는 대신, 자바는 JUnit이라는 프레임워크로 테스트를 실행하여 반복 실행 및 여러 테스트를 한번에 실행하기 쉽게함
🖥️ MemoryMemberRepository
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();
}
}
🖥️ MemoryMemberRepositoryTest
class MemoryMemberRepositoryTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach //항상 새로운 객체와 의존관계 생성
public void beforeEach() {
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach
public void afterEach() {
memberRepository.clearStore();
}
@Test
public void save(){
//given
Member member = new Member();
member.setName("spring");
//when
memberRepository.save(member);
//then
Member result = memberRepository.findById(member.getId()).get();
assertThat(result).isEqualTo(member); // Assertions.assertEquals(member, result);
}
@Test
public void findByName(){
//given
Member member1 = new Member();
member1.setName("spring1");
memberRepository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
memberRepository.save(member2);
//when
Member result = memberRepository.findByName("spring1").get();
// then
assertThat(result).isEqualTo(member1);
}
}
동일한 인스턴스를 가지고 테스트 해야함
👉 MemberService 에서 직접 MemberRepository를 생성
따라서 MemberService의 MemberRepository와 테스트에서 사용하는 memberRepository가 다른 인스턴스이므로 제대로된 테스트가 아님
private final MemberRepository memberRepository = new MemoryMemberRepository();
MemberService memberService = new MemberService();
MemoryMemberRepository memberRepository = new MemoryMemberRepository();
👉 외부에서 MemberService 의 MemberRepository를 주입 = DI
@BeforeEach를 사용하여 각 test를 진행하기 전에 사용할 인스턴스들을 생성
🖥️ MemberService
private final MemberRepository memberRepository;
private MemberService(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
🖥️ MemberServiceTest
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach
public void beforeEach() {
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
🖥️ MemberServiceIntergrationTest
@SpringBootTest
@Transactional
class MemberServiceIntergrationTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
public void 회원가입() throws Exception {
//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
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("이미 존재하는 회원입니다.");
}
}