728x90

143기 자바 개발자 양성과정(김경호 강사님)  수강 후기

 
 
 


6개월(2023.05.17~2023.11.15)간의 자바 수업을 마치는 날이 되었습니다. 
 
4월즈음 비전공자인 제가 웹 개발자가 되기를 결심하고 많은 학원들의 커리큘럼을 비교해보고 
아이티윌을 선택하게 되었습니다. 
6개월이라는 기간은 4년의 전공생들의 학습량을 따라 잡기엔 턱없이 부족한 시간입니다. 
그래서 저는 짧은 시간동안 웹 개발자로서 갖춰야할 필수적인 기술들을 배울 수 있으면서 
기초를 탄탄하게 잡을 수 있는 커리큘럼을 원했고 
고심끝에 아이티윌의 커리큘럼을 선택하게 되었습니다. 
 
김경호 강사님은 기본을 중요하게 생각하십니다. 
그래서 자바, 객체지향의 개념을 가르치는데 긴 시간 공을 들이시고 기초가 갖춰지고나면 
프레임워크, API 는 빠르게 터득하실 수 있습니다. 복습도 꾸준히 하셔야해요
 
 
https://www.itwill.co.kr/cmn/eduCrseMain/1000000/all/CRSE_00000000000650eduCrseMainDetail.do

 

자바 개발자 양성 과정

국비지원 무료교육

www.itwill.co.kr

 
여기부턴 팁을 몇가지 드리려고 해요 
 
학원 개강 첫날은 일찍 오셔야 해요 
좋은 자리를 선점해야 한달간 편해지실거에요 
너무 뒷자리에 앉으면 사람 머리에 가려져서 강사님 화면 밑부분이 잘 안보일 수 있어요 
수업에 집중도 잘 안될 수 있구요 
 
그리고 개강첫날 웰컴키트로 치약, 칫솔, 물티슈, 충전기, 볼펜 등을 주기 때문에 특별히 챙길 필요는 없습니다. 
 
과정 중 총 세번의 프로젝트가 있어요 
처음 2번의 프로젝트는 
JDBC를 사용한 세미 프로젝트, MyBatis와 JSP를 사용한 프로젝트로 약 일주일간 진행됩니다. 
그리고 파이널 프로젝트는 
스프링부트 프레임워크, JPA 등 그간 배운 기술들을 사용해 한달간 프로젝트를 진행하게 됩니다. 
파이널 프로젝트를 할때는 학원에서 다루지 않은 다른 다양한 API, 프레임워크들을 공부하여 적용할 정도의 능력을 갖추기 때문에 본인이 얼마나 노력하는지에 따라 파이널 프로젝트에 다양한 기술들을 적용해볼 수 있어요 
 
개강전까지 시간적 여유가 있다면 
정보처리기사 꼭 준비하세요 
학원에서 공부하면서 준비하는건 쉽지 않습니다. 
저는 학원 등록하고 1달간의 시간이 남아있어서 한달간 
정보처리기사 실기 준비해서 합격하고 (필기는 옛날에 땄었어요)
학원에서 소개해준 온라인 강의(플러터, 자바 기초) 들었어요 
빠르면 1, 2주 안에 학습할 수 있는 양이고 
플러터는 다트 언어를 사용해 주로 프론트엔드쪽을 다루는 프레임워크지만 
나중에 웹개발 프론트엔드를 이해할 때 꽤나 도움이 되었어요 
컴포넌트의 개념을 이해하기도 좋았구요 
 

 
비전공자를 위한 이해할 수 있는 IT 지식 
요 책도 읽었어요 
 
이해하기 쉽게 써놓긴 했는데 한번 읽고는 개념이 완벽하게 이해되진 않아요 
그래도 이 책 한번 읽고 나중에 수업 때 개념 듣고 실습해보면 
그때 책에서 말한게 이거였구나 그럼 이런 기능을 하는 거겠네 하고 이해하는데 큰 도움이 됩니다. 
 
학원 수강할 때 내일배움카드를 발급 받으면 50만원의 지원금이 나와요 
50만원은 Hrd-net 카드 내역에서 확인할 수 있어요 

K-디지털 기초역량훈련

https://www.hrd.go.kr/hrdp/ma/pmmao/newIndexRenewal.do

 

직업훈련포털 HRD-Net

오늘도 더 성장할 나를 위한 직업훈련 지식포털 안녕하세요. 로그인을 해 주세요. 로그인 간편인증 로그인 개인 기업 회원가입

www.hrd.go.kr

이 돈은 카드 발급일로부터 1년간 온라인 강의 듣는데 사용할 수 있어서 
적극 활용하시길 추천드립니다. 

 
6개월간 아이티윌 김경호 강사님께 정말 많이 배웠고 기초부터 탄탄하게 쌓을 수 있어서 정말 좋은 시간이었습니다. 
그리고 143기 동기분들도 고생많으셨어요 

