Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 외부링크 유효성검사/랜딩페이지 조회/삭제 API 구현 #297

Merged
merged 8 commits into from
Jun 17, 2024

Conversation

choyoungwoo9
Copy link
Collaborator

🎟️ 태스크

(백엔드) 외부 링크 추가 API에 대한 유효성 검사
(백엔드) 랜딩페이지 접속시 외부링크 정보 전송하기
(백엔드) 외부 링크 삭제 API 구현

✅ 작업 내용

  • 외부 링크 추가 API에 대한 유효성 검사
  • 랜딩페이지 접속시 외부링크 정보 전송하기
  • 외부 링크 삭제 API 구현

🖊️ 구체적인 작업

외부 링크 추가 API에 대한 유효성 검사

  • 유효하지 않은 URL에 대한 e2e 테스트 추가
  • 검증로직 추가

랜딩페이지 접속시 외부링크 정보 전송하기

  • 랜딩페이지 접속시 프로젝트의 링크 리스트를 반환하는지 확인하는 E2E테스트 추가
    • 프로퍼티 이름을 link에서 linkList로 변경
  • 프로젝트의 링크를 반환하는 서비스, 레포지토리 구현
  • 랜딩페이지 접속시 프로젝트의 링크 리스트를 반환하게 구현
    • initLandingDto에서 linkDto클래스 만들어 link의 데이터 형식을 만들도록 구현
    • 웹소켓 게이트웨이에서 접속시 link정보 함께 반환하도록 구현

외부 링크 삭제 API 구현

  • 링크 삭제 E2E 테스트 추가
  • 링크삭제 서비스, 레포지토리 구현
  • 링크 삭제 API 구현
    • 웹소켓 게이트웨이에서 링크 삭제 요청시 삭제 후 브로드캐스팅하도록 구현
    • 링크삭제 요청 DTO 추가

🤔 고민 및 의논할 거리

  • 유효한 URL임을 판단하는 로직이 컨트롤러에 들어가야할지 서비스에 들어가야할지 고민해보았고 컨트롤러에 넣기로 결정했습니다. 왜냐하면 컨트롤러(프레센테이션 계층)의 역할 중 하나가 입력을 처리하는것인데 유효성검사하고자 하는 URL은 클라이언트의 입력이기 때문입니다.
  • 가장 고민이 되었던 부분은 유효한 URL을 판별하는게 비즈니스로직인가? 였습니다. 만약 비즈니스 로직이라면 서비스 계층에 들어가야 할 거라고 생각되었습니다.
  • 그러나 URL을 판별하는것은 비즈니스로직이라고 보기 힘들다고 결정했습니다. 비즈니스 로직이라 함은 서비스가 하고자 하는 중요한 의사결정을 코드로 표현한 것입니다. 만약 URL을 특정 사이트(ex)레서 내 사이트 혹은 협약을 맺은 사이트)로 제한하거나 특정 사용자(ex)팀장)만 URL을 등록할 수 있다면 우리서비스가 하고자 중요한 의사결정이므로 비즈니스로직일 수 있습니다. 하지만 저희가 원하는것은 유효한 URL형식을 확인하는 정도이기 때문에 비즈니스로직이 아니라고 생각했습니다.
  • 이러한 고민과 의사결정을 태스크 문서에 적어놓았습니다. 궁금하시면 한번 구경해주세용~

- 유효하지 않은 URL에 대한 e2e 테스트 추가
- 검증로직 추가
- 랜딩페이지 접속시 프로젝트의 링크 리스트를 반환하는지 확인하는 E2E테스트 추가
- 프로퍼티 이름을 link에서 linkList로 변경
- 프로젝트의 링크를 반환하는 레포지토리 구현
- 프로젝트의 링크를 반환하는 서비스 구현
- initLandingDto에서 linkDto클래스 만들어 link의 데이터 형식을 만들도록 구현
- 웹소켓 게이트웨이에서 접속시 link정보 함께 반환하도록 구현
- 링크 삭제 서비스 구현
  - 테스트 추가
- 링크 삭제 레포지토리 구현
- 웹소켓 게이트웨이에서 링크 삭제 요청시 삭제 후 브로드캐스팅하도록 구현
- 링크삭제 요청 DTO 추가
@choyoungwoo9 choyoungwoo9 added BE 🎉feature 새로운 기능 labels Jun 17, 2024
@choyoungwoo9 choyoungwoo9 requested a review from kimsj-git June 17, 2024 02:12
Comment on lines +11 to +39
function IsURL() {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'IsURL',
target: object.constructor,
propertyName: propertyName,
options: { message: 'invalid url format' },
validator: {
validate(value: any) {
const URLPattern = new RegExp(
'^(https?:\\/\\/)' +
'((([a-z\\d가-힣]([a-z\\d가-힣-]*[a-z\\d가-힣])*)\\.?)+[a-z가-힣]{2,}|' +
'((\\d{1,3}\\.){3}\\d{1,3}))' +
'(\\:\\d+)?' +
'(\\/[-a-z\\d%_.~+가-힣]*)*' +
'(\\?[;&a-z\\d%_.~+=-가-힣]*)?' +
'(\\#[-a-z\\d_가-힣]*)?$',
'i',
);
return URLPattern.test(value);
},
},
});
};
}

class Link {
@IsString()
@IsURL()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

커스텀 데코레이터를 만드셨군요👍

Comment on lines 242 to 268
const expectCreateLinkAndReturnFirstLinkId = (socket, url, description) => {
return new Promise<void>((resolve, reject) => {
socket.on('landing', async (data) => {
const { content, action, domain } = data;
expect(domain).toBe('link');
expect(action).toBe('create');
expect(content?.description).toBe(description);
expect(content?.id).toBeDefined();
expect(content?.url).toBe(url);
expect(content?.description).toBe(description);
socket.off('landing');
resolve(content.id);
});
});
};

const expectDeleteLink = (socket, linkId) => {
return new Promise<void>((resolve, reject) => {
socket.on('landing', async (data) => {
const { content, action, domain } = data;
expect(domain).toBe('link');
expect(action).toBe('delete');
expect(content?.id).toBe(linkId);
socket.off('landing');
resolve();
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

socket.once()를 사용하면 socket.off('landing') 부분을 제거할 수도 있지 않을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은아이디어라고 생각합니다! 즉시 적용할게요~

Comment on lines 92 to 93
if (result) return true;
else return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분을 이렇게 바꿔도 간결하고 의미 전달이 잘 될거같은데 어떻게 생각하시나요?🤔

return result ? true : false

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삼항연산자는 항상 생각이 잘 안나는 것 같아요. 좋다고 생각합니다! 바로 적용할게요~

- socket.on후 socket.off로 이벤트의 리스너를 지우는 방식을 socket.once로 이벤트 발생시 바로 한번만 호출되고 리스너가 없어지도록 변경
- 삼항연산자를 사용해 더 짧고 가독성있게 변경
@kimsj-git kimsj-git merged commit 1ea93a5 into dev Jun 17, 2024
1 check passed
@kimsj-git kimsj-git deleted the feature/create-external-link branch June 17, 2024 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BE 🎉feature 새로운 기능
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants