-
[๊ฐ์] ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB์ ๊ทผ ๊ธฐ์ 2SPRING/INFLEARN 2021. 4. 5. 05:53
์คํ๋ง ๊ณต๋ถ~ [๋ฌด๋ฃ] ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น 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๋ช ์ ๋ชฉ๋ก์์ ๋ณผ ์ ์๋ค. 'SPRING > INFLEARN' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