728x90

프로젝트 기간: 2023 - 10 - 16 ~ 2023 - 11 - 11

레퍼런스 : 다나와 https://www.danawa.com/

 

스마트한 쇼핑검색, 다나와! : 가격비교 사이트

가격비교 사이트 - 온라인 쇼핑몰, 소셜커머스 전 상품 정보 가격비교 사이트, 비교하면 다나와

www.danawa.com

인원 : 8명

GitHub 주소 https://github.com/choliea/danaga

 

GitHub - choliea/danaga: final project Danaga shopping mall By team.Avengers 2023-10-16

final project Danaga shopping mall By team.Avengers 2023-10-16 - GitHub - choliea/danaga: final project Danaga shopping mall By team.Avengers 2023-10-16

github.com

파트 : 프로덕트 

사용 언어 : 자바, 자바스크립트

 

 

사용 기술 스택 : 

스프링 부트를 활용한 쇼핑몰 웹 사이트 제작 프로젝트 

 

ERD

 

 

Product part Table

 

 

https://youarethebestcoding.tistory.com/128

 

다나가 쇼핑몰 프로젝트 ER diagram과 Entity

Tool : ERDCloud https://www.erdcloud.com/ ERDCloud Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool. www.erdcloud.com 프로젝트 전체 테이블 프로덕트 관련 테이블 Product 테이블 :

youarethebestcoding.tistory.com

 

 

구현한 기능 및 서비스 

카테고리 선택시 해당 카테고리의 제품들이 가지고 있는 스펙들을 불러와 조건 검색을 할 수 있다. 

카테고리 선택, 옵션 선택, 정렬 기준 선택, 검색 버튼 클릭시마다 검색하여 제품들을 보여준다. 

 

옵션 선택하여 조건 검색 

같은 종류의 조건에 대하여는 합연산, 다른 종류의 조건에 대하여는 곱연산 적용

 

 

예를들어, 운영체제의 윈도우11과 윈동우10을 동시에 선택하면 

윈도우11 또는 윈도우10인 제품을 검색하고 

운영체제의 윈도우11, 화면비율 16:9 를 선택하면

윈도우11이면서 화면비율 16:9인 제품을 검색한다. 

 

제품명 검색은 대소문자 구분하지 않고 검색한다. 

 

https://youarethebestcoding.tistory.com/130

 

스프링부트 프로젝트 JPA 활용

JPA에 대해서 다룬 포스트가 있다. https://youarethebestcoding.tistory.com/115 Spring Data JPA begins http://projects.spring.io/spring-data/ Spring Data Spring Data’s mission is to provide a familiar and consistent, Spring-based programming mod

youarethebestcoding.tistory.com

 

 

페이징은 무한스크롤API를 이용하였다. 

https://youarethebestcoding.tistory.com/133

 

Intersection Observer 무한스크롤 구현하기

#무한스크롤 기존 페이징 방식에서 벗어나 최근 떠오르는 페이징 방식이다. 특정 개수만큼만 로딩하고 특정 뷰포트를 넘어가면 다음 아이템을 로딩하는 방식으로 비동기 방식으로 html을 누적

youarethebestcoding.tistory.com

 

 

 

 

프로덕트 검색 전체 시연

 

제품 상세페이지 

제품 상세페이지에서는 해당 제품과 동일한 모델의 다른 옵션으로 구성된 제품을 선택할 수 있고

선택시 해당 제품의 상세 페이지로 전환된다.

 

DESCRIPTION 탭에서는 제품의 설명 이미지 파일을 로딩하고 

SPECIFICAION 탭에서는 제품의 상세 스펙을 표로 보여준다. 

 

로그인 상태에서 제품의 하트를 클릭하면 Toast 메세지와 함께 관심상품에 등록된다. 

 

제품 상세 페이지에 들어가본 제품은 최근 본 상품에 등록되고 

로그인 하지 않은 상태에서 본 제품도 로그인 후 최근 본 상품에 등록되게 된다. 

 

최근 본 상품은 등록된지 30일이 지나는 시점에 자동으로 삭제된다. 

 

 

배포 

AWS CLI를 이용해 elasticbeanstalk 환경을 구축하고 github action을 이용해 

 

무중단 자동 배포 환경 구축 

배포된 사이트 index 페이지 

 

https://youarethebestcoding.tistory.com/134

 

스프링부트 프로젝트 CI/CD 환경 구축 (with.AWS + GIthub Actions)

이번 프로젝트에서는 AWS의 ElasticBeanstalk 을 이용해 application을 배포하고 github actions를 이용해 aws에 무중단 배포할 수 있는 환경을 구축하였다. AWS의 서비스에 관해서는 이미 다룬 적이 있으니 생

youarethebestcoding.tistory.com

 

 

 

 

