Blog
About Me
citeFred’s Blog
/
Blog Post
/
[NestJS] 0. NestJS 들어가기
Blog
About Me
citeFred’s Blog
/
Blog Post
/
[NestJS] 0. NestJS 들어가기
Share
Blog
About Me
[NestJS] 0. NestJS 들어가기
Category
Programming Study
Author
Tags
NestJS 과정
PinOnMain
1 more property
NestJS, TypeORM 이해하기
Table of Content
NestJS를 통한 백엔드 서버 구축
NestJS Tutorials
[NestJS] 1. NestJS 소개
[NestJS] 2. NestJS 기본 요소
[NestJS] 3. NestJS CRUD Operation 개발
[NestJS] 4. Pipe를 통한 유효성 체크와 예외처리
[NestJS] 5. DB와 TypeORM 연동
[NestJS] 6. DB+TypeORM → CRUD Operation 연동 리팩토링 | 🎯 중요
[NestJS] 7. 회원가입 및 로그인 인증 구현과 JWT | 🎯 중요
[NestJS] 8. 엔터티의 연관 관계(Relationships) feat. 문제 인식과 해결
[NestJS] 9. 로깅과 AOP
NestJS R&D
[NestJS] 10. 프로젝트 문제 인식과 컨벤션 리팩토링, 트러블 슈팅
[NestJS] 11. 심화 목표 키워드
[NestJS] 12. Kakao 다음 우편번호 API 주소 입력 추가
[NestJS] 13. 게시글 페이징(Pagenation)과 무한스크롤(Infinity Scroll)
[NestJS] 14. Kakao API 소셜 로그인 기능 구현(OAuth)
[NestJS] 15. CSR과 프론트엔드의 API 요청(Fetch API / HttpClient API)
[NestJS] 16. 파일 입출력(I/O) 기능 구현
[NestJS] 17. 게시글 및 회원 관리 기능 보완(CRUD) 리팩토링
[NestJS] 18. 프론트엔드의 접근 권한 설정(Guard)과 데이터 로드(Resolver)
[NestJS] 19. Slide(Swiper) 기능 구현
[NestJS] 20. Architecture Diagram 그리기와 README.md 프로젝트 소개 꾸미기
[NestJS] 21. AWS 클라우드 서비스와 배포
… 계속하여 추가 기능 개발
Related Posts
Search
클라이언트 약식 소셜 로그인(OAuth)을 백엔드 서버 중심 인증방식으로 변경
•
보안 및 관례상 프로덕션 환경에서는 Credential 획득 및 관리를 백엔드에서 처리하는 것이 일반적인 관례이자 더 안전한 방식
•
따라서 이전 클라이언트 사이드로 Credential을 전달하던 약식 구현에서 백엔드 중앙집중식 구현으로 변경하고자 한다.
[OAuth2.0] Google Social Login 구현 - 백엔드 중앙 관리식 로직 구현
소셜 로그인은 모두 비슷한 과정
•
이전 카카오 로그인 구현과 결과적으로 동일한 과정을 거친다.
1.
인증 제공자(Provider)인 Google 디벨로퍼 콘솔에 접근해서 API 기능을 이용할 애플리케이션을 생성
2.
REST API 키
등 인증 키, 토큰 등을 받음
3.
해당 토큰과 함께 백엔드서버가 프로바이더 서버로 요청하는 중첩 구조를 만들게 됨
•
일반로그인 :
사용자 → 서버(서비스 서버) → 사용자
•
소셜로그인 : 사용자 → 서버(
서비스 서버 → 프로바이더 서버 → 서비스 서버
) → 사용자
•
실제 애플리케이션에서 구현하는 과정을 정리
[OAuth2.0] Google Social Login 구현 - 클라이언트 사이드 약식
데이터 바인딩을 위한 @Input 데코레이터
@input 데코레이터를 통한 데이터 바인딩
Angular에서 데이터 바인딩을 위한 데코레이터는 주로
@Input()
을 사용하여 부모 컴포넌트로부터 값을 받아오는 데 사용됩니다. 이 데코레이터는 자식 컴포넌트에서 부모 컴포넌트의 데이터를 바인딩할 수 있게 해줍니다.
다음은 Angular에서
@Input()
데코레이터를 사용하여 데이터 바인딩을 구현하는 간단한 예시입니다.
1.
자식 컴포넌트 생성 먼저 자식 컴포넌트를 생성하고,
@Input()
을 사용하여 데이터를 받을 준비를 합니다.
Angular의 @Input 데코레이터 사용 방법
문제 인식
•
문제 상태 분석
◦
개발PC에서 SSH로 NAS에 접근(특정 계정의 세션 ex)citefred 유저로 SSH세션 생성됨)
◦
파일업로드 관련 애플리케이션 실행(npm run start) - 해당 유저의 세션에서 실행되고 있음
◦
개발PC의 SSH로 접속한 터미널을 종료 또는 만료로 종료 되면 NAS에서도 해당 세션을 종료 시키면서 파일업로드 애플리케이션도 함께 종료됨
해결 방안 탐색
•
특정 유저가 로그인하는 방식의 SSH 세션은 결국 해당 접속을 종료하면 세션이 종료되면서 관련 프로세스가 모두 종료됨
•
따라서, NAS가 계속하여 실행되는 root 유저로 접근하면 해결 할 수 있지만 root계정으로 터미널에 접근하는 것을 개방하는 것은 위험성이 있음
•
NAS 자체에서 제공하는
Docker를 통해 실행하면 root에서 실행하는것이므로 지속적인 프로세스를 유지 할 수 있음
NAS 내 파일업로드 애플리케이션의 특정 SSH에 종속된 세션 만료 문제 + Docker와 Host의 컨텍스트 인식 문제
NAS 파일 스토리지를 활용하기
•
NAS:
◦
역할: 대용량 스토리지로서 AWS S3의 스토리지 서비스 역할 대체
◦
Nginx:
▪
역할: NAS의 정적 파일을 서빙
▪
기능: AWS S3의 정적 파일 URL 제공 역할 대체
◦
NAS 내부 파일 서버 애플리케이션:
▪
역할: NestJS API로 파일 시스템 전용 서버 기능: 서비스 백엔드 서버의 파일 시스템(I/O) 기능이 독립화된 별도 서비스
▪
매개체 역할: NAS와 서비스 백엔드 서버 간의 파일 관련 매개체 역할 수행 (리버스 프록시)
•
서비스 백엔드 서버:
◦
역할: NestJS 기반의 서비스 관련 API 서버
◦
기능: 웹 애플리케이션의 기본적인 CRUD 기능 제공
◦
데이터 저장: 파일 경로를 데이터베이스에 URL Path 형태로 저장
•
서비스 프론트엔드 서버:
◦
역할: 웹 애플리케이션의 전체 뷰 페이지 렌더링 담당
◦
기능: 백엔드 API와 통신을 통한 동적 페이지 렌더링 파일 제공: 각종 파일은 백엔드로부터 전달받는 URL Path를 통해 제공
NAS 파일서버 구축과 웹서버(Nginx)를 통한 파일 서빙
문제 인식
HTTPS 배포를 통해 모든 서버들은 SSL을 통해 HTTPS 요청/응답을 받는 구조로 변경되고 있음
•
이 중 PixelStreaming을 하는 웹시그널링서버(WebRTC/Stun-Turn Server)가 동일한 도메인 인증서를 사용하면서 프론트엔드 서비스 내에 iFrame으로 PixelStreaming 화면을 임베딩 하는 부분의 오류가 발생
•
동일 오리진에 따른 문제
•
chrome-error://chromewebdata/:1 Refused to display '
https://metaverseacademy.site:8443/
' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
해결 방안 탐색
해결 시도
•
보안을 위하여 다른 사이트에서 로드할 때 허용 범위가 지정되어 있다.
•
호출하는 사이트(A 프로젝트)는 호출 당하는 사이트(B 프로젝트)에서 막은거라 할 수 있는 일은 없다.
•
호출 당하는 사이트(B 프로젝트)에서 X-Frame-Options 설정을 해준다.
◦
DENY: 시도하는 사이트에 관계없이 페이지를 프레임에 표시 X
◦
SAMEORIGIN: 페이지는 모든 조상 프레임이 페이지 자체와 동일한 출처인 경우에만 표시
•
호출당하는 입장인 B 프로젝트에서 응답 헤더에 X-Frame-Options를 세팅해서 보내주어야 한다.
•
httpResponse.setHeader("X-Frame-Options", "allow-from A프로젝트 IP주소:포트번호");
httpResponse
.
setHeader
(
"X-Frame-Options"
,
"allow-from http://localhost:8080"
)
;
Java
복사
해결 시도와 결과
호출 당하는 입장인 Pixel Streaming의 서버에서 헤더 추가 설정 필요
•
아래는 SignalingWebServer의 cirrus.js의 부분이다.
•
해당 서버 프로젝트는
helmet
은 HTTP 헤더를 설정하여 앱을 일반적인 웹 취약점으로부터 보호하는 데 도움이 되는 Express.js 미들웨어를 사용하고 있는 것으로 파악되었다.
if
(
config
.
UseHTTPS
)
{
app
.
use
(
helmet
(
)
)
;
app
.
use
(
hsts
(
{
maxAge
:
15552000
// 180 days in seconds
}
)
)
;
//Setup http -> https redirect
console
.
log
(
'Redirecting http->https'
)
;
app
.
use
(
function
(
req
,
res
,
next
)
{
if
(
!
req
.
secure
)
{
if
(
req
.
get
(
'Host'
)
)
{
var
hostAddressParts
=
req
.
get
(
'Host'
)
.
split
(
':'
)
;
var
hostAddress
=
hostAddressParts
[
0
]
;
if
(
httpsPort
!=
443
)
{
hostAddress
=
`
${
hostAddress
}
:
${
httpsPort
}
`
;
}
return
res
.
redirect
(
[
'https://'
,
hostAddress
,
req
.
originalUrl
]
.
join
(
''
)
)
;
}
else
{
console
.
error
(
`
unable to get host name from header. Requestor
${
req
.
ip
}
, url path: '
${
req
.
originalUrl
}
', available headers
${
JSON
.
stringify
(
req
.
headers
)
}
`
)
;
return
res
.
status
(
400
)
.
send
(
'Bad Request'
)
;
}
}
next
(
)
;
}
)
;
}
JavaScript
복사
•
실제로 파라미터로 UseHttps boolean을 받는 것으로 보아
HTTPS 사용 시에만
helmet
적용:
helmet
미들웨어는
config.UseHTTPS
가
true
일 때만 활성화되고 있다.
•
helmet
설정 변경으로
helmet()
호출 시에
frameguard
옵션을 명시적으로 설정하여
X-Frame-Options
헤더의 동작을 변경하고자 한다.
1.
첫번째로 해당 부분이 실질적으로 위 문제를 발생시키는지 확인
하기 위하여
frameguard
옵션 자체를 비활성화 해본다.
if
(
config
.
UseHTTPS
)
{
app
.
use
(
helmet
(
{
frameguard
:
false
// frameguard 미들웨어 비활성화
}
)
)
;
app
.
use
(
hsts
(
{
maxAge
:
15552000
// 180 days in seconds
}
)
)
;
JavaScript
복사
•
이를 통해 해당
helmet
미들웨어가 해당 부분을 제어하고 있는 것으로 파악
되었다.
2.
이 상태로는 보안상 취약점을 발생 시킬 수 있으므로 명시적으로 해당 도메인에 대한 출처 허용으로 스코프를 좁히고자 한다.
if
(
config
.
UseHTTPS
)
{
app
.
use
(
helmet
(
{
frameguard
:
false
// frameguard 미들웨어 비활성화
}
)
)
;
app
.
use
(
(
req
,
res
,
next
)
=>
{
res
.
setHeader
(
"Content-Security-Policy"
,
`
frame-ancestors 'self' https://metaverseacademy.site:443 https://www.metaverseacademy.site:443;
`
)
;
next
(
)
;
}
)
;
app
.
use
(
hsts
(
{
maxAge
:
15552000
// 180 days in seconds
}
)
)
;
...
JavaScript
복사
이렇게 헤더를 추가 설정해준다. 이후 모바일로도 문제 없이 실행되는 모습
Refused to display in a frame because it set 'X-Frame-Options' to 'sameorigin'.
샘플 모습
1.
프론트엔드의 파일 업로드 요청 시작
2.
백엔드 컨트롤러의 요청 흐름
a.
(백엔드) 컨트롤러 요청 도착 → (백엔드) 파일 서비스 전달
b.
(백엔드) 파일 서비스 → (NAS) 파일 저장 서버 컨트롤러로 요청
c.
(NAS) 파일 저장 컨트롤러 → NAS 파일 서비스 → NAS 스토리지 내 저장
d.
(백엔드) 파일 정보 및 NAS 정적 서빙 경로 데이터베이스 저장
3.
프론트엔드의 파일 데이터베이스 목록 조회 화면
4.
강의실의 시청 화면 진입 모습
5.
시청 화면 요청 시 NAS의 웹서버로부터 서빙되는 영상의 모습
백엔드서버→NAS API 파일 업로드→NAS 영상 서빙 뷰 페이지 반환까지의 구현 샘플
도메인 구매 후, DNS 관리페이지 -> A Record 설정 -> 서버 외부 IP 연결
•
http://www.metaverseacademy.site
•
http://metaverseacademy.site/
•
두개의 접근 주소 HTTP 일반 배포 상태 확인 (이후 → SSL 발급 후 HTTPS 보안 배포로 연결)
자체 서버(로컬) HTTPS 배포를 위한 WACS를 통한 자체 Let’s Encrypt 인증서 발급과 연결
Standalone?
Standardalone?
Angular에서 "Standalone" 컴포넌트는 Angular 14 이상에서 도입된 기능으로, 모듈 없이 독립적으로 사용할 수 있는 컴포넌트를 의미합니다. 이는 컴포넌트의 재사용성과 관리성을 높이며, 더 간편하게 애플리케이션을 구성할 수 있게 해줍니다.
Standalone 컴포넌트의 특징
1.
모듈 불필요: 기존의 Angular 컴포넌트는 반드시 모듈에 포함되어야 했지만, Standalone 컴포넌트는 독립적으로 사용할 수 있습니다.
컴포넌트의 standalone의 필요성과 적용 범위 고려
|
Main Page
|
Category
|
Tags
|
About Me
|
Contact
|
Portfolio