본문 바로가기

외부 활동/JSCODE[NEST]

2회차 익명 게시판 서비스 개발 시작!

Level 2 

이번 레벨 부터 본격적으로 서비스 개발을 시작한다.

학습 목표

  • URL, Http Method를 활용한 기본 라우팅 방법 학습
  • Request Body, Query Params, Path Params 사용해보기
  • ORM 사용
    • 엔티티(테이블) 생성
    • 기본적인 CRUD 활용
  • 요청부터 응답까지 전체 과정 경험
  • REST API 설계
  • HTTP Status Code (상태 코드)
  • Postman 사용법

 

요구 사항

  1. 게시글 작성 기능
  • 게시글은 제목, 내용을 포함한다.
  • 게시글이 저장될 때, id(PK, primary key)도 같이 Auto-increment 형식으로 저장돼야 한다.
  • 게시글 작성에 성공했을 때, 응답값으로 작성된 게시글에 대한 정보를 보여주어야 한다.
  1. 게시글 전체 조회 기능
  • 게시글을 조회할 때 id, 제목, 내용의 값이 포함돼야 한다.
  1. 특정 게시글 조회 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 조회한다.
  • 게시글을 조회할 때 id, 제목, 내용의 값이 포함돼야 한다.
  1. 특정 게시글 수정 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 수정할 수 있어야 한다.
  • 게시글의 제목, 내용을 수정할 수 있다.
  • 게시글 수정에 성공했을 때, 응답값으로 수정된 게시글에 대한 정보를 보여주어야 한다.
  1. 특정 게시글 삭제 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 삭제할 수 있어야 한다.

 

 

 

우선 첫번째로 게시판의 정보를 저장할 데이터베이스 생성을 먼저 진행 하였다.

첫 데이터베이스 생성을 하며 나는 아직 기본 개념이 부족하다는  것을 깨달았다.

현재 데이터 그립에서 하는게 어떤 환경에서 왜 하는지를 모르고 여지껏 프로젝트를 팀원들을 따라 해왔던 것이었다.

 

 

우선 mysql -u root -p를 사용하여 루트 사용자로 로그인을 한다. 

그러면 mysql 클라이언트 프로그램이 실행되고 데이터베이스 서버에 로그인 할 수 있다.

그리고 show databases;를 입력하면 생성한 데이터 베이스를 확인 할 수 있다.

 

 

MYSQL를 만들어 생성.

처음 Name은 왼쪽에 뜨는 Project Data Sources이며  Hoet는 localhost 포트는 맞게 생성해 주되 주로 mysql은 3306이다,.

 

그리고 User와 Password를 입력하면 된다.

 

rds를 이용할 경우 aws에서 데이터베이스 생성시 만든 계정으로 하고 Host는 엔드 포인트로 한다.

하지만 이번에는 로컬에서 진행을 하므로 locahost로 Host를 맞추며 root계정으로 진행을 하였다.

 

 

그리고 Post 테이블을 만들어 준다.       그리고 오른쪽은 이미 postman을 사용하여 데이터를 넣은 결과이다.

 

 

 

이전의 데이터베이스 소스가 왼쪽 창에 뜨지 않아 다시 기록하려 한다.

databaseExplorer창에 내가 사용하려는 데이터베이스가 없을경우

다시 처음부터datasource를 생성한뒤 

 

 

 

 

콘솔에 데이터베이스들이 뭐뭐 있는지 확인하고

 

 

 

 

 

 

 

 

 

 

 

 

이제 다시 본격적으로 코딩을 시작해보려고한다.

개발을 마친 컨트롤러와 서비스단의 코드이다.

 

우선 기본적인 게시판생성 조회 삭제 수정 로직은 이해를 하였다.

하지만 아직 typeorm의 내장 함수들에 대해는 잘 모르는것 같다.

구글링을 통해 해결 하긴 했지만 공식 문서를 참조하여 정보를 얻는 습관을 기르려고 노력해야겠다.

 

 

 

 

 

Level 3 익명 게시판’의 기능 추가 (정렬, 검색, 개수 제한)

