๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‡ธ๐Ÿ‡ต๐Ÿ‡ท๐Ÿ‡ฎ๐Ÿ‡ณ๐Ÿ‡ฌ

[์ธํ”„๋Ÿฐ] ๊น€์˜ํ•œ ์Šคํ”„๋ง ์ž…๋ฌธ ์ •๋ฆฌ 1-4

์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ ์„น์…˜ 1 ~ ์„น์…˜ 4 ๊ฐ•์˜ ๋‚ด์šฉ ์ •๋ฆฌ 


โœ” ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

 

https://start.spring.io/

 

ํ™ˆํŽ˜์ด์ง€์—์„œ ํ”„๋กœ์ ํŠธ ์„ค์ • ํ›„ generate

zip ํŒŒ์ผ ์••์ถ• ํ’€๊ณ  ์ธํ…”๋ฆฌ์ œ์ด์—์„œ import (์••์ถ•์„ ํ‘ผ ํด๋”์•ˆ์˜ build.gradleํŒŒ์ผ์„ ์„ ํƒํ•ด์„œ open)

File > Settings > Build, execution, ... > Build Tools > Gradle ์—์„œ Build and run using, Run tests using ์„ IntelliJ๋กœ ๋ฐ”๊ฟ”์คŒ

 

 

โ˜‘ ์œˆ๋„์šฐ ๋‹จ์ถ•ํ‚ค ์‚ฌ์šฉ

 

์ธํ…”๋ฆฌ์ œ์ด ๋‹จ์ถ•ํ‚ค ๊ฒ€์ƒ‰ ๋ฐฉ๋ฒ•

โ–ช File -> Settings -> Keymap -> ๋‹จ์ถ•ํ‚ค ์ด๋ฆ„ ๊ฒ€์ƒ‰

ex) Ctrl + Alt + Shift + T : Refactor This

 

 

โœ” Welcome Page

 

- Thymleaf (ํ…œํ”Œ๋ฆฟ ์—”์ง„) Thymeleaf

ํŒŒ์ผ๊ฒฝ๋กœ src-main-resources-static-index.html ์ƒ์„ฑ

//java/hello.hellospring/controller/HelloController
@Controller
public class HelloController {
     @GetMapping("hello")
     public String hello(Model model) {
     model.addAttribute("data", "hello!!");
     return "hello";
     }
}
//resources/templates/hello.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'์•ˆ๋…•ํ•˜์„ธ์š”. ' + ${data}" >์•ˆ๋…•ํ•˜์„ธ์š”. ์†๋‹˜</p>
</body>
</html>

 

์›น ๋ธŒ๋ผ์šฐ์ €์— localhost:8080/hello์„ ์ž…๋ ฅ -> getMapping -> ๋‚ด์žฅ ํ†ฐ์ผ“ ์„œ๋ฒ„ -> @Getmapping์ด hello๋กœ ๋˜์–ด์žˆ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ฐพ์•„ ๋ฉ”์„œ๋“œ ์‹คํ–‰ -> ๋ฉ”์„œ๋“œ๋Š” model์— addAttribute๋กœ key๊ฐ€ data์ธ hello!! ์ธ value๋ฅผ ๋‹ด๊ณ  hello๋ฅผ ๋ฆฌํ„ด ->  viewResolver๊ฐ€ ๋ฆฌํ„ด๋œ ๋ฌธ์ž์™€ ๋Œ€์‘ํ•˜๋Š” html ํŒŒ์ผ์„ ์ฐพ์Œ -> html ํŒŒ์ผ์ด ์›น๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋„์›Œ์ง

 

 

 

โœ” ์ •์  ์ปจํ…์ธ 

 

- html ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ์›น ๋ธŒ๋ผ์šฐ์ €์— ๋ณด์—ฌ์คŒ , ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์ •์  ์ปจํ…์ธ  ๊ธฐ๋Šฅ์„ ์ž๋™์œผ๋กœ ์ œ๊ณต

 

 

์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ url ์š”์ฒญ -> ๋‚ด์žฅ ํ†ฐ์ผ“ ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ๋ฐ›๊ณ  ์Šคํ”„๋ง์œผ๋กœ ๋„˜๊ฒจ์คŒ -> ์ปจํŠธ๋กค๋Ÿฌ์—์„œ hello-static์„ ์ฐพ๊ณ  ์—†์œผ๋ฉด resources/static ์—์„œ hello-static.html์„ ์ฐพ์Œ -> ์›น ๋ธŒ๋ผ์šฐ์ €์— ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ถœ๋ ฅํ•จ

 

 

 

โœ” MVC

 

- Model, View, Controller๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐœ๋ฐœ

 

 