프로젝트 관련 포스트 

https://youarethebestcoding.tistory.com/129

 

스프링부트 프로젝트 계층에 따른 데이터 전송 형태

클라이언트는 브라우저에서 요청을 하고 응답을 받는다. 이때 요청은 서버에서 필요한 데이터를 담아야하고 서버측에서 응답할땐 클라이언트에게 공개할 데이터만 담아서 보내면 된다. 일반

youarethebestcoding.tistory.com

 

 

https://youarethebestcoding.tistory.com/131 

 

스프링부트 프로젝트 서비스와 예외처리

이번 프로젝트를 하면서 예외 처리에 대해서 고민 많았고 실제로 작업하면서 몇번씩 수정을 거치게 되었다. 일단 예외가 발생했을 때 발생원인이 명확한 경우 구체적인 예외 사유를 알 수 있게

youarethebestcoding.tistory.com

 

https://youarethebestcoding.tistory.com/132

 

Thymeleaf Layout

#타임리프 레이아웃 코드의 재사용이 가능한 부분을 템플릿화할 수 있게 도와주는 타임리프 라이브러리 #레이아웃을 사용하는 이유 타임리프의 insert나 replace 기능은 많이 사용하지만 이 기능에

youarethebestcoding.tistory.com

 

728x90

Entity 공통으로 포함할 createdAt, updatedAt 필드를 

BaseEntity를 만들어 다른 Entity들이 상속할 수 있게 SuperClass로 사용

@Data

@MappedSuperclass

public class BaseEntity {

@CreationTimestamp

@Column(updatable = false)

private LocalDateTime createdAt;

@UpdateTimestamp

private LocalDateTime updatedAt;

}

entity 관리를 위해 entity 생성, 수정 시간을 기록하는 createAt, updatedAt을 가진다. 

ToString, HashCode, Equals를 포함하는 Data 어노테이션과 

BaseEntity 테이블을 따로 만들지 않고 superclass로 하여 자식 클래스들이 필드만 사용할 수 있게 하기 위해 

@MappedSuperclass 어노테이션을 사용한다. 

 

@Data

@EqualsAndHashCode(callSuper = true)

@ToString(callSuper=true)

@AllArgsConstructor

@NoArgsConstructor

@Builder

@Entity