학습 목표

  • 정렬 기능
  • 검색 기능
  • 데이터 조회 시 limit 걸기
  • createdAt 컬럼 배우기

✅ 요구 사항

  1. 게시글 작성 기능
  • 게시글에 생성 시간도 같이 저장한다.
  1. 게시글 전체 조회 기능
  • 게시글을 조회할 때 생성 시간의 값도 포함돼야 한다.
  • 최근에 작성된 순으로 게시글이 조회되어야 한다.
  • 데이터 조회 개수는 최대 100개까지만 할 수 있어야 한다.
  1. 특정 게시글 조회 기능
  • 게시글을 조회할 때 생성 시간의 값도 포함돼야 한다.
  1. 특정 게시글 수정 기능
  • (추가 요구사항 없음)
  1. 특정 게시글 삭제 기능
  • (추가 요구사항 없음)
  1. 게시글 검색 기능
  • 검색 키워드로 게시글을 검색할 수 있어야 한다.
  • 검색 키워드가 포함된 제목을 가진 게시글을 전부 조회한다.
  • 최근에 작성된 순으로 게시글이 조회되어야 한다.
  • 데이터 조회 개수는 최대 100개까지만 할 수 있어야 한다.

 

 

우선 게시글 생성 시간을 저장하기 위해 데이터베이스에 컬럼을 추가 해준다 

 

그리고 Post. entity에 

 @CreateDateColumn({ name: 'created_at' })
  createdAt: Date | null;

를 추가 해준다. 처음 Data만 반환형으로 적어 이전에 null이었던 값들이 데이터 베이스에 처음 입력한 시간으로 거진 입력이 된것을 확인하였다 아마 | null을 추가 하지 않아서 무조건 Date 타입으로 입력이 되었다고 생각을 한다.

 

 

 

그리고 서비스 단에서 typeorm을 사용하여 

조회 개수를 take를 사용하여 맞혀 주고

정렬 순서를 createdAt에 맞혀서 정렬하였다.

 

 

 

 

 

그리고 마지막으로 게시글 검색 기능을 구현 하였다.

파라미터로 제목을 받아오게 url을 구성을 하고 서비스 단에서 typeorm에서 제공해주는 sql의 쿼리문?을 사용하여 제목이 포함된 게실물을 조회하게 하였다.

 

 

 

환경변수 설정

$ npm i --save @nestjs/config

그러면 .env를 사용할 수 있게 된다.

import를 시켜준다.

 

 

 

 

 

 

가장 상위 경로에서 .env를 만들어 주고 

 

음 우선 env가 인식을 안하는 관계로 우선 PASS

 

 

Level 4 ‘익명 게시판’의 기능 추가 (유효성 검사, 예외 처리)

 

학습 목표

  • 유효성 검사
  • 예외 처리

✅ 요구 사항

  1. 게시글 작성 기능
  • 게시글 제목, 내용은 필수적으로 포함해야 한다.
  • 제목은 1글자 이상 15글자 이하여야 한다.
  • 내용은 1글자 이상 1000글자 이하여야 한다.
  • 제목은 공백으로만 이루어질 수는 없다.
  1. 특정 게시글 조회 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기
  1. 특정 게시글 수정 기능
  • 게시글 작성할 때의 유효성 검사 조건과 동일하게 가져가야 한다.
  1. 특정 게시글 삭제 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 삭제하기 위해 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기
  1. 게시글 검색 기능
  • 검색 키워드는 공백을 제외한 1글자 이상이어야 한다.

 

 

 

 

 

 

  1. 게시글 작성 기능
  • 게시글 제목, 내용은 필수적으로 포함해야 한다.
  • 제목은 1글자 이상 15글자 이하여야 한다.
  • 내용은 1글자 이상 1000글자 이하여야 한다.
  • 제목은 공백으로만 이루어질 수는 없다.

우선 유효성 검사를 위해 패키지를 설치한다.

 

 npm i --save class-validator class-transformer

main.ts에 

