240730 TIL

송형근·2024년 7월 30일

TIL

목록 보기
2/43
post-thumbnail

스파르타 Java 단기 심화 과정


코드카타


짝수와 홀수

https://school.programmers.co.kr/learn/courses/30/lessons/12937

— 문제 설명

  • 정수 num이 짝수일 경우 "Even"을 반환하고 홀수인 경우 "Odd"를 반환하는 함수, solution을 완성해주세요.

— 제한 조건

  • num은 int 범위의 정수입니다.
  • 0은 짝수입니다.

— 입출력 예

numreturn
3"Odd"
4"Even"

— 문제 풀이

class Solution {
    public String solution(int num) {
        if(num%2==0){ // 짝수
            return "Even";
        }else {
            return "Odd";
        }
    }
}

Spring 숙련 2주차 강의


Entity의 Fetch Type


  • 지연 로딩( Lazy Loading )
    • 연관 관계가 설정된 Entity의 정보를 필요할 때 가져오는 방식
  • 즉시 로딩( Eager Loading )
    • 연관된 모든 Entity의 정보를 즉시 가져오는 방식
  • @OneToMany, @ManyToMany 어노테이션은 Lazy가 default
  • @ManyToOne, @OneToOne 어노테이션은 Eager가 default
  • FetchType.Lazy 로 설정된 Entity의 정보를 조회할 경우 반드시 @Transactional 어노테이션을 추가해야 한다.
  • https://github.com/lukeydokey/Sparta-Spring/commit/01d7262623d2bb55e8a000854f457e15b0cb4457

Cascade (영속성 전이)


  • 영속 상태의 Entity에서 수행되는 작업들이 연관된 Entity까지 전파되는 상황을 의미
  • 연관관계 설정 어노테이션에서 cascade 옵션을 사용해 아래의 예시처럼 영속성 전이 설정 가능
  • 예시
    @Entity
    @Getter
    @Setter
    @Table(name = "users")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
    
        @OneToMany(mappedBy = "user", cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
        private List<Food> foodList = new ArrayList<>();
    
        public void addFoodList(Food food) {
            this.foodList.add(food);
            food.setUser(this);
        }
    }
  • https://github.com/lukeydokey/Sparta-Spring/commit/507de1c2f7e925eda1634dde0ca3a064148358ef

고아 Entity 삭제


  • Cascade.Remove 옵션을 적용하면 Entity 객체 삭제 시 연관된 Entity 객체도 삭제할 수 있음
  • 하지만 연관된 Entity와의 관계를 제거한다고 해서 Entity 객체가 삭제되진 않음
  • 연관 관계가 사라져서 고아 상태가 된 Entity를 제거하기 위해 JPA에서는 orphanRemoval 사용 가능 ( default 값은 false )
    • @ManyToOne 어노테이션에서는 사용 불가 ( 해당 Entity 객체를 참조하는 다른 Entity 객체들이 있을 수 있기 때문 )
  • 설정 시 연관 관계가 끊어지면 연관된 Entity가 삭제 되며, Entity 객체 삭제 시에도 Cascade.Remove 처럼 연관된 Entity가 삭제됨
  • 예시
    @Entity
    @Getter
    @Setter
    @Table(name = "users")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
    
        @OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST, orphanRemoval = true)
        private List<Food> foodList = new ArrayList<>();
    
        public void addFoodList(Food food) {
            this.foodList.add(food);
            food.setUser(this);
        }
    }
  • https://github.com/lukeydokey/Sparta-Spring/commit/ed514fc59794a462c7a8ddf296c4935c497c0b83

실습 프로젝트 ( My Select Shop )


요구사항

  • 키워드로 상품 정보 검색
    • 네이버 쇼핑 API
    • 상품 이름, 링크 URL, 이미지 URL, 최저가
  • 관심 상품 등록
    • 상품 이름, 링크 URL, 이미지 URL, 최저가
    • 희망 최저가 0원으로 설정
  • 관심 상품의 희망 최저가 설정
    • 관심 상품의 희망 최저가만 업데이트
  • 관심 상품 조회
    • 등록된 모든 관심상품 정보 조회
    • UI에 최저가 표시 조건
      • 희망하는 최저가보다 실제 최저가가 낮은 경우

프로젝트 환경 세팅

관심 상품 CRU API 구현

