프로젝트

사용자 인증을 위한 이메일을 통한 인증 코드 전송을 진행합니다.


메일 인증 설정

1. email 전송 서비스 개발

  • 목적: 실제로 사용되는 메일인지 확인을 위한 인증 코드를 포함한 메일을 전송합니다.
  • 메소드: sendMail(String to, MailComponents subject, MailComponents content)
  • 코드
  /*
   * 이메일을 전송하는 메서드
   * 1) 메일 인증
   * 2) 비밀번호 초기화
   *
   * @param to      수신자 이메일 주소
   * @param subject 이메일 주제
   * @param content    이메일 내용
   */
  public void sendMail(String to, MailComponents subject, MailComponents content) {

      SimpleMailMessage mail = new SimpleMailMessage();

      // 인증 메일을 보내는 경우
      if (subject.equals(VERIFICATION_SUBJECT)) {
          createMail(mail, to, subject, content, 6);
      }

      send(mail);
  }
  /*
   * SimpleMailMessage 객체를 생성하는 메서드
   *
   * @param to      수신자 이메일 주소
   * @param subject 이메일 주제
   * @param text    이메일 내용
   * @param length  생성할 인증 코드 길이
   * @return 생성된 SimpleMailMessage 객체
   */
  private SimpleMailMessage createMail(SimpleMailMessage mail,
                                       String to,
                                       MailComponents subject,
                                       MailComponents text,
                                       int length) {
      mail.setTo(to);
      mail.setSubject(subject.getContent());
      // 메일 내용 구성
      mail.setText(String.format(text.getContent(), createUUID(length)));
      return mail;
  }
  /*
   * 이메일을 전송하는 메서드
   *
   * @param mail SimpleMailMessage 객체
   */
  private void send(SimpleMailMessage mail) {
      try {
          javaMailSender.send(mail);
      } catch (MailException e) {
          throw new CustomException(EMAIL_SENDING_FAILED);
      }
  }
  • yml 설정
  • mail: host: smtp.gmail.com port: 587 username: (@gmail.com 메일) password: (16자) properties: mail: smtp: auth: true starttls: enable: true

2. gmail에서 SMTP용 계정 설정

  • 방법
    • 성공적인 메일 전송을 위해서는 메일의 IMAP 설정을 활성화시켜야 합니다.
    • 앱 비밀번호 사용을 위해서 2단계 인증 활성화 > 앱 비밀번호호 16자를 yml에서 사용

3. 회원가입에 따른 성공적인 전송

실수 목록

  • .ignore에서 .yml 설정
    : 의도대로면 *.yml를 사용해야함 / 그러나 git 관련 yml이 존재하므로 해당 yml 파일을 정확한 명칭 넣기
    ex) application-local.yml
  • group or artifact에 대문자 사용

    : 소문자로 구성하여 타 클래스와 구분이 되게 생성

  • swagger config를 안 추가함

    : api 정리를 위해서 필요

  • swagger 동작 미확인

    : localhost:8080/swagger-ui/가 잘 동작하는지 확인

앞으로 계획

  • 기본 프로젝트 : java, spring boot 논의된 내용 + 소문자로 group, artifact 작성 후 생성
  • .ignore에서 특정 yml(기본, local, dev, prod) 생성
  • dependency : lombok, jpa, mariadb, redis, springfox 등 내용 추가
  • 공통 클래스 생성 : BaseEntity 및 예외 처리(code, globalHandler - vaild, custom, undefined, custom, response)
  • config 작성 : redis, security, swagger
  • git 관련 설정 추가 : 레포지토리 바로 아래 .github -> workflow(git 리뷰어와 브랜치 설정) & PR과 Issue 템플릿 추가

github

  • branch가 main - dev - 나머지 가 될 수 있게 구성 후, 매 pr마다 새 branch -> dev로 merge
  • 나머지 멤버의 review가 필요하게 설정
  • pr과 issue 템플릿에 맞춰서 작성

'Project > 프리온보딩' 카테고리의 다른 글

[sns-feed] PR 피드백 정리  (0) 2023.10.29
[sns-feed] 많이 사용된 태그  (0) 2023.10.28
[sns-feed] 시간 기반 태그 추천  (0) 2023.10.24

작업시, 내가 주의한 점

  1. 설계 단계에서 어떤 이유로 해당 데이터 구조 및 방식을 사용하였는지

  2. 논의된 코드 컨벤션 이용 : api(/api/v1/복수형) & DTO 와 Request/ResponseDTO

  3. 각 기능별 함수 분리 및 주석 작성


PR 피드백

  1. System.out.println () 대신 @SLFJ4 log.info() 이용
  1. 커밋을 단순변경 단위가 아닌 기능단위로
    • ex) 태그 검색기능 추가 , 핫태그 이메일 전송 기능 추가
    • 브랜치도 분리하여 feature/log-add , feature/log-hot-tag
  1. @AllArgsConstructor 대신 @Builder
  1. Restful api 는 복수형을 권장 & 명시적으로 경로앞에 "/"
  1. ResponseEntity<?> -> 반환 resposne 클래스 명시적으로 지정
  1. 정의된 HTTP 상태 코드를 사용
    • ResponseEntity.status(response.getStatus()).body(response) 에 getStatus() 대신 HttpStatus.OK
  1. @Api / @ApiOperation 을 이용해서 swagger 문서 넣기

'Project > 프리온보딩' 카테고리의 다른 글

[tasty-spots-finder] skeleton 프로젝트  (0) 2023.10.31
[sns-feed] 많이 사용된 태그  (0) 2023.10.28
[sns-feed] 시간 기반 태그 추천  (0) 2023.10.24

Redis

  • Key-Value 구조로, Value는 String, Set, Sorted Set, Hash, List 등다양하게 가능

Sorted Set : 정렬 (↔ List : 순서, 중복o)

  • set에 score라는 가중치 필드가 추가된 데이터 형태
  • 일반 set과 달리 저장된 member의 순서도 관리
  • score에 따라 오름차순 정렬 → 사전 순
  • 장점 : 특정 범위 내 데이터 쉽게 조회, score 기준으로 정렬된 데이터
  • 단점 : 데이터 추가/삭제 경우, member와 score 모두 관리

→ 좋아요 처리나 일일 방문자수 기록하는 경우 (중복x)

HyperLogLogs

  • 중복된 요소의 개수를 카운트하기 위한 집합 기반 데이터 구조
  • 장점 : 정확성을 위해 메모리를 적게 사용 (모든 값이 12kb)
  • 단점 : 중복된 데이터의 근사치를 파악 (오차 범위 0.81%)

→ 데이터의 대략적인 근사치를 파악하고 메모리를 효율적으로 사용하는 경우

💡 결론

 

필터(Filter) vs 인터셉터(Interceptor)

  • 상황 : posting의 저장과 검색에서 tag를 사용한 경우

Filter

  • 서블릿에 요청이 전달되기 전(서블릿 컨테이너)/후에 url 패턴에 맞는 작업 처리
  • request, response 조작 가능
  • 용도 : 공통된 보안, 인증 작업 / 모든 요청에 대한 로깅 / 압축 및 인코딩

Interceptor

  • 서블릿에 요청이 컨트롤러 호출 전(스프링 컨테이너)/후에 요청/응답을 참조
  • 스프링에서 예외처리 가능
  • 용도 : 세부적인 보안 작업 / api 호출에 대한 로깅 / request 정보 가공

AOP

  • 공통으로 사용되는 관심사의 모듈화를 목적으로 함
  • 주로 RestController를 이용하면서 JSON으로 반환해 뷰랜더링의 후 처리 작업이 필요 없게 됨

AOP, 커스텀 에러 핸들러, 필터를 이용해서 요청/응답을 가로채서 수행하는 방식 이용

'Project > 프리온보딩' 카테고리의 다른 글

[tasty-spots-finder] skeleton 프로젝트  (0) 2023.10.31
[sns-feed] PR 피드백 정리  (0) 2023.10.29
[sns-feed] 시간 기반 태그 추천  (0) 2023.10.24

시간 기반 태그 추천 방식

  1. 시간 기반 DB 쿼리
    • 장점 : 최근에 사용된 tag 기록을 통한 추천 가능
    • 단점 : 성능 이슈(지속적인 태그 기록과 시간 필터링 조회)
  2. 캐싱과 스케줄링 활용
    • 장점 : DB 부하 감소, 응답 속도 향상, 데이터 일관성, 스케일 아웃(대규모) 가능 ↔ 쿼리
    • 단점 : 설정, 관리 복잡함
  3. 스트리밍 데이터 처리
    • 간단한 방식 : 콘솔 출력(운영x), 파일 기록
    • Apache Kafka를 이용해 로그 수집 가능

데이터 형태

  • 로그 데이터 : 많은 양 저장할 수 있지만, 실시간 분석 어려움
    • IT인프라에서 발생하는 모든 상황의 데이터(서비스나 시스템 이벤트의 기록)
    • 최근 사용성 및 행동 패턴 확인, 모델링 등 목적으로 사용되는 행동 기반 데이터
  • DB 데이터 : 일관되고 안전한 저장이 가능하지만, 배치 형태에 따라 실시간 작업에 부족함

데이터 저장

  • 파일 : 단순하지만, 대용량 로그 데이터의 검색과 분석에 제한
  • 데이터베이스 : 구조화되어 검색과 분석이 쉽지만, 부하와 설정 복잡함
  • Kafka 등

결론

  • 로그보다 DB 데이터가 “사용 빈도”만 분석에는 더 적합
  • 완벽한 실시간 작업은 아니지만, redis로 효율적인 시간으로 작업 → 메모리 캐싱 > DB 저장
  • 스케줄링은 설정과 관리가 복잡하지만, 한번 학습하면 적용은 간편해질 것으로 예상

캐싱과 스케줄링을 통해서 추가 기능 구현 + DB 대신 redis를 저장소로 이용
{: .notice--warning}

'Project > 프리온보딩' 카테고리의 다른 글

[tasty-spots-finder] skeleton 프로젝트  (0) 2023.10.31
[sns-feed] PR 피드백 정리  (0) 2023.10.29
[sns-feed] 많이 사용된 태그  (0) 2023.10.28

원인

매번 github에서 git clone 명령어를 통해 정보를 받다보니, 보안으로 인한 properties 추가 혹은 test 폴더 제거 등 추가적으로 putty를 통해 ec2 내부에 접속해서 진행해야하는 작업이 많았습니다.

 

그에 따라 편하게 실행이 가능한 코드를 로컬 컴퓨터 내부에서 작업하여 바로 jar 파일을 전송 후 실행만 하는 방식을 이용해서 처리의 불편함과 속도를 높여보았습니다.

 

진행

  • 먼저, 만든 spring 서버 프로젝트에서 test 폴더를 지워서 jar 파일로 만들 수 있는 형태를 취하였습니다.
  • 마지막으로 properties를 확인하면서 프로젝트를 확인합니다.
  • 그리고 프로젝트 내부로 들어와서 "./gradlew clean build" 명령어를 통해서 jar 파일의 형태로 변경시킵니다.
  • 해당 jar 파일을 원하는 곳에 이동시키기 위해서 권한을 향상시키는 과정이 필요할 수도 있습니다.
  • 저는 window라서 해당 파일의 속성 -> 보안 -> 고급 -> 추가(D) 에서 Everyone이 접근하며, 권한을 가지게 설정하였습니다.
  • fileZila에 접속한 뒤, aws에서 설정한 ip와 <ubuntu, key>를 이용해서 ec2에 접근합니다.
  • putty로 이동할 폴더의 바깥까지 도달한 뒤에 "chmod -R 775 폴더명"로 해당 폴더의 권한을 향상시켜서 외부에서 파일이 삽입될 수 있게 수정합니다.
  • 그 후, 원하는 파일을 끌어서 원하는 자리에 배치시키면 잘 전송될 것 입니다.
  • 다시 putty로 가서 jar을 실행시키는 "java -jar 프로젝트명-0.0.1-SNAPSHOT.jar"를 시켜주시면 완성입니다!

 