app.useGlobalPipes(new ValidationPipe());를 추가

 

 

  1. 특정 게시글 조회 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기

 

 

 

 

 

 

 

  1. 특정 게시글 수정 기능
  • 게시글 작성할 때의 유효성 검사 조건과 동일하게 가져가야 한다.

 

 

 

 

  1. 특정 게시글 삭제 기능
  • 게시글의 id(PK, primary key)로 특정 게시글을 삭제하기 위해 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기

 

 

  1. 게시글 검색 기능
  • 검색 키워드는 공백을 제외한 1글자 이상이어야 한다.

 

 

 

안된다..==> 질문 ㄱㄱ

 

 

 

 

 

LEVLE 5 협업의 기본, API 문서 만들기!

 

학습 목표

  • API 문서 작성

✅ 요구 사항

아래 API에 대해 API 문서를 작성해라.

  1. 게시글 작성 기능
  2. 게시글 전체 조회 기능
  3. 특정 게시글 조회 기능
  4. 특정 게시글 수정 기능
  5. 특정 게시글 삭제 기능
  6. 게시글 검색 기능

✅ 제약 조건

  • Swagger, Github Wiki, Notion, Postman, Gitbook 중 사용하기
  • API 문서에 아래의 내용은 반드시 포함시키기
    • URL 주소 / HTTP 메서드
    • API 설명
    • 요청 형태
      • Path Parmas
      • Query Params
      • Body Params
      • 필수 여부
      • 데이터 타입
    • 응답 형태
      • 응답 코드(status code)
      • 각 응답 코드별 설명
      • 응답 형태 (response value)
      • 응답 값에서 각 파라미터의 의미
      • 응답 값에서 각 파라미터의 필수 여부
      • 응답 값에서 각 파라미터의 데이터 타입

 

나는 nest를 쓰는 만큼 Swagger를 사용하여 api문서를 작성하고자 한다.

 

 

npm install --save @nestjs/swagger

그리고 공식문서에 맞게 main.ts에 코드를 작성해 준다.

이러면  http://localhost/api  로 가면 swagger 볼 수 있다.

 

 

 

==> dto에 대한 설명 ( 파라미터)

 

 

 

==> 쿼리에 대한 설명( 파라미터)

 

 

나머지는 차차 구글링과 공식문서등을 통해 부족한 부분을 채웠다.

 

 

 

 

 

 

 

 

+ 막힌 부분 해결

 

1.  port: +process.env.PORT, //이부분은 환경 변수 안되는데 질문  process.env.PORT  3306 에서

string 형식은 number형식에 할당할수 없다는에러가 떴다.

 

=>  1.  const port = parseInt(process.env.PORT, 10); // 10진수로 파싱하여 숫자로 변환

      2.  const port = +process.env.PORT;

 

2. 컨트롤러 구성시 Get이 먼저 나와야 하는 이유

==>

NestJS의 데코레이터(decorator)의 우선순위는 라우팅 매칭과 미들웨어 실행에 영향을 미칩니다. NestJS는 데코레이터의 우선순위를 기준으로 요청을 올바른 핸들러 함수로 라우팅하고, 미들웨어를 실행합니다.

  1. 경로 매칭 우선순위:
    • NestJS에서 경로 매칭은 가장 구체적인 경로와 HTTP 메서드에 가장 높은 우선순위를 부여합니다.
    • 경로가 더 구체적인 데코레이터는 상위에 배치되어야 합니다. 예를 들어, /users/:id와 /users/profile 경로가 있다면 /users/profile 경로를 처리하는 데코레이터가 먼저 나와야 합니다.
    • 경로에 매칭되는 핸들러 함수가 여러 개 있는 경우, 가장 먼저 일치하는 핸들러 함수가 실행됩니다.
  2. HTTP 메서드 매칭 우선순위:
    • HTTP 메서드에 따라 데코레이터의 우선순위가 있습니다. 일반적으로 @Get()이나 @Post()와 같은 HTTP 메서드 데코레이터가 가장 높은 우선순위를 가지며, 나머지 HTTP 메서드 데코레이터는 그보다 아래에 배치되어야 합니다.
    • 같은 경로에 여러 개의 HTTP 메서드 데코레이터가 존재하는 경우, 해당 경로의 요청에 가장 먼저 매칭되는 데코레이터에 해당하는 핸들러 함수가 실행됩니다.
  3. 미들웨어 우선순위:
    • NestJS의 미들웨어는 @UseGuards(), @UseInterceptors(), @UseFilters()와 같은 데코레이터를 통해 설정됩니다.
    • 미들웨어 데코레이터의 우선순위는 상위에서 하위로 내려가는 순서입니다. 즉, 상위에 위치한 미들웨어 데코레이터가 먼저 실행됩니다.
    • 미들웨어는 요청을 가로채고 수정하거나 검증하는 등의 작업을 수행할 수 있습니다. 따라서 미들웨어의 순서는 중요하며, 요청 처리 파이프라인에서 원하는 동작을 보장하기 위해 적절한 우선순위를 유지해야 합니다.