์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ url ์š”์ฒญ -> ๋‚ด์žฅ ํ†ฐ์ผ“ ์„œ๋ฒ„ -> hello-mvc ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ฐพ์Œ -> ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ Model ์— ๊ฐ’์ด spring์ธ key name์„ ๋‹ด๊ณ  hello-template์„ return -> viewResolver๊ฐ€ resources/templates ์—์„œ hello-template.html ํŒŒ์ผ์„ ์ฐพ๊ณ  ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์—ฐ๊ฒฐ -> Thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์€ ๋ Œ๋”๋ง ํ›„ ์›น ๋ธŒ๋ผ์šฐ์ €์— ๋„˜๊น€

 

 

 

โœ” API

 

- ์„œ๋ฒ„๊ฐ€ JSON์ด๋ผ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ํฌ๋งท์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

* JSON : key-value ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ตฌ์กฐ

@Controller
public class HelloController {
 @GetMapping("hello-string")
 @ResponseBody
 public String helloString(@RequestParam("name") String name) {
     return "hello " + name;
 }
}

@ResponseBody๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด viewResolver๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š์Œ -> HttpMessageConverter๊ฐ€ ๋™์ž‘

- ๊ธฐ๋ณธ ๋ฌธ์ž์ฒ˜๋ฆฌ : StringHttpMessageConverter

- ๊ธฐ๋ณธ ๊ฐ์ฒด์ฒ˜๋ฆฌ : MappingJackson2HttpMessageConverter

@ResponseBody๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๊ฐ์ฒด๊ฐ€ JSON์œผ๋กœ ๋ฐ˜ํ™˜๋จ

 

 

 

โœ” ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ -  ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

 

test/java/ํ”„๋กœ์ ํŠธ๋ช… ์•„๋ž˜์— repository ํด๋”๋ฅผ ์ž‘์„ฑํ•˜๊ณ  MemoryMemberRepositoryTest(๊ตฌํ˜„์ฒด ์ด๋ฆ„+Test) ํŒŒ์ผ์„ ์ƒ์„ฑ

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();

	// @Test : ํ…Œ์ŠคํŠธ ์œ ๋‹› ์ƒ์„ฑ (๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„์ฒด์ธ MemoryMemberRepository ๊ฐ์ฒด๋ฅผ repository๋กœ ์ƒ์„ฑ)
    @Test
    public void save(){ //save ํ•จ์ˆ˜์˜ ๋™์ž‘์„ ํ…Œ์ŠคํŠธ
        //given
        Member member = new Member(); //Member ๊ฐ์ฒด ์ƒ์„ฑ
        member.setName("spring"); //name spring์œผ๋กœ ์„ธํŒ…

        //when
        repository.save(member); // repository์— ์ƒ์„ฑ๋œ ๋ฉค๋ฒ„ ๊ฐ์ฒด๋ฅผ save ํ•จ์ˆ˜์— ์ €์žฅ

        //then
        Member result = repository.findById(member.getId()).get();
        //member์— ์ €์žฅ๋œ id๋กœ findByIdํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด repository์— ์ €์žฅ๋œ Member๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด๊ณ (get()), ๊บผ๋‚ธ Member ๊ฐ์ฒด(result)๊ฐ€ save๋ฅผ ํ†ตํ•ด ์ €์žฅํ–ˆ๋˜ member์™€ ๋™์ผํ•œ ๊ฐ์ฒด์ธ์ง€ ํ™•์ธ
      
        assertThat(member).isEqualTo(result); //์‹คํ–‰ํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ์ง„ํ–‰
    }

    @Test
    public void findByName(){
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        //when
        Member result = repository.findByName("spring1").get();

        //then
        assertThat(result).isEqualTo(member1);
    }

    @Test
    public void findAll(){
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        //when
        List<Member> result =  repository.findAll();

        //then
        assertThat(result.size()).isEqualTo(2);
    }
}

 

๐Ÿ”ธ ํ…Œ์ŠคํŠธ ์œ ๋‹›์„ ํ•œ๋ฒˆ์— ํ…Œ์ŠคํŠธํ•˜๋ฉด error ๋ฐœ์ƒ ๊ฐ€๋Šฅ 

๐Ÿ”ธ ๋ฉ”๋ชจ๋ฆฌ DB์— ์ด์ „ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚จ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์— ์˜ํ–ฅ์ด ๊ฐ€์ง€ ์•Š๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง€์›Œ์•ผํ•จ

๐Ÿ”ธ ํ…Œ์ŠคํŠธ๋Š” ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ์˜ ์ˆœ์„œ์— ์˜์กด๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ํ…Œ์ŠคํŠธ๋Š” ์ข‹์€ ํ…Œ์ŠคํŠธ๊ฐ€ ์•„๋‹˜

import org.junit.jupiter.api.AfterEach;
class MemoryMemberRepositoryTest {
    @AfterEach
    public void afterEach(){
        repository.clearStore();
    }
}

