๐Ÿคต๐Ÿผ์–•๊ณ  ์–•์€ ๊ฐœ๋ฐœ์ž์˜ ํฌํŠธํด๋ฆฌ์˜ค ๋งŒ๋“ค๊ธฐ 3๐Ÿคต๐Ÿผ

๋ฌธ์„ยท2021๋…„ 3์›” 14์ผ
0

๐ŸŽˆ DRF ๊ตฌ์„ฑํ•˜๊ธฐ

์„œ๋ฒ„ ๋งŒ๋“ค ๋•Œ DRF ๋Š” ์ •๋ง ํŽธ๋ฆฌํ•˜๋‹ค. ๋ง๊ทธ๋Œ€๋กœ ๋š-๋”ฑ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์šฐ์„  ๋ชจ๋ธ์„ ๋งŒ๋“ค์–ด๋ณด์ž.
class Item(models.Model): 
    id = models.IntegerField(primary_key=True)
    category = models.CharField(max_length=30)
    title = models.CharField(max_length=30)
    stack = models.CharField(max_length=200)
    markdown_content = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    
    def set_stack(self, x):
        self.stack = json.dumps(x)

    def get_stack(self):
        return json.loads(self.stack)
    
    def __str__(self):
        return self.title

    class Meta:
        db_table = "item"

from rest_framework import serializers 


class ItemSerializer(serializers.ModelSerializer): 
    class Meta:
         model = Item
         fields = ('id','category','title','stack','markdown_content','created_date')
ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋ชจ๋ธ๊ณผ Serializer๋ฅผ ์ •์˜ํ–ˆ๋‹ค. Serializer๋Š” ๋ชจ๋ธ object๋ฅผ front์—์„œ ๊บผ๋‚ด์“ฐ๊ธฐ ์‰ฝ๊ฒŒ ๊ฐ€๊ณตํ•ด์ฃผ๋Š” ๋†ˆ์ด๋‹ค. Item class์˜ set_stack, get_stack ์€ List ํ˜•ํƒœ์˜ Column์„ ๊ฐ€๊ณตํ•ด์ฃผ๊ธฐ์œ„ํ•ด ์ผ๋‹ค. SQL์—์„œ List๋ฅผ ๊ฐ€๊ณตํ•ด์“ฐ๋Š” ๊ฒƒ์€ ์šฐ์•„ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ๋ง๊ทธ๋Œ€๋กœ ํ† ์ด ํ”„๋กœ์ ํŠธ๋‹ˆ๊นŒ.
์ด์ œ View๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž
class ItemViewSet(APIView):    

    def get(request,**kwargs):
        qs = Item.objects.all()
        sc = ItemSerializer

        category = kwargs.get('category')

        qs = qs.filter(category=category)
        sc = sc(qs,many=True)
        sc = (json.dumps(sc.data))
        
        return HttpResponse(sc)
์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„๋กœ data๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ถ€๋ถ„์ด๋‹ค. react์—์„œ ์š”์ฒญํ•œ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ **kwargs๋กœ ๋ฐ›๋Š”๋‹ค. **kwargs ๋Š” ์š”์ฒญํ•œ ๊ฐ’์„ dict๋กœ ๋ฐ›์•„์ฃผ๋Š” ๋†ˆ์ธ๋ฐ ๋ณดํ†ต ์˜ˆ์ธก '๋ถˆ'๊ฐ€๋Šฅํ•œ ๊ฐ’์ด ์˜ฌ ๋•Œ ์จ์ฃผ๋ฉด ์œ ์—ฐํ•˜๊ฒŒ ์ž‘๋™ํ•œ๋‹ค. all() ๋ถ€๋ถ„์—์„œ ๋ฐ”๋กœ filter๋กœ ํ•œ ์ค„๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋„ ๋ฌผ๋ก  ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ ์  ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๋‹ค ๋ณด๋‹ˆ ์ผ๋‹จ ์ˆ˜์ •์„ ๋ฏธ๋ฃจ๊ณ  ์žˆ๋‹ค. Serializer ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  json.dumps๋กœ json ํ˜•ํƒœ๋กœ ๊ฐ€๊ณต ํ›„ ๋ฐ”๋กœ Json์„ react์—๊ฒŒ ๋ณด๋‚ด์ค€๋‹ค.
path('item/<str:category>/',ItemViewSet.get)
react์—์„œ๋Š” ์ƒ๊ธฐ path์™€ ๊ฐ™์ด example.com/item/categoryA/ ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  json์„ ๋ฆฌํ„ด๋ฐ›๋Š”๋‹ค. ์ฐธ๊ณ ๋กœ ์–‘์ชฝ ๋‹ค ๋งจ ๋์— / ๋ฅผ ๋ถ™์—ฌ์•ผ ํ•จ์— ์ฃผ์˜ํ•˜์ž. ํฌํŠธํด๋ฆฌ์˜ค์˜ Admin์„ ๋งŒ๋“ค์–ด์„œ ์ƒˆ๋กœ์šด ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๋„ฃ์œผ๋ฉด ์นดํ…Œ๊ณ ๋ฆฌ ํƒญ์ด ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋˜์–ด ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค ์˜ˆ์ •์ด๋‹ค. Velog์˜ ํƒœ๊ทธ ์ฒ˜๋Ÿผ.