public class ProductDetail extends BaseEntity {

ProductDetail 엔터티는 BaseEntity를 상속하고 

superclass(BaseEntity)의 @Data 어노테이션(Equals,HashCode,ToString)을 사용하기위해 

@EqualsAndHashCode,ToString 어노테이션에 callSuper 속성을 true로 한다. 

 

 

product와 productDetail은 1:1 관계이고 

ProductDetail이 Product_id를 FK로 갖고 있으므로 OwnerTable이라 할 수 있다. 

 

public class Product extends BaseEntity {

@Id

@GeneratedValue(strategy = GenerationType.SEQUENCE)

private Long productId;

 

private String name;

private Integer price;

private Integer stock;

 

 

//1:1 (Owner table 아님)

@OneToOne(mappedBy = "product", cascade = CascadeType.PERSIST)

private ProductDetail productDetail;

 

Product는 ProductDetail 객체를 가지고 

1:1 맵핑이므로 @OneToOne 어노테이션을 붙인다. 

 

OwnerTable이 아닌 클래스에서 OwnerTable 의 클래스를 mapping할 때 속성으로 

mappedBy를 작성해줘야 한다. 

Product가 가지고 있는 ProductDetail은 Product에 의해 mapping 되므로 mappedBy product 

 

cascade는 product를 작업할때 product가 가진 productDetail도 함께 작업할지에 대한 옵션이다. 

all, detach, merge, persist, refresh, remove가 있고 persist는 영속성에 추가할 때 관련 엔터티도 함께 추가된다. 

 

public class ProductDetail extends BaseEntity {

@Id

@GeneratedValue(strategy = GenerationType.SEQUENCE)

private Long productDetailId;

private String description;

 

/*

* 1:1 OWNER TABLE 참조키를 갖고 있어서

*/

@OneToOne(cascade = CascadeType.PERSIST)//save할 때 연관된 프로덕트도 같이 하겠다.

@JoinColumn(name="product_id")

@ToString.Exclude

private Product product;//tostring시 product의 detail의 product의 detail 순환참조 stackoverflow

 

 

ProductDetail은 Product를 FK로 가지고 있으므로 OwnerTable이라고 할 수 있다. 

마찬가지로 @OneToOne 어노테이션을 사용하고 cascade 설정을 줄 수 있다. 

오너테이블에서 FK 엔터티를 맵핑할때는 mappedBy 속성이 필요없다. 

대신 @JoinColumn 어노테이션을 작성해줄 수 있다. (default로 해주긴함)

JoinColumn 은 default로 name="FK" 를 가진다. 

JoinColumn의 이름은 productDetail 테이블에서 product를 컬럼으로 가져올때 가질 물리적 이름이다. 

productDetail 테이블에서 Product엔터티는 product_id 라는 FK로 가져가기 때문에 name="product_id"

관례상 보통 모든 엔터티의 PK(Id)는 [entityName]Id 가 아닌 "Id"로 동일하게 주더라도 

JPA에서 productDetail에 product는 product_id로 설정해준다. 

 

만약 ProductDetail에서 Product를, 혹은 Product에서 ProductDetail를 참조하여 ToString을 호출하면 

Product의 ToString은 product가 가진 ProductDetail을 ToString하다가 또 Product를 만나 Product를 ToString 하고 

순환참조하다 stackOverflow에 빠질 것이다. 

이를 막기 위해서 

@ToString.Exclude 어노테이션을 하면 ProductDetail에서 ToString 하는 과정에서 Product를 제외하고 ToString 하기 때문에 순환참조를 막을 수 있다. 

 

ProductDetail Save() 

ProductDetail(Owner Table)에서 save 할때 

productDetail이 가지는 product를 set 해주면 

알아서 product에도 product가 가지는 productDetail을 set해준다. 

Product product = Product.builder().name("name").price(1111).stock(111).build();

ProductDetail detail = ProductDetail.builder().description("des").build();

//연관관계설정

detail.setProduct(product);

productDetailRepository.save(detail);

 

>>> ProductDetail->ProductProduct(super=BaseEntity(createdAt=2023-10-11T18:01:41.229506, updatedAt=2023-10-11T18:01:41.229506), productId=2, name=name, price=1111, stock=111, productDetail=ProductDetail(super=BaseEntity(createdAt=2023-10-11T18:01:41.247503, updatedAt=2023-10-11T18:01:41.247503), productDetailId=1, description=des))

 

Product테이블 save 결과

 

ProductDetail 테이블 save 결과 

 

productDetail는 product를 가지기 때문에 productDetail에 product를 set 하여야 하고 

product는 그렇지 않아도 상관없다. 

productDetail의 product에 cascade persist가 적용되어 product도 함께 save 되었다. 

 

반면 

void productWithProductDetailSaveAndRead() {

 

ProductDetail productDetail=ProductDetail.builder().description("desc").build();

 

Product product=Product.builder().name("name").price(60000).stock(300).build();

/*

* 연관관계설정(OWNER테이블아닌경우)

* Product-->ProductDetail

*/

product.setProductDetail(productDetail);

productDetail.setProduct(product);

productRepository.save(product);

}

오너테이블이 아닌 product에서 product를 함께 save 하기 위해서는 

product는 productDetail을 set 해야하고 

productDetail은 product를 set 해야한다. 

 

만약 

product.setProductDetail(productDetail);

// productDetail.setProduct(product);

productRepository.save(product);

productDetail에 product를 set하지 않으면 

productDetail에 product_id가 null로 된 것을 확인할 수 있다. 

 

Provider와 Product는 1:N 관계이다. 

//1:n(owner table 아님)

@Builder.Default//초기값 주기

@OneToMany(mappedBy = "provider",cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)

private List<Product> products=new ArrayList<>();

Provider(One) Product(Many)이므로 

Provider의 Product는 컬렉션으로 가지고 OneToMany 어노테이션을 사용한다. 

provider는  ownerTable이 아니므로 mappedBy 속성을 부여한다. 

Builder.Default 값은 

Provider클래스의 List<Product>에 new ArrayList<>() 를 초기값을 추기 위해 붙여주는 어노테이션이다. 

 

fetch type이란

Jpa가 Entity를 조회할 때 연관관계에 있는 객체들을 전부 접근할지, 필요할때만 접근할지에 대한 설정이다. 

default는 최적화를 위해 Lazy이고 

연관 관계에 있는 Entity를 가져오지 않고, getter로 접근하는 경우만 가져온다. 

Eager는 항상 연관관계에 있는 Entity를 모두 가져온다. 

 

 

Product는 Provider를 

//n:1 Owner Table

@ManyToOne(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)//default : lazy

@JoinColumn(name="provider_id")

@ToString.Exclude

private Provider provider;

 

ManyToOne으로 매핑한다. 

 

 

Product product = Product.builder().name("name").price(10000).stock(100).build();

Product product2 = Product.builder().name("name2").price(20000).stock(200).build();

Product product3 = Product.builder().name("name3").price(30000).stock(300).build();

Provider provider = Provider.builder().name("name").build();

product.setProvider(provider);

product2.setProvider(provider);

product3.setProvider(provider);

List<Product> products = provider.getProducts();

products.add(product);

products.add(product2);

products.add(product3);

provider.setProducts(products);

 

providerRepository.save(provider);

product1,2,3, provider를 생성하고 

product들에 provider를 set하고 

Provider의 Products를 가져온다. 

Products는 초기값으로 new ArrayList<>()를 갖고 있다. 

Provider의 products에 product를 add 하고 setProducts 한 후 provider를 save한다. 

한 transaction 안에 (@Transactional)있다면 products.add(product1,2,3) 만 해주고 provider에 다시 setProducts 하지 않아도 context에서 확인하고 save 처리해준다. 

 

 

반대로 Product에서는 

Provider provider=Provider.builder()

.name("name")

.build();

 

Product product=Product.builder()

.name("name")

.price(10000)

.stock(100)

.build();

/***** 연관설정 Product-->Provider *****/

product.setProvider(provider);

productRepository.save(product);

product에  provider만 set해줘도 된다. 

 

 

category엔터티는 

@Column(unique = true,nullable = false)

private String code;

code 컬럼을 unique로 갖고 있다. 

@Column에 unique, nullable 속성을 추가해준다. 

 

@OneToMany(cascade = {CascadeType.ALL},orphanRemoval = true,mappedBy = "category",fetch = FetchType.EAGER)

@Builder.Default

private List<Product> products=new ArrayList<>();

 

orphanRemoval 속성은 자식 엔터티가 고아가 되면 삭제해주는 속성이다. 

이렇게 하면 

findCategory.getProducts().clear();

카테고리에서 product리스트를 지우면 카테고리에서 프로덕트를 갖지 않게되므로 쫓겨난 프로덕트는 고아가 된다. 

그럼 그 고아엔터티를 삭제해주어 product테이블에서도 삭제된다. 

 

'Java > Spring Boot' 카테고리의 다른 글

Thymeleaf Layout  (1) 2023.11.24
JPA 계층형 게시판  (0) 2023.10.10
Spring Data JPA begins  (0) 2023.10.06
Spring CRUD with RestAPI  (0) 2023.09.20
Spring addViewControllers  (0) 2023.09.14
728x90

properties 파일을 yaml 파일로 바꾸고 싶을 때 

https://mageddo.com/tools/yaml-converter

 

'Web' 카테고리의 다른 글

SPA(single page application) Handlebars 활용하기  (1) 2023.09.21
HTML5 Basic  (0) 2023.09.19
Mybatis Mapper  (0) 2023.09.19
MyBatis Config  (0) 2023.09.19
AJAX Asynchronous Javascript And XML  (0) 2023.09.18
728x90

public class Board {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

@SequenceGenerator(sequenceName = "board_boardno_seq", name = "board_boardno_seq")

private Long boardno;

private String title;

private String writer;

private String content;

@ColumnDefault("sysdate")

@CreationTimestamp

private LocalDateTime regdate;

private Long readcount;

private Long groupno;

private Long step;

private Long depth;

}

@UpdateTimestamp도 있어서 update시 regdate에 time을 넣어줄 수 있지만 

CreationTimestamp와 중복하여 사용할 수 없다. 

사용하려면 updatedate 필드를 만들어서 붙여야 한다. 

 

@ColumnDefault 어노테이션은 jpa에서 insert할 때는 무시한다. 

하지만 sql을 사용할때는 적용되기 때문에 붙여준다. 

 

Repository

 

List<Board> findByStepGreaterThanAndGroupno(Long step,Long groupNo);

List<Board> findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(Long boardNo);

//Page<Board> findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(Long boardNo,Pageable pageable);

 

 

new_save() 새글 작성하기

void new_save() {

Board board1= Board.builder()

.title("게시판101")

.content("내용101")

.writer("101")

.build();

Board savedBoard1 = boardRepository.save(board1);

savedBoard1.setGroupno(savedBoard1.getBoardno());

savedBoard1.setStep(1L);

savedBoard1.setDepth(0L);

savedBoard1.setReadcount(0L);

savedBoard1= boardRepository.save(savedBoard1);

System.out.println(">>>savedBoard1:"+savedBoard1);

 

 

답글 작성

void reply_save() {

Board findBoard100 = boardRepository.findById(100L).get();

 

List<Board> updateBoardList100 =

boardRepository.findByStepGreaterThanAndGroupno(findBoard100.getStep(), findBoard100.getGroupno());

for (Board tempBoard : updateBoardList100) {

tempBoard.setStep(tempBoard.getStep()+1);

}

boardRepository.saveAll(updateBoardList100);

 

Board board101=Board.builder()

.title("게시판타이틀101")

.content("내용101")

.writer("김경호101")

.groupno(findBoard100.getGroupno())

.step(findBoard100.getStep()+1)

.depth(findBoard100.getDepth()+1)

.readcount(0L)

.build();

boardRepository.save(board101);

 

그룹넘버가 같고 step이 더 큰 글(답글을 달려는 원글의 답글들 , 원글이 답글이 될 수도 있다)에 step을 증가시킴 

board101 글을 원글보다 step, depth를 증가시키고 save 

 

void board_select() {

List<Board> boardList = boardRepository.findAll();

for (Board board : boardList) {

System.out.println(board);

}

boardList = boardRepository.findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(0L);

for (Board board : boardList) {

System.out.println(board);

}

 

글 목록 전체 조회 

list를 groupno 내림차순, step 오름차순으로 정렬하여 select 

orderBy 할때 앞에 조건문이 필요하여 BoardnoGreaterThanEqual 추가해주고 0L인자로 준다. 

 

 

페이징 작업

void board_select_page() {

List<Board> boardList=boardRepository.findAll();

System.out.println(">>>boardList:"+boardList.size());

 

int currentPage=14; //현재페이지

int size=7; //페이지당게시물수

 

Pageable pageable=PageRequest.of(currentPage-1,

size,

Sort.by("groupno").descending()

.and(Sort.by("step").ascending())

);

/*

PageRequest.of(page, size)

- page zero-based page index.(요청페이지)

- size the size of the page to be returned.(페이지당 게시물 수)

*/

Page<Board> page = boardRepository.findAll(pageable);

for (Board board : page.getContent()) {

System.out.println(board);

}

}

Pageable 인터페이스

 

  1. pageNumber: 페이지 번호를 나타냅니다. 0부터 시작하며 첫 번째 페이지는 0입니다. 이 속성은 몇 번째 페이지를 가져올지를 결정합니다.
  2. pageSize: 한 페이지에 표시될 항목 수를 나타냅니다. 예를 들어, 페이지당 10개의 항목을 표시하려면 pageSize를 10으로 설정합니다.
  3. offset: 페이지의 시작 항목의 오프셋입니다. 이것은 pageNumber * pageSize의 값과 같습니다. 데이터베이스 쿼리를 작성할 때 특정 페이지의 데이터를 가져오는 데 사용됩니다.
  4. sort: 페이지의 항목을 정렬하는 데 사용됩니다. Sort 타입의 객체로 정렬 방법과 정렬할 필드를 지정할 수 있습니다. 다음은 Sort를 사용하는 예입니다.이것은 "fieldName" 필드를 오름차순으로 정렬하는 방법을 나타냅니다.
    Sort sort = Sort.by(Sort.Order.asc("fieldName"));
  5. unpaged(): 페이지네이션을 사용하지 않고 모든 데이터를 한 번에 가져오도록 지정합니다. 주로 모든 데이터를 가져올 때 사용됩니다.
  6. next(): 다음 페이지로 이동하는 Pageable 객체를 생성합니다.
  7. previousOrFirst(): 이전 페이지로 이동하거나 첫 번째 페이지로 이동하는 Pageable 객체를 생성합니다.
  8. first(): 첫 번째 페이지로 이동하는 Pageable 객체를 생성합니다.
  9. hasNext(): 다음 페이지가 있는지 확인합니다.
  10. getSort(): 현재 페이지에 적용된 정렬 정보를 가져옵니다.

 

 

Pageable 인터페이스는 데이터베이스 조회 결과를 정렬하고 페이지를 나누고 그 페이징 관련 정보를 담고 있다. 

Pageable pageable=PageRequest.of(currentPage-1,

size,

Sort.by("groupno").descending()

.and(Sort.by("step").ascending())

);

PageRequest의 of (page,size)메서드를 사용하면 페이지를 전체 리스트를 size로 나누어 페이징했을 때 구한 page의 paging 정보를 Pageable 인터페이스로 반환해준다.

 

추가로 page,size, Sort(정렬)을 대입할 수도 있다. 

Sort.by("groupno").descending().and(Sort.by("step").ascending())

 

 

findAll 메서드에 Pageable을 인자로 대입하면 해당 Pageable의 Page를 반환해주고 

Page의 getContent 하여 리스트를 얻을 수 있다. 

반대로 Page에서 getPageable 을 하면 Pageable을 얻을 수 있다. 

 

 

  1. getContent(): 페이지에 포함된 데이터 항목들을 반환합니다. 이 메서드를 통해 현재 페이지의 데이터를 가져올 수 있습니다.
  2. getNumber(): 현재 페이지 번호를 반환합니다. 페이지 번호는 0부터 시작합니다.
  3. getSize(): 페이지 크기(한 페이지 당 항목 수)를 반환합니다.
  4. getTotalPages(): 전체 페이지 수를 반환합니다.
  5. getTotalElements(): 전체 항목 수를 반환합니다. 이는 모든 페이지를 합친 총 데이터 항목 수입니다.
  6. hasContent(): 페이지에 데이터가 포함되어 있는지 여부를 확인합니다.
  7. hasNext(): 다음 페이지가 있는지 여부를 확인합니다.
  8. hasPrevious(): 이전 페이지가 있는지 여부를 확인합니다.
  9. isFirst(): 현재 페이지가 첫 번째 페이지인지 여부를 확인합니다.
  10. isLast(): 현재 페이지가 마지막 페이지인지 여부를 확인합니다.
  11. nextPageable(): 다음 페이지로 이동하는 데 필요한 Pageable 객체를 반환합니다.
  12. previousPageable(): 이전 페이지로 이동하는 데 필요한 Pageable 객체를 반환합니다.

'Java > Spring Boot' 카테고리의 다른 글

Thymeleaf Layout  (1) 2023.11.24
JPA Object Relation Mapping  (0) 2023.10.11
Spring Data JPA begins  (0) 2023.10.06
Spring CRUD with RestAPI  (0) 2023.09.20
Spring addViewControllers  (0) 2023.09.14
728x90

EC2 (Elastic Computer Cloud) : 애플리케이션을 실행할 수 있는 서버 컴퓨터라고 생각하면 된다. 

                  우리는 EC2로 서버를 실행시키고 클라이언트가 애플리케이션을 실행하려면 EC2의 IP나 EC2에서 제공하는                      퍼블릭 도메인으로 애플리케이션에 접근할 수 있다.

DNS (Domain Name System) : IP 주소는 사람들이 기억하고 사용하기 어렵기 때문에 IP를 대신할 수 있는 이름인                                Domain(도메인)을 IP 주소와 맵핑시켜놓아 Domain을 입력하면 해당하는 IP 주소를 찾아 그 주소의

                  애플리케이 션에 접근하게 해주는 시스템 

 

Route 53 : 우리 컴퓨터는 IP 말고도 DNS서버 IP도 가지고 있다. 

                  DNS 서버 IP는 IP 제공자인 ISP(Internet Service Provider, SKT, KT, ..텔레콤 ) 인터넷 서비스 제공 회사에서

                  제공한다.  ISP의 DNS 서버에 우리가 원하는 IP 주소가 없으면 다른 DNS 서버에서 우리가 원하는

                  IP 주소를 찾아준다. 그러한 DNS 서버 중 하나가 Route 53

Application Load Balancer : 트레픽이 증가하여 새로운 EC2 인스턴스를 만들어 서버를 증설한 경우, IP가 다르기 때문에                      새로 만든 EC2 인스턴스는 여전히 접근할 수 없다. 애플리케이션 로드 밸런서는 EC2 인스턴스들을 연결하여 

                  트레픽을 적절히 분배해준다.  EC2 인스턴스들이 공유하는 가상의 IP를 만들어 Route 53에 등록하고

                  Route 53은 도메인을 검색할 때 이 가상의 IP를 반환해준다. 

 

Target Group : 애플리케이션 로드 밸런서에 연결된 EC2 인스턴스들을 말한다. 

 

AutoScaliing Group (ASG,오토 스케일링 그룹) : ASG는  인스턴스가 다운되었을 때 EC2를 실행하고 타깃 그룹에 올리고                      서비스 상태를 확인하는 작업을 자동으로 해주고 트래픽에 따라 스케일인(ScaleIn), 스케일아웃(ScaleOut)

                  하여 서버를 증설하거나 수축하는 등 타켓 그룹의 인스턴스를 관리하는 역할을 한다.

                  최소, 최대, 적정 인스턴스 수를 정하여 관리할 수 있다.

 

VPC (Virtual Private Cloud, 가상 사설 클라우드) : 사용자의 AWS 계정 전용 가상 네트워크, 특별한 설정 없이는 네트워크                   안에 생성되는 EC2 외부(인터넷, 다른 AWS 계정)에서 접근할 수 없는 독립된 가상의 네트워크로 계정의

                 주인만이 네트워크에 접근 하는하다. 

 

Subnet (서브-네트워크) : VPC 내에 존재하는 여러 개로 쪼개진 네트워크로 서브넷 내에 EC2 서버를 생성한다. 

Elastic Bean Stalk (일래스틱 빈스톡) : 배포를 위한 인프라 구축을 대신 해주는 서비스로,

                  사용자가 필요한 리소스를 알려주면 일래스틱 빈스톡이 로드 밸런서, 오토 스케일링 그룹,

                  RDS(데이터베이스), EC2 환경을 구축하고 EC2에 우리 애플리케이션을 실행시켜준다. 

                  내부적으로 JSON, YML 파일을 인풋으로 받아 설정파일의 리소스와 리소스 관계를 읽어 인프라를 구축해주는                    AWS 클라우드포메이션(CloudFormation) 서비스를 이용한다.(Infrastructure as Code,코드를 읽어 인프라구축)

 

 

 

728x90

프로그레스 배열이 주어지고 진행 속도 배열이 주어진다. 

프로그레스가 100이 되면 배포할 수 있는데 , 순서에 따라 배포할 수 있기 때문에 

앞의 프로그레스가 100이 되지 않으면 뒤의 프로그레스는 100이 되어보 배포될 수 없다. 

그래서 앞에서부터 순서대로 기능이 완성되어 배포할 때 한번에 여러개가 동시에 배포될 수 있다. 

매번 배포할 때마다 몇개의 완성된 기능이 배포되는지 반환 

 

일단 하루가 지나면 프로그레스의 모든 기능들은 스피드만큼 프로그레스가 증가한다. 

그리고 매일 프로그레스가 100이 넘었는지 확인해주고 넘었으면 다음 프로그레스도 함께 확인하고 

다음 프로그레스가 100이 아닌 것을 확인했을 때, 그때까지 100이 넘어 배포해야할 프로그레스의 개수를 list에 넣는다. 

 

for (int i = 0; i < speeds.length; i++) {

progresses[i] += speeds[i];

}

매일 모든 프로그레스가 스피드만큼 증가

 

if (progresses[j] >= 100) {

count++;

continue;

}

프로그레스가 100이 넘었는지 확인하고 넘었으면 배포할 개수 count를 증가시키고 다음 프로그레스도 확인한다. 

 

카운트가 0 이 아니라면 ( 배포해야할 순서의 프로그레스가 100이 넘었다면 ) list에 count를 추가하고 다시 카운트를 0으로 초기화한다. 

if (count != 0) {

answer.add(count);

count = 0;

}

 

 

 

전체풀이

public ArrayList<Integer> solution(int[] progresses, int[] speeds) {

ArrayList<Integer> answer = new ArrayList<Integer>();

int count = 0;

for (int j = 0; j < progresses.length; j++) {

if (progresses[j] >= 100) {

count++;

continue;

} else {

j--;

for (int i = 0; i < speeds.length; i++) {

progresses[i] += speeds[i];

}

}

if (count != 0) {

answer.add(count);

count = 0;

}

}

if (count != 0) {

answer.add(count);

}

return answer;

}

j를 감소시키는 이유는 프로그레스가 100이 넘지 않았는데 다음 프로그레스를 확인하면 안되기 때문에 다시 j를 감소시키고 하루가 지났다 가정하고 모든 프로그레스를 스피드만큼 증가시키고 재확인할 수 있게 해준다. 

 

마지막 남은 프로그레스가 100이 되면 count를 증가시킨 후  continue로 빠져나와 list에 추가하지 못하기 때문에 

for문을 빠져나온 후 한번더 list에 추가해준다. 

 

 

'Java > Coding Test' 카테고리의 다른 글

카펫 문제 풀이  (0) 2023.10.06
올바른 괄호 문제 풀이  (1) 2023.10.05
크레인 인형뽑기 게임 문제 풀이  (0) 2023.10.04
로또의 최고 순위와 최저 순위 문제 풀이  (0) 2023.10.04
다트 게임 문제 풀이  (0) 2023.10.04
728x90

배열 : 같은 데이터타입을 가진 저장소

- 배열은 객체이고 배열형의 변수는 저장소의 참조변수를 가진다.

- 배열은 같은 타입만 정의가 가능하다. 여러 타입의 데이터를 하나의 배열에 넣을 수 없다. 

- 배열의 길이는 고정되어있다. 

 

배열객체 변수의 선언 

Type[] identifier;

Type identifier[];

int[] intArray;

int intArray[];

배열객체의 초기화 

intArray = new int[5];

intArray[0] = 80;

intArray = new int[] {1,2,3,4,5};

객체를 원소로 가지는 배열의 초기화 

Account acc1 = new Account(1111, "LEE", 5600, 0.8);

Account[] accounts = {acc1,

new Account(2222, "KIM", 568000, 3.5),

new Account(3333, "PARK", 965000, 6.9)

};

 

 

배열 객체를 생성하면 초기값이 주어진다.

intArray  = new int[5];

// new int[5] 로 생성함과 동시에 intArray[0] ~intArray[4]까지 각 원소는 모두 0 으로 초기화된다.

정수형은 0

실수형은 0.0

논리형은 false

문자형은 공백

Object는 null로 초기화한다.

 

배열객체는 다음과 같은 멤버를 가지고 있으며 

length 변수를 통해 배열의 길이를 알아낼 수 있다.

배열의 활용

반복문 

for (int i = 0; i < rankArray.length; i++) {

totArray[i]=korArray[i]+engArray[i]+mathArray[i];

avgArray[i]=totArray[i]/3.0;

if(avgArray[i]>=90)

gradeArray[i]='A';

else if(avgArray[i]>=80)

gradeArray[i]='B';

else if(avgArray[i]>=70)

gradeArray[i]='C';

else if(avgArray[i]>=60)

gradeArray[i]='D';

}

+ Recent posts