ElysiaJS의 개쩌는 점

구름미각·2024년 3월 19일
9


https://elysiajs.com/

우선 우리가 기존에 알던 ExpressJS에서 사용하던 방식인

app.get('/', (req, res, next)=>{
	res.send('hello');
});

같은 간단한 라우팅 방식을 지원하지만

ElysiaJS는 좀 더 사람에 맞춰 설계되었기 때문에 함수형으로 이루어져 있다.

import { Elysia } from 'elysia' 

new Elysia()
	.get('/', () => 'Hello World') 
	.listen(3000)

그리고 bun을 사용했기 때문에 기존 ExpressJS보다 21배 나 빠른 성능을 제공한다고 자랑한다.

고정 라우팅, 동적 라우팅, 와일드 카드

엔드포인트 끝에서 값을 가져와 값에 맞는 콘텐츠를 전달할 때 동적 라우팅을 사용합니다.
ElysiaJS는 함수 자체에서 파라미터를 받아와 요청을 처리할 수 있습니다.

new Elysia()
	.get('/id/:id', ({ params: { id } }) => 'hi '+id)

또한 하나 뿐만 아니라
여러 개의 파라미터를 받아와 요청을 처리할 수 있습니다.

new Elysia()
    .get('/id/:id', ({ params: { id } }) => 'hi '+id)
    .get('/id/:id/:name', ({ params: { id, name } }) => 'hi '+id + ' and ' + name)

만약 파라미터의 개수에 제한을 두고 싶지 않다면 와일드 카드를 사용할 수 있습니다.
사용법은 간단합니다 기존 :id를 둔 공간에 *만 넣고 원하는 파라미터를 받아와 요청을 처리할 수 있습니다.

new Elysia().get('/id/*', ({ params }) => params['*']).listen(3000)

메소드

우리가 알고 있는 라우팅 메소드는 GET, POST, DELETE, PUT, PATCH 등등 기본적으로 http에서 기본적으로 사용되는 메소드로 사용합니다.

const app = new Elysia()
    .get('/', () => 'hello')
    .post('/hi', () => 'hi')
    .listen(3000)

또한 메소드를 특정할 수 없을 때 .all()을 사용해 모든 메소드에 대한 요청을 받을 수 있습니다.

new Elysia().all('/', () => 'hi').listen(3000)

프레임워크는 다릅니다.
한 가지 특징이 하나 있는 데, 커스텀 메소드라는 기능입니다.
따로 엔드 포인트에 커스텀 메소드를 추가해 모든 메소드를 사용하고도 더 추가하고 싶은게 있을 때 새로 메소드를 만들 수 있습니다.

const app = new Elysia() 
	.get('/', () => 'hello') 
	.route('search', '/', () => 'connect') 
	.listen(3000)

자체 테스트

보통 많은 개발자들이 Postman과 같은 REST 클라이언트를 많이 쓰는데 여기에선 그럴 필요 없습니다.
그냥 여기서 자체 테스트를 지원하거든요.
Elysia.handle이라는 함수를 쓰시면 됩니다.

const app = new Elysia()
    .get('/', () => 'hello')
    .post('/hi', () => 'hi')
    .listen(3000)

app.handle(new Request('http://localhost/')).then(console.log)

이러면 좀 더 간편하게 테스트가 가능하겠죠?

set response

set.status

set을 사용해 status를 조작 가능하다.

new Elysia()
    .onBeforeHandle(({ set }) => {
        set.status = 418

        return 'I like tea'
    })
    .get('/', () => 'hi') //성공했을 경우에 200을 status로 지정

//또는
new Elysia()
    .get('/', ({ set }) => {
        // with auto-completion
        set.status = "I'm a teapot"

        return 'I like tea'
    })

set.headers

set을 이용해 헤더를 조작 가능하다.

new Elysia()
    .get('/', ({ set }) => {
        set.headers['x-powered-by'] = 'Elysia'

        return 'a mimir'
    })
    .listen(3000)

set.redirect

set을 이용해 리다이렉션을 설정가능하다.

new Elysia()
    .get('/', ({ set }) => {
        set.redirect = 'https://youtu.be/whpVWVWBW4U?si=duN5cBbJuWgCrQRA&t=8'
    })
    .listen(3000)

에러일 경우에는

기본적으로 404 같은 오류를 일으킬 경우 따로 에러를 던져버리지만

throw new Error();

ElysiaJS같은 경우에는 다르다.
만약 중간에 DB와 연결을 시도했지만, 실패했을 경우는 그냥 try catch 사용해서 에러 처리를 하시면 되는 데,

new Elysia() 
	.get('/', ({error}) => {
		try{
			//님들 코드적어둔거
		}.catch(err){
			error(500, err);
		}
	});

상대가 오류란 것을 알 수 있게 error() 함수를 사용해서 status와 메시지를 보낼 수 있습니다.(추천)
아니면 set.status를 사용해서 상태를 결정해 에러를 처리할 수 있다.

new Elysia()
    .onBeforeHandle(({ set }) => {
        set.status = 418

        return 'I like tea'
    })
    .get('/', () => 'hi') //성공했을 경우에 200을 status로 지정

//또는
new Elysia()
    .get('/', ({ set }) => {
        // with auto-completion
        set.status = "I'm a teapot"

        return 'I like tea'
    })

