Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
36d4bc6
Create CI.yml
Martinel2 Mar 30, 2025
3d26ad0
test
Martinel2 Apr 29, 2025
8969d93
update first class
Martinel2 Apr 29, 2025
abd17e9
에러코드 및 결과 메시지를 위해 클래스 생성 author-김재형
Martinel2 Apr 29, 2025
288839e
에러코드 및 결과 메시지를 위해 클래스 생성 author-김재형
Martinel2 Apr 29, 2025
9ecb8ba
글 작성 관련 테스트 코드 작성 및 MemberControllerTest 수정 author-김재형
Martinel2 Apr 29, 2025
47940db
글 작성 관련 테스트 코드 작성 및 MemberControllerTest 수정 author-김재형
Martinel2 Apr 29, 2025
2f5eed5
add가 제대로 되지않아 재 업로드-테스트코드 작성
Martinel2 Apr 29, 2025
b5844d0
글 작성관련 테스트 코드 작성 - 파일 추가
Martinel2 Apr 29, 2025
4dd8ef9
글 관련 도메인(entity) 생성
Martinel2 Apr 29, 2025
1b48143
글 관련 리포지토리 생성
Martinel2 Apr 29, 2025
d01bbcd
글 관련 도메인(entity) 생성
Martinel2 Apr 29, 2025
9699c88
글 관련 리포지토리 생성
Martinel2 Apr 29, 2025
ecc361d
서비스인터페이스 및 구현 클래스 작성
Martinel2 Apr 29, 2025
b9d854a
컨트롤러를 위한 Dto클래스 작성
Martinel2 Apr 29, 2025
16682c6
컨트롤러 클래스 작성
Martinel2 Apr 29, 2025
5665a46
서비스인터페이스 및 구현 클래스 작성
Martinel2 Apr 29, 2025
e1eb15c
컨트롤러를 위한 Dto클래스 작성
Martinel2 Apr 29, 2025
a142266
컨트롤러 클래스 작성
Martinel2 Apr 29, 2025
a276517
글 관련 기능 클래스들 구현
Martinel2 Apr 29, 2025
bc790f1
글과 관련된 모든 클래스 병합하기
Martinel2 Apr 29, 2025
8270d43
글 관련 기능들을 main에 업데이트합니다.
Martinel2 Apr 29, 2025
b1cf3f9
Create README.md
Martinel2 Apr 30, 2025
c89c49b
Update README.md
Martinel2 Apr 30, 2025
d08de15
검색을 위한 JPA 및 서비스, 컨트롤러 업데이트
Martinel2 Apr 30, 2025
db77dbe
Merge pull request #12 from Martinel2/develop-post-main-update
Martinel2 Apr 30, 2025
1330f7f
검색기능을 위한 JPA, 컨트롤러,서비스 클래스 업데이트
Martinel2 Apr 30, 2025
3affda1
검색기능을 위한 JPA, 컨트롤러,서비스 클래스 업데이트
Martinel2 Apr 30, 2025
eb6e829
잘못된 컨트롤러 주소 수정
Martinel2 Apr 30, 2025
4906346
Merge pull request #15 from Martinel2/develop-post-main-update
Martinel2 Apr 30, 2025
6594978
Merge pull request #16 from Martinel2/develop-post-main
Martinel2 Apr 30, 2025
15f2a08
Merge pull request #17 from Martinel2/main
Martinel2 Apr 30, 2025
e523643
추가오류 수정
Martinel2 Apr 30, 2025
5d65a03
댓글/대댓글 테스트코드 작성
Martinel2 Apr 30, 2025
a50cb69
도메인 클래스 추가
Martinel2 Apr 30, 2025
2031ee6
리포지토리 작성
Martinel2 Apr 30, 2025
76c3b9d
댓글 서비스 코드 작성
Martinel2 Apr 30, 2025
be57719
댓글 dto 코드 작성
Martinel2 Apr 30, 2025
0f7d7ce
댓글 controller 코드 작성
Martinel2 Apr 30, 2025
4f81218
댓글/대댓글 테스트코드 작성
Martinel2 Apr 30, 2025
6eafab2
도메인 클래스 추가
Martinel2 Apr 30, 2025
9ecf964
리포지토리 작성
Martinel2 Apr 30, 2025
6a938fb
댓글 서비스 코드 작성
Martinel2 Apr 30, 2025
423b101
댓글 dto 코드 작성
Martinel2 Apr 30, 2025
03992ba
댓글 controller 코드 작성
Martinel2 Apr 30, 2025
a1090e3
추가오류 수정
Martinel2 Apr 30, 2025
bac7017
댓글/대댓글 기능을 위해 구현한 코드들을 업데이트 합니다.
Martinel2 Apr 30, 2025
561e06f
댓글 기능을 모두 구현완료하여 이를 업데이트 합니다.
Martinel2 Apr 30, 2025
0b8fae3
Update CI.yml
Martinel2 Apr 30, 2025
be2b179
댓글/대댓글 기능을 추가 합니다.
Martinel2 Apr 30, 2025
562854e
메일 보내기 관련 테스트 코드 추가
Martinel2 May 19, 2025
13649ce
메일 보내기 기능 구현
Martinel2 May 19, 2025
cd7c6d3
팔로워 추가- 테스트 필요...
Martinel2 May 19, 2025
1fe7425
댓글이 달릴 시 메일으로 알림이 오는 기능 구현
Martinel2 May 19, 2025
066a536
Ci Cd를 위한 파일들 추가
Martinel2 May 26, 2025
6ac99c0
Ci Cd를 위한 파일들 추가 수정
Martinel2 May 26, 2025
0f17533
Ci 실패 수정하기-1
Martinel2 May 26, 2025
049edf9
Ci 실패 수정하기-2
Martinel2 May 26, 2025
97f8e3f
cd실패 수정하기-1
Martinel2 May 26, 2025
5f7a61b
Cd 실패 수정하기-2
Martinel2 May 26, 2025
04d1463
화면띄워서 테스트하기
Martinel2 May 26, 2025
54ba26d
화면띄워서 테스트하기
Martinel2 May 26, 2025
61e2c8e
Merge pull request #29 from Martinel2/ci/cd
Martinel2 Jun 6, 2025
6de2fe2
Merge pull request #30 from Martinel2/develop
Martinel2 Jun 6, 2025
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
85 changes: 82 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Java CI with Gradle

