SPRING/INFLEARN

[๊ฐ•์˜] ์Šคํ”„๋ง ์ž…๋ฌธ - ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB์ ‘๊ทผ ๊ธฐ์ˆ  2

ozllzL 2021. 4. 5. 05:53

์Šคํ”„๋ง ๊ณต๋ถ€~

inf.run/reCZ

 

[๋ฌด๋ฃŒ] ์Šคํ”„๋ง ์ž…๋ฌธ - ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB ์ ‘๊ทผ ๊ธฐ์ˆ  - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์ „๋ฐ˜์„ ๋น ๋ฅด๊ฒŒ ํ•™์Šตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., ์Šคํ”„๋ง ํ•™์Šต ์ฒซ ๊ธธ์žก์ด! ๊ฐœ๋ฐœ ๊ณต๋ถ€์˜ ๊ธธ์„ ์žƒ์ง€ ์•Š๋„๋ก ๋„์™€๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๐Ÿ“ฃ ํ™•์ธํ•ด์ฃผ์„ธ

www.inflearn.com

๋ฌด๋ฃŒ๋ถ€๋ถ„๋งŒ ์˜ฌ๋ฆฌ๊ฒ ์Œ

์ถœ์ฒ˜ : inf.run/reCZ ๊ฐ•์˜

 

3. ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ

- ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ

๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๊ฐ€ ์„ ์ •๋˜์ง€ ์•Š์Œ์„ ๊ฐ€์ •

์ปจํŠธ๋กค๋Ÿฌ → ์„œ๋น„์Šค → ๋ฆฌํฌ์ง€ํ† ๋ฆฌ → DB

          โ†˜      ↓        โ†™

                 ๋„๋ฉ”์ธ

์„œ๋น„์Šค : ํšŒ์› ์ค‘๋ณต ๊ฐ€์ž…์ด ์•ˆ๋œ๋‹ค ๊ฐ™์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง

           ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋Œ์•„๊ฐ€๋„๋ก ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด

๋ฆฌํฌ์ง€ํ† ๋ฆฌ : ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๊ณ 

๋„๋ฉ”์ธ : ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๊ณ  ๊ด€๋ฆฌ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ ๊ฐ์ฒด

 

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ตฌํ˜„์ฒด๋กœ ๋งŒ๋“ค์–ด์„œ ๋‚˜์ค‘์— ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์„ ์ • ํ›„ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„

 

 

- ํšŒ์› ๋„๋ฉ”์ธ๊ณผ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ

 

//Member.java - member ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ
public class Member {

    private Long id;//id ์‹๋ณ„์ž, ์‹œ์Šคํ…œ์ด ์ž๋™ ์ €์žฅ
    private String name;//์ด๋ฆ„

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

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

    public void setName(String name) {
        this.name = name;
    }
}
//MemberRepository.java
public interface MemberRepository {
    Member save(Member member);
    Optional<Member> findById(Long id); //id๋กœ ํšŒ์› ์ฐพ๊ธฐ
    Optional<Member> findByName(String name); //์ด๋ฆ„์œผ๋กœ ํšŒ์› ์ฐพ๊ธฐ
    //Optional -> null๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฑฐ ๋ฐฉ์ง€
    List<Member> findAll();
}
//MemoryMemberRepository.java
public class MemoryMemberRepository implements MemberRepository {

    private static Map<Long, Member> store = new HashMap<Long, Member>();
    private static long sequence = 0L; //key๊ฐ’ ์ƒ์„ฑ

    @Override
    public Member save(Member member) {
        member.setId(++sequence);//id ๋Š” ์‹œ์Šคํ…œ์ด ์ •ํ•ด์ค€๋‹ค.
        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(); //  map์— ์ด๋ฆ„์ด ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ๋ฐ˜ํ™˜. ์—†์œผ๋ฉด null์ด ํฌํ•จ๋˜์„œ ๋ฐ˜ํ™˜
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }
}

 

- ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

JUnit์ด๋ผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ํ…Œ์ŠคํŠธ ์‹คํ–‰

//MemoryMemberRepositoryTest.java
public 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(); //์ €์žฅํ•œ ๋ฉค๋ฒ„ ์ฐพ๊ธฐ
        //optional์—์„œ๋Š” get์œผ๋กœ ๋ฐ”๋กœ ๊บผ๋‚ผ ์ˆ˜ ์žˆ์Œ(์ข‹์€ ๋ฐฉ๋ฒ• x)
        //1)System.out.println("Result = " + (result == member));
        //2)Assertions.assertEquals(member, null);
        //3)
        assertThat(member).isEqualTo(result);
    }

    @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);
    }

    //์ˆœ์„œ๋Š” ๋ณด์žฅ ํ•  ์ˆ˜ ์—†๋‹ค. ์•ž์—์„œ ํ…Œ์ŠคํŠธ ํ•œ๋ฒˆ์ด ๋๋‚˜๊ณ  ๋‚˜๋ฉด clear๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
    //-> ์ˆœ์„œ๊ฐ€ ์ƒ๊ด€ ์—†๊ฒŒ ๋งŒ๋“ค์ž

}

์ž˜๋จ ํ‚ค์—จ

- ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ

//MemberService.java
public class MemberService {
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    //ํšŒ์›๊ฐ€์ž…
    public Long join(Member member){
        //๊ฐ™์€ ์ด๋ฆ„ ์ค‘๋ณตํšŒ์› x
       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();
    }

    //id๋กœ ์‚ฌ๋žŒ ์ฐพ๊ธฐ
    public Optional<Member> findOne(Long memberID){
        return memberRepository.findById(memberID);
    }
}

 

- ํšŒ์› ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ

<<๋‹จ์ถ•ํ‚ค>>

ctrl+shift+t -> test class ๋งŒ๋“ค์–ด์ค€๋‹ค

ctrl+alt+v -> Optional๋กœ ๊ฐ์‹ธ๊ธฐ/reCZ

shift+F10 -> ์‹คํ–‰

//MemberServiceTest.java
class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    } // -> 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
    public void ์ค‘๋ณต_ํšŒ์›_์˜ˆ์™ธ(){
        //given
        Member member1 = new Member();
        member1.setName("spring");
        Member member2 = new Member();
        member1.setName("spring");

        //when
        memberService.join(member1);
        /*1)
        try {
            memberService.join(member2);
            fail(); //fail์—์„œ ๊ณ„์† ์˜ค๋ฅ˜๋‚จ ์ด์œ  ์•Œ์•„๋‚ผ ๊ฒƒ
        }catch(IllegalStateException e){
            assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
        }*/
        //2)
        IllegalStateException e = assertThrows(IllegalStateException.class,
                () -> memberService.join(member1));

        //then

    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

 

 

๋„˜ ์–ด๋ ต๋‹ค... ๋‹ค์‹œ ๊ณต๋ถ€ํ•ด์•ผํ• ๋“ฏ

4. ์Šคํ”„๋ง ๋นˆ๊ณผ ์˜์กด ๊ด€๊ณ„

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

์Šคํ”„๋ง ๋นˆ ๋“ฑ๋ก

   1) ์ปดํฌ๋„ŒํŠธ ์Šค์บ”, ์ž๋™ ์˜์กด ๊ด€๊ณ„ ์„ค์ • (@Component๋ฅผ ํฌํ•จํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜)

   ์Šคํ”„๋ง์€ ์ปดํฌ๋„ŒํŠธ ์• ๋…ธํ…Œ์ด์…˜(@)์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•œ๋‹ค.

   @AutoWired๋Š” ์–˜๋„ค๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์„  ๊ฐ™์€ ๋А๋‚Œ

   ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ํ•˜๋‚˜์”ฉ๋งŒ ๋“ฑ๋กํ•ด ์‚ฌ์šฉํ•œ๋‹ค.(์‹ฑ๊ธ€ํ†ค) ์„ค์ • ๊ฐ€๋Šฅ ํ•˜๊ธด ํ•˜์ง€๋งŒ ์›ฌ๋งŒํ•˜๋ฉด ์‹ฑ๊ธ€ํ†ค

   DI์—๋Š” ํ•„๋“œ ์ฃผ์ž…, setter ์ฃผ์ž…, ์ƒ์„ฑ์ž ์ฃผ์ž… 3๊ฐ€์ง€ ๋ฐฉ๋ฒ• -> ์ƒ์„ฑ์ž ์ฃผ์ž… ๊ถŒ์žฅ

MemberController -> MemberService -> MemberRepository

//MemberController.java
@Controller
public class MemberController {
    private final MemberService memberService; //= new MemberService(); ์—ฌ๋Ÿฌ๊ฐœ ์“ฐ๋Š” ๊ฑด ์˜๋ฏธ๊ฐ€ ์—†์Œ

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

   2) ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ง์ ‘ ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋ก

   ๋‹ค์Œ์— ๋‚˜์˜ด

 

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

@Configuration
public class SpringConfig {
    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

 

5. ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - ์›น MVC ๊ฐœ๋ฐœ

- ํšŒ์› ์›น ๊ธฐ๋Šฅ - ํ™ˆ ํ™”๋ฉด ์ถ”๊ฐ€

//HomeController
@Controller
public class HomeController {

    @GetMapping("/") //์šฐ์„  ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— index.html ๋ฌด์‹œ
    public String home(){
        return "home";
    }

}

์‹คํ–‰

- ํšŒ์› ์›น ๊ธฐ๋Šฅ - ๋“ฑ๋ก

//MemberForm.java
public class MemberForm {
    private String name;

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

    public String getName() {
        return name;
    }
}
//MemberController.java
@Controller
public class MemberController {
    private final MemberService memberService; //= new MemberService(); ์—ฌ๋Ÿฌ๊ฐœ ์“ฐ๋Š” ๊ฑด ์˜๋ฏธ๊ฐ€ ์—†์Œ

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

    @GetMapping("/members/new")
    public String createForm(){
        return "members/createMemberForm";
    }
    @PostMapping("/members/new")
    public String create(MemberForm form){
        Member member = new Member();
        member.setName(form.getName());

        memberService.join(member);
        System.out.println(member.getName());
        return "redirect:/";
    }
}

์ž˜ ๋‚˜์˜จ๋‹ค. ๊น€์ฒ ์ˆ˜๋ฅผ ์ž…๋ ฅํ•ด ๋ณด์•˜๋‹ค.

 

System.out.println(member.getName());์„ ์ถ”๊ฐ€ํ•œ ํ›„ ๊ฒฐ๊ณผ ์•„์ฃผ ๋‚˜์ด์Šค

- ํšŒ์› ์›น ๊ธฐ๋Šฅ - ์กฐํšŒ

 

//MemberController.java ์˜ ์ผ๋ถ€
@GetMapping(value = "/members")
    public String list(Model model) {
        List<Member> members = memberService.findMembers();
        model.addAttribute("members", members);
        return "members/memberList";
    }

ํšŒ์› ๊ฐ€์ž…์‹œํ‚จ 3๋ช…์„ ๋ชฉ๋ก์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.