ElysiaJS는 표준 요청/응답을 기반으로 만들어져 있어서 그냥 문자열만 return 해도 아무 상관이 없지만 Resposne() 클래스를 사용하는 것을 더 선호한다면 사용할 수 있습니다. 물론 결과는 같겠지요.

import { Elysia } from 'elysia'

new Elysia()
    .get('/', () => new Response('hi'))
    .listen(3000)

정적 콘텐츠 전달법

ElysiaJS는 정적 콘텐츠를 import 하지 않아도 경로만 있다면 알아서 읽고 콘텐츠를 전달합니다.
음악파일이나 이미지파일 또는 영상파일을 보내더라도 방법은 같습니다. 그냥 파일을 보내주는 것 뿐이니까요.

import { Elysia } from 'elysia'

new Elysia()
    .get('/video', Bun.file('kyuukurarin.mp4'))

서버 state 설정(Store)

Store는 ElysiaJS 앱에서 글로벌로 변경 가능한 오브젝트, 상태이다.
이는 마치 프론트엔드 상에서 사용하는 state와 비슷한 경험을 제공합니다.
state는 사용하기 이전에 무조건 등록 돼야 합니다.

new Elysia()
    .state('version', 1)
    .get('/', ({ store: { version } }) => version)

Decorate(불변)

Decorate는 직접 context에 속성을 할당합니다.
기존 store와 다른 점은 Decorate는 읽기 전용이며, 다시 할당할 수 없습니다.
변하지 않는 속성을 할당하기 위해 합리적인 방법입니다.
마찬가지로 사용하기 전 먼저 할당되어 있어야 합니다.

new Elysia()
    .decorate('logger', new Logger())
    // ✅ 앞 줄이 먼저 선언되어야 함
    .get('/', ({ logger }) => {
        logger.log('hi')

        return 'hi'
    })

Derive

Decorate와 비슷하게, 직접 context에 속성을 할당할 수 있지만,
서버가 시작되기 전에 할당하는 대신 요청이 발생할 때마다 할당을 일으킵니다.
일반적으로 파생(기존에 있던 것을 기반으로 생성)만 가능합니다.

new Elysia()
    .derive(({ headers }) => {
        const auth = headers['authorization']
        return {
            bearer: auth?.startsWith('Bearer ') ? auth.slice(7) : null
        }
    })
    .get('/', ({ bearer }) => bearer)

state에 값을 넣는 방법

키-값
오브젝트
Remap(다시 선언하기)

new Elysia()
    .state('counter', 0) //key-value
    .state('logger', {  //Object
	    logger: new Logger(), 
	    trace: new Trace(), 
	    telemetry: new Telemetry() 
	})
    .state('counter', 0)
    .state('version', 1)
    .state(({ version, ...store }) => ({ //Remapping
        ...store,
        elysiaVersion: 1
    }))
    // ✅ remapping으로 인해 새로 만들어짐.
    .get('/', ({ store }) => store.elysiaVersion)
    // ❌ remapping으로 인해 제외됨.
    .get('/', ({ store }) => store.version)

Affix

보다 원활한 환경을 제공하기 위해 일부 플러그인에는 하나씩 다시 매핑하기에는 부담스러운 속성이 있을 수 있으므로, prefix와 suffix가 있는 Affix를 사용한다면 인스턴스에 있는 모든 속성을 다시 매핑할 수 있다.

const setup = new Elysia({ name: 'setup' })
    .decorate({
        argon: 'a',
        boron: 'b',
        carbon: 'c'
    })

const app = new Elysia()
    .use(setup.prefix('decorator', 'setup'))
    .get('/', ({ setupCarbon }) => setupCarbon)

참조와 값

값을 변화 시키기 위해 직접 만질 필요가 없고 참조를 사용해 값을 변화 시키는 것이 중요하다.
자바스크립트에서 속성에 접근할 때, 직접 만지게 될 경우에는 참조가 사라지고, 새로운 값으로 변화시키기 때문이다.

우린 아래에서 store.counter 값을 접근할 수 있다.

const store = {
    counter: 0
}

store.counter++
console.log(store.counter) // ✅ 1

하지만 아래와 같이 새로운 값으로 참조를 하게 될 경우 참조에 접근할 수 없다.

const store = {
    counter: 0
}

let counter = store.counter

counter++
console.log(store.counter) // ❌ 0
console.log(counter) // ✅ 1
import { Elysia } from 'elysia'

new Elysia()
    .state('counter', 0)
    // ✅ 참조를 사용했기 때문에 값이 공유됨.
    .get('/', ({ store }) => store.counter++)
    // ❌ 새로운 값이 덮어 씌웠기 때문에, 연결이 사라짐
    .get('/error', ({ store: { counter } }) => counter)

우선 여기까지만 적겠다.
더 많은 내용이 문서에 있지만 제대로 적지 못한 것이 많다.
자세한 것은 공식 문서를 보는 걸 추천한다.

profile
(돈과 인맥을 만들어 나가는)학생 개발자

2개의 댓글

comment-user-thumbnail
2025년 2월 19일

개쩌는점 2
https://dl.acm.org/doi/abs/10.1145/3605098.3636068

아니 논문이 있다..............

1개의 답글

관련 채용 정보