@AfterEach :  ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋‚˜์„œ ๋ฌด์กฐ๊ฑด ์‹คํ–‰

@BeforeEach : ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „์— ํ˜ธ์ถœ, ํ…Œ์ŠคํŠธ๊ฐ€ ์„œ๋กœ ์˜ํ–ฅ์ด ์—†๋„๋ก ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์ƒˆ๋กœ ๋งบ์–ด์คŒ

 

 

โœ” ์Šคํ”„๋ง ๋นˆ

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๋นˆ(Bean)
์ž๋ฐ”์—์„œ new๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

 

โ˜‘ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”๊ณผ ์ž๋™ ์˜์กด ๊ด€๊ณ„ ์„ค์ •

package hello.hellospring.controller;

import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class MemberController {
	private final MemberService memberService;
 	// ํšŒ์› ์„œ๋น„์Šค๋Š” ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜์–ด ์ƒ์„ฑ๋œ ํ•˜๋‚˜์˜ ํšŒ์› ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ๊ฐ์˜ ์ปจํŠธ๋กค๋Ÿฌ๋“ค์ด ๊ณต์œ 
    
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}
}

@Controller๋ฅผ ์‚ฌ์šฉํ•ด MemberController๋ผ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ƒ์„ฑ

@Autowired : ์ƒ์„ฑ์ž์— @Autowired ๊ฐ€ ์žˆ๋‹ค๋ฉด ์Šคํ”„๋ง์ด ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ฐพ์•„์„œ ๋„ฃ์–ด์คŒ 

- ๊ฐ์ฒด ์˜์กด๊ด€๊ณ„๋ฅผ ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์„ DI, ์˜์กด์„ฑ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•จ

 

์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ž๋™ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•

@Controller

@Service

@Repository // ์…‹ ๋‹ค @Component๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ

@Service
public class MemberService { 
	private final MemberRepository memberRepository;

	@Autowired
 	public MemberService(MemberRepository memberRepository) {
 		this.memberRepository = memberRepository;
 	}
}
@Repository
public class MemoryMemberRepository implements MemberRepository {}

@SpringBootApplication์„ ์‹คํ–‰ํ•˜๋ฉด ์†ํ•ด์žˆ๋Š” ํŒจํ‚ค์ง€ ๋‚ด์˜ @Controller, @Service, @Repository๋ฅผ ํ†ตํ•ด ๊ฐ๊ฐ์ด ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜๊ณ , @Autowired๋ฅผ ํ†ตํ•ด ์˜์กด๊ด€๊ณ„๋ฅผ ๊ฐ€์ง

์Šคํ”„๋ง์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋ก ์‹œ ์ค‘๋ณต๋˜์ง€ ์•Š๊ฒŒ ์œ ์ผํ•˜๊ฒŒ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋งŒ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋“ฑ๋ก

 

โ˜‘ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ง์ ‘ ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋กํ•˜๊ธฐ

 

@Service, @Repository, @Autowired ์• ๋…ธํ…Œ์ด์…˜์„ ์ œ๊ฑฐํ•˜๊ณ  ์ง„ํ–‰

MemberController๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค. spring container์— ์ €์žฅํ•˜๊ณ  Controller๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ

package hello.hellospring;

import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //ํด๋ž˜์Šค๋ช… ์•ž์— @Configuration์„ ๋“ฑ๋กํ•˜๋ฉด ์Šคํ”„๋ง์ด ์„ค์ • ํŒŒ์ผ์ž„์„ ์ธ์‹, ์ปจํ…Œ์ด๋„ˆ์— ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ์ค€๋น„
public class SpringConfig {
	//@Bean์„ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ ๋ฐ˜๋“œ์‹œ @Configuration์„ ๊ฐ™์ด ์‚ฌ์šฉ
    @Bean //์ˆ˜๋™์œผ๋กœ Bean ๊ฐ์ฒด ์ƒ์„ฑ
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

 

โ˜‘ DI์˜ 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•

 

โ–ช Field ์ฃผ์ž…

@Autowired private MemberService memberService;

๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์•ž์— @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ž„

 

โ–ช Setter ์ฃผ์ž…

@Controller
public class MemberController {
    private MemberService memberService;

    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }
}

setter๊ฐ€ public์œผ๋กœ ์„ค์ •๋˜์–ด์žˆ์–ด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ

 

โ–ช ์ƒ์„ฑ์ž ์ฃผ์ž…

@Controller
public class MemberController {
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

์กฐ๋ฆฝ(์ƒ์„ฑ์ž ํ˜ธ์ถœ) ์‹œ์ ์— ์ƒ์„ฑ์ž๋ฅผ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ์— ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•˜๊ณ , ์ดํ›„์—๋Š” ์˜์กด๊ด€๊ณ„๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๊ฑฐ์˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž ์ฃผ์ž… ๊ถŒ์žฅ