on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]

Expand Down Expand Up @@ -45,4 +43,85 @@ jobs:
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/build/test-results/test/TEST-*.xml'
files: '**/build/test-results/test/TEST-*.xml'

cd:
runs-on: ubuntu-latest
needs: ci

steps:
- uses: actions/checkout@v4

- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: Project
path: ./build/libs

# Docker Hub login
- name: Login to Docker Hub
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin

# Build and Push Docker Image
- name: Build and Push Docker Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/devlog:latest .
docker push ${{ secrets.DOCKER_USERNAME }}/devlog:latest

- name: Create .ssh directory and add EC2 host key
run: |
mkdir -p ~/.ssh
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts

- name: Create private key file
run: |
echo "${{ secrets.SSH_PRIVATE_KEY }}" > private_key.pem
chmod 600 private_key.pem

- name: Upload project files to EC2
run: |
rsync -avz --progress --checksum --exclude 'node_modules' --exclude '.git' \
-e "ssh -i private_key.pem" ./ \
${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }}:/home/${{ secrets.EC2_USER }}/project/

- name: Deploy to EC2 and restart Docker containers using Docker Compose
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/${{ secrets.EC2_USER }}/project/

# 환경 변수 파일 생성
echo "MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}" > .env
echo "MYSQL_PASSWORD=${{ secrets.MYSQL_PASSWORD }}" >> .env
echo "DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }}" >> .env

# Stop and remove existing containers
docker-compose down || true