Scheduler 구현

  • 매일 새벽 1시 관심 상품 제목으로 검색해서, 최저가 정보를 업데이트하는 스케줄러가 필요
  • SpringBootApplication쪽에 @EnableScheduling 어노테이션 추가
  • 스케줄러 작성
    @Slf4j(topic = "Scheduler")
    @Component
    @RequiredArgsConstructor
    public class Scheduler {
    
        private final NaverApiService naverApiService;
        private final ProductService productService;
        private final ProductRepository productRepository;
    
        // 초, 분, 시, 일, 월, 주 순서
        @Scheduled(cron = "0 0 1 * * *") // 매일 새벽 1시
        public void updatePrice() throws InterruptedException {
            log.info("가격 업데이트 실행");
            List<Product> productList = productRepository.findAll();
            for (Product product : productList) {
                // 1초에 한 상품 씩 조회합니다 (NAVER 제한)
                TimeUnit.SECONDS.sleep(1);
    
                // i 번째 관심 상품의 제목으로 검색을 실행합니다.
                String title = product.getTitle();
                List<ItemDto> itemDtoList = naverApiService.searchItems(title);
    
                if (itemDtoList.size() > 0) {
                    ItemDto itemDto = itemDtoList.get(0);
                    // i 번째 관심 상품 정보를 업데이트합니다.
                    Long id = product.getId();
                    try {
                        productService.updateBySearch(id, itemDto);
                    } catch (Exception e) {
                        log.error(id + " : " + e.getMessage());
                    }
                }
            }
        }
    
    }
  • https://github.com/lukeydokey/Sparta-Spring/commit/b2e18aef595111d53b854a51ae0045e6b83df3ca

회원 기능 구현

회원별 상품 API 구현

상품 페이징 및 정렬기능 구현

  • List를 그냥 받아오는 것이 아닌 페이지, 오름 내림차순, 정렬 기준 등을 설정하고 싶을 경우
    • Page, Sort, Pageable을 활용
      • 구현

        public Page<ProductResponseDto> getProducts(User user, int page, int size, String sortBy, boolean isAsc) {
                Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
                Sort sort = Sort.by(direction, sortBy);
                Pageable pageable = PageRequest.of(page, size, sort);
        
                UserRoleEnum userRoleEnum = user.getRole();
        
                Page<Product> productList;
        
                if(userRoleEnum == UserRoleEnum.USER){
                    productList = productRepository.findAllByUser(user, pageable);
                }else {
                    productList = productRepository.findAll(pageable);
                }
        
                return productList.map(ProductResponseDto::new);
            }
  • https://github.com/lukeydokey/Sparta-Spring/commit/95a294b3b98dc1ee1865866ab97af8c4a58fdef8

상품 폴더 설계

  • 요구사항
    1. 폴더 생성
      1. 회원별 폴더를 추가
      2. 폴더를 추가할 때 1개~N개를 한번에 추가 가능
    2. 관심상품에 폴더 설정
      1. 관심상품에 폴더는 N개 설정 가능
      2. 관심상품이 등록되는 시점에는 어느 폴더에도 저장되지 않음
      3. 관심상품 별로 1번에서 생성한 폴더를 선택하여 추가 가능
    3. 폴더 별 조회
      1. 회원은 폴더 별로 관심상품 조회
      2. 조회 방법
        1. '전체' 클릭 시: 폴더와 상관 없이 회원이 저장한 전체 관심상품들을 조회
        2. '폴더명' 클릭 시: 폴더별 저장된 관심상품들을 조회
  • 폴더 - 유저 : ManyToOne 관계
  • 폴더 - 상품 : ManyToMany 관계
    • 중간 테이블 필요
  • https://github.com/lukeydokey/Sparta-Spring/commit/674bae157d8feb4e35a461ba492806d82a601167

폴더 생성 및 조회 구현

관심 상품에 폴더 정보 추가 구현

폴더별 관심상품 조회 구현


스파르타 Java 단기 심화 개강 과제

실습 프로젝트 (My Select Shop) 배포

AWS RDS 생성

  • MySQL 생성
    • Public IP할당
    • RDS 생성 시 Create할 DB 명 shop
    • 보안그룹 인바운드 3306 port 추가
  • 프로젝트 application.properties 수정
    • datasource.url=jdbc:mysql://{생성한RDS URL}:3306/shop
    • datasource.username={생성할 때 설정한 user}
    • datasource.password={생성할 때 설정한 userPW}

EC2 인스턴스 생성

  • Ubuntu 22.04
  • Openjdk 17 설치
  • 보안그룹 인바운드 22, 80, 8080 port 추가

프로젝트 빌드

  • Gradle Build
  • .jar 위치
    • build/libs/.jar
  • EC2 인스턴스 내로 jar 파일 복사
    • Filezilla or MobaXterm

Jar 실행

java -jar {JAR파일명}.jar
  • 8080 포트로 접속 확인

포트 포워딩

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
  • 80포트 (http)로 접근 시 8080 포트로 포워딩

프로젝트 프로세스 백그라운드 실행 유지

nohup java -jar JAR파일명.jar &
  • nohup : no hang up의 약자
    • 세션을 종료하더라도 프로세스 실행이 유지가 됨
  • & : 프로세스 백그라운드 실행
  • nohup과 &를 합치면 프로세스를 데몬 형태로 실행이 가능
  • 데몬 : 리눅스에서 지속적인 서비스 요청을 처리하기 위해 백그라운드에서 계속 실행되는 프로세스
profile
기록을 남겨보자

0개의 댓글