๐Ÿคข๐Ÿคข๐Ÿคข

API ์„œ๋ฒ„๋ฅผ ๋ถ™์—ฌ heroku์— ๋ฐฐํฌํ•˜์—ฌ url๋กœ ์ ‘๊ทผ์„ ํ•ด๋ณด๋‹ˆ ์žฅ๊ณ ๊ฐ€ ๋‚˜์˜จ๋‹ค. ์ฆ‰ API ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์— ๋…ธ์ถœ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ๋…ธ์ถœ์ด ๋˜๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ heroku์—์„œ react์˜ router๋ณด๋‹ค django์˜ url์„ ์šฐ์„ ์œผ๋กœ ๋‘์–ด react๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. react๊ฐ€ ๋‚˜์™€๋„ refresh๋ฅผ ํ•˜๋ฉด ๋‹ค์‹œ api ์„œ๋ฒ„(์žฅ๊ณ ) ๊ฐ€ ๋‚˜์˜จ๋‹ค.
๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด์ž. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” react ๋ฅผ 5000๋ฒˆ ํฌํŠธ, django ๋ฅผ 8000๋ฒˆ ํฌํŠธ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ด๋“ค๊ณผ์˜ ํ†ต์‹ ์€ axios ๋กœ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ง€์ •ํ•ด์„œ ํ•œ๋‹ค.
 return await axios
    .get('http://127.0.0.1:8000/project/');
   
}
heroku๋Š” ์–ด๋–จ๊นŒ. ec2์™€ ๊ฐ™์€ laas์— ๋ฐฐํฌ๋ฅผ ํ–ˆ๋‹ค๊ณ  ํ•˜๋ฉด apache ์„ค์ •์— ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํฌํŠธ๋กœ ์„ค์ •ํ•˜์—ฌ ์ด๋“ค๊ณผ์˜ ์ถฉ๋Œ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค. (์ถฉ๋Œ์„ ๋ง‰๋Š”๋‹ค๋Š”๊ฒŒ ์ด์ƒํ•œ ํ‘œํ˜„์ด๊ธด ํ•˜๋‹ค. ์• ์ดˆ์— ์„œ๋ฒ„&ํด๋ผ์ด์–ธํŠธ url, port ์ถฉ๋Œ ๋”ฐ์œ„์˜ ๊ฐœ๋…์€ ์žˆ์ง€๋„ ์•Š๋‹ค.) ํ•˜์ง€๋งŒ heroku์— ๋‹จ์ผ app์œผ๋กœ ์žฅ๊ณ ,๋ฆฌ์•กํŠธ ์กฐํ•ฉ์„ ๋ฐฐํฌํ•˜๋‹ค ๋ณด๋‹ˆ ์˜ˆ์ƒ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ํฌํŠธ๋ฅผ ๋”ฐ๋กœ ์„ค์ •ํ•  ๋ฐฉ๋ฒ•๋„ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ํ”„๋ก ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” url์ด ์žฅ๊ณ ๋กœ ๋“ค์–ด์™”์„๋•Œ ํ”„๋ก ํŠธ๋กœ ๋ณด๋‚ด์ค„ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
react_views_regex = r'\/|\b'.join([

    # List all your react routes here
    'Select',
    'skills',
    'projects',
    'experience'

]) + r'\/'

urlpatterns = [
    #path('',include(router.urls)),
    #path('item/',ItemViewSet)
    path('item/<str:category>/',ItemViewSet.get),
    re_path('admin/', admin.site.urls),
     re_path(react_views_regex,index),
     re_path(r'^media/(?P<path>.*)$', serve, {
    "document_root": settings.MEDIA_ROOT
}),
    re_path(r'^static/(?P<path>.*)$', serve,
        {'document_root': settings.STATIC_ROOT}),
 ]

react_views_regex ์— ํ”„๋ก ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” url์„ ๋“ฑ๋กํ•ด ๋†“์•˜๋‹ค. ๋ชจ๋“  url์„ ๋งตํ•‘ํ•  ํ•„์š”๋Š” ์—†๊ณ  ํ”„๋ก ํŠธ url ํŒจํ„ด์—์„œ ๊ณตํ†ต๋˜๋Š” ๋ฃจํŠธ ๋ถ€๋ถ„๋งŒ ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค. ๋ฃจํŠธ์ธ '/' ๋ฅผ ์„ค์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ์žฅ๊ณ  ์–ด๋“œ๋ฏผ, API ์„œ๋ฒ„ url ๊นŒ์ง€ ํ”„๋ก ํŠธ๋กœ ๊ฐ€๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ก ํŠธ์— ์‚ฌ์šฉ๋˜๋Š” ๊ณตํ†ต url ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ์ข‹๋‹ค. ์ €๋Ÿฐ์‹์œผ๋กœ urls.py์— ๋“ฑ๋กํ•ด์ฃผ๋ฉด ์•„๊นŒ์™€ ๊ฐ™์€ ์ถฉ๋Œ์€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.

https://whoami-moonseok.herokuapp.com/

0๊ฐœ์˜ ๋Œ“๊ธ€