나중

해당 부분은 jar 파일을 올리기 위해서 elastic Beanstalk를 이용하는 방식도 있지만, 해당 내용은 다음에 작성해보겠습니다!

'Project > AWS' 카테고리의 다른 글

[AWS] RDS + EC2  (0) 2023.03.14
[AWS] 알림 설정  (0) 2023.03.14

commit의 브랜치 이동

실수로 main에 commit을 진행하고 있던 작업을 friends 브랜치로 이동시키는 작업을 예시로 설명드리겠습니다.

 

git checkout [이동할 브랜치]

1. 현재 main 브랜치에서 우선 friends 브랜치로 이동합니다.

 

Problem : 그런데, checkout을 위해서는 application.properties 파일에 대해서 overwritten이 발생하는 문제가 있다고 합니다. 해당 문제를 해결하기 위해서 저는 test용으로 수정해두었기에 이전 버전과 동일한 상태로 파일을 만들어서 해당 문제를 해결하였습니다.

 

 

git reflog

2. git reflog 명령을 통해서 가져올 commit 목록을 확인합니다.

 

저는 이중에서 가장 아래 commit을 이동시켜보도록 하겠습니다.

 

 

git cherry-pick [id]

3. 다음은 현재 브랜치로 commit을 가져올 타이밍입니다.

 

Problem : 이번에도 아직 로컬에 변경사항이 남아있어서 commit 또는 stach 처리를 진행하라고 합니다. 저는 현재까지의 변경사항에 대해 commit을 진행 후 해당 작업을 반복하였습니다.

 

무사히 cherry-pick에 의해서 main -> friends 브랜치로 commit이 이동한 것을 확인할 수 있습니다!

 


해당 작업 중에서 처음보는 오류가 많았지만, 잘 읽고 찾아보니 기존에 존재하는 파일이 add 혹은 commit이 진행되지 않은 상태로 남아있다보니 발생한 문제가 많았던 것 같습니다.

이러한 부분을 유의하여 작업을 하다보면, 더 속도가 빨라질 것 같는 생각이 듭니다.

 

또는 아래의 방법으로 local에서는 main에서 작업했어도 git에는 특정 원격 브랜치에 올리는 방법을 이용하시는 것도 좋습니다.

 


특정 원격 브랜치로 push

이용하는 방법은 git push origin 이후에 main 브랜치(local)에서 실제 git의 friends 브랜치에 올리겠다는 명령을 통해서 다른 브랜치에서 작업한 것처럼 local 작업을 올릴 수도 있습니다.

 

 

위 작업을 진행하면, github repository에서는 다음의 내용을 확인할 수 있습니다.

 

해당 작업에서 pull request 버튼을 통해서 해당 작업을 실제 프로젝트 code에 적용할지 여부를 확인 받기 위해 PR을 보낼 수 있게 됩니다.


local에서 작업을 하다보니, 자주 발생하는 문제였기에 이렇게 정리해봄으로써 git을 더 유용하게 사용할 수 있게 되는 좋은 시간이였다는 생각이 듭니다.

git에서 commit를 하는 경우에는 일반적으로 정해진 형식이 있다.

 

기본 구조

제목/본문/꼬리말 세가지 파트로 나누고, 각 파트는 한줄씩 건너서 구분합니다.

type: Subject

body

footer
  • Subject : 50자 이하면서 대문자로 시작하고, 마침표로 끝나지 말아야합니다.
    • feat: Summarize changes in around 50 characters or less
  • Body : 72자 이내로 커밋의 내용과 이유를 설명해 필요한 경우만 사용됩니다.
  • Footer : 선택사항으로 문제 ID 참조에 사용됩니다.
    • Resolves: #123

 

Commit Type

  • feat: 새로운 기능 추가
  • fix: 버그 수정
  • docs: 문서 수정
  • style: 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
  • refactor: 코드 리펙토링
  • test: 테스트 코드, 리펙토링 테스트 코드 추가
  • chore: 빌드 업무 수정, 패키지 매니저 수정

 


참고 자료 : git 스타일 가이드