# Pull the latest Docker image
#docker-compose pull

# Start the containers using Docker Compose
docker-compose up -d --build

#- name: Add EC2 public IP to /etc/hosts
# run: |
# echo "$EC2_PUBLIC_IP backend" | sudo tee -a /etc/hosts
# env:
# EC2_PUBLIC_IP: ${{ secrets.EC2_HOST }}

#- name: Wait for init server
# run: sleep 650

#- name: Test HTTP response
# run: |
# curl -v http://backend:8080


- name: Remove private key file
run: rm -f private_key.pem

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ bin/
*.iws
*.iml
*.ipr
out/
*.properties
!**/src/main/**/out/
!**/src/test/**/out/

Expand Down
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 최신 21-jdk-alpine 이미지로부터 시작
FROM openjdk:21-jdk-slim

EXPOSE 8080

# 작업 디렉토리를 /app으로 설정
WORKDIR /app

# 현재 디렉토리의 모든 파일을 컨테이너의 /app 디렉토리로 복사
COPY . .

#ENV SPRING_PROFILES_ACTIVE=prod
# 빌드된 JAR 파일을 컨테이너로 복사
ARG JAR_FILE=build/libs/devlog-0.0.1-SNAPSHOT.jar
RUN mv ${JAR_FILE} app.jar

# 컨테이너가 실행될 때 실행될 명령어 지정
# 오류남! 왜냐하면, spring.profiles.active=prod를 사용하려면, application.properties에 spring.profiles.active=prod를 추가해야함
ENTRYPOINT ["java", "-jar", "app.jar"]
#ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar","app.jar"]
257 changes: 257 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
## 글과 댓글, 대댓글 기능 구현하기

- 우리가 만드는 사이트 - 개발 진로 관련 정보 공유 블로그

## 글 작성하기

- 로그인한 사용자만이 글을 작성할 수 있다.
- 제약사항
- 글을 작성하기 위해서는 로그인을 해야한다.
- 작성완료될 글은 제목이나 내용이 공백일 수 없다.

- 추가로 고려해볼만한 사항
- 사진과 같은 파일을 삽입하는 경우
- 업로드된 파일이 보여질 위치를 링크와 같은 형태로 조정하는 방식 → velog 방식
- 삽입을 하면 그 파일자체를 보여주어 이를 작성자가 옮길 수 있도록 하는 방식 → notion 방식
- 업로드 될 파일의 크기 제한은 얼마나?

- 글의 문법
- 네이버 블로그와 같은 기본적인 문법을 따르도록 할까? (최근엔 마크다운 서식을 따르도록 업데이트 되었다고함)
- 아니면 notion,velog와 같이 마크다운을 사용가능하도록 할까?

- 시나리오
- 글 작성(create)테스트
- 성공 테스트
- given
- 로그인한 사용자
- 제목과 글이 공백이 아님
- when
- ‘글 작성하기’ 버튼을 누른 후 글을 작성함
- ‘작성’ 버튼을 눌러 글 작성을 완료함
- then
- 성공적으로 글이 작성됨(201 created)

- 예외 테스트
- 상황 1. 로그인 하지 않은 사용자
- → 이 경우는 스프링 시큐리티 url 설정으로 쉽게 해결 가능할 것이라 예측
- given
- 로그인하지않은 사용자
- when
- 사용자가 ‘글 작성하기’ 버튼을 클릭함
- then
- 로그인을 권유하는 알림을 띄우도록 함. → 프론트
- 오류는 (403 Forbidden)

- 상황 2. 로그인 O, 글 제목 또는 내용이 공백인 경우
- given
- 로그인한 사용자
- 글 제목 또는 내용을 공백으로 제공
- when
- 사용자가 ‘글 작성하기’버튼을 클릭 후 글을 작성하고 ‘작성’을 눌러 글 저장을 시도
- then
- 글에서 공백으로 주어진 부분을 하이라이트하여 보여줄 수 있도록 함 →프론트
- 400 bad request