==> 이렇게 nest에서우선 순위가 있다.

 

 

3. 컨트롤러에서 ValidationPipe 사용 해결 하기 !

+해결완료

 

 

search(@Param('title') params: SearchTitleDto)

search(@Param() params: SearchTitleDto)

로 수정 하였다.

 

@Param('title') 데코레이터는 title 경로 파라미터의 값을 params 변수에 직접 할당합니다. 이 경우에는 params 객체가 아니라 title 값이 DTO(SearchTitleDto)의 인스턴스에 할당

 

 

 

4.Promise<Post>같은 반환 형에 대한 이해 부족

 

우선 반환형이 Promise인 이유는 async await를 사용해서 Pomise로 반환이 되며 Post라는 객체의 배열로 받기 때문이다.

여기서 Post는  생성자에서 선언한 DB에서 주입받은 post entity 객체이다.

  constructor(
    @InjectRepository(Post)
    private postRepository: Repository<Post>,
  ) {}

 

  • @InjectRepository(Post) : @InjectRepository() 데코레이터는 TypeORM에서 제공하는 데코레이터로, Repository 인스턴스를 주입받을 때 사용됩니다. Post는 Entity(데이터베이스 테이블에 매핑되는 클래스)를 나타냅니다. 이 데코레이터를 사용하여 postRepository에 Repository<Post> 인스턴스를 주입합니다.

 

  • private postRepository: Repository<Post> : 클래스 내부의 postRepository 멤버 변수를 선언하고, Repository<Post> 타입의 인스턴스를 할당합니다. 이를 통해 postRepository를 클래스의 다른 메서드에서 사용할 수 있게 됩니다.

이렇게 의존성 주입을 사용하면 클래스의 생성자를 통해 외부에서 필요한 의존성을 주입할 수 있습니다. 이는 코드의 유연성과 재사용성을 높여주며, 테스트와 모듈화를 용이하게 합니다. @InjectRepository() 데코레이터를 사용하여 TypeORM의 Repository 인스턴스를 주입받을 수 있으며, 해당 Repository를 통해 데이터베이스와 상호작용할 수 있습니다.

 

 

 

지금 까지 반환형을 적어주지 않고 개발을 하였는데 큰 문제가 없었다. 

이는 TypeScript의 타입 추론 기능을 통해 메서드의 반환형이 자동으로 추론되기 때문이었다.

 

그러나 명시적인 반환형을 선언하는 것은 코드의 가독성을 높이고 개발자와 동료들이 코드를 이해하기 쉽게 해준다.

 

또한, TypeScript는 명시적인 반환형을 통해 타입 체크를 보다 엄격하게 할 수 있어서 잠재적인 버그를 미리 방지하는 데 도움이 된다.  

 

즉 이런 이유에서 nestjs에서 typescript를 사용하므로 거의 무조건 적으로 반환형을 적어주도록 하자 !

 

await async와 반환형의 Promise 개념에 대해 아래 링크를 참조 하자 @!

 

 

현재도 왜 컨트롤러에서의 반형환은 Promise<Post>로하면 안되는지 이해가 안되어 그냥 뺴놓았다.

또한 반황형을 적으면 타입으로 사용되었따고 하는데 차후 깊게 공부할때 이해해보자..