블로그
전체 102024. 03. 19.
3
[인프런 워밍업 클럽 0기] BE 후기
여느 때처럼 인프런 강의를 들으러 사이트에 들어왔더니 인프런 워밍업 클럽을 모집한다는 배너가 보였습니다. 혼자 공부를 하다 보니 목표를 세워도 미루기도 하는 식이였는데 인프런 워밍업 클럽에 참여하면 미션도 있고 미니 프로젝트도 있다고 하여 참여하였습니다. 앞부분은 아는 내용도 많아서 쉬웠지만 뒤로 갈 수로 공부하며 진행하였고 내가 궁금했던 부분들은 이미 다른 분들이 질문을 해서 답변을 얻은 것들을 보면서 공부했습니다. 중간중간 코치님의 라이브를 통해 현재 회사에서는 어떻게 일을 하고 어떤 것을 사용하고 문제를 어떻게 해결하는지 등 많은 내용을 공유해 주셨고 마지막 라이브 때는 열정적으로 2시간 40분 정도 라이브를 해주셨습니다. 열정적으로 알려주셔서인지 시간이 너무 빨리 간 느낌입니다. 수료식 때는 온라인으로 참여하였고 여기서도 많은 것을 알 수 있었고 많은 도움을 받을 수 있었습니다. 러너 분들이 포기하지 않고 완주 목표를 달성할 수 있게 도와주시고 배려 해주시는 운영진분들, 하나라도 더 알려주시는 코치님 그리고 열심히 참여하셨던 러너 분들과 함께할 수 있어서 뜻깊은 시간이 된 것 같습니다. 다음에도 기회가 된다면 참여하고 싶습니다.
백엔드
・
인프런
・
인프런워밍업클럽
・
스터디0기
2024. 03. 10.
0
[인프런 워밍업 클럽 0기] BE 3주차 회고
인프런 워밍업 클럽 0기 스터디 마지막 최종 회고 이 워밍업 클럽을 통해 다시 한번 스프링 공부를 할 수 있었고 JPA에 대해 공부할 수 있었습니다. 3주라는 시간동안 많은 것을 배울 수 있는 시간이였습니다. 코치님께서 해주신 라이브 중 가장 기억에 많이 남는 것은 마지막 라이브였던 것 같습니다. 마지막 라이브에서 코치님께서 하나라도 더 알려주시려고 하시는 것을 보고 더 집중에서 들었고 참여 하셨던 분들이 말씀하시 것 처럼 시간이 정말 빨리 가더군요. 거의 2시간 40분 정도 라이브를 해주셨는데 내용도 알차고 실무에서는 어떻게 일을 하는지 어떤것을 고려해야 하는지 알 수 있어서 많은 도움이 될 것 같습니다. 디스코드에 질문을 올리면 정성스러운 답변도 정말 많은 도움이 되었습니다. 하나라도 더 알려주고 싶어 하시는 마음이 느껴졌습니다.^^ 이렇게 많은 분들과 같이 공부할 수 있는 시간을 만들어 주신 인프런 관계자 분들과 열정적으로 라이브와 질문에 답변해주신 코치님 그리고 러너분들 모두 감사하다는 말씀을 드리고 싶습니다. 모두 응원하겠습니다!!!
백엔드
・
백엔드
・
워밍업
2024. 03. 03.
0
[인프런 워밍업 클럽 0기] BE 2주차 회고
2주차 학습 내용과 공부한 내용 정리 ORM(Object Relational Mapping)우리가 일반 적으로 알고 있는 애플리케이션 Class와 RDB(Relational DataBase)의 테이블을 매핑(연결)한다는 뜻이며, 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이다. JPAJava 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스인터페이스 이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현함 사용이유는?JPA를 사용하여 얻을 수 있는 가장 큰 장점은 SQL이 아닌 객체 중심으로 개발할 수 있다는 것이다. 이에 생산성이 좋아지고 유지보수 또한 수월해진다. 트랜잭션데이터베이스 트랜잭션은 데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다.데이터베이스의 상태를 변경시키기 위해 수행하는 작업 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산을 의미한다. 영속성 컨텍스트란?엔티티를 영구 저장하는 환경엔티티 매니저가 영속성 컨텍스트에 엔티티를 보관하고 관리한다.영속성 컨텍스트에 저장된 상태를 영속 상태, 저장되었다가 분리된 상태를 준영속 상태라고 한다. 마무리남은 한주에는 미니프로젝트를 완료하고 더 나아가서 기능을 추가한다거나 해서 더 발전된 프로그램을 만들고 싶습니다.
백엔드
・
백엔드
・
워밍업
2024. 02. 27.
0
[인프런 워밍업 클럽 0기] BE 7일차 과제
controller@RequestMapping("/api/v1") @RestController public class FruitController { private final FruitService fruitService; public FruitController(FruitService fruitService) { this.fruitService = fruitService; } @PostMapping("/fruit") public void saveFruit(@RequestBody FruitDTO request) { fruitService.save(request); } @PutMapping("/fruit") public void sellFruit(@RequestBody FruitDTO request) { fruitService.sell(request); } @GetMapping("/fruit/stat") public FruitResponse getStat(@RequestParam String name) { return fruitService.getStat(name); } @GetMapping("/fruit/count") public FruitCountResponse count(@RequestParam String name) { return fruitService.count(name); } @GetMapping("/fruit/list") public FruitListResponse getList(FruitListRequest fruitListRequest) { return fruitService.getList(fruitListRequest); } } service@Service public class FruitService { private final FruitRepository fruitRepository; public FruitService(FruitRepository fruitRepository) { this.fruitRepository = fruitRepository; } public void save(FruitDTO request) { fruitRepository.save(new Fruit(request.getName(), request.getWarehousingDate(), request.getPrice())); } public void sell(FruitDTO request) { Fruit fruit = fruitRepository.findById(request.getId()).orElseThrow(IllegalArgumentException::new); fruit.changeIs_sold(); fruitRepository.save(fruit); } public FruitResponse getStat(String name) { List salesList = fruitRepository.findByNameAndIsSoldIsFalse(name); List notSalesList = fruitRepository.findByNameAndIsSoldIsTrue(name); long salesAmount = salesList.stream().mapToLong(Fruit::getPrice).sum(); long notSalesAmount = notSalesList.stream().mapToLong(Fruit::getPrice).sum(); return new FruitResponse(salesAmount, notSalesAmount); } public FruitCountResponse count(String name) { return new FruitCountResponse(fruitRepository.countByNameAndIsSoldIsTrue(name)); } public FruitListResponse getList(FruitListRequest fruitListRequest) { if ("GTE".equals(fruitListRequest.getOption())) { return new FruitListResponse(fruitRepository.findAllByPriceGreaterThanEqualAndIsSoldIsFalse(fruitListRequest.getPrice())); } if ("LTE".equals(fruitListRequest.getOption())) { return new FruitListResponse(fruitRepository.findAllByPriceLessThanEqualAndIsSoldIsFalse(fruitListRequest.getPrice())); } throw new IllegalArgumentException("과일 리스트를 불러올 수 없습니다."); } } repository@Repository public interface FruitRepository extends JpaRepository { List findByNameAndIsSoldIsFalse(String name); List findByNameAndIsSoldIsTrue(String name); long countByNameAndIsSoldIsTrue(String name); List findAllByPriceGreaterThanEqualAndIsSoldIsFalse(Long price); List findAllByPriceLessThanEqualAndIsSoldIsFalse(Long price); } domain@Entity @Getter public class Fruit { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column(nullable = false) private LocalDate warehousingDate; @Column(nullable = false) private long price; @Column(nullable = false, columnDefinition = "boolean default false") private boolean isSold; public Fruit(String name, LocalDate warehousingDate, long price) { this.name = name; this.warehousingDate = warehousingDate; this.price = price; } public Fruit() { } public void changeIs_sold() { this.isSold = true; } } dto@Data @AllArgsConstructor @RequiredArgsConstructor public class FruitDTO { private Long id; private String name; private LocalDate warehousingDate; private long price; private boolean is_sold; @Data @AllArgsConstructor @RequiredArgsConstructor public static class FruitResponse { private long salesAmount; private long notSalesAmount; } @Data @AllArgsConstructor @RequiredArgsConstructor public static class FruitCountResponse { private long count; } @Data @AllArgsConstructor @RequiredArgsConstructor public static class FruitListRequest { private String option; private long price; } @Data @AllArgsConstructor @RequiredArgsConstructor public static class FruitListResponse { private List list; } }
백엔드
・
백엔드
・
워밍업
2024. 02. 26.
0
[인프런 워밍업 클럽 0기] BE 6일차 과제
문제 1을 해결하기 전에 과제4에서 했던 코드를 조금 수정을 한뒤 과제를 진행 하였다.문제1DTO@Data @AllArgsConstructor @RequiredArgsConstructor public class FruitDTO { private long id; private String name; private LocalDate warehousingDate; private long price; private boolean is_sold; @Data @AllArgsConstructor public static class FruitResponse { private long salesAmount; private long notSalesAmount; } } controller@RequestMapping("/api/v1") @RestController public class FruitController { private final FruitService fruitService; public FruitController(FruitService fruitService) { this.fruitService = fruitService; } @PostMapping("/fruit") public void saveFruit(@RequestBody FruitDTO request) { fruitService.save(request); } @PutMapping("/fruit") public void sellFruit(@RequestBody FruitDTO request) { fruitService.sell(request); } @GetMapping("/fruit/stat") public FruitResponse getStat(@RequestParam String name) { return fruitService.getStat(name); } } Service@Service public class FruitService { private final FruitMysqlRepository fruitRepository; public FruitService(FruitMysqlRepository fruitRepository) { this.fruitRepository = fruitRepository; } public void save(FruitDTO request) { fruitRepository.save(request); } public void sell(FruitDTO request) { if (fruitRepository.isFruitNotExist(request)) { throw new IllegalArgumentException("존재하지 않는 과일 입니다."); } fruitRepository.sell(request); } public FruitResponse getStat(String name) { return fruitRepository.getStat(name); } }Repository@Repository public class FruitMysqlRepository implements FruitRepository { private final JdbcTemplate jdbcTemplate; public FruitMysqlRepository(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void save(FruitDTO request) { String sql = "INSERT INTO fruit (name, warehousingDate, price) VALUES (?, ?, ?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); } public void sell(FruitDTO request) { String sql = "UPDATE fruit SET is_sold = 1 WHERE id = ?"; jdbcTemplate.update(sql, request.getId()); } public boolean isFruitNotExist(FruitDTO request) { String readSql = "SELECT * FROM fruit WHERE id = ?"; return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty(); } public FruitResponse getStat(String name) { String salesSql = "select sum(price) from fruit where is_sold = 1 group by name having name = ?"; String notSalesSql = "select sum(price) from fruit where is_sold = 0 group by name having name = ?"; long salesAmount = jdbcTemplate.queryForObject(salesSql, Long.class, name); long notSalesAmount = jdbcTemplate.queryForObject(notSalesSql, Long.class, name); return new FruitResponse(salesAmount, notSalesAmount); } } 문제2FruitRepository interfacepublic interface FruitRepository { void save(FruitDTO request); void sell(FruitDTO request); FruitResponse getStat(String name); boolean isFruitNotExist(FruitDTO request); } 수정 된 Service@Service public class FruitService { private final FruitRepository fruitRepository; public FruitService(FruitRepository fruitRepository) { this.fruitRepository = fruitRepository; } public void save(FruitDTO request) { fruitRepository.save(request); } public void sell(FruitDTO request) { if (fruitRepository.isFruitNotExist(request)) { throw new IllegalArgumentException("존재하지 않는 과일 입니다."); } fruitRepository.sell(request); } public FruitResponse getStat(String name) { return fruitRepository.getStat(name); } } FruitMemoryRepository@Primary @Repository public class FruitMemoryRepository implements FruitRepository { List fruitList = new ArrayList(); private long seq = 0L; @Override public void save(FruitDTO request) { fruitList.add(new FruitDTO( ++seq, request.getName(), request.getWarehousingDate(), request.getPrice(), false)); } @Override public void sell(FruitDTO request) { fruitList.get((int)request.getId()).set_sold(true); } public boolean isFruitNotExist(FruitDTO request) { return fruitList.size()
백엔드
・
백엔드
・
워밍업
2024. 02. 25.
0
[인프런 워밍업 클럽 0기] BE 1주차 회고
1일 차어노테이션과 API에 대해 생각해 볼 수 있었습니다.과제 : 어노테이션에 대해 찾아보며 몰랐던 내용을 정리하면 공부하였습니다. 2일 차API를 설계하여 통신하는 방법을 공부했습니다.과제 : 시간이 없어서 과제를 다 못해서 안 올렸지만 다음에 완성해서 올리려고 합니다. 3일 차익명 클래스와 람다에 관해 공부했습니다.개인적으로 익명 클래스와 람다 그리고 제네릭, collection 부분은 계속 반복해서 공부해야 될 것 같습니다. 코드를 보면 이해는 되지만 실제로 프로젝트 등에 적용을 해보는 연습이 필요할 것 같습니다.과제 : 이번 기회에 공부를 하면서 익명 클래스와 람다에 대해 좀 더 알 수 있는 시간이었습니다. 4일 차API를 설계하여 개발하고 postman으로 결과를 확인하며 공부하였습니다.과제 : 간단한 과일가게 API 개발이어서 큰 어려움은 없었지만 이런 기초를 단단히 쌓아야 나중에 도움이 될 것으로 생각합니다. 5일 차클린코드란 무엇인가 생각해 보는 시간이었습니다.과제 : 최대한 깔끔하게 작성해 보려고 했습니다. 1주 차 후기개인적으로 제일 좋았던 과제는 익명 클래스와 람다에 관해 공부할 수 있었던 과제였습니다.이번에 공부를 했으니 실제로 프로젝트나 다른 과제에 적용을 해보고 싶습니다.
백엔드
・
백엔드
・
워밍업