---

- 작성된 글은 아이디, 제목 등을 통해 조회가 가능해야한다.
- 제약사항
- ‘내 글 보기’에서는 자신이 작성한 글만 조회가 되어야 한다.
- 이때, ‘내 글 보기’ 라는 버튼은 로그인 한 사용자들에게만 보이는 버튼
- url을 바꾸어 접근 시도시 인가되지 않은 사용자이므로 거부하도록 시큐리티 설정
- 만일 velog와 같이 태그를 달 수 있도록 한다면 태그를 통해서도 조회가 가능해야한다.

- 시나리오
- 글 조회(Read)테스트
- 성공 테스트
- 글을 작성한 작성자는 ‘내 글 보기’를 통해 자신이 쓴 글을 조회 가능하다.
- given
- 로그인한 사용자
- 작성된 글이 존재함
- when
- 내 글 보기 버튼을 클릭하여 작성 글 조회
- then
- 성공적으로 자신이 쓴 글을 확인할 수 있음
- 200 ok
- 예외 테스트
- 상황 1.
- → 이 경우는 스프링 시큐리티 url 설정으로 쉽게 해결 가능할 것이라 예측
- given
- 로그인하지않은 사용자
- when
- 사용자가 ‘글 작성하기’ 버튼을 클릭함
- then
- 로그인을 권유하는 알림을 띄우도록 함.
- 오류는 (403 Forbidden)

- 상황 2. 로그인 O, 글 제목 또는 내용이 공백인 경우
- given
- 로그인한 사용자
- 글 제목 또는 내용을 공백으로 제공
- when
- 사용자가 ‘글 작성하기’버튼을 클릭 후 글을 작성하고 ‘작성’을 눌러 글 저장을 시도
- then
- 글에서 공백으로 주어진 부분을 하이라이트하여 보여줄 수 있도록 함 →프론트
- 400 bad request


---

- 작성된 글은 검색결과에 노출되어야 한다.
- 제약사항
- 만일 글에 태그를 달 수 있도록 한다면 태그를 통해서도 조회가 가능해야한다.
- 글 검색시 글의 제목 또는 내용에 포함된 단어를 통해 검색결과에 도출되어야 한다.
- 글 작성자를 이용하여 검색 시, ‘ 내 글 보기’와 같이 그 사람이 작성한 글만 조회가 되어야 한다.
- 아이디는 완전히 일치하는 경우만 찾을 수 있도록

- 시나리오
- 성공 테스트
- given
- 검색할 문자열 (공백 x)
- 문자열을 통해 검색 가능한 작성된 글
- when
- 문자열을 통해 검색을 시도
- then
- 검색 가능한 글이 정상적으로 검색결과에 노출됨
- 200 ok
- 예외 테스트
- 검색할 문자열이 공백인 경우
- given
- 검색할 문자열이 공백으로 제공
- when
- 공백으로 검색시도
- then
- 공백으로 검색이 불가능하다는 오류메세지 띄우기
- 400 bad request


---

- 글을 수정할 수 있다.
- 제약사항
- 글 수정은 그 글을 작성한 작성자만의 권한이다
- 글을 작성한 작성자가 자신이 글을 작성할 때 사용한 아이디로 로그인 된 상태
- 즉, 내 글 보기를 통해 해당 글이 보이는 상태
- 수정한 제목, 내용이 공백이여서는 안된다.
- 수정하기 사용시, 원래 작성했던 글의 템플릿 그대로 작성틀로 옮겨져야한다.
- 수정한 내용을 작성을 눌러 저장하면 그 글에 수정된 내용이 덮어쓰기 되어야한다.
- 시나리오
- 성공 테스트
- 수정하기 사용시, 원래 작성했던 글의 템플릿 그대로 작성틀로 옮겨져야한다.
- given
- 로그인한 사용자
- when
- 자신이 작성한 글을 눌러 수정버튼을 클릭
- then
- 수정한 글의 내용을 그대로 ‘작성하기’에서 사용했던 틀에 옮겨진 채로 화면에 노출
- 200 ok
- 수정한 내용을 작성을 눌러 저장하면 그 글에 수정된 내용이 덮어쓰기 되어야한다.
- given
- 로그인한 사용자
- when
- 작성 버튼을 눌러 글 저장 시도
- then
- 수정한 글의 내용을 원래 작성했던 글에 덮어쓰기 해야함.
- 200 ok
- 예외 테스트
- 수정된 내용이 공백인 경우
- given
- 로그인한 사용자
- 수정된 내용이 공백으로 제공
- when
- 작성 버튼을 눌러 글 저장 시도
- then
- 공백인 부분을 하이라이트하여 보여줌 → 프론트
- 400 bad request

