02-06 08:48
Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Archives
관리 메뉴

기록을 합시다.

[Numble] 넘블 회고록 -내가 만드는 MBTI 성격 유형 테스트- 본문

공부/etc

[Numble] 넘블 회고록 -내가 만드는 MBTI 성격 유형 테스트-

울집고양이세마리 2023. 7. 26. 04:13

넘블 회고록

프로젝트 참여 배경

원래는 유료였지만, 우연치 않게 게임을 열심히 해서 무료로 MBTI 성격 유형 테스트 관련 넘블 프로젝트에 참여하게 되었습니다. (운이 정말 좋았음..) 혼자 하는 프로젝트보다는 같이 하는 프로젝트가 조금 더 동기 부여가 되었기 때문에 정말 좋은 기회를 잡았던 것 같습니다.

특히 저보다 잘 하시는 분이 많아 조금 위축되기도 했었지만 위축된 만큼 열심히 노력을 했더니 배운 게 정말 많았습니다.

배운 점 (정말 많이 배움)

FetchType이 뭘까?

저는 ERD에 그려져있는 것 중에서 Archive 테이블에 관련된 코드들을 작성하게 되었습니다.

그러다가, 다른 분들이 JPA로 Foreign key를 설정하는 것을 보고, FetchType.LAZY를 보고 궁금증이 들었습니다.

인터넷을 검색해보니, FetchType.LAZY는 Foreign Key로 설정한 것을 바로 조인 되지 않도록 한다고 하였습니다.

이에 반해 FetchType.Eager는 Foreign Key로 설정되면 바로 조인이 되어서 성능에 문제가 있다고 합니다.

DTO를 Camel Case에서 Snake Case로 바꾸기

저는 DTO의 내용물을 ResponseEntity에 담아 json 형식으로 바꾸는 건 알지만, 안에 있는 key 값이 Java에서 작성한 Camel Case를 어떻게 Snake Case로 바꾸는지 몰랐습니다.

하지만 팀원분들 덕분에, 총 두 가지의 방법으로 key값을 Snake Case로 바꾸는 방법을 알게 되었습니다.

1. JsonNaming Annotation을 이용해서 Snake Case로 바꾸기

@Data
@JsonNaming(value=PropertyNamingStrategies.SnakeCaseStrategy.class)
public class ArchiveDto {
    private Long archiveSeq;
    private String result;
    private String type;
    private LocalDateTime createdAt;

    public ArchiveDto(Archive archive){
        archiveSeq = archive.getArchiveSeq();
        result = archive.getFeature().getName();
        type = archive.getFeature().getType().toString();
        createdAt = archive.getCreatedAt();
    }

}

2. JsonProperty Annotation을 이용해서 Snake Case로 바꾸기

@Data
public class ArchiveDto {
    @JsonProperty("archive_seq")
    private Long archiveSeq;
    private String result;
    private String type;
    @JsonProperty("created_at")
    private LocalDateTime createdAt;

    public ArchiveDto(Archive archive){
        archiveSeq = archive.getArchiveSeq();
        result = archive.getFeature().getName();
        type = archive.getFeature().getType().toString();
        createdAt = archive.getCreatedAt();
    }

}

위와 같이 두 가지 방법으로 Camel Case를 Snake Case로 바꿀 수 있다는 걸 알게 된 좋은 경험이었습니다.

DTO를 구조적으로 나누니 진짜 편하다.

제가 맡은 모든 테스트들의 기록들을 반환해주는 API를 구현하기 위해서 아래와 같은 Json Format 구조를 생각해봤습니다.

{
  "archives_with_categories": [
    {
      "category_id": 0,
      "category_title": "string",
      "archives": [
        {
          "archive_seq": 0,
          "result": "string",
          "type": "string",
          "created_at": "2023-07-06T09:28:49.168Z"
        }
      ]
    }
  ]
}

이를 구현하기 위해서 어떤 방식으로 데이터를 담아서 돌려줘야 할까 고려했습니다.

그리하여 첫 번째로는 기록을 담을 수 있는 DTO를 만들었습니다.

@Data
@JsonNaming(value=PropertyNamingStrategies.SnakeCaseStrategy.class)
public class ArchiveDto {
    private Long archiveSeq;
    private String result;
    private String type;
    private LocalDateTime createdAt;

    public ArchiveDto(Archive archive){
        archiveSeq = archive.getArchiveSeq();
        result = archive.getFeature().getName();
        type = archive.getFeature().getType().toString();
        createdAt = archive.getCreatedAt();
    }

}

두 번째로는 특정 테스트에 해당하는 기록들을 담는 DTO를 만들었습니다.

