s3 설정

application.yml

cloud:
  aws:
    s3:
      bucket: bucketname
    region:
      static: ap-northeast-2
    stack:
      auto: false
    credentials:
      access-key: accessKey
      secret-key: secretKey

 

S3Buckets.java

@Configuration
@ConfigurationProperties(prefix = "aws.s3.buckets")
public class S3Buckets {

    private String airbnb;


    public String getAirbnb() {
        return airbnb;
    }

    public void setAirbnb(String airbnb) {
        this.airbnb = airbnb;
    }
}

 

@Configuration
public class S3Config {

    @Value("${cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secret-key}")
    private String secretKey;

    @Value("${cloud.aws.region.static}")
    private String region;


    @Bean
    public S3Client s3Client(){
        S3Client client = S3Client.builder()
                .region(Region.AP_NORTHEAST_2)
                .build();

        return client;
    }

    @Bean
    public AmazonS3Client amazonS3Client(){
        BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder
                .standard()
               .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
                .withRegion(region)
                .build();
    }

 

@Service
@RequiredArgsConstructor
public class S3Service {

    private final S3Client s3Client;
    
    public void putObject(String bucketName,String key, byte[] file){

        PutObjectRequest objectRequest = PutObjectRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();

      s3Client.putObject(objectRequest, RequestBody.fromBytes(file));

    }

 

 

이미지 저장

저장 경로는 버킷네임 / listing-image / 유저아이디 / UUID_filename  로 설정하였습니다

public Set<String> saveListingImage(List<MultipartFile> files,Integer account_id) {
    Set<String> fileNameList = new HashSet<>();
        files.forEach(file -> {
            try {
                String profileImageId = UUID.randomUUID().toString()+"_"+file.getOriginalFilename();
                s3Service.putObject(s3Buckets.getAirbnb(),
                        "listing-images/%s/listing/%s".formatted(account_id,profileImageId),
                        file.getBytes());
                fileNameList.add(profileImageId);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        });
        return fileNameList;
}

 

이미지 url 불러오기

public List<String> getListingImages(Integer listing_id, Integer account_id) {
    Listing listing = listingRepository.findListingWithImagesById(listing_id).orElseThrow();
    List<String> fileNameList = new ArrayList<>();
    listing.getImages().stream().map(image->{
        String url = amazonS3Client.getUrl(s3Buckets.getAirbnb(),
                "listing-images/%s/listing/%s".formatted(account_id,image)).toString();
      return  fileNameList.add(url);
    });
    return fileNameList;

 

 

aws s3

controller

ListingController.java

service

ListingService.java

 

repository 

Querydsl

private JPQLQuery<Listing> listingListFetchJoin(){
   return from(listing).distinct()
            .innerJoin(account).on(listing.host.eq(account))
            .leftJoin(reservation).on(reservation.listing.eq(listing))
            .leftJoin(category).fetchJoin()
            .leftJoin(listing.reviews, review).fetchJoin()
            .orderBy(listing.id.desc())
            .select(listing);
}
@Override
public Page<Listing> listingListPage(ListingSearchCondition condition, Category category, Pageable pageable) {
    QueryResults<Listing> listingQueryResults = listingListFetchJoin().where(
            locationEq(condition.getLocationValue()),
            dateEq(condition.getStartDate(), condition.getEndDate()),
            categoryEq(category)
    ).offset(pageable.getOffset()).limit(pageable.getPageSize()).fetchResults();
    List<Listing> results = listingQueryResults.getResults();
    long total = listingQueryResults.getTotal();
    return new PageImpl<>(results,pageable,total);
}

조건 지역, 카테고리, 날짜

private BooleanExpression locationEq(String locationValue){
    return hasText(locationValue) ? listing.map.location.eq(locationValue) : null;
}

private BooleanExpression categoryEq(Category category){
    if(category != null){
        return  listing.categories.any().in(category);
    }
    return null;
}
private BooleanExpression dateEq(LocalDate startDate ,LocalDate endDate){
    if(startDate != null && endDate != null){
       return listing.startDate.lt(startDate).and(listing.endDate.gt(endDate));
    }
    return null;
}

 

 

 

react-query

useInfiniteQuery 무한 스크롤

src/pages/listing/ListingPage.jsx

  const {
    status,
    data: listings,
    error,
    isFetching,
    isFetchingNextPage,
    isFetchingPreviousPage,
    fetchNextPage,
    fetchPreviousPage,
    hasNextPage,
    hasPreviousPage,
  } = useInfiniteQuery(
    ["listings", url],
    async ({ pageParam = 1 }) => await getAllListing(token, url, pageParam),
    {
      getNextPageParam: (lastPage, pages) =>
        !lastPage.last ? lastPage.number + 2 : null ?? undefined,
    }
  );
  

 

 

src/pages/utils/request.jsx

axios라이브러리 사용, axios create함수에 baseUrl 만들어 사용

const newRequest = axios.create({
  baseURL: "http://localhost:8081/api/v1",

});

export const getAllListing = async (token, url, pageParam) => {
  const response = await newRequest.get(`/listing?page=${pageParam}${url}`, {
    headers: { Authorization: `Bearer ${token}` },
  });
  return response.data;
};

 

 

 

 

 

깃허브 -> ansible서버 war 저장-> Ansible playbook  사용하여 컨테이너 생성

 

 

빌드 후 조치

 

 

 

Dockerfile

FROM tomcat:9.0

COPY ./hello-world.war /usr/local/tomcat/webapps

 

예제1.

이미지 생성

devops-playbook1.yml

- hosts: all
#   become: true  

  tasks:
  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args: 
        chdir: /root

 

예제2.

이미지 생성

컨테이너 생성

devops-playbook2.yml

- hosts: all
#   become: true  

  tasks:
  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args: 
        chdir: /root

  - name: create a container using cicd-project-ansible image
    command: docker run -d --name my_cicd_project -p 8081:8080 cicd-project-ansible

 

예제3.

기존 이미지 컨테이너 삭제 

이미지 생성

컨테이너 생성

devops-playbook3.yml


- hosts: all
#   become: true  

  tasks:
  - name: stop current running container
    command: docker stop my_cicd_project
    ignore_errors: yes

  - name: remove stopped cotainer
    command: docker rm my_cicd_project
    ignore_errors: yes

  - name: remove current docker image
    command: docker rmi cicd-project-ansible
    ignore_errors: yes

  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args: 
        chdir: /root

  - name: create a container using cicd-project-ansible image
    command: docker run -d --name my_cicd_project -p 8081:8080 cicd-project-ansible

+ Recent posts