
@Controller
public class HomeController {
	// localhost:9090 -> home.html
	
	@GetMapping
	public String home() {
		return "home";
	}
}
members -> 공통
Member의 빈 객체 model에 넘겨줘야한다.
@ModelAttribute 사용
model.addAttribute("member",new Member());
-> @ModelAttribute("member")Member member
return "redirect:/";
'/'요청으로 가서 home.html로 리턴 하도록 요청이 가고,return home 할 때 viewResolver가 받아서 화면에 있는 값을 찾아서 뿌려준다.@Controller
@RequestMapping("/members")
// 생성자 주입 
@RequiredArgsConstructor
public class MemberController {
	private final MemberRepository memberRepository;
	
	 * model.addAttribute("member",new Member());
	 * 		-> @ModelAttribute("member")Member member
	 */
	@GetMapping("/add")
	public String addForm(@ModelAttribute("member")Member member) {
		// model.addAttribute("member",new Member());
		return "/members/addMemberForm";
	}
	
	// 저장, 홈화면으로 이동
	@PostMapping("/add")
	public String save( @ModelAttribute Member member){
		memberRepository.save(member);
		return "redirect:/";
	}
	
}
@Repository
public class MemberRepository {
	private static Map<Long, Member> store = new HashMap<Long, Member>();
	private static long sequence = 0L;
	
	public Member save(Member member) {
		member.setId(++sequence);
		store.put(member.getId(), member);
		return member;
	}
	
	public Member findById(Long id) {
		return store.get(id);
	}
	
	public List<Member> findAll(){
		return new ArrayList<Member>(store.values());
	}
	
	// 전체 리스트에서 받아온 Id와 파라미터로 받아온 Id가 일치하는지 여부 확인
	public Member findByLoginId(String loginId) {
		List<Member> all = findAll();
		for(Member m : all) {
			if(m.getLoginId().equals(loginId)) {
				return m;
			}
		}
		// 아니라면 null값
		return null;
	}
	
}
PostConstruct가 붙은 메서드는 클래스가 service(로직을 탈 때? 로 생각 됨)를 수행하기 전에 발생한다. 이 메서드는 다른 리소스에서 호출되지 않는다해도 수행된다. 생성자(일반)가 호출 되었을 때, 빈(bean)은 아직 초기화 되지 않았다. (예를 들어, 주입된 의존성이 없음) 하지만, @PostConstruct를 사용하면, 빈(bean)이 초기화 됨과 동시에 의존성을 확인할 수 있다.class를 스프링 컨테이너에 bean객체로서 등록이 되있어야지만  스프링부트에서 제공해주는 anontation을 사용가능, 이 class자체가 Spring bean에 등록이 되려면 Component 스캔의 대상이 되어야함 -> @Component 사용@Component
@RequiredArgsConstructor
public class TestDataInit {
	
	private final MemberRepository memberRepository;
	
	// 테스트 데이터 추가
	@PostConstruct
	public void init() {
		// save 라는 Repository안에 save메서드에다 member라는 객체를 파라미터값으로 넘겨줘야한다.
		// 그래야 memberRepository에 임의의 데이터가 저장 
		// TestDataInit가 MemberRepository를 의존
		Member member = new Member();
		member.setLoginId("test");
		member.setPassword("test!");
		member.setName("테스터");
		member.setEmail("test@gmail.com");
		memberRepository.save(member);
		
	}
}
Id가 메모리 상에 존재하지 않으면 return null 실패처리, Id 있다면 member 전체 결과값을 return, 이 비즈니스 로직을 service에서 처리한다.public class LoginController {
	// loginService 의존 
	private final LoginService loginService;
	@GetMapping("/login")
	public String loginForm(@ModelAttribute("loginForm") LoginForm loginForm) {
		return "/login/loginForm";
	}
	
	@PostMapping("/login")
	public String login(@ModelAttribute LoginForm form,
			Model model, RedirectAttributes redirectAttributes) {
		Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
		if(loginMember == null) {
			// 로그인 실패
			model.addAttribute("msg", "로그인 실패");
			return "login/loginForm";
		}
		// 로그인 성공
		redirectAttributes.addFlashAttribute("msg","로그인성공");
		return "redirect:/";
	}
}
loginId가 db에 있는지 없는지 select해서 가져옴MemberRepository를 LoginService가 의존한다.Member member = memberRepository.findByLoginId(loginId);@Service
@RequiredArgsConstructor
public class LoginService {
	// MemberRepository 의존
	private final MemberRepository memberRepository;
	
	public Member login(String loginId, String password) {
		Member member = memberRepository.findByLoginId(loginId);
		
        // member.getLoginId().equals(loginId) 없어도 됌!
		if(member != null && member.getLoginId().equals(loginId)
				&& member.getPassword().equals(password)) {
			// 로그인 성공
			return member;
		}else {
			return null;
		}
	}
	
}
<script>
	let message = "[[${msg}]]";
	if(message != ""){
		alert(message);
	}
	
</script>