---

- 글은 삭제할 수 있다.
- 제약사항
- 글을 삭제하는 것은 그 글의 작성자와 관리자만의 권한이다.
- 글을 작성한 작성자가 자신이 글을 작성할 때 사용한 아이디로 로그인 된 상태
- 즉, 내 글 보기를 통해 해당 글이 보이는 상태
- 삭제된 글은 글의 댓글, 대댓글 모두 같이 삭제됨
- 삭제된 글을 url로 접근하려할 시 404 not found
- 진짜로 삭제할 것인지 물어보는 창을 띄우도록하기
- 시나리오
- 성공테스트
- given
- 로그인한 사용자
- 로그인한 사용자가 작성한 삭제할 글
- when
- 삭제 버튼을 통해 삭제시도
- then
- 삭제 성공
- 200 ok


---

---

---

## 댓글 기능 구현하기

-대댓글도 같은 로직을 따를 것. 다만, 다르게 구현할 필요는 있을듯

- 댓글은 로그인한 사용자들만 달 수 있다.
- 제약사항
- 로그인한 사용자들만 댓글 작성이 가능
- 댓글은 공백일 수 없음
- 작성자가 자신의 글에 댓글을 달면, 표시를 다르게하여 작성자임이 확인되도록 한다.
- 삭제되지 않은 글에만 댓글 작성 가능
- 시나리오
- 성공 테스트
- given
- 로그인한 사용자
- 공백이 아닌 댓글 문자열
- when
- 로그인한 사용자가 공백이 아닌 댓글 작성 시도
- then
- 성공적으로 댓글이 작성된다
- 201 created

---

- 댓글은 작성자/관리자만이 삭제할 수 있다.
- 제약사항
- 로그인한 사용자중 댓글을 작성한 사람만 댓글 삭제가 가능하다.
- 시나리오
- given
- 로그인한 사용자
- 로그인한 사용자가 작성한 삭제할 댓글
- when
- 삭제 버튼을 통해 삭제시도
- then
- 삭제 성공
- 200 ok


---

- 대댓글은 상위 댓글이 삭제되더라도 삭제되지 않는다.
- 제약사항
- 시나리오
- 성공테스트
- given
- 삭제할 대댓글을 가진 댓글
- when
- 삭제 버튼을 통해 댓글 삭제시도
- then
- 삭제 성공
- 200 ok
- 삭제 후에도 대댓글은 남아있도록함.

---

---
### 참고 사이트

[대댓글 (댓글의 댓글) 기능 구현하기](https://velog.io/@hhss2259/%EB%8C%80%EB%8C%93%EA%B8%80-%EB%8C%93%EA%B8%80%EC%9D%98-%EB%8C%93%EA%B8%80-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0)

[[HTTP] HTTP 상태 401(Unauthorized) vs 403(Forbidden) 차이](https://mangkyu.tistory.com/146)

[[사소한 TIP] Spring Data JPA에서 FindBy 와 FindAllBy 차이점](https://revf.tistory.com/270)
Binary file added build/libs/devlog-0.0.1-SNAPSHOT.jar
Binary file not shown.
Loading