Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step 6 #8

Open
wants to merge 10 commits into
base: jinny-codes
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Deploy to Amazon EC2

on:
push:
branches:
- master
env:
AWS_REGION: us-east-2
S3_BUCKET_NAME: mypoolcbucket
CODE_DEPLOY_APPLICATION_NAME: poolc-reborn
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: poolc-codedeploy-deployment-group

permissions:
contents: read

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production

steps:

- name: Checkout
uses: actions/checkout@v3


- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'


- name: Build with Gradle
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
with:
arguments: clean build -x test


- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}


- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
--source .


- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
37 changes: 13 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
# PoolC-Spring-Practice

풀씨 백엔드와 유사하지만, 일부 기능들을 개선한 서버를 만들어봅시다. 물론 풀씨 페이지는 규모가 상당히 크기에, 모든 컴포넌트를 만들 수 없으니 기본적인 것들만 구현해 봅시다.
풀씨 (동아리) 서버와 유사하지만 주요기능에 집중하여 개선한 서버 사이드 프로젝트입니다.

진행 방식
---
- Spring 프로그래밍 연습 스터디는, 하나의 큰 과제를 수행해야 합니다.
- Java 스터디에 비해 자유도가 조금 높으며, 요구 사항이 다소 추상적입니다.
- 직접적인 main 브랜치로의 커밋은 금지 되며, 반드시 Step 수행 이후 Pull Request 요청을 통해 확인이 진행됩니다.
- 본인의 닉네임/이름에 해당하는 브랜치를 만들고, 각 Step 에 대한 브랜치를 만들어서 PR을 진행해 주세요.
- ex) KBC 브랜치를 만들고, Step 1에 대한 결과물은 KBC-step1 로 만들어 주세요.
- 그 이후, PR은 KBC-step1 -> KBC 꼴로 요청해 주세요.
- 각 커밋의 단위는 최소화 해야하며, 다음과 같은 커밋 메시지 양식을 준수해 주세요.
- https://vsfe.notion.site/Git-Convention-84e1df4868974a58a1609b052e815095
### 주요 기능 목록
- 회원가입, 로그인 및 회원수정
- 유저 등급 분리 및 관리
- 동아리 회원 확인 기능
- 세미나 등록, 신청, 수정 기능
- Naver API를 사용하거나 직접 입력으로 책 등록, 책 대출 및 반납 기능
- AWS를 이용한 CI/CD 프로세스 구축
- Github Action을 이용한 Pre-hook, Post-hook

요구 사항 (공통)
---
- 해당 과제는 여러 Step으로 구성되어 있으며, 앞 Step에 대한 PR 및 리뷰가 완료 되어야 뒤 Step을 진행할 수 있습니다.
- 포함된 라이브러리는 기본적인 라이브러리만 포함되어 있으며, 필요에 따라 추가 라이브러리를 사용해도 됩니다.
- 모든 Java 코드는 반드시 Java 코드 컨벤션 가이드를 준수해야 합니다.
- 작성한 메서드에 대한 테스트 코드 작성이 진행되어야 합니다.
- Jacoco 기준, Test Coverage 및 Branch Coverage가 80% 이상이어야 합니다.
- 통합 테스트/단위 테스트 여부는 자유롭게 설정하셔도 됩니다.
- 하지만, 통합 테스트 수행 시, 실제 DB에 전혀 영향이 가지 않아야 합니다.
- 사용하는 DB는 제한이 없습니다.
### 사용 기술

요구 사항 (단계)
---
- 특정 Step 을 마치지 못했다면, 그 다음 Step의 요구 사항을 보지 않는 것을 권장합니다. https://vsfe.notion.site/Spring-PoolC-Backend-Reborn-281c69c2eaf543459fedace987868ea4
- Spring Boot
- MySQL
- AWS 배포
23 changes: 23 additions & 0 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
version: 0.0
os: linux

files:
- source: /
destination: /home/ubuntu/app
overwrite: yes

permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu

hooks:
AfterInstall:
- location: scripts/stop.sh
timeout: 60
runas: ubuntu
ApplicationStart:
- location: scripts/start.sh
timeout: 60
runas: ubuntu
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ dependencies {
tasks.named('test') {
useJUnitPlatform()
}
jar {
enabled = false
}
21 changes: 21 additions & 0 deletions scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
19 changes: 19 additions & 0 deletions scripts/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"

DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)

# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
fi
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ public ApiSearchRequest(String query, NaverApiInvokerCommand command) {
this.query = query;
this.command = command;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ private RequestEntity.HeadersBuilder<?> buildRequest(HttpMethod method, URI uri)
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,28 @@ public class User {
@IncludeCharInt
private String username;

@NotEmpty(message = "암호는 필수 입력 항목입니다.")
@NotBlank(message = "암호는 필수 입력 항목입니다.")
@Size(min = 8)
private String password;

@NotBlank(message = "이름은 필수 입력 항목입니다.")
private String name;

@Email
@NotEmpty(message = "이메일은 필수 입력 항목입니다.")
@NotBlank(message = "이메일은 필수 입력 항목입니다.")
private String email;

@NotEmpty(message = "전화번호 필수 입력 항목입니다.")
@NotBlank(message = "전화번호 필수 입력 항목입니다.")
@Pattern(regexp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
private String mobileNumber;

@NotEmpty(message = "전공은 필수 입력 항목입니다.")
@NotBlank(message = "전공은 필수 입력 항목입니다.")
private String major;

@NotNull(message = "학번은 필수 입력 항목입니다.")
private int studentId;

@NotEmpty(message = "자기소개는 필수 입력 항목입니다.")
@NotBlank(message = "자기소개는 필수 입력 항목입니다.")
private String description;

@Enumerated(EnumType.STRING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,4 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

return http.build();
}


}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.poolc.springproject.poolcreborn.service;

import com.poolc.springproject.poolcreborn.api.NaverApiInvoker;
import com.poolc.springproject.poolcreborn.api.NaverApiInvokerCommand;
import com.poolc.springproject.poolcreborn.exception.InvalidRequestException;
import com.poolc.springproject.poolcreborn.exception.InvalidStateException;
import com.poolc.springproject.poolcreborn.model.book.Book;
Expand Down Expand Up @@ -35,7 +34,7 @@ public class BookService {
private final UserRepository userRepository;
public void saveBook(BookRequest bookRequest, String username) throws InvalidRequestException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new InvalidRequestException(Message.USER_DOES_NOT_EXIST));
.orElseThrow(() -> new InvalidRequestException(Message.USER_DOES_NOT_EXIST));

if (user != null && user.isAdmin() && !bookRepository.existsByIsbn(bookRequest.getIsbn())) {
Book book = new Book();
Expand Down Expand Up @@ -89,7 +88,7 @@ public void returnBook(Long currentBookId, String username) throws Exception {
}
}

public void registerNaverBook(ApiSearchRequest searchRequest, Long bookId) throws Exception{
public void registerNaverBook(ApiSearchRequest searchRequest, Long bookId) throws Exception {
List<BookDto> bookDtoList = bookSearch(searchRequest);
BookDto bookDto = bookDtoList.get(bookId.intValue());
Book book = bookMapper.buildBookFromBookDto(bookDto);
Expand All @@ -113,4 +112,4 @@ public List<BookDto> bookSearch(ApiSearchRequest searchRequest) throws InvalidRe
ResponseEntity<String> result = invoker.naverBookSearchApi();
return fromJSONtoBookDtoList(result.getBody());
}
}
}