당연히 기본적으로 aws 계정이 있어야 하며, 해당 과정을 진행했다고 가정하고 아래의 내용을 진행하면 됩니다.

 

RDS

먼저, 검색창에 RDS를 넣어서 아래의 페이지로 이동하면, 보이는 데이터베이스 생성 버튼을 누르면 됩니다.

잠시 로딩 시간이 지나가면, 아래의 창으로 넘어가게 됩니다.

 

해당 화면에서 default 값은 제외하고, 어떤 방식으로 진행해야하는지 설명드리겠습니다.

우선 엔진옵션에서 DB를 설정해야하며, 저는 PostgreSQL을 선택하겠습니다.

 

 

다음으로, 템플릿프리 티어로 설정해야지 요금 부과가 되지 않습니다.

 

 

설정에서 DB 인스턴스 식별자를 프로젝트 이름 pointer으로 설정하고, 마스터 암호8자이상으로 설정합니다.

이것은 나중에 datagrip으로 RDS를 연결시에 사용할 비밀번호입니다.

 

 

스토리지는 기본으로 할당된 스토리지 20GiB, 최대 스토리지 임계값1000GiB인지 확인합니다.

 

 

연결에서는 DB 서브넷 그룹보안그룹이 모두 default라는 것을 확인합니다.

 

 

그리고 연결퍼블릭 액세스로 바꾸어서 datagrip에서 접근할 수 있게 해야합니다.

 

 

나머지는 default 값으로 놔두고, 이제는 데이터베이스 생성 버튼을 누르면, 시간이 소요된 후 생성됩니다.

 

 

EC2

검색창에 EC2를 넣어서 아래의 페이지로 이동하면, 보이는 인스턴스 시작 버튼을 누르면 됩니다.

잠시 로딩 시간이 지나가면, 아래의 창으로 넘어가게 됩니다.

 

애플리케이션 및 OS 이미Ubuntu를 선택하고, 아래에 프리티어 사용 가능인지 확인합니다.

 

 

키 페어에서 새 키 페어 생성 버튼을 누르면, 아래의 창이 보입니다.

해당 페이지에서 키 페어 이름을 설정 후 키 페어 생성 버튼을 눌러서 키 페어를 다운 받습니다.

 

 

여기서도 나머지는 default로 해두고, 인스턴스 시작 버튼을 누르면 바로 인스턴스가 생성됩니다.

 

 

 

탄력적 IP

EC2에게 ip를 할당하기 위해서 EC2 화면에서 왼쪽 바 > 탄력적 IP에 들어갑니다.

 

 

탄력적 IP 주소 할당 버튼을 누르면, 아래의 화면이 보이고 할당 버튼을 통해 탄력적 IP 주소를 만들 수 있습니다.

 

 

* 주의 : 탄력적 IP는 프리티어에서 1개만 만들 수 있으며, 요금이 부과되지 않으려면 EC2와 바로 연결해야 합니다!

 

EC2 - 탄력적 IP 연결

위의 과정을 위해서 탄력적 IP 주소 메인 화면에서 작업 버튼 > 탄력적 IP 주소 연결을 누릅니다.

 

 

 

아래의 화면에서 인스턴스 부분에서 위에서 만든 (pointer) 인스턴스를 찾아넣고, 연결을 진행하면 됩니다.

 

 

보안그룹 : EC2-RDS 연결

탄력적 IP 바로 위에 있는 보안 그룹으로 들어가면, 아래 화면이 보입니다.

default는 RDS의 보안그룹이기에 남은 1개인 launch-wizard-1은 EC2의 보안그룹입니다.

 

그리하여 우선 EC2 보안 그룹 ID를 클릭해 들어가서 인바운드 규칙 편집 버튼을 누르면, 아래 화면이 보입니다.

 

 

우선 기본적으로 존재하는 HTTP 유형의 80 포트는 내버려두고,

그외로 4가지 보안 그룹으로 총 5개의 그룹이 존재하게 만듭니다.

 

저희는 PostgreSQL과 연결할 것이므로 규칙 추가 버튼을 통해서 2개를 생성합니다.

1. 유형 : PostgreSQL / 소스 : 내 IP

2. 유형 : PostgreSQL / 소스 : 사용자 지정 / 검색 : RDS와 연결된 보안그룹(default) 

-> RDS와 EC2 보안 그룹을 서로 연결해주는 과정을 통해서 2개의 연결이 가능해집니다.

 

그 다음으로 모든 HTTP 요청이 들어올 수 있도록 합니다.

3. 유형 : HTTP / 소스 : 사용자 지정 / 검색 : 0.0.0.0/0

 

그리고 SSH를 통해 개인 IP에서 접근할 수 있도록 합니다.

4. 유형 : SSH / 소스 : 내 IP

 

오른쪽 끝에 규칙 저장 버튼을 통해서 위 인바운드 규칙을 저장할 수 있습니다.

(다음으로, 인바운드 규칙 말고 아웃바운드 규칙에서는 <유형 : 모든 트래픽 / 대상 0.0.0.0/0>이 존재하는지 확인합니다.)

 

이번에는 남은 보안 그룹인default 들어가서 위와 같은 방식으로 인바운드 규칙 편집 버튼을 누릅니다.

여기서는 PostgreSQL에 대해 2가지 규칙을 생성하면 됩니다. => EC2의 규칙과 동일

1. 유형 : PostgreSQL / 소스 : 사용자 지정 / 검색 : RDS와 연결된 보안그룹(default) 

2. 유형 : PostgreSQL / 소스 : 내 IP

 

위 과정을 거쳤으면, EC2-RDS가 서로 연결이 되었습니다.

 

DataGrip

DB를 다루는 툴로서 해당 개발툴을 자주 이용하기에 해당 툴과 aws의 RDS를 연결하는 방법을 알아보겠습니다.

datagrip을 무료로 1년간 사용하기 위해서는 jetBrain에서 학생 인증을 받으면 됩니다.

 

datagrip에 진입하면, 오른쪽 위에는 해당 모양 +을 누르면 원하는 형태의 DB를 찾을 수 있습니다.

 

 

해당 DB를 이용하고 싶지만, 과거 프로젝트를 진행한 적 없으면 DB를 다운받아야하므로 Data Sources -> Drivers로 이동합니다. 여기서 원하는 DB를 고르고, 붉은 색이 보이면 다운되지 않았으므로 OK를 눌러서 해당 내용을 받아야합니다.

 

 

다시 Data Sources로 돌아오면여기서 RDS의 엔드 포인트Host에 붙여넣고, 데이터베이스 생성시 User는 default로 progres이고 Password는 위에서 입력한 값을 넣으면 됩니다.

 

 

그 후 Test Connection을 눌러서 연결을 시키면, 완성이 됩니다.

 

수고 많으셨습니다!!

'Project > AWS' 카테고리의 다른 글

[AWS] 서버 jar 파일을 ec2에 올리기 (FileZIia)  (0) 2023.07.11
[AWS] 알림 설정  (0) 2023.03.14

우선 해당 aws를 사용하기 전에 aws는 과금이 되기 쉬우므로 그에 따라서 알림을 받을 수 있도록 하는 것이 중요하다!

 

과금 알림 설정

먼저 오른쪽 위에 있는 자신의 계정이름(12hyeon)이 적혀있는 부분을 누르면, 아래의 화면이 보이게 됩니다.

해당 화면에서 계정 > Budgets 화면에서 "예산 생성" 버튼을 통해서 월별 비용 예산, 프리티어를 초과하면 알려주는 제로 지출 예산으로 해당 예산을 만들면 됩니다. 

 

템플릿을 선택 후 아래 보이는 이메일 수신자에 자신의 이메일을 작성해두고, 맨 아래의 "예산 생성" 버튼을 누르면 초과되는 경우에 해당 메일로 알림이 가게 만들 수 있습니다.

'Project > AWS' 카테고리의 다른 글

[AWS] 서버 jar 파일을 ec2에 올리기 (FileZIia)  (0) 2023.07.11
[AWS] RDS + EC2  (0) 2023.03.14

+ Recent posts