1. 요구사항 분석

스크린샷 2022-02-07 오전 10.53.24.png

2. 도메인 , repository구현

@Data
//Data를 쓰면 위험하다. Getter,Setter, toString, 등등 다 만들어주기 때문에 -> 핵심 도메인 모델에 쓰기에는 적절하지 않다.
//실제 개발에서는 Getter,Setter정도만 사용하자
//Dto(단순하게 데이터 왔다갔다할 때는 사용 가능)
public class Item {
    private Long id;
    private String itemName;
    private Integer price;
    private int quantity;

    public Item(){

    }

    public Item(String itemName, Integer price, int quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}
@Repository
//component스캔의 대상이 된다.
public class ItemRepository {
    private static final Map<Long,Item> store = new HashMap<>(); //static
    //실무에서는 동시에 여러 쓰레드가 접근할 수 있기 때문에 Hashmap을 사용하지 않고 Cuncurrent Hashmap을 사용해야 한다.
    private static long sequence = 0L; //static -> 싱글톤을 유지하기 위해
    //얘도 automic long 같은거를 사용해야 함

    public Item save(Item item){
        item.setId(++sequence);
        store.put(item.getId(),item);
        return item;
    }
    public Item findById(Long id){
        return store.get(id);
    }
    public List<Item> findAll(){
        return new ArrayList<>(store.values());
    }
    public void update(Long itemId, Item updateParam){
        Item findItem = findById(itemId);
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
    }
    **//중복이냐 명확성이냐? -> 명확성을 따르자!
    //지금 update에서 id빼고 다 사용되니까 원래는 따로 객체를 만드는 것이 맞다.**

    public void clearStore(){
        store.clear();
    }
}
class ItemRepositoryTest {

    ItemRepository itemRepository = new ItemRepository();

    **//깔끔한 테스트를 위해 사용, 테스트 끝날 때마다 리포지토리를 초기화한다.
    @AfterEach
    void afterEach(){
        itemRepository.clearStore();
    }**

    @Test
    void save() {
        //given
        Item item = new Item("itemA",10000,10);
        //when
        Item savedItem = itemRepository.save(item);

        //then
        Item findItem = itemRepository.findById(item.getId());
        assertThat(findItem).isEqualTo(savedItem);
    }

    @Test
    void findAll() {
        //given
        Item item1 = new Item("item2",10000,10);
        Item item2 = new Item("item1",20000,20);
        itemRepository.save(item1);
        itemRepository.save(item2);
        //when
        List<Item> result = itemRepository.findAll();

        //then
        assertThat(result.size()).isEqualTo(2);
        assertThat(result).contains(item1,item2);
    }

    @Test
    void update() {
        //given
        Item item = new Item("itemA",10000,10);
        Item savedItem = itemRepository.save(item);
        Long itemId = savedItem.getId();

        //when
        Item updateParam = new Item("item2", 20000, 30);
        itemRepository.update(itemId,updateParam);

        //then
        Item findItem = itemRepository.findById(itemId);
        assertThat(findItem.getItemName()).isEqualTo(updateParam.getItemName());
        assertThat(findItem.getPrice()).isEqualTo(updateParam.getPrice());
        assertThat(findItem.getQuantity()).isEqualTo(updateParam.getQuantity());
    }
}

3. 상품 목록

3-1. BasicItemController

**@Controller**
**@RequestMapping("/basic/items")**
**@RequiredArgsConstructor**
public class BasicItemController {
    private final ItemRepository itemRepository;

    @GetMapping
    public String items(Model model){
        List<Item> items = itemRepository.findAll();
        model.addAttribute("items",items);
        return "basic/items";
    }

    /**
     * 테스트용 데이터 추가
     */
    @PostConstruct
    public void init(){
        itemRepository.save(new Item("itemA",10000,10));
        itemRepository.save(new Item("itemB",20000,20));
    }
}

→ itemRepository에서 모든 상품을 조회한 후 모델에 담아 뷰 템플릿을 호출한다.

//@RequiredArgsConstructor
public class BasicItemController {
  //private final ItemRepository itemRepository;

	@RequiredArgsConstructor면 아래를 자동으로 생성해준다.
	@Autowired
	public BasicItemController(ItemRepository itemRepository) {
	    this.itemRepository = itemRepository;
	}