개발자
[ 서론 ] Low-level 이해도 향상, 객체 지향적 사고 증진, 공부량 증가를 위해 Spring 느낌의 프레임워크를 개발하려 합니다. [ 본론 1 ] 프레임워크 사용자의 편의성 확대를 위해, MVC의 Controller에 해당하는 영역을 어떻게 설계해야할지 고민 중에 있습니다. 아래 코드 블럭에 나열한 코드 중 개발하며 재미를 느끼실 것 같은 항목을 투표 영역에서 투표해주시거나, 답변을 통해 더 나은 방안을 추천해주시면 감사하겠습니다. [ 본론 2 ] (개인적으로 느끼기에) 매우 거대한 프레임워크를 혼자 개발하고 있는 만큼, 많은 문제와 고민에 봉착하고 있습니다. 이와 관련해 현직자 분들의 소중한 조언을 구하고자 합니다. 부디 시간 들여주시어 답변해주시면 감사하겠습니다. [ 결론 ] 프레임워크 개발이라는 저에겐 다소 어려운 길에 있어 조언을 구하고자 합니다. 부디 소중한 시간내어 답변 남겨주시면 정말로 감사드리겠습니다. ... 현재 소프트웨어 계열 고등학교에 재학 중이며, 백엔드 개발자가 되기 위해 공부하고있는 2학년 학생입니다. 최근 들어, 면접을 경험하신 선배 분들과 조금 대화를 나누다보니 제 지식 수준이 매우 낮다는 것을 깨닫게되었습니다. HTTP, TCP 등 (TCP/IP 4계층 모델 기준) 3,4 계층 프로토콜의 통신 과정, 데이터베이스와 Java 애플리케이션의 Low-Level(JDBC, R2DBC 혹은 더 낮은 수준) 통신 과정, 프레임워크를 사용하는 이유, 그 외 기타 등등. 조금은 깊은 지식에서부터, 원초적인 것들까지, 백엔드 개발자로서 알아야할 것들에 대해 제 수준이 턱없이 부족함을 느끼고 있습니다. 그럼에도 불구, 슬럼프와 비슷한 상태에 빠져있어 작년보다 공부량도 적어졌고, 의지와 기운도 많이 상실한 상태입니다. 아마도 구체적인 목표가 없기에 그런 게 아닌가 하여 공부도 겸하고, 저 자신을 자극할만한 거대한 목표를 한 가지 잡았습니다. Java 백엔드 애플리케이션 프레임워크를 만든다는, 저에겐 어쩌면 지나칠 수도 있는 어려운 도전에 임해보려 합니다. 프레임워크 하나를 기획할 시간을 없기에 Spring의 추상적인 틀을 기반으로 개발-수정 프로세스로 진행하고자 합니다. 프레임워크 주도의 IoC 컨테이너, 어노테이션 기반의 모듈(Spring과 Java에서의 Bean 개념) 관리, 클래스 단위의 설정 정보 관리가 프레임워크의 주요 포인트입니다. Spring의 Core 모듈에 해당하는 기반 프레임워크가 IoC 컨테이너를 포함해 부분적으로 구현되어있습니다. 그리고 현재 Spring Web, Spring MVC 등에 해당하는 WAS 프레임워크 구현을 시작한 상태입니다. MVC에서 Controller에 해당하는 부분을 디자인하는 과정에 있는데, 현직자분들의 생각하시는 최선의 Controller 디자인에 대해 의견을 수집하고자 합니다. 포함된 코드 블럭은 대중적인 프레임워크의 Controller/Router 디자인들입니다. 각 디자인별로 선호하시는 항목에 대해 부여된 번호를 투표를 통해 선택해주시면 감사하겠습니다. 또한 이 프로젝트에 대해 조언 혹은 비판, 의견을 답변 혹은 메일, 링크드인 통해 남겨주시면 대단히 감사드리겠습니다. 그 외 개인적인 문의 사항과 제안 또한 환영합니다. leetyxodud312@gmail.com 아래는 프레임워크 깃허브 주소입니다. 문서화 작업은 진행 중에 있어 다소 부끄러운 수준입니다. 양해 부탁드립니다. https://github.com/Project-Smoodi 끝까지 읽어주심에 다시 한 번 감사의 말씀 드립니다.
1// Controller, Router와 관련되지 않은 부분은 생략했습니다.
2
3// 1번, Spring Boot / Nest.js 스타일, 어노테이션 기반 설정
4// 메소드를 한 개의 API로, 클래스는 API 여러 개를 도메인 혹은 임의의 기준으로 묶은 분류로 사용
5
6// Spring Boot
7@RequestMapping("/api/domain") // 일종의 분류
8public class Controller {
9
10 @GetMapping("/get-request") // 단일 API, 메소드를 통해 정의
11 public void api(
12 // 주입 받는 대상이 특정 가능한 타입일 경우 알아서 처리
13 // 현재의 경우, 요청의 전체 정보를 담은 객체인 HttpServletRequest
14 HttpServletRequest request,
15 @RequestParam("key") // 어노테이션 및 매개 변수 기반의 요청 요소
16 String value
17 ) {
18 /* Do something... */
19 }
20}
21
22// Nest.js
23@Controller('api/domain') // 일종의 분류
24export class Controller {
25
26 @Get('get-request') // 단일 API, 메소드를 통해 정의
27 api(
28 @Req() // 요청 정보의 인자는 어노테이션으로 타겟팅
29 request: Request,
30 @Param('key')
31 value: string
32 ) {
33 /* Do something.. */
34 }
35}
36
37//
38//
39//
40
41// 2번, Express.js, 메소드 호출을 통한 API 설정, 콜백 함수로 서비스 로직 정의
42const express = require('express')
43const app = express() // 단일 프레임워크 설정 객체를 수정하며 서비스 구성
44
45app.get( // express의 특정 객체의 메소드 호출로 API 설정
46 '/api/domain/get-request', // 메소드 매개변수로 경로 지정
47 (req, res) => { // 콜백 함수를 통한 비즈니스 로직 구성
48
49 // 요청 및 응답 정보를 모두 담은 객체를 넘겨 받아
50 // 읽고 쓰는 방식으로 비즈니스 로직 구성
51 const contentType = req.get('Content-Type');
52
53 /* Do Something.. */
54})
55
56//
57//
58//
59
60// 3번, Ktor 스타일, Kotlin 문법을 극한으로 활용한 디자인으로 추정
61// 솔직히 뭔지 모르겠습니다..
62// Ktor 공식 Docs에서 인용
63
64fun Application.configureRouting() { // 진입점으로 추정
65
66 routing { // Kotlin의 함수 타입 인자의 특수 표현식, 힙합
67 staticResources("static", "static")
68
69 //updated implementation
70 route("/tasks") { // SpringBoot에서의 Controller class 역할로 추정
71 get { // 단일 API
72 val tasks = TaskRepository.allTasks()
73 call.respond(tasks)
74 }
75
76 get("/byName/{taskName}") {
77 val name = call.parameters["taskName"]
78 if (name == null) {
79 call.respond(HttpStatusCode.BadRequest)
80 return@get
81 }
82
83 val task = TaskRepository.taskByName(name)
84 if (task == null) {
85 call.respond(HttpStatusCode.NotFound)
86 return@get
87 }
88 call.respond(task)
89 }
90 get("/byPriority/{priority}") {
91 val priorityAsText = call.parameters["priority"]
92 if (priorityAsText == null) {
93 call.respond(HttpStatusCode.BadRequest)
94 return@get
95 }
96 try {
97 val priority = Priority.valueOf(priorityAsText)
98 val tasks = TaskRepository.tasksByPriority(priority)
99
100 if (tasks.isEmpty()) {
101 call.respond(HttpStatusCode.NotFound)
102 return@get
103 }
104 call.respond(tasks)
105 } catch (ex: IllegalArgumentException) {
106 call.respond(HttpStatusCode.BadRequest)
107 }
108 }
109 }
110 }
111}
112
113//
114//
115//
116
117// 4번, Fast API, 써보지 않은 프레임워크입니다.
118// Fast API 공식 Docs에서 인용
119
120app = FastAPI() // Node.js 기반 프레임워크와 전반적으로 비슷해보입니다.
121
122
123@app.get("/")
124def read_root():
125 return {"Hello": "World"}
126
127
128@app.get("/items/{item_id}")
129def read_item(
130 item_id: int,
131 // 타입을 통한 요청 정보 대상 선택, 아래의 경우 URL Parameter.
132 // http://url.com/items/1&q=asdf
133 q: Union[str, None] = None
134):
135 return {"item_id": item_id, "q": q}
136
137//
138//
139//
140
141// 4번, Django.
142// Django 공식 Docs에서 인용
143
144// urls.py
145from django.urls import path
146
147from . import views // 아래의 views.py 파일인 것 같습니다.
148
149
150urlpatterns = [
151 // path라는 함수(추정)를 통해 경로와 라우팅할 함수를 지정하는 것 같습니다.
152 path("articles/<int:year>/", views.year_archive),
153 path("articles/<int:year>/<int:month>/", views.month_archive),
154 path("articles/<int:year>/<int:month>/<int:pk>/", views.article_detail),
155]
156
157// vies.py
158from django.shortcuts import render
159
160from .models import Article
161
162// 함수 기반 단일 API.
163def year_archive(request, year):
164 a_list = Article.objects.filter(pub_date__year=year)
165 context = {"year": year, "article_list": a_list}
166 return render(request, "news/year_archive.html", context)
답변 0
첫 답변을 기다리고 있어요.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
지금 가입하면 모든 질문의 답변을 볼 수 있어요!