From 21c9fa9054b2278ab12e70d293543811dcd0bf3a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 9 Jan 2024 20:33:40 +0900 Subject: [PATCH 1/2] Revert "Merge pull request #19 from Sehee-Lee-01/feat#11-codestyle" This reverts commit 4e8c97167d935560aaa1daeef6f940fa9fc806cf, reversing changes made to ccb1ab62cf20a22454236bdbaa6c2ffe14a006fe. --- .idea/codeStyles/Project.xml | 58 --- .idea/codeStyles/codeStyleConfig.xml | 5 - build.gradle | 11 +- config/checkstyle/checkstyle.xml | 365 ------------------ config/checkstyle/configuration_1_3.dtd | 54 --- config/checkstyle/suppressions.xml | 8 - config/checkstyle/suppressions_1_2.dtd | 16 - .../com/backendoori/ootw/OotwApplication.java | 6 +- .../backendoori/ootw/domain/BaseEntity.java | 2 +- 9 files changed, 5 insertions(+), 520 deletions(-) delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 config/checkstyle/checkstyle.xml delete mode 100644 config/checkstyle/configuration_1_3.dtd delete mode 100644 config/checkstyle/suppressions.xml delete mode 100644 config/checkstyle/suppressions_1_2.dtd diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 4d5fd611..00000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index d0bbb07d..5d9d90df 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,6 @@ plugins { id 'io.spring.dependency-management' version '1.1.4' id 'java' id 'jacoco' - id 'checkstyle' } group = 'com.backendoori' @@ -83,14 +82,6 @@ jacocoTestCoverageVerification { } } } - dependsOn jacocoTestReport -} -checkstyle { - toolVersion = "10.12.5" - configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") - configProperties = [ - "org.checkstyle.google.suppressionfilter.config" : "suppressions.xml", - "org.checkstyle.google.suppressionxpathfilter.config": "suppressions.xml" - ] + dependsOn jacocoTestReport } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml deleted file mode 100644 index 2dcd740e..00000000 --- a/config/checkstyle/checkstyle.xml +++ /dev/null @@ -1,365 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/checkstyle/configuration_1_3.dtd b/config/checkstyle/configuration_1_3.dtd deleted file mode 100644 index 40771d17..00000000 --- a/config/checkstyle/configuration_1_3.dtd +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml deleted file mode 100644 index 27e6779f..00000000 --- a/config/checkstyle/suppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/config/checkstyle/suppressions_1_2.dtd b/config/checkstyle/suppressions_1_2.dtd deleted file mode 100644 index 6fe68c90..00000000 --- a/config/checkstyle/suppressions_1_2.dtd +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - diff --git a/src/main/java/com/backendoori/ootw/OotwApplication.java b/src/main/java/com/backendoori/ootw/OotwApplication.java index d781021c..e29ef933 100644 --- a/src/main/java/com/backendoori/ootw/OotwApplication.java +++ b/src/main/java/com/backendoori/ootw/OotwApplication.java @@ -6,8 +6,8 @@ @SpringBootApplication public class OotwApplication { - public static void main(String[] args) { - SpringApplication.run(OotwApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(OotwApplication.class, args); + } } diff --git a/src/main/java/com/backendoori/ootw/domain/BaseEntity.java b/src/main/java/com/backendoori/ootw/domain/BaseEntity.java index 08e56e7a..442577b7 100644 --- a/src/main/java/com/backendoori/ootw/domain/BaseEntity.java +++ b/src/main/java/com/backendoori/ootw/domain/BaseEntity.java @@ -1,8 +1,8 @@ package com.backendoori.ootw.domain; -import java.time.LocalDateTime; import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import java.time.LocalDateTime; import lombok.Getter; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; From 04f36186438d3e1fbb90e9f9803ca7cb61866db3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 19 Jan 2024 09:51:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=201?= =?UTF-8?q?=EC=B0=A8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/README.md b/README.md index 5fc2c69d..8517dc14 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,194 @@ # outfit-of-the-weather [#OOTW] 그날의 날씨를 보고 오늘의 코디를 공유하는 커뮤니티 By 빽엔두리 + +### 클론 타겟 + +- [꾸온꾸](https://korean.visitkorea.or.kr/detail/rem_detail.do?cotid=14a13909-134a-4a0e-a581-fc1ace95d925) +- 현재 날씨를 확인하고 날씨에 맞춰 아바타를 코디한 후 전국의 여행지를 배경으로 사진을 찍어 업로드하는 게시판 +- 레퍼런스 이미지 + +![스크린샷 2024-01-16 오후 3.17.30.png](https://prod-files-secure.s3.us-west-2.amazonaws.com/a557051f-c7ef-49b4-83dc-fbd1373d5693/6cef6311-6a06-48cd-9643-c1a131869bec/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-01-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_3.17.30.png) + +### 개발 목표 + +- 현재의 날씨를 보고 그에 맞는 아바타 코디를 선택해 이미지를 저장할 수 있고 저장한 이미지를 공유할 수 있는 게시판을 만드는 것을 1차 프로젝트 mvp로 삼고 진행 +- 이후 프로젝트 고도화에 따라 여러 기능을 추가적으로 구현 예정 +- 최종적으로 해당 콘텐츠를 메인으로 아바타 아이템 상거래가 가능한 커머스 시스템 도입을 목표로 진행 예정 + +
+moscow + +- Must Have: 날씨 API 기반 게시글, 사용자 인증, 이미지 서비스 +- Should Have: 댓글, 무한 스크롤, 사용자 인증/인가, 소셜 로그인, 좋아요, 해시태그, 히스토리 +- Could Have: 검색, 서비스 구독, 사용자 권한, 사용자 인증/인가 +- Won't Have: 게시글 북마크, 알림, 이메일, 아바타 아이템 커머스, 통합회원, 휴대폰 인증 + +
+ +### 기술 스택 + +- java 17 +- springboot 3.2.0 +- spring security +- jsonwebtoken jjwt 0.12.3 +- openfeign 4.1.0 +- spring data jpa +- spring data redis +- spring mail +- green mail +- minio 8.5.7 + +### 팀 역할(SM, PO, Dev) + + + + + + + + + + + + + + + + + +
SMPODev
이세희이중원김현우
+ + + + + +
+ +1. 그라운드 룰 + - **트러블 슈팅** 경험은 **2주 내**에 기록하고 공유 + - [Git Wiki](https://github.com/spring-comes-to-us/outfit-of-the-weather/wiki)에 작성 + - **가독성**을 중요하게 생각하여 코드 작성. + - 서로의 지식을 **공유**하고 코드와 의견을 **존중**하자 +2. 스크럼 규칙 + + | 진행 시간 | 내용 | + | --- | --- | + | 매일 오전 9시, 15~30분
(QR 찍고 진행) | - 어제 한 일(전날 커밋 기록) 공유
- 오늘 할 일(체크 리스트) 공유 | + | 금요일 오전 9시
(QR 찍자마자 진행) | - 스프린트(1주) 회고, 피드백 | +3. 트러블 슈팅 +4. 프로젝트 관리 + +## 주요 기능 + +### 유저 기능 + +- 회원가입 + - Email 검증 + - [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322#section-3.4.1)기준의 정규 표현식 검증 + - 최대 길이 255 + - Password 검증 + - 최소 한 개 이상의 영문자, 숫자, 특수문자가 각각 필요 + - 최소 길이 8, 최대 길이 30 + - DTO에서`@Password`커스텀 어노테이션 기반으로 진행 + - Entity 생성자를 통한 2차 검증 +- 인증 코드 발송 + - 회원가입 시 회원가입한 Email로 인증 코드 날리는 시스템 도입 (재전송 가능) + - Spring `MailSender`로 회원 가입자 이메일로 회원 가입 인증 코드 전송 + - mail을 보내는 메서드는 `@Async`를 이용하여 비동기 처리 + - 회원 정보를 저장하되 회원 인증 여부(`certified`)를 `false`로 저장하고 `true`가 될 때까지 로그인 서비스를 이용할 수 없게 설정 + - `GreenMail` 라이브러리를 통한 인증 코드 전송 테스트 진행 +- 회원가입 코드 인증 + - 가입한 이메일과 코드를 body에 담아 회원 가입 인증 진행 + - 회원 테이블의 `certified` column을 `true`로 변경하고 로그인 하여 사용할 수 있게 만듬 + - 인증 코드를 `Redis`에서 관리 + - Redis TTL 설정으로 10분이 지난 인증 코드는 만료 처리 +- 로그인 + - jwtToken 기반의 인증 시스템 도입 + - 로그인 정보를 받은 후 유저 검증 후 `TokenProvider`를 통해 토큰 발급 및 검증 + - 토큰 프로세스는 `jsonwebtoken jjwt` 라이브러리를 활용 +- Token 인증 필터 + - SecurityFilter 내부에 `JwtAuthenticationFilter`를 추가 + - `JwtAuthenticationFilter`에서 로그인 시 사용한 토큰을 파싱 후 `userId`를 기반으로 `UsernameAuthenticationToken`을 생성 + 후 `SecurityContext`에 저장 + - 로그인이 필요한 API에서 `Authentication` 객체를 받거나 직접 `principal`을 호출하는 메서드로 user 정보 호출 + +### 현재 날씨 조회 기능 + +- 기상청 OpenAPI 호출 + - `OpenFeign`을 이용하여 기상청 API를 호출 + - 기상청 API 응답 중 현재 날씨 정보(현재 기온, 강수 형태, 하늘 상태) 정보 조회 + - 복잡한 OpenAPI 응답을 처리하기 위해 `@JsonDeserialize` 를 이용하여 API 응답 비직렬화 구현 + - 요청이 제한된 기상청 API를 반복적으로 호출하는 문제 상황 + - 추후 날씨 요청 위치를 Enum(시.도.동 등)으로 관리하고 Redis 기능을 이용하여 캐싱 기능 추가하여 외부 API 중복 호출을 줄일 예정 +- `Coordinate` 클래스 유효성 검사 + - `@Grid` 커스텀 어노테이션 기반으로 Controller에서 유효성 검사 진행 + +### 게시판 기능 + +- 게시판 CRUD 기능 작성 + - 로그인 여부에 따라 보여주는 정보 분기문 작성 + - jmeter 부하 테스트 중 게시글 목록 조회 성능이 가장 안 좋은 것을 확인 + - 추후 조회 성능을 더 분석해보고 개선 예정 + - 목록 조회는 필터 조회 기능을 추가할 예정 + - 게시글 생성 시 `OpenFeign`을 이용하여 기상청 OpenAPI 호출 + - 게시글 작성 시 일교차(최저/최고 기온) 정보 반영하여 저장 + - 레이어별 요청 값 유효성 검사 + - 요청 dto에서 annotation으로 1차 유효성 검사 + - Entity 생성시 2차 유효성 검사 +- 게시판 좋아요 기능 + - 좋아요 여부(`isLike`) 바꿔주는 Patch API로 좋아요 기능 처리 + - 게시글에 좋아요가 눌러진 숫자를 게시판 테이블에 추가 + - 좋아요 동시성 문제 해결 + - 한 사람이 한 게시물에 대해 여러 번 좋아요를 눌러서 생기는 문제 + - 여러 사람이 한 게시물에 대하여 동시에 좋아요를 누르는 문제 + - 비관적 락(`Pessimistic Lock`)을 사용하여 동시성 문제 해결 + - jmeter 부하 테스트 중 두 번째로 성능이 안 좋은 것을 확인 + (평균 시간이 전체 조회를 제외하고 가장 오래 걸림) + - 추후 성능 테스트 결과 확인 후 낙관적 락(`Optimistic Lock`) or `Redis`를 이용한 성능 개선 예정 + +### 아바타 이미지 기능 + +- 아바타 이미지 등록 및 조회 기능 +- Enum Validation annotation 생성 및 적용 + - 모든 Enum 타입을 String으로 받고 그 Enum에 해당하는 값이 존재하지 않을 시 예외를 반환하는 annotation 생성 +- AvatarItem 전용 validation 클래스로 Entity validation 진행 +- 파일 저장 오픈 소스 `MinIO` 도입 + - 추후 배포 시 S3와의 호환성을 위해 로컬 작업에서 MinIO를 도입 + + → S3 설정과 MinIO 설정 및 메서드가 동일하여 interface로 작성, 배포 버전에서는 S3 도입 예정 + + - Docker를 이용해 컨테이너로 이미지 저장소 생성 + - `MinIO` 설정 후 이미지 저장 및 이미지 URL 반환 서비스 생성 + - 게시판, 아바타 이미지에 로직 진행 중 이미지 저장 후 실패하면 이미지 삭제하는 로직 추가 + - 대용량 이미지, 이미지 이외의 타입을 필터링 해주는 annotation 기반 validation 적용 + - Post, AvatarItem 등 이미지를 사용하는 테이블이 많아 이미지를 관리할 수 있는 별도의 테이블 생성 + - 추후 아바타 이미지/게시글의 수정 삭제 로직 후 발생 가능한 이미지 정합성 문제 확인 및 scheduling을 도입, 일정 시간 마다 `@Async` 를 이용하여 비동기적으로 처리 작업중 + - filename의 unique 조건을 위해 UUID를 이용한 filename 생성 도입 + +### CI 도입(Github Action) + +- pull request 시 테스트 코드를 모두 돌려보는 CI 환경 생성 + - 로컬환경과 동일하게 Docker-compose 기반의 컨테이너 구동 후 test, build를 진행하는 방식 적용 +- github secret 기반으로 환경 변수 지정 +- Jacoco 테스트 리포트 자동화 + +### Jacoco 도입 + +- test coverage를 설정하여 기능 개발 시 test code를 작성하지 못한 케이스 확인 +- 메서드 개행 제한 및 분기문에 따른 test 기준 추가 + - Class Line Coverage → 70% 이상 + - Branch Coverage → 70% 이상 + - Method Line Count → 20줄 +- 전체 프로젝트 테스트 커버리지 **✨98.48%✨** (2024.01.18 15:00 기준) + +### Check style 도입 + +- google checkstyle 파일을 기반으로 팀 프로젝트에 적합한 코드 스타일 컨벤션 정의 + - import 문, 여백 등 코드 스타일 컨벤션을 build 시 확인할 수 있도록 gradle 설정 +- 정의한 checkstyle 파일을 통해 Intelij 코드 스타일 자동 정렬 설정 + +### JMeter 부하 테스트 실행 + +- 수치로 나타난 객관적인 성능을 파악하기 위해 일부 API 부하 테스트 진행 +- 동시 접속이 많아지면 일부 요청이 예외를 반환하는 것을 확인 + - 최대 DB Connection Pool을 조절함으로써 해결