//카테고리에 맞는 기록들을 묶어놓은 DTO 
@Builder
@Data
@JsonNaming(value=PropertyNamingStrategies.SnakeCaseStrategy.class)
public class ArchivesWithCategory {
    private Long categoryId;
    private String categoryTitle;
    private List<ArchiveDto> archives;
}

세 번째로는 여러 테스트들의 기록들을 담는 DTO를 만들었습니다.

@Data
@Builder
@JsonNaming(value=PropertyNamingStrategies.SnakeCaseStrategy.class)
public class ArchivesWithCategories {
    private List<ArchivesWithCategory> archivesWithCategories;
}

이렇게 DTO들을 구조적으로 나누니, Service단에서 DTO에 데이터를 담아서 반환해주는 작업이 더 수월해졌으며, 특정 테스트에 해당하는 기록들을 반환하는 API를 만들 때에도 유용하게 사용하였습니다.

Swagger 사용법

지금까지 제가 했던 프로젝트는 Spring Boot와 Thymeleaf를 이용해서 개발해왔습니다. 그리하여 Spring Boot로 Rest API를 만들어본 건 이 프로젝트가 처음이었습니다.

그리하여 Swagger가 뭔지 이제야 알게 되었고, 아래와 같이 Swagger를 어떻게 사용해야하는 지에 대해 순서를 익히게 되었습니다.

CI/CD 경험

구현할 기능이 생각보다 적었기 때문에 저는 다른 팀원들에게 더 많은 기능을 맡기고, 상대적으로 적은 기능을 개발하게 되었습니다. 그리하여 프로젝트 참여율을 보완하기 위해서 클라우드 및 CI/CD 쪽을 맡게되었습니다.

CI/CD라는 건 솔직히 이야기만 들어봤지만 실제로 경험해보는 건 처음이라 많이 두근거렸습니다. 그리하여 열심히 CI/CD의 정확한 개념이 뭔지 알아보고, Github Action을 통해 직접 적용해보기도 했습니다.

그리고 처참히 실패했습니다...

하지만 정말 웃기게도, 단순한 것들 때문에 약 8시간을 날렸었습니다.

그 중에서도 gradlew build 명령어는 윈도우 터미널에서 주로 사용하는 것이었어서 오류가 났었기에 ./gradlew build로 명령어를 바꿨습니다. 하지만 ./gradlew: Permission denied 에러가 떠, 또 chmod +x gradlew 명령어를 통해 권한을 수정해주어 실행을 하도록 했습니다.

이에 더해 yml에서 사용할 비밀 키들에서 에러가 났었는데 , 알고보니 비밀 키들을 Environment secrets로 둬버렸어서 에러도 났었습니다.

그리하여 얼레벌레 빠르게 Repository secrets로 키들을 이사시켜줬습니다.

최종적으로 여러 난관들을 거쳐서 CI/CD를 결국에는 성공시켰습니다.

 

진짜 행복하다.. 😃

NginX+Let’s Encrypt를 통해 HTTPS 적용하기

처음에는 별 고민도 없이 웹서버를 두지 않았고, 단순히 jar파일을 도커 컨테이너에 넣어 호스트 포트를 80번으로하여 접속할 수 있게 했습니다. 이 때는 HTTPS 설정을 왜 해야하는지 몰랐기 때문입니다.

결국에는 프론트엔드에서 API를 호출할 때 CORS에러가 나게 되었고, 이를 해결하기 위해서 SSL 설정을 해주어야 했습니다. (이젠 HTTPS 설정의 필요성을 느끼고 있습니다..)

이를 위해서 어떻게 HTTPS를 적용할지 고려해보았고, 결국은 도커 컨테이너의 호스트 포트를 80번으로 두지 않고, 8001번과 같이 임의의 번호로 호스트 포트를 설정했습니다.

후에는 NginX를 설치하였고, NginX의 conf파일을 수정하여 server_name 및 proxy_pass를 설정하였고, let’s encrypt를 설치하여 SSL을 설정하였습니다.

마지막으로, load balancer 설정을 하기 위해 upstream 설정해주기도 하였습니다.

이러한 과정들을 통해 HTTPS 연결을 할 수 있었고, 프론트엔드의 CORS 에러를 해결할 수 있었습니다.

HTTPS 환경에서 Swagger 사용하기

SNginx로 HTTPS 설정을 한 뒤, Swagger에 들어가 테스트를 해보았습니다. 그러나 이상하게도 http:// 로 API 요청을 보내 Swagger에서 CORS 에러가 났었습니다. (이젠 CORS가 싫다)

그리하여 인터넷 검색을 통해 OpenAPIDefinition 어노테이션을 이용해 고쳐냈습니다.

 

Comments