bong-u/til

๐Ÿ  home ๐Ÿˆ repository ๐Ÿ“ก rss
new RAG ์ด๋ก  ์ •๋ฆฌ + OpenSearch
๐Ÿค– ์ธ๊ณต์ง€๋Šฅ
RAG (Retrieval-Augmented Generation) RAG๋Š” ๊ฒ€์ƒ‰๊ณผ ์ƒ์„ฑ์„ ๊ฒฐํ•ฉํ•œ ๋ชจ๋ธ๋กœ, ๊ฒ€์ƒ‰์„ ํ†ตํ•ด ์–ป์€ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ƒ์„ฑ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋ธ LLM์˜ ๋ฌธ์ œ์  ํ• ๋ฃจ์‹œ๋„ค์ด์…˜: ์ƒ์„ฑ ๋ชจ๋ธ์ด ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์— ์—†๋Š” ๋‚ด์šฉ์„ ์ƒ์„ฑํ•˜๋Š” ํ˜„์ƒ ์ตœ์‹ ์˜ ์‘๋‹ต์„ ๊ธฐ๋Œ€ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์˜ค๋ž˜๋˜์—ˆ๊ฑฐ๋‚˜ ์ผ๋ฐ˜์ ์ธ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฌธ์ œ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฌธ์ œ RAG๋Š” ์œ„์—์„œ ์„œ์ˆ ํ•œ LLM ๋ฌธ์ œ์˜ ์ผ๋ถ€๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์ด๋‹ค. OpenSearch OpenSearch๋Š” ์˜คํ”ˆ์†Œ์Šค ๊ฒ€์ƒ‰ ๋ฐ ๋ถ„์„ ์—”์ง„์œผ๋กœ, ์—˜๋ผ์Šคํ‹ฑ์„œ์น˜์˜ ํฌํฌ ๋ฒ„์ „ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค : ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฃผ์š” ๊ธฐ๋Šฅ ๋ถ„์‚ฐ ๊ฒ€์ƒ‰ ๋ฐ ๋ถ„์„ ๋ณด์•ˆ ์‹œ๊ฐํ™”์™€ ๋Œ€์‹œ๋ณด๋“œ ์ง€์› index์™€ document index : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค document : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ถ„์„๊ธฐ Analyzer (Character Filter + Tokenizer + Token Filter) ํ…์ŠคํŠธ๋ฅผ ํ† ํฐํ™”ํ•˜๊ณ  ํ•„ํ„ฐ๋งํ•˜๋Š” ๊ณผ์ •์„ ์ˆ˜ํ–‰ ๋ถ„์„ ๊ณผ์ • Character Filter ํŠน์ • ๋ฌธ์ž๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ Tokenizer ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ณต๋ฐฑ์„ ๊ธฐ์ค€์œผ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ถ„๋ฆฌ Token Filter ํ† ํฐ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ OpenSearch์—์„œ ์ง€์›ํ•˜๋Š” ์š”์†Œ Tokenizer Standard Tokenizer : ๊ณต๋ฐฑ์„ ๊ธฐ์ค€์œผ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ถ„๋ฆฌ, ๋ฌธ์žฅ ๋ถ€ํ˜ธ ์‚ญ์ œ Letter Tokenizer : ๋ฌธ์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ถ„๋ฆฌ Whitespace Tokenizer : ๊ณต๋ฐฑ์„ ๊ธฐ์ค€์œผ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ถ„๋ฆฌ Ngram Tokenizer : ๋ถ€๋ถ„ ๋ฌธ์ž์—ด๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ถ„๋ฆฌ Token Filter Standard Token Filter : ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Œ Lowercase Token Filter : ํ…์ŠคํŠธ๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜ Synonym Token Filter : ๋™์˜์–ด ์ฒ˜๋ฆฌ Analyzer Standard Analyzer : Standard Tokenizer + Standard Token Filter Simple Analyzer : Letter Tokenizer + Lowercase Token Filter Whitespace Analyzer : Whitespace Tokenizer + Lowercase Token Filter OpenSearch ์ ‘๊ทผ์„ ์œ„ํ•œ cURL ๋ช…๋ น์–ด ์ธ๋ฑ์Šค ์กฐํšŒ 1curl -X GET -u {username}:{password} \ 2"http://localhost:9200/_cat/indices" ํŠน์ • ์ธ๋ฑ์Šค ์กฐํšŒ 1curl -X GET -u {username}:{password} \ 2"http://localhost:9200/{index_name}" ์ „์ฒด ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์กฐํšŒ 1curl -X GET -u {username}:{password} \ 2"http://localhost:9200/{index_name}/_search" ํŠน์ • ๊ฒ€์ƒ‰์–ด๋กœ ๊ฒ€์ƒ‰ํ•œ ๊ฒฐ๊ณผ ์กฐํšŒ 1curl -X GET -u {username}:{password} \ 2"http://localhost:9200/{index_name}/_search" \ 3-H "Content-Type: application/json" \ 4-d '{"query": {"match": {"field": "value"}}}' ์ธ๋ฑ์Šค ์‚ญ์ œ 1curl -X DELETE -u {username}:{password} \ 2"http://localhost:9200/{index_name}"
new OpenSearch๋ฅผ ํ™œ์šฉํ•œ RAG ์‹ค์Šต
๐Ÿค– ์ธ๊ณต์ง€๋Šฅ
๋ฐฐ๊ฒฝ ํ…Œ์ปค ๋ถ€ํŠธ์บ ํ”„์—์„œ ํŒ€ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ์ค‘์ด๋‹ค. ์šฐ๋ฆฌ ํŒ€์˜ ์ฃผ์ œ๋Š” ํŠน์ • ์ธ๋ฌผ์—๊ฒŒ ์ƒ๋‹ด์„ ๋ฐ›๋Š” ๊ฒƒ ๊ฐ™์€ ๋Œ€ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ์ฑ—๋ด‡์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ํŠน์ • ์ธ๋ฌผ์ด ํ–ˆ๋˜ ๋ง์„ ๋ชจ์•„ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ RAG ๋ชจ๋ธ์— ์ ์šฉ์‹œํ‚ค๋ ค๊ณ  ํ•œ๋‹ค. ์ˆœ์„œ ์ผ๋ก  ๋จธ์Šคํฌ๊ฐ€ TED์—์„œ ํ•œ ์ธํ„ฐ๋ทฐ๋ฅผ ํ…์ŠคํŠธ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. OpenSearch ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„๋ฒ ๋”ฉํ•ด์„œ OpenSearch์— ์ €์žฅํ•œ๋‹ค. RAG ๋ชจ๋ธ์ด OpenSearch๋ฅผ ์ฟผ๋ฆฌํ•˜์—ฌ ๋Œ€๋‹ต์„ ์ƒ์„ฑํ•œ๋‹ค. 1. ์ผ๋ก  ๋จธ์Šคํฌ ์ธํ„ฐ๋ทฐ ํ…์ŠคํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ ํŠœ๋ธŒ์—์„œ “์Šคํฌ๋ฆฝํŠธ ๋ณด๊ธฐ"๋ฅผ ํ†ตํ•ด ์ธํ„ฐ๋ทฐ ์ž๋ง‰์„ ๊ฐ€์ ธ์˜จ๋‹ค. 122:03 2EM: ์ด ํฐ ํŠธ๋Ÿญ์„ ๋ชฐ๋ฉด์„œ ๋ง๋„ ์•ˆ๋˜๋Š” ์›€์ง์ž„์„ ๋ณด์˜€์ฃ . 3CA: ์•„์ฃผ ๋ฉ‹์ง€๋„ค์š”. ์ž, ๊ทธ๋Ÿผ ์ •๋ง ๊ต‰์žฅํ•œ ์‚ฌ์ง„์—์„œ 422:09 5์กฐ๊ธˆ์€ ๋œ ๊ต‰์žฅํ•œ ์‚ฌ์ง„์„ ๋ณด์ฃ . "์œ„๊ธฐ์˜ ์ฃผ๋ถ€๋“ค"์ธ๊ฐ€์—์„œ ๋‚˜์˜ค๋Š” ๊ท€์—ฌ์šด ์ง‘ ์‚ฌ์ง„์ธ๋ฐ์š”. 622:15 7์ด๊ฒŒ ๊ฐ‘์ž๊ธฐ ์™œ ๋‚˜์˜จ๊ฑฐ์ฃ ? 8... ์ผ๋ก  ๋จธ์Šคํฌ๊ฐ€ ํ•œ ๋ง๋งŒ ์†์ˆ˜ ์ •๋ฆฌํ•œ๋‹ค. 1๋„ค. ์ œ ์Šค์Šค๋กœ๋„ ๊ทธ ์งˆ๋ฌธ์„ ์ž์ฃผ ํ•˜๋Š” ํŽธ์ž…๋‹ˆ๋‹ค. 2์ €ํฌ๋Š” LA์˜ ์ง€ํ•˜์— ๊ตฌ๋ฉ์„ ๋‚ด๋ ค๊ณ  ํ•˜๋Š”๋ฐ์š”. ์ด๋Š” ๊ตํ†ต ์ฒด์ฆ์„ ์™„ํ™”์‹œํ‚ค๊ธฐ ์œ„ํ•œ 33์ฐจ์› ๋„คํŠธ์›Œํฌ์˜ ํ„ฐ๋„์ด ๋  ์ˆ˜๋„ ์žˆ๋Š” ์‹œ๋ฐœ์ ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. 4๊ตํ†ต ์ฒด์ฆ์€ ์˜ค๋Š˜๋‚  ์šฐ๋ฆฌ์˜ ์˜ํ˜ผ์„ ํƒˆํƒˆ ํ„ฐ๋Š” ๋ฌธ์ œ ์ค‘์˜ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. 5์„ธ๊ณ„ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์˜ํ–ฅ์„ ๋ผ์น˜๊ณ  ์žˆ์ฃ . ์ธ์ƒ์—์„œ ๋„ˆ๋ฌด๋„ ๋งŽ์€ ๋ถ€๋ถ„์„ ๊ฐ€์ ธ๊ฐ‘๋‹ˆ๋‹ค. 6... 2. OpenSearch ๋„์ปค ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ 1docker create -it -p 9200:9200 -p 9600:9600 -e OPENSEARCH_INITIAL_ADMIN_PASSWORD={password} -e "discovery.type=single-node" -v opensearch_vol:/usr/share/opensearch/data --name opensearch opensearchproject/opensearch ์„ค๋ช… -p 9200:9200 : OpenSearch HTTP ํฌํŠธ -p 9600:9600 : OpenSearch ๋ชจ๋‹ˆํ„ฐ๋ง ํฌํŠธ -e OPENSEARCH_INITIAL_ADMIN_PASSWORD={password} : ์ดˆ๊ธฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ • -e “discovery.type=single-node” : ๋‹จ์ผ ๋…ธ๋“œ๋กœ ์‹คํ–‰ -v opensearch_vol:/usr/share/opensearch/data : ๋ฐ์ดํ„ฐ ๋ณผ๋ฅจ ๋งˆ์šดํŠธ SSL ์˜ค๋ฅ˜ ๋ฐœ์ƒ๊ณผ ํ•ด๊ฒฐ ํ•˜์ง€๋งŒ ์œ„ ๋ช…๋ น์–ด๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค 12024-07-05 22:15:12 Caused by: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: ... 22024-07-05 22:15:12 at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1314) ~[netty-handler-4.1.110.Final.jar:4.1.110.Final] 32024-07-05 22:15:12 at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1387) ~[netty-handler-4.1.110.Final.jar:4.1.110.Final] 42024-07-05 22:15:12 at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530) ~[netty-codec-4.1.110.Final.jar:4.1.110.Final] 52024-07-05 22:15:12 at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469) ~[netty-codec-4.1.110.Final.jar:4.1.110.Final] 62024-07-05 22:15:12 ... 16 more ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„์ด ๊ธธ์ง€ ์•Š๊ณ , ํ•ด๋‹น ํฌํŠธ๋Š” ์™ธ๋ถ€์— ๋…ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ SSL์„ ๋„๊ณ  ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด๊ฒฐํ•˜์˜€๋‹ค. 1/usr/share/opensearch/config/opensearch.yml 2# ๋ณ€๊ฒฝ ์ „ 3plugins.security.ssl.http.enabled: true 4# ๋ณ€๊ฒฝ ํ›„ 5plugins.security.ssl.http.enabled: false 3. ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ ์ž„๋ฒ ๋”ฉ ๋ฐ OpenSearch์— ์ €์žฅ RAG ์„ธ์…˜์„ ํ•ด์ฃผ์‹  ๋ฉ˜ํ† ๋‹˜์ด ์งœ์ค€ ์ฝ”๋“œ๋ฅผ ์ ๊ทน! ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ•˜์˜€๋‹ค. OpenSearch ์ธ๋ฑ์Šค ์ƒ์„ฑ 1from opensearchpy import OpenSearch 2import torch 3from transformers import AutoTokenizer, AutoModel 4from langchain.text_splitter import RecursiveCharacterTextSplitter 5from langchain_community.document_loaders import TextLoader 6from langchain_community.vectorstores import OpenSearchVectorSearch 7 8INDEX_NAME = "elon_musk" 9FILE_NAME = "ted_elon_musk_script.txt" 10 11## OpenSearch ์—ฐ๊ฒฐ ์„ค์ • 12client = OpenSearch( 13 hosts=[{"host": "localhost", "port": 9200}], http_auth=("admin", {password}) 14) 15 16## ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ 17loader = TextLoader(file_path=FILE_NAME, encoding="utf-8") 18docs = loader.load() 19 20text_splitter = RecursiveCharacterTextSplitter( 21 chunk_size=100, 22 chunk_overlap=0, 23 separators=["\n"], 24 length_function=len, 25) 26 27documents = text_splitter.split_documents(docs) 28 29# print(documents) 30 31## Embedding ๋ชจ๋ธ ์ •์˜ 32class MyEmbeddingModel: 33 def __init__(self, model_name): 34 self.tokenizer = AutoTokenizer.from_pretrained(model_name) 35 self.model = AutoModel.from_pretrained(model_name) 36 37 def embed_documents(self, doc): 38 inputs = self.tokenizer( 39 doc, return_tensors="pt", padding=True, truncation=True, max_length=512 40 ) 41 42 with torch.no_grad(): 43 outputs = self.model(**inputs) 44 embeddings = outputs.last_hidden_state.mean(dim=1).tolist() 45 46 return embeddings 47 48 def embed_query(self, text): 49 inputs = self.tokenizer( 50 [text], padding=True, truncation=True, return_tensors="pt", max_length=512 51 ) 52 with torch.no_grad(): 53 outputs = self.model(**inputs) 54 embeddings = outputs.last_hidden_state.mean(dim=1).tolist() 55 return embeddings 56 57 58## index ๊ตฌ์กฐ ์ •์˜ 59index_body = { 60 "settings": { 61 "analysis": { 62 "tokenizer": { 63 "nori_user_dict": { 64 "type": "nori_tokenizer", 65 "decompound_mode": "mixed", 66 "user_dictionary": "user_dic.txt", 67 } 68 }, 69 "analyzer": { 70 "korean_anlyzer": { 71 "filter": [ 72 "synonym", "lowercase", 73 ], 74 "tokenizer": "nori_user_dict", 75 } 76 }, 77 "filter": { 78 "synonym" :{ 79 "type": "synonym_graph", 80 "synonyms_path" : "synonyms.txt" 81 } 82 } 83 } 84 } 85} 86 87## Embedding ๋ชจ๋ธ ์ƒ์„ฑ 88my_embedding = MyEmbeddingModel("monologg/kobert") 89 90## OpenSearch์— ๋ฐ์ดํ„ฐ ์‚ฝ์ž… 91vector_db = OpenSearchVectorSearch.from_documents( 92 index_name=INDEX_NAME, 93 body=index_body, 94 documents=documents, 95 embedding=my_embedding, 96 op_type="create", 97 opensearch_url="http://localhost:9200", 98 http_auth=("admin", {password}), 99 use_ssl=False, 100 verify_certs=False, 101 ssl_assert_hostname=False, 102 ssl_show_warn=False, 103 bulk_size=1000000, 104 timeout=360000, 105) 106 107result = vector_db.add_documents(documents, bulk_size=1000000) tokenizer๋Š” ํ•œ๊ตญ์–ด๋ฅผ ์ง€์›ํ•˜๋Š” “nori_tokenizer"๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค. embedding ๋ชจ๋ธ์€ ์ €๊ฑฐ ๋ง๊ณ ๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, ์–ด๋–ค ๋ชจ๋ธ์ด ํ”„๋กœ์ ํŠธ์— ๊ฐ€์žฅ ๋ถ€ํ•ฉํ•˜๋Š” ๋ชจ๋ธ์ธ์ง€๋Š” ์‹คํ—˜์„ ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค. curl์„ ํ†ตํ•ด localhost:9200/elon_musk/_search๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด ์ž„๋ฒ ๋”ฉํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ”๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 4. RAG ๋ชจ๋ธ์ด OpenSearch๋ฅผ ์ฟผ๋ฆฌํ•˜์—ฌ ๋Œ€๋‹ต ์ƒ์„ฑ 1from langchain.prompts import PromptTemplate 2from langchain.chains import LLMChain 3from langchain_openai import ChatOpenAI 4from opensearchpy import OpenSearch 5import os 6 7INDEX_NAME = "elon_musk" 8 9# ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • 10os.environ["OPENAI_API_KEY"] = {api_key} 11 12llm = ChatOpenAI( 13 model_name="gpt-3.5-turbo", 14) 15 16prompt_template = PromptTemplate( 17 input_variables=["context", "question"], 18 template=""" 19Imagine you are {character_name}, 20a wise and experienced advisor. Given the context: "{context}", 21how would you respond to this inquiry: "{question}"?', 22(in korean) 23""", 24) 25 26 27llm_chain = LLMChain(llm=llm, prompt=prompt_template) 28 29client = OpenSearch( 30 hosts=["http://localhost:9200"], 31 http_auth=("admin", {password}), 32 use_ssl=False, 33 verify_certs=False, 34 ssl_assert_hostname=False, 35 ssl_show_warn=False, 36) 37 38def search_documents(query): 39 search_body = {"query": {"match": {"text": query}}} 40 response = client.search(index=INDEX_NAME, body=search_body) 41 hits = response["`its"]["hits"] 42 return [hit["_source"]["text"] for hit in hits] 43 44if __name__ == "__main__": 45 question = input("Enter your question\n") 46 search_results = search_documents(question) 47 48 print(search_results) 49 50 # context = " ".join(search_results) 51 context = "" 52 53 response = llm_chain.invoke({"character_name": INDEX_NAME, "context": context, "question": question}) 54 55 print (response["text"]) OpenSearch์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•˜์—ฌ RAG ๋ชจ๋ธ์— ๋„ฃ์–ด ๋Œ€๋‹ต์„ ์ƒ์„ฑํ•œ๋‹ค. search_documents ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด OpenSearch์— ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ context๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒฐ๊ณผ ์งˆ๋ฌธ ํ…Œ์Šฌ๋ผ์— ๋Œ€ํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•ด? RAG๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ๋•Œ์˜ ๋Œ€๋‹ต ํ…Œ์Šฌ๋ผ๋Š” ํ˜์‹ ์ ์ธ ๊ธฐ์—…์œผ๋กœ์„œ ๋ฏธ๋ž˜๋ฅผ ํ–ฅํ•œ ๋น„์ „์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์˜ ์ „๊ธฐ ์ž๋™์ฐจ ๊ธฐ์ˆ ๊ณผ ์—๋„ˆ์ง€ ์†”๋ฃจ์…˜์€ ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์ฃผ๋ชฉ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์Šฌ๋ผ์˜ ํ˜์‹ ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ์ง€์† ๊ฐ€๋Šฅํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ์— ๋Œ€ํ•ด ๋งค์šฐ ๊ธ์ •์ ์œผ๋กœ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. RAG๋ฅผ ์‚ฌ์šฉํ• ๋•Œ ์ ์šฉ๋œ context [‘๊ธธ๊ฒŒ ๊ฐˆ ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š์•„์š”.\n๊ทธ๋Ÿฌ๋„ค์š”. ์ €๋Š” ์ตœ๋Œ€ํ•œ ์˜ค๋žซ๋™์•ˆ ํ…Œ์Šฌ๋ผ์— ๋จธ๋ฌผ ์ƒ๊ฐ์ด์—์š”.\n๊ทธ๋ฆฌ๊ณ  ์ค€๋น„ ์ค‘์— ์žˆ๋Š” ํฅ๋ฏธ๋กœ์šด ์ผ๋„ ๋งŽ๊ณ ์š”. ์•„์‹œ๋‹ค์‹œํ”ผ, ๋ชจ๋ธ 3์ด ์ถœ์‹œ ์˜ˆ์ •์ด๊ณ ์š”.’, ‘์˜ฌํ•ด ๋ง๊นŒ์ง€ LA์—์„œ ๋‰ด์š•๊นŒ์ง€\n์™„์ „ ์ž์œจ ์ฃผํ–‰์œผ๋กœ ํšก๋‹จํ•˜๋Š” ๊ณ„ํš์— ๋งž์ถฐ์„œ ์ง„ํ–‰ ์ค‘์ด์—์š”.\n์‚ฌ๋žŒ์ด ํ…Œ์Šฌ๋ผ์— ํƒ€์„œ ์šด์ „๋Œ€๋ฅผ ์žก์ง€ ์•Š๊ณ  “๋‰ด์š•"์„ ์ฐ์œผ๋ฉด ๊ทธ๋ฆฌ๋กœ ๊ฐ„๋‹ค๋Š” ๋ง์ด๋„ค์š”.’, ‘๊ธธ๊ฒŒ ๊ฐˆ ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š์•„์š”.\n๊ทธ๋Ÿฌ๋„ค์š”. ์ €๋Š” ์ตœ๋Œ€ํ•œ ์˜ค๋žซ๋™์•ˆ ํ…Œ์Šฌ๋ผ์— ๋จธ๋ฌผ ์ƒ๊ฐ์ด์—์š”.\n๊ทธ๋ฆฌ๊ณ  ์ค€๋น„ ์ค‘์— ์žˆ๋Š” ํฅ๋ฏธ๋กœ์šด ์ผ๋„ ๋งŽ๊ณ ์š”. ์•„์‹œ๋‹ค์‹œํ”ผ, ๋ชจ๋ธ 3์ด ์ถœ์‹œ ์˜ˆ์ •์ด๊ณ ์š”.’, ‘์˜ฌํ•ด ๋ง๊นŒ์ง€ LA์—์„œ ๋‰ด์š•๊นŒ์ง€\n์™„์ „ ์ž์œจ ์ฃผํ–‰์œผ๋กœ ํšก๋‹จํ•˜๋Š” ๊ณ„ํš์— ๋งž์ถฐ์„œ ์ง„ํ–‰ ์ค‘์ด์—์š”.\n์‚ฌ๋žŒ์ด ํ…Œ์Šฌ๋ผ์— ํƒ€์„œ ์šด์ „๋Œ€๋ฅผ ์žก์ง€ ์•Š๊ณ  “๋‰ด์š•"์„ ์ฐ์œผ๋ฉด ๊ทธ๋ฆฌ๋กœ ๊ฐ„๋‹ค๋Š” ๋ง์ด๋„ค์š”.’] RAG๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ๋Œ€๋‹ต ์ €๋Š” ํ…Œ์Šฌ๋ผ๋ฅผ ๋งค์šฐ ๊ธ์ •์ ์œผ๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์Šฌ๋ผ๋Š” ํ˜์‹ ์ ์ธ ๊ธฐ์ˆ ๊ณผ ์ง€์† ๊ฐ€๋Šฅํ•œ ๋ฏธ๋ž˜๋ฅผ ์œ„ํ•œ ๋น„์ „์„ ๊ฐ–์ถ˜ ๊ธฐ์—…์œผ๋กœ์„œ, ์ž์œจ ์ฃผํ–‰ ๊ธฐ์ˆ ์„ ํ†ตํ•ด ์šฐ๋ฆฌ์˜ ์‚ถ์„ ํ˜์‹ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ „๊ธฐ์ฐจ ์‹œ์žฅ์„ ์„ ๋„ํ•˜๊ณ  ํ™˜๊ฒฝ์— ์นœํ™”์ ์ธ ์ฐจ๋Ÿ‰์„ ์ œ๊ณตํ•˜๋Š” ๋ฉ‹์ง„ ๊ธฐ์—…์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์Šฌ๋ผ์˜ ๋ฏธ๋ž˜๊ฐ€ ๋ฐ๊ณ  ํฅ๋ฏธ๋กœ์šด ์ผ๋“ค์ด ๊ณ„์†ํ•ด์„œ ์ผ์–ด๋‚  ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค. ๊ณ ์ฐฐ ํ™•์‹คํžˆ RAG๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ๋•Œ๋Š” ๊ฐ๊ด€์ ์ด๊ณ  ์ผ๋ฐ˜์ ์ธ ๋Œ€๋‹ต์„ ํ•˜๋Š” ๋ฐ˜๋ฉด, RAG๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ…Œ์Šฌ๋ผ์— ๋Œ€ํ•ด ๊ธ์ •์ ์ธ ์ผ๋ก  ๋จธ์Šคํฌ์˜ ๋Œ€๋‹ต๊ณผ, ์ž์œจ์ฃผํ–‰ ๊ธฐ์ˆ ์„ ์–ธ๊ธ‰ํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ฐ˜์˜ํ•˜์—ฌ ๋Œ€๋‹ต์„ ์ƒ์„ฑํ•˜์˜€๋‹ค.
new ์ปดํŒŒ์ผ๋Ÿฌ๊ฐœ๋ก 
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
๊ฐœ์š” ์ปดํ“จํ„ฐ์™€ ์ธ๊ฐ„์ด ์†Œํ†ตํ•˜๋Š” ๋ฐฉ๋ฒ• ์–ด์…ˆ๋ธ”๋ฆฌ์–ด ์–ด์…ˆ๋ธ”๋ฆฌ์–ด์˜ ๋ฒˆ์—ญ๊ธฐ๋Š” ์–ด์…ˆ๋ธ”๋Ÿฌ(Assembler)๋ผ๊ณ  ํ•œ๋‹ค cpu์นฉ์…‹์ด ๋ฐ”๋€”๋•Œ๋งˆ๋‹ค ์–ด์…ˆ๋ธ”๋ฆฌ์–ด๊ฐ€ ๋ฐ”๋€๋‹ค ๊ณ ๊ธ‰์–ธ์–ด ๊ณ ๊ธ‰์–ธ์–ด์˜ ๋ฒˆ์—ญ๊ธฐ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ(Compiler)๋ผ๊ณ  ํ•œ๋‹ค ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ •ํ™•ํ•œ ์ •์˜ ์–ด๋–ค ์–ธ์–ด๋กœ ์“ฐ์—ฌ์ง„ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ™์€ ์—ญํ• ์˜ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ 1952๋…„ ๊ทธ๋ ˆ์ด์Šค ํ˜ธํผ(Grace Hopper)๊ฐ€ UNIVAC์šฉ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์–ธ์–ด A-0 ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ œ์ž‘ ์ปดํŒŒ์ผ๋Ÿฌ vs ์ธํ„ฐํ”„๋ฆฌํ„ฐ ํ”„๋กœ๊ทธ๋žจ ์ฒ˜๋ฆฌ๊ณผ์ • ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ฒ˜๋ฆฌ ๊ณผ์ • Lexical analysis (์–ดํœ˜ ๋ถ„์„) token์„ ์ƒ์„ฑํ•˜๋Š”์ผ, token์€ ์–ดํœ˜์˜ ์ตœ์†Œ ๋‹จ์œ„ Syntax analysis (๊ตฌ๋ฌธ ๋ถ„์„) token์„ ์ฝ์–ด์„œ ์˜ค๋ฅ˜๋ฅผ ๊ฒ€์ƒ‰, ๊ตฌ๋ฌธ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ ๋‹ค (์ฃผ๋กœ ํŠธ๋ฆฌํ˜•ํƒœ) Semantic analysis (์˜๋ฏธ ๋ถ„์„) type checking Intermediate code generation (์ค‘๊ฐ„ ์ฝ”๋“œ ์ƒ์„ฑ) ์ค‘๊ฐ„ ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ Code optimization (์ฝ”๋“œ ์ตœ์ ํ™”) ์ค‘๊ฐ„ ์ฝ”๋“œ๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ๋ณ€ํ™˜ Code generation (์ฝ”๋“œ ์ƒ์„ฑ) ๋ชฉ์  ์ฝ”๋“œ ์ƒ์„ฑ Lexical analysis (์–ดํœ˜ ๋ถ„์„) token : ๋ฌธ๋ฒ•์ ์œผ๋กœ ์˜๋ฏธ์žˆ๋Š” ์ตœ์†Œ ๋‹จ์œ„ FSA (Finite State Automata, ์œ ํ•œ ์ƒํƒœ ์˜คํ† ๋งˆํƒ€) token์„ ์ธ์‹ํ•˜๋Š” ๋ฐฉ๋ฒ• ์‹œ์ž‘ ์ƒํƒœ ํ•œ ๊ฐœ์™€ ๋ ์ƒํƒœ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๊ฐ€์ง DFA (Deterministic Finite Automata) FSA์˜ ํ•œ ์ข…๋ฅ˜ ๊ฐ ์ƒํƒœ์—์„œ ๋ป—์–ด๋‚˜๊ฐ€๋Š” edge๊ฐ€ ํ•˜๋‚˜์”ฉ๋งŒ ์กด์žฌ ฮต๊ฐ€ ๋ถ™์€ edge ์—†์Œ ๋ถ„์„ํ•œ ํ† ํฐ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• Lexeme = <ํ† ํฐ๋ฒˆํ˜ธ, ํ† ํฐ ๊ฐ’> ์˜ˆ์‹œ if X < Y … (29, 0) (1, X) (18, 0) (1, Y) … ์‹๋ณ„์ž์˜ ํ† ํฐ๋ฒˆํ˜ธ๋Š” 1๋ฒˆ, ์ƒ์ˆ˜๋Š” 2๋ฒˆ ๋“ฑ์œผ๋กœ ๊ณ ์ • Syntax analysis (๊ตฌ๋ฌธ ๋ถ„์„) token์„ ์ฝ์–ด์„œ ์˜ค๋ฅ˜๋ฅผ ๊ฒ€์ƒ‰, parse tree๋ฅผ ๋งŒ๋“ ๋‹ค CFG (Context Free Grammer) ๊ตฌ๋ฌธ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• G = (N, T, P, S) N = nonterminal symbol ์•ŒํŒŒ๋ฒณ ๋Œ€๋ฌธ์ž๋กœ ํ‘œํ˜„ T = terminal symbol (token) ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž+์ˆซ์ž, ์—ฐ์‚ฐ์ž, ๊ตฌ๋ถ„์ž, ํ‚ค์›Œ๋“œ ๋“ฑ P = production rule ์˜ˆ) S -> T+T, T -> ‘0’|‘1’|‘2’ S = start symbol L(G) : ์ด ๋ฌธ๋ฒ•์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์–ธ์–ด ์—ฌ๋Ÿฌ๊ฐ€์ง€ CFG ํ‘œํ˜„๋ฒ• BNF (Backus-Naur Form) EBNF (Extended BNF) ์œ ๋„ (derivation) ์ƒ์„ฑ ๊ทœ์น™๋ฅผ ์ ์šฉํ•˜์—ฌ ๋ฌธ์žฅ์„ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ • ์œ ๋„๋ฅผ ํ•˜๋Š” ๊ณผ์ •์—์„œ ํ•˜๋‚˜์”ฉ ๊ณจ๋ผ์„œ ๋ฐ”๊ฟˆ ์œ ๋„ ํŠธ๋ฆฌ : ์œ ๋„ ๊ฒฝ๋กœ๋ฅผ ์ถ”์ƒํ™” ์‹œ์ผœ ํ‘œํ˜„ํ•œ ๊ฒƒ ์ขŒ์ธก ์œ ๋„(leftmost derivation) ๊ฐ€์žฅ ์™ผ์ชฝ์— ์žˆ๋Š” nonterminal์„ ๋จผ์ € ๋Œ€์น˜ ์šฐ์ธก ์œ ๋„(rightmost derivation) ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋Š” nonterminal์„ ๋จผ์ € ๋Œ€์น˜ ๋ชจํ˜ธ์„ฑ (ambiguity) ๋ฌธ๋ฒ• G์— ์˜ํ•ด ์ƒ์„ฑ๋˜๋Š” ์–ด๋–ค ๋ฌธ์žฅ์ด ๋‘๊ฐœ ์ด์ƒ์˜ ์œ ๋„ํŠธ๋ฆฌ๋ฅผ ๊ฐ–๋Š”๋‹ค๋ฉด ๋ฌธ๋ฒ• G๋Š” ๋ชจํ˜ธํ•˜๋‹ค๊ณ  ํ•œ๋‹ค ๋ชจํ˜ธํ•˜์ง€ ์•Š์€ ๋ฌธ๋ฒ•์€ ์ขŒ์ธก ์œ ๋„์™€ ์šฐ์ธก ์œ ๋„๊ฐ€ ๊ฐ™๋‹ค ๋ชจํ˜ธ์„ฑ ํ•ด๊ฒฐ ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„ ๋„์ž… ๊ฒฐํ•ฉ ๋ฒ•์น™ ๋„์ž… Left Recursion์€ ์ขŒ์ธก ๊ฒฐํ•ฉ์— ์‚ฌ์šฉ ex) A -> A+a | a Right Recursion์€ ์šฐ์ธก ๊ฒฐํ•ฉ์— ์‚ฌ์šฉ ex) A -> a+A | a ๊ตฌ๋ฌธ ๋ถ„์„์˜ 2๊ฐ€์ง€ ๋ฐฉ์‹ top-down, bottom-up Top-down parsing Top-down ๋ฐฉ์‹ ์ขŒ์ธก ์œ ๋„์™€ ๊ฐ™์€ ์ˆœ์„ ์˜ ์ƒ์„ฑ ๊ทœ์น™ ์ ์šฉ backtracking : ์œ ๋„๋œ ๋ฌธ์ž์—ด๊ณผ ์ž…๋ ฅ ๋ฌธ์ž์—ด์ด ๊ฐ™์ง€ ์•Š์œผ๋ฉด ๋‹ค๋ฅธ ์ƒ์„ฑ๊ทœ์น™ ์ ์šฉ Bottom-up ๋ฐฉ์‹ ์šฐ์ธก ์œ ๋„์˜ ์—ญ์ˆœ์˜ ์ƒ์„ฑ ๊ทœ์น™ ์ ์šฉ LL ํŒŒ์‹ฑ ์™ผ์ชฝ->์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ฝ์–ด์„œ ์ขŒํŒŒ์Šค ์ƒ์„ฑ backtracking X, ๋น ๋ฅด๋‹ค ๊ฒฐ์ •์ ์œผ๋กœ ํŒŒ์‹ฑ ์‚ฌ์šฉ๋œ ์ •์˜ ฮต-์ƒ์„ฑ๊ทœ์น™ Nonterminal A๊ฐ€ ฮต๋ฅผ ์œ ๋„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด A๋ฅผ nullableํ•˜๋‹ค๊ณ  ๋ถ€๋ฅธ๋‹ค lhs, rhs A->XXX์—์„œ lhs๋Š” A, rhs๋Š” XXX โŠ• (Ring Sum) A์— ฮต๊ฐ€ ์žˆ์œผ๋ฉด, AโŠ•B = (A์—์„œ ฮต๋นผ๊ณ  A ํ•ฉ์ง‘ํ•ฉ B) A์— ฮต๊ฐ€ ์—†์œผ๋ฉด, AโŠ•B = A First nonterminal A๋กœ ๋ถ€ํ„ฐ ์œ ๋„๋˜์–ด ์ฒซ๋ฒˆ์งธ๋กœ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š” terminal์˜ ์ง‘ํ•ฉ X->Y1Y2Y3์ผ๋•Œ, FIRST(X) = FIRST(X) U FIRST(Y1) โŠ• FIRST(Y2) โŠ• FIRST(Y3) Follow A ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” terminal์˜ ์ง‘ํ•ฉ A->ฮฑBฮฒ, ฮฒ != ฮต ์ผ๋•Œ, FOLLOW(B) = FOLLOW(B) U (FIRST(ฮฒ)-{ฮต}) A->ฮฑB ๋˜๋Š” A->ฮฑBฮฒ, FIRST(ฮฒ)์— ฮต๊ฐ€ ์†ํ•  ๋•Œ, FOLLOW(B) = FOLLOW(B) U FOLLOW(A) LL์กฐ๊ฑด FIRST(ฮฑ)์™€ FIRST(ฮฒ)๊ฐ€ ๊ฒน์น˜๋ฉด ์•ˆ๋œ๋‹ค FIRST(ฮฑ)์— ฮต๊ฐ€ ์žˆ์œผ๋ฉด, FOLLOW(ฮฑ)์™€ FIRST(ฮฒ)๊ฐ€ ๊ฒน์น˜๋ฉด ์•ˆ๋œ๋‹ค LL ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ฌธ๋ฒ• = LL ํŒŒ์‹ฑ ๋˜๋Š” ๋ฌธ๋ฒ• LL(1) ๋ฌธ๋ฒ• ์ž„์˜์˜ ๋ฌธ๋ฒ•์— ๋Œ€ํ•˜์—ฌ LL ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” CFG 1 : LOOKAHEAD๊ฐ€ 1๊ฐœ๋ผ๋Š” ์˜๋ฏธ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ LL(1)๋ฌธ๋ฒ•์ด ๋˜์ง€ ์•Š๋Š”๋‹ค ๋ชจํ˜ธํ•œ ๋ฌธ๋ฒ• ์šฐ์„ ์ˆœ์œ„ ์ฃผ๊ธฐ, ๊ฒฐํ•ฉ๋ฒ•์น™ ๋ฐ˜์˜์œผ๋กœ ํ•ด๊ฒฐ left-factoring์ด ๋˜๋Š” ๊ฒฝ์šฐ ๊ณตํ†ต ์•ž๋ถ€๋ถ„์„ ์ƒˆ๋กœ์šด nonterminal๋กœ ๋งŒ๋“ค์–ด ํ•ด๊ฒฐ left-recursiveํ•œ ๊ฒฝ์šฐ ์ง์ ‘ recursion : A -> Aฮต ์ธ๊ฒฝ์šฐ ๊ฐ„์ ‘ recursion : A -> B, B -> A ์ธ๊ฒฝ์šฐ LOOKAHEAD ์–ด๋–ค ๊ทœ์น™์ด ์ ์šฉ๋˜์—ˆ์„๋•Œ ๋งจ ์ฒ˜์Œ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” terminal ์ง‘ํ•ฉ A->X1X2X3์ผ๋•Œ, LOOKAHEAD(A) = FIRST(X1) โŠ• FIRST(X2) … โŠ• FOLLOW(A) Strong LL(1) LL(1)๊ณผ ํ•ญ์ƒ ๋™์ผ (1์ด ์•„๋‹๋•Œ๋Š” ๋‹ค๋ฆ„) LOOKAHEAD(A->ฮฑ)์™€ LOOKAHEAD(A->ฮฒ)๊ฐ€ ๊ฒน์น˜์ง€ ์•Š๋Š” ๋ฌธ๋ฒ• LL(1) ํŒŒ์„œ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• Recursive descent parser ์žฅ์  : ์ง๊ด€์  ์‰ฝ๋‹ค ๋‹จ์  : ์ƒ์„ฑ ๊ทœ์น™์ด ๋ฐ”๋€Œ๋ฉด ๊ตฌ๋ฌธ ๋ถ„์„๊ธฐ๋ฅผ ๊ณ ์ณ์•ผ ํ•œ๋‹ค Predictive parser PDA(PushDown Automata)์— ๊ธฐ๋ฐ˜ ์ƒ์„ฑ ๊ทœ์น™์ด ๋ฐ”๋€Œ๋ฉด ํŒŒ์‹ฑ ํ…Œ์ด๋ธ”๋งŒ ์ˆ˜์ • ํŒŒ์‹ฑํ…Œ์ด๋ธ” ์˜ˆ์‹œ (?์—๋Š” ๊ทœ์น™๋ฒˆํ˜ธ๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค) a b S ? ? A ? ? ํŒŒ์‹ฑํ…Œ์ด๋ธ”์— ๋‘๊ฐœ ์ด์ƒ์˜ ์ƒ์„ฑ ๊ทœ์น™์ด ๋“ค์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ -> NOT LL(1) Stack์˜ ์˜ˆ์‹œ Bottom-up parsing left-recursive ๋ฌธ๋ฒ•๋„ ํŒŒ์‹ฑ ๊ฐ€๋Šฅ LL(k) ์ขŒ์ธก์œ ๋„ ๊ธฐ๋ฐ˜ k๊ฐœ์˜ symbol์„ lookahead Top-down parsing, recursive descent parsing, predictive parsing, LL parser ํŒŒ์ŠคํŠธ๋ฆฌ๋ฅผ pre-roder๋กœ ์ˆœํšŒ ๋ฐ ์ƒ์„ฑ LR(k) ์šฐ์ธก์œ ๋„ ๊ธฐ๋ฐ˜ k๊ฐœ์˜ symbol์„ lookahead Bottom-up parsing, shift-reduce parsing, LR parser ํŒŒ์ŠคํŠธ๋ฆฌ๋ฅผ post-order๋กœ ์ˆœํšŒ ๋ฐ ์ƒ์„ฑ Reduce S=>ฮฑฮฒฯ‰์ด๊ณ  A->ฮฒ์ด๋ฉด ฮฒ๋ฅผ A๋กœ ๋Œ€์น˜ํ•˜๋Š” ๊ฒƒ : S=>ฮฑAฯ‰ ์‹œ์ž‘ symbol์ด ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ reduce ํ•œ๋‹ค Handle S=>ฮฑฮฒฯ‰์ด๊ณ  A->ฮฒ์ด๋ฉด ฮฒ๋ฅผ ฮฑฮฒฯ‰์˜ handle์ด๋ผ๊ณ  ํ•œ๋‹ค ๋‘ ๊ฐœ ์ด์ƒ์˜ handle์ด ์กด์žฌํ• ๋•Œ -> ๋ชจํ˜ธํ•˜๋‹ค Shift์™€ Reduce๋กœ Parsing ํ•˜๊ธฐ Stack์˜ ์˜ˆ์‹œ Issue Shift์™€ Reduce ์ค‘ ์–ด๋А ๊ฒƒ์„ ํ• ๊นŒ? Stack์˜ top์—์„œ ์–ผ๋งˆ๋งŒํผ์„ handle๋กœ ๋ณผ ๊ฒƒ์ธ๊ฐ€? ํ•ด๊ฒฐ๋ฐฉ๋ฒ•: LR Parsing Table YACC LALR ํŒŒ์„œ ์ƒ์„ฑ๊ธฐ foo.y –(yacc)–> y.tab.c –(gcc)–> a.out *.y ํŒŒ์ผ ๊ตฌ์กฐ 1<์„ ์–ธ๋ถ€> 2... 3%% 4... 5exp : exp '+' term; 6factor : ident; 7... 8%% 9<์—ฌ๋Ÿฌ ํ•จ์ˆ˜> ๋ชจํ˜ธํ•œ ๋ฌธ๋ฒ•์œผ๋กœ LR Conflict ๋ฐœ์ƒ ์‹œ ์„ ์–ธ๋ถ€์—์„œ ์šฐ์„ ์ˆœ์œ„ ์ง€์ •ํ•˜์—ฌ ํ•ด๊ฒฐ LR Parsing Table Action table : Action + Parser ์ƒํƒœ Goto table : Parser ์ƒํƒœ LR(0) ํŒŒ์‹ฑ ํ…Œ์ด๋ธ” ๋งŒ๋“ค๊ธฐ LR(0) ์•„์ดํ…œ rhs์— ์ (’.’) symbol์„ ๊ฐ€์ง„ ์ƒ์„ฑ ๊ทœ์น™ ex) A->ฮฑ.ฮฒ, A->. closure ์ (’.’)๋’ค์— non-terminal์ด ์˜ค๋ฉด ์žฌ๊ท€์ ์œผ๋กœ ์ถ”๊ฐ€ S’ -> S, S -> (L)|id, L -> S | L,S closure({[S’->.S]}) = {[S’->.S], [S->.(L)], [S->.id]} goto goto(I, X)์ด๋ฉด ์ ์„ X๋’ค๋กœ ์˜ฎ๊ธฐ๊ณ  closure๋ฅผ ์ทจํ•œ๋‹ค X๊ฐ€ ์—†์œผ๋ฉด ๋„ฃ์ง€ ์•Š๋Š”๋‹ค I={[G->E=E], [E->E.+T]} ์ผ๋•Œ, goto(I, +) = closure({E->E+.T}) : ์ ์„ +๋’ค๋กœ ์˜ฎ๊น€ C0 ์ƒ์„ฑ๊ทœ์น™ S’->S์—์„œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋กœ closure์™€ goto๋ฅผ ์ ์šฉํ•˜์—ฌ ์–ป์€ ๋ชจ๋“  ํƒ€๋‹นํ•œ LR(0)์˜ ์•„์ดํ…œ ์ง‘ํ•ฉ๋“ค Item์˜ ์ข…๋ฅ˜ [A->X.Y] : X!=ฮต์ผ๋•Œ kernel item [A->.X] : closure item [A->X.] : reduce item SLR ํŒŒ์‹ฑ ํ…Œ์ด๋ธ” ๋งŒ๋“ค๊ธฐ reduce Item์ด [X->ฮฑ.]์ผ๋•Œ, FOLLOW(X)์˜ ๋ชจ๋“  terminal์—๋งŒ reduce action์„ ๋„ฃ๋Š”๋‹ค ๋‚˜๋จธ์ง€๋Š” LR(0)๊ณผ ๋˜‘๊ฐ™๋‹ค LR(0)๋ณด๋‹ค conflict๊ฐ€ ์ ์–ด, ๋” ์ •๊ตํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. LALR Parsing ์ •๊ตํ•œ ์ˆœ์„œ LR(0) < SLR < LALR(1) < LR(1) ํŒŒ์„œ ์ƒํƒœ์˜ ๊ฐœ์ˆ˜ SLR = LALR « LR(1) SDD, AST SDD (Syntax Directed Definition) SDD : semnatic action์„ ์ •์˜ํ•˜๋Š” ์ถ”์ƒ์ ์ธ ๋ช…์„ธ์„œ Semnatic Actions : ๊ทœ์น™์— ๋Œ€ํ•œ Action Yacc/Bison : $$, $1, $2, ... ์‚ฌ์šฉ ANTLR : $<name> ์‚ฌ์šฉ Type declaration Attribute ์ข…๋ฅ˜ synthesized attr. : children์— ์˜ํ•ด ๊ณ„์‚ฐ (terminal) inherited attr. : parent, sibling์— ์˜ํ•ด ๊ณ„์‚ฐ AST (Abstract Syntax Tree) ํŒŒ์ŠคํŠธ๋ฆฌ์—์„œ ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ฑฐํ•œ ํ˜•ํƒœ AST๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ํŒŒ์‹ฑ๋‹จ๊ณ„์—์„œ ๋งŒ๋“ค๊ธฐ : LL, LR ํŒŒ์ŠคํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ๋งŒ๋“ค๊ธฐ : SDD ์‚ฌ์šฉ (Yacc etc.) evaluation : ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๋ฉด์„œ ์ž‘์—…ํ•˜๋Š” ํ–‰์œ„ On-the-fly evaluation S-attributed SDD: synthesized attribute๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” SDD L-attributed SDD: synthesized attribute๋งŒ ๊ฐ€์ง€๋Š” ๊ฒฝ์šฐ + ๊ฐ’์ด ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ˜๋Ÿฌ ๊ณ„์‚ฐ์ด ์ด๋ฃจ์–ด์ง€๋Š” ๊ฒฝ์šฐ IR (Intermediate Representation) IR์ด๋ž€? Tree๋‚˜ Instruction list ํ˜•ํƒœ instruction(node)๊ฐ€ ์ ์–ด์•ผ ์ตœ์ ํ™”/๋ฒˆ์—ญ์— ์ข‹์Œ High Level IR High์™€ Low๋Š” ์ƒ๋Œ€์ ์ธ ๊ฐœ๋… High level IR: ์—ฌ๊ธฐ์„œ๋Š” AST์˜ ๋ณ€ํ˜•๋งŒ ์ƒ๊ฐ ์ข…๋ฅ˜ : AST, TCOL Low Level IR ๋‹จ์ˆœํ•œ instruction์œผ๋กœ ๊ตฌ์„ฑ ๊ฐ€์ƒ๊ธฐ๊ณ„(์ฃผ๋กœ RISC)๋ฅผ emulate N-tuple ํ‘œ๊ธฐ๋ฒ• (3-address code) a = b OP c ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ๊ณ„์–ด๊ฐ€ ๊ฐ€์ง€๋Š” ํ”ผ์—ฐ์‚ฐ์ž ๊ฐœ์ˆ˜ <= 3 quadruple : (์—ฐ์‚ฐ์ž, ํ”ผ์—ฐ์‚ฐ์ž1, ํ”ผ์—ฐ์‚ฐ์ž2, ๊ฒฐ๊ณผ) Stack machine code Java byte code, U-code : AST๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ์ด ์šฉ์ด Tree ํ‘œํ˜„ ๊ธฐ๊ณ„์–ด ์ƒ์„ฑ ์šฉ์ด IR ์˜ˆ์‹œ GCC - GIMPLE (3-address code) GCC์˜ ์ค‘๊ฐ„์ฝ”๋“œ : GENERIC -> GIMPLE -> RTL 1D.1954 = x*10 // D.1954๋Š” ์ž„์‹œ๋ณ€์ˆ˜ 2gimple_assign <mult_exprt, D.1954, x, 10> LLVM - bit (3-address code) LLVM IR : ์–ธ์–ด์™€ ๋จธ์‹ ์— ๋…๋ฆฝ์  1@var = global i32 14 ; ์ „์—ญ๋ณ€์ˆ˜ var์— 14 ๋Œ€์ž… 2define i32 @main() nounwind { ; i32(int) ๋ฐ˜ํ™˜ํ˜• 3 entry: 4 %a = alloca i32, align 4 ; ์ง€์—ญ๋ณ€์ˆ˜ a ์„ ์–ธ, int ํ• ๋‹น 5 %1 = load i32 * @var ; %1 ์ž„์‹œ๋ณ€์ˆ˜์— var๊ฐ’ ๋Œ€์ž… 6 ret i32 %1 ; ์ž„์‹œ๋ณ€์ˆ˜ ๊ฐ’ ๋ฐ˜ํ™˜ 7} JVM - byte code (stack machine code) ๊ฐ€์ƒ ๊ธฐ๊ณ„ ์ฝ”๋“œ (Bytecode, MSIL) ๊ฐ€์ƒ ๊ธฐ๊ณ„์—์„œ ๋™์ž‘ํ•˜๋„๋ก ํ•จ ์ด์‹์„ฑ, ํ˜ธํ™˜์„ฑ์ด ๋ชฉ์  : java bytecode๋Š” machine ํ˜ธํ™˜์„ฑ, c# msil์€ language ํ˜ธํ™˜์„ฑ 1public Employee(String strName, int num) 2{name = strName; idNumber = num; storeData(strName, num);} 3Method Employee(java.lang.String, int) 4 50 aload_0 ; 0๋ฒˆ์งธ ๋กœ์ปฌ๋ณ€์ˆ˜(this)๋ฅผ ์Šคํƒ์— push 61 invokespecial #3 <Method java.lang.Object()> ; ํ•จ์ˆ˜ ํ˜ธ์ถœ 7--- 84 aload_0 95 aload_1 ; strName์„ ์Šคํƒ์— push 106 putfield #5 <Field java.lang.String name> ; name์— strName ๋Œ€์ž… 11--- 129 aload_0 1310 iload_2 ; num์„ ์Šคํƒ์— push 1411 putfield #7 <Field int idNumber> ; idNumber์— num ๋Œ€์ž… 15--- 1614 aload_0 1715 aload_1 ; strName์„ ์Šคํƒ์— push 1816 iload_2 ; num์„ ์Šคํƒ์— push 1917 invokespecial #9 <Method void storeData(java.lang.String, int)> ; ํ•จ์ˆ˜ ํ˜ธ์ถœ 2020 return line number : ๋ช…๋ น์ด ์‹œ์ž‘ํ•˜๋Š” ๋ฐ”์ดํŠธ ์ฃผ์†Œ aload : ๊ฐ์ฒด๋ฅผ push, iload : ์ •์ˆ˜๋ฅผ push ์›๋ž˜๋Š” aload๊ฐ€ ๋ช…๋ น, ์ž์ฃผ ์“ฐ๋Š” ๋ช…๋ น aload 0์„ ๋ฌถ์–ด์„œ bind -> aload_0 CIL (Common Intermediate Language) (stack machine code) C#, VB.NET, J# ๋“ฑ์—์„œ ์‚ฌ์šฉ MSIL์€ ์˜›๋‚  ์ด๋ฆ„ 1.assembly Hello {} ; .assembly: ์–ด์…ˆ๋ธ”๋ฆฌ ์„ ์–ธ 2.assembly extern mscorlib {} 3.method static void Main() { 4 .entrypoint 5 .maxstack 1 6 ldstr "Hello, world!" ; stack์— ์ €์žฅ 7 call void [mscorlib]System.Console::WriteLine(string) 8 ret 9} GCC RTL(Register Transfer Language) (Tree๊ตฌ์กฐ ์ฝ”๋“œ) Lisp S-expression ์‚ฌ์šฉ 1(set (reg:SI 140) 2 (plus:SI (reg:SI 138) 3 (reg:SI 139))) => reg140 = reg138+reg139 IR generation 3-address Translation ๊ทœ์น™ Binary operations: t = [[el OP e2]] Unary operations: t = [[OP el]] Array access: t = [[ v[e] ]] Structure access: t = [[ v.f ]] Short-circuit OR: t = [[ el SC-OR e2]] Statement sequence: [[s1; s2; ...; sN]] Variable assignment: [[ v = e ]] Array assignment: [[ v[e1] = e2 ]] If: [[ if(e) then s ]], [[ if(e) then s1 else s2]] While: [[ while (e) s ]] Switch: [[ switch (e) case v1:s1, ..., case vN:sN ]] Function Call: [[ call f(e1, e2, ..., eN) ]] Fucntion Return: [[ return e ]] Statement Expression Statement๋„ expression ์ฒ˜๋Ÿผ ๊ฐ’์„ ๊ฐ€์ง€๋„๋ก ํ™•์žฅ t = [[ S ]]๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฒฐ๊ณผ๊ฐ’์„ ์ €์žฅํ•˜์ž Nested Expressions t = [[ (a - b) * (c + d) ]] t = [[ if c then if d then a = b ]] ๊ฐ€์žฅ ํฐ ๋ฉ์–ด๋ฆฌ๋ถ€ํ„ฐ ๋ฐ”๊พผ๋‹ค Storage Management 2๊ฐ€์ง€ Storage Register : ๋น ๋ฅธ ์ ‘๊ทผ, ๊ฐ„์ ‘ ์ ‘๊ทผ ๋ถˆ๊ฐ€ Memory : ์ƒ๋Œ€์ ์œผ๋กœ ๋А๋ฆฐ ์ ‘๊ทผ, ๊ฐ„์ ‘ ์ ‘๊ทผ ๊ฐ€๋Šฅ 2๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ์‹ All memory approach ๋ชจ๋“  ๋ณ€์ˆ˜๋ฅผ memory์— ์ €์žฅ, ๊ฐ€๋Šฅํ•œ๊ฒƒ๋งŒ register Standard approach Global, Statics, Local(composite)๋Š” memory์— ์ €์žฅ Local(scalar)๋Š” memory ๋˜๋Š” virtual register์— ์ €์žฅ Memory์˜ 4๋Œ€ ์˜์—ญ Code space : ๋ช…๋ น์–ด๋ฅผ ์ €์žฅ read-only์ผ๋•Œ ๋น ๋ฆ„ Static data : ํ”„๋กœ๊ทธ๋žจ๊ณผ lifetime์„ ํ•จ๊ป˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ Stack : Local ๋ณ€์ˆ˜๋“ค Heap : ๋™์ ์œผ๋กœ ํ• ๋‹น๋˜๋Š” ๋ฐ์ดํ„ฐ File Format Windows : PE (Portable Executable) Unix : ELF (Executable and Linkable Format) ๋ณ€์ˆ˜ ๋ฐ”์ธ๋”ฉ environment : <๋ณ€์ˆ˜, storage location> ์ •๋ณด state: <๋ณ€์ˆ˜, ๊ฐ’> ์ •๋ณด ์–ด๋–ค ๋ณ€์ˆ˜ N์ด storage location S์— ์ง€์ •๋˜๋ฉด ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค๊ณ  ํ•œ๋‹ค Static Allocation ํ”„๋กœ๊ทธ๋žจ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ ๋ณ€ํ•˜์ง€ ์•Š๋Š” location์œผ๋กœ ๋ฐ”์ธ๋”ฉ Heap Allocation ์—ฐ์†์ ์ธ global ์˜์—ญ์˜ ์ผ๋ถ€๋ฅผ OS๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๊ฒƒ ํ”„๋กœ๊ทธ๋žจ ์ˆ˜ํ–‰ ์ค‘ ์š”์ฒญ๊ณผ ๋ฐ˜ํ™˜ Stack Management Run-time stack : ํ•œ ํ•จ์ˆ˜ call๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ๋‘๋Š” frames Activation record : ํ•จ์ˆ˜ ์ˆ˜ํ–‰์„ ์œ„ํ•œ execution env(local var, parameter, return address, etc.) Top frame : ํ˜„์žฌ ์ˆ˜ํ–‰์ค‘์ธ ํ•จ์ˆ˜์˜ frame Stack pointers SP : Frame top FP : Frame base ๋‘ ๊ฐœ๋ฅผ ์“ฐ๋Š” ์ด์œ  ๊ฐ€๊นŒ์šด ๊ฑฐ ๊ธฐ์ค€์œผ๋กœ offset ๊ณ„์‚ฐ -> small offset ์œ ์ง€ ์ˆ˜ํ–‰ ์ค‘ top frame์˜ ์œ„์น˜๋ฅผ ์•Œ ์ˆ˜ ์—†์Œ Semantic Analysis - Symbol Tables Scope Identifier: ์‹๋ณ„์ž Lexical Scope: ํŠน์ • ๋ฒ”์œ„ ์‹๋ณ„์ž์˜ Scope: ๊ทธ ์‹๋ณ„์ž์˜ ์„ ์–ธ์ด ์ฐธ์กฐ๋˜๋Š” lexical scope Symbol Table Name Kind Type Attribute foo func int, int -> int extern m arg int tmp var char const ํ•˜๋‚˜์˜ lexical๋งˆ๋‹ค ํ•˜๋‚˜์˜ symbol table symbol table์€ ๊ณ„์ธต์ ์ด๋‹ค ํ˜„์žฌ scope์— ์—†์œผ๋ฉด ์ƒ์œ„ scope๋กœ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ์ฐพ๋Š”๋‹ค Symbol Table Implementation AST๊ฐ€ ๋งŒ๋“ค์–ด์ ธ์•ผ ๊ฐ€๋Šฅ Local Table์€ hash table ์‚ฌ์šฉ Global Table์€ N-array tree ๊ตฌ์กฐ ์‚ฌ์šฉ ์ฝ”๋“œ๋ฅผ ์ˆœ์ฐจ๋Œ€๋กœ ์ฝ์œผ๋ฉด์„œ ๋งŒ๋“ฌ (scope ์Šคํƒ์„ ์‚ฌ์šฉ) Type Checking Type Expressions Array types: T[], T[10] Structure types : {id1: T1, id2: T2 …} Pointer types: T* Function types: T1 X T2 X … X Tn -> T_return Type Judgement A โ”œ E : T A ์ƒํ™ฉ์—์„œ E๋Š” Tํƒ€์ž…์„ ๋งŒ์กฑํ•œ๋‹ค A โ”œ if(E) S1 else S2 : T ์œ„ ์กฐ๊ฑด์€ ๋ชจ๋“  E, S1, S2, A, T์— ๋Œ€ํ•œ ๊ฐ€์ •์ด ์„ฑ๋ฆฝํ•  ๋•Œ ๊ฒฐ๋ก  T๊ฐ€ ์„ฑ๋ฆฝํ•œ๋‹ค Proof Tree (ํƒ€์ž… ์œ ๋„ ํŠธ๋ฆฌ) ์—ญ์‚ผ๊ฐํ˜• ๋ชจ์–‘ ๋งŒ์กฑํ•˜๋Š” proof tree๊ฐ€ ์žˆ๋‹ค -> ํƒ€์ž… ์˜ค๋ฅ˜๊ฐ€ ์—†๋‹ค ๊ทธ ์™ธ Semantic Analyses break, continue, goto ๋ฌธ์ด ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ์žˆ๋Š” ์ง€ ๋“ฑ ์ปดํŒŒ์ผ๋Ÿฌ ํ›„๋ฐ˜๋ถ€ (๋น ๋ฅด๊ณ , ์‹ค์ œ ๋Œ์•„๊ฐ€๋Š” ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๊ธฐ) Instruction Selection Tree ๊ธฐ๋ฐ˜ Intermediate Representation MEM(e) : ์ฃผ์†Œ e๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ•œ word์˜ ๋‚ด์šฉ TEMP(t) : ๋ ˆ์ง€์Šคํ„ฐ t SEQ(s1, s2): ๋ฌธ์žฅ s1 ์ˆ˜ํ–‰ ํ›„ s2 ์ˆ˜ํ–‰ ESEQ(s, e): ๋ฌธ์žฅ s ์ˆ˜ํ–‰ ํ›„ (๊ฒฐ๊ณผ ์—†์Œ) e๊ฐ€ ์ถ”๊ฐ€ ์ˆ˜ํ–‰ BINOP(o, e1, e2) : ์—ฐ์‚ฐ์ž o, ํ”ผ์—ฐ์‚ฐ์ž e1, e2, ๊ฒฐ๊ณผ ์ €์žฅ๋œ ์ฃผ์†Œ ๋ฐ˜ํ™˜ const(i): ์ •์ˆ˜ ์ƒ์ˆ˜ i Register Allocation ์ตœ์ ํ™” ํ•˜๊ธฐ ์œ„ํ•ด ์ตœ๋Œ€ํ•œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ Register์— ์ €์žฅ Interference ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ definition์ด live range ์—์„œ ๊ณตํ†ต operation์„ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๊ฒฝ์šฐ Interference Graph : ์„œ๋กœ interfere ํ•˜๋ฉด ์—ฐ๊ฒฐํ•˜๋Š” ๊ทธ๋ž˜ํ”„ Graph coloring : ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋Š” ๋‹ค๋ฅธ ์ƒ‰์œผ๋กœ ์น ํ•˜๊ธฐ Instruction Scheduling instruction์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ์–ด stall ๊ฐœ์ˆ˜ ๋“ฑ์„ ์ค„์—ฌ์„œ ์ˆ˜ํ–‰์†๋„๋ฅผ ๋†’์ด๋Š” ๊ฒƒ stall : ๋‹ค๋ฅธ ๋ช…๋ น์–ด ์ˆ˜ํ–‰์„ ๊ธฐ๋‹ค๋ฆฌ๋А๋ผ CPU๋ฅผ ๋‚ญ๋น„ํ•˜๋Š” ๊ฒƒ ๋ชฉํ‘œ Wasting time์„ ์ค„์ธ๋‹ค ๋™์ผํ•œ ์ฝ”๋“œ๊ฐ€ ๋‚˜์™€์•ผํ•œ๋‹ค register spilling์„ ํ”ผํ•ด์•ผํ•œ๋‹ค Static scheduling ๋‹จ๊ณ„ Local basic scheduling, Loop scheduling, global scheduling Local basic scheduling List scheduling : greedy, heuristic, local technique ์‚ฌ์šฉ precedence graph๋ฅผ ๋งŒ๋“ ๋‹ค ๊ฐ ๋…ธ๋“œ์— priority function์„ ์ ์šฉํ•œ๋‹ค “ready-operation queue"๋ฅผ ์—์„œ ready operation์„ ํ•˜๋‚˜ ์„ ํƒ ํ›„ scheduling, ready operation queue๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. Longest latency-weighted path๋ฅผ ์ด์šฉํ•ด์„œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•œ๋‹ค ๊ธฐํƒ€ Optimization ๋ฐฉ๋ฒ• addr r1 1 -> inc r1 ํŠน์ˆ˜ ์„ฑ์งˆ์˜ ๋ ˆ์ง€์Šคํ„ฐ ํ™œ์šฉ ํŠน์ˆ˜ ๋ชฉ์ ์˜ ๋ช…๋ น์–ด ํ™œ์šฉ Register ๊ฐ„ mov ์ œ๊ฑฐ ์ค‘๋ณต๋œ load ์ œ๊ฑฐ Control Flow Optimizations(์ตœ์ ํ™”) ์ฃผ์–ด์ง„ ์ž…๋ ฅ ํ”„๋กœ๊ทธ๋žจ์„ ์ข€ ๋” ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ถ„๋ฅ˜ ๋ฐฉ๋ฒ• ๋ถ„์„ : Control Flow Analysis vs Data Flow Analysis ์ตœ์ ํ™” Inner basic block(local) vs Inter basic block(global) Cyclic code opt vs Acyclic code opt Control Flow Analysis Control Flow ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ€๋Šฅํ•œ ์ˆ˜ํ–‰์ˆœ์„œ (๋ถ„๊ธฐ) Branch Execution -> dynamic control flow : ์‹คํ–‰ ํ•ด๋ด์•ผ ํ™•์ธ ๊ฐ€๋Šฅ Compiler -> static control flow : ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ถ„์„ํ•ด์„œ ์•Œ ์ˆ˜ ์žˆ์Œ Analysis ์ •์  ์„ฑ์งˆ (static property): ํ”„๋กœ๊ทธ๋žจ ์ˆ˜ํ–‰ ์—†์ด ๋„์ถœ ๋˜๋Š” ์„ฑ์งˆ CFA(Control Flow Analysis) : ์ฝ”๋“œ์˜ ๋ถ„๊ธฐ ๊ตฌ์กฐ๋ฅผ CFG ํ˜•ํƒœ๋กœ ํ‘œํ˜„ Basic Block ๋™์ผํ•œ execution condition์„ ์ ์šฉ๋ฐ›๋Š” instruction ๋ฌถ์Œ instruction ์™ธ์—๋Š” branch๊ฐ€ ์—†์Œ Maximal basic block ๊ตฌํ•˜๊ธฐ BB์˜ leader(์ฒซ๋ฒˆ์งธ instruction)๋ฅผ ์ฐพ๋Š”๋‹ค ๋‹ค์Œ leader ์ด์ „๊นŒ์ง€์˜ instruction์„ ๊ตฌํ•œ๋‹ค Weighted CFG Profiling: ๋ฐ˜๋ณตํ•ด์„œ ์ˆ˜ํ–‰ํ•ด๋ณด๋ฉด์„œ ์‹คํ–‰ํšŸ์ˆ˜๋ฅผ ์–ป์Œ ์–ป์€ weight๋ฅผ edge์— ํ‘œ์‹œ Control Flow Optimization Acyclic Code Loop๊ฐ€ ์—†๋Š” ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ์ตœ์ ํ™”๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฌ์›€ ์ข…๋ฅ˜ Inner basic block opt. = Intra opt. = Local opt. Inter basic block opt. = Global opt. Inner Basic Block Optimization Commn subexpression elimination ๊ณตํ†ต๋œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ํ•œ๋ฒˆ๋งŒ ๊ณ„์‚ฐ Algebraic simplification ๋Œ€์ˆ˜๋ฒ•์น™์„ ์ด์šฉํ•˜์—ฌ ์‹์„ ๊ฐ„์†Œํ™” ex) x=1*y; -> x=y; Strength reduction ์—ฐ์‚ฐ์ž์˜ ๋น„์šฉ์ด ์ ์€ ๊ฒƒ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ ex) x=x*2; -> x=x+x; ex) y=a/4; -> y=a>>2; Constant folding / propagation folding: ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ์ƒ์ˆ˜์‹์„ ์ง์ ‘์‹œ๊ฐ„ propagation : ๊ณ ์ •๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ๋ณ€์ˆ˜๋ฅผ ์ƒ์ˆ˜๋กœ ๋Œ€์ฒด Inter Basic Block Optimization Global application of inner basic block optimization Global common subexpression elimination basic block ๊ฐ„์˜ ๊ณตํ†ต ๋ถ€๋ถ„์‹์— ๋Œ€ํ•ด ํ•œ๋ฒˆ๋งŒ ๊ณ„์‚ฐ Global constant folding / propagation basic block ๊ฐ„์˜ ์ƒ์ˆ˜๋ฅผ ์ธ์‹ํ•˜์—ฌ ํ•œ๋ฒˆ๋งŒ ๊ณ„์‚ฐ Other transformation Branch to unconditional branch ๋ถˆํ•„์š”ํ•œ ๋ถ„๊ธฐ ์ œ๊ฑฐ Unconditional branch to branch ๋ถ„๊ธฐ ํ›„ ๋ฐ”๋กœ ๋ถ„๊ธฐ -> ๋ถ„๊ธฐ ํ•œ๋ฒˆ์œผ๋กœ ๋ณ€๊ฒฝ Branch to next basic block (next instr) ๋ถ„๊ธฐ ํ›„ ๋ฐ”๋กœ ๋‹ค์Œ basic block์œผ๋กœ ๋ถ„๊ธฐ ์ œ๊ฑฐ Basic block merging ๋‘ basic block์„ ํ•ฉ์นจ Branch to same target ๊ฐ™์€ basic block์œผ๋กœ ๋ถ„๊ธฐํ•˜๋Š” ๊ฒƒ์„ ์ œ๊ฑฐ Branch target expansion ๋ถ„๊ธฐ ๋Œ€์ƒ์ด ๋˜๋Š” basic block์„ ํ•ฉ์นจ Unreachable code elimination Entry์—์„œ ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋Š” ‘unreachable’ block ์ œ๊ฑฐ Loop Optimization Loop๋Š” ํ•œ๋ฒˆ optimizeํ•˜๋ฉด ํšจ๊ณผ๊ฐ€ ํฌ๋‹ค Loop unrolling : ๋ฐ˜๋ณต๋ฌธ์„ ํ’€์–ด์„œ ๋ฐ˜๋ณต ํšŸ์ˆ˜๋ฅผ ์ค„์ž„ Loop invarient : ๋งค๋ฒˆ ๋™์ผํ•œ ๊ฐ’์„ ๋‚ด๋Š” ๋ฌธ์žฅ์„ ๋ฐ˜๋ณต๋ฌธ ๋ฐ–์œผ๋กœ ๋นผ๋ƒ„ Count up to zero : i๋ฅผ ๊ฐ์†Œํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๋ณ€๊ฒฝ (i๋ฅผ 0๊ณผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด n๊ณผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋น ๋ฆ„) Dataflow Analysis + Optimization Dataflow Analysis ํ”„๋กœ๊ทธ๋žจ ๋‚ด์— ๊ฐ data ๊ฐ’๋“ค์ด ์ƒ์„ฑ/์†Œ๋ฉธ๋˜๋Š” ์ •๋ณด๋ฅผ ๋ชจ์œผ๋Š” ๊ฒƒ Reaching Definition Analysis definition : ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ assign๋˜๋Š” ๊ฒƒ reach : definition d๊ฐ€ ํŠน์ • ์œ„์น˜ p์— ๋„๋‹ฌํ•œ๋‹ค kill : definition d์˜ ๋‘๊ฐœ์˜ ํฌ์ธํŠธ์‚ฌ์ด์—์„œ ๋‹ค๋ฅธ definition์ด ์กด์žฌํ•œ๋‹ค GEN/KILL GEN: ๋ธ”๋ก ๋‚ด์—์„œ ์ƒ์„ฑ๋œ definition KILL: ๋ธ”๋ก ๋‚ด์—์„œ ์†Œ๋ฉธ๋œ definition IN/OUT IN : ์ด์ „ ๋ธ”๋ก์˜ OUT์˜ ํ•ฉ์ง‘ํ•ฉ OUT : IN์—์„œ GEN์„ ๋”ํ•˜๊ณ  KILL์„ ๋บ€ ๊ฒƒ
new Nginx์—์„œ HTTPS ์„ค์ •ํ•˜๊ธฐ
๐Ÿ”จ ๊ฐœ๋ฐœ ๋„๊ตฌ
๋ฐฐ๊ฒฝ ํ…Œ์ปค ๋ถ€ํŠธ์บ ํ”„๋ฅผ ์ง„ํ–‰์ค‘์ด๋‹ค. ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ์€ docker-compose๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. AWS EC2์— ๊ตฌ๋™ ์ค‘์ธ ์„œ๋ฒ„์— HTTPS๋ฅผ ์ ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๋„๋ฉ”์ธ ๊ตฌ๋งค ์—†์ด ์‹œ๋„๋ฅผ ํ–ˆ์œผ๋‚˜, AWS์—์„œ ์ œ๊ณตํ•˜๋Š” ๋„๋ฉ”์ธ์œผ๋กœ SSL ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์—†์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ๋„๋ฉ”์ธ์„ ๊ตฌ๋งคํ•˜๊ณ , Route 53์„ ํ†ตํ•ด ๋„๋ฉ”์ธ์„ ์—ฐ๊ฒฐํ–ˆ๋‹ค. ๋ชฉํ‘œ Nginx๋ฅผ ์ด์šฉํ•˜์—ฌ HTTPS๋ฅผ ์ ์šฉํ•œ๋‹ค. ๋ฐฉ๋ฒ• 1. docker-compose.yml์— certbot ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. 1certbot: 2 image: certbot/certbot 3 container_name: certbot 4 volumes: 5 - ./certbot/conf:/etc/letsencrypt 6 - ./certbot/www:/var/www/certbot 7 depends_on: 8 - nginx 9 10 # certbot์„ ๋ฌดํ•œ๋ฃจํ”„๋กœ ๋Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ 11 entrypoint: "/bin/sh -c 'trap exit TERM; while :; do sleep 6h & wait $${!}; done;'" 2. nginx.conf๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. # certbot์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ • location /.well-known/acme-challenge/ { allow all; root /var/www/certbot; } 3. certbot ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ™œ์šฉํ•ด์„œ SSL ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰๋ฐ›๋Š”๋‹ค. 1docker exec -it certbot certbot certonly \ 2 # ์›น ๋ฃจํŠธ ๋ฐฉ์‹์œผ๋กœ ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑ 3 --webroot \ 4 # ์›น ์„œ๋ฒ„์˜ ์›น ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ๋ฅผ ์ง€์ • 5 --webroot-path=/var/www/certbot \ 6 # ์ธ์ฆ์„œ ๊ฐฑ์‹  ๋ฐ ์ค‘์š”ํ•œ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ์ง€์ • 7 --email {์ด๋ฉ”์ผ ์ฃผ์†Œ} \ 8 # Let's Encrypt ์„œ๋น„์Šค ์•ฝ๊ด€์— ๋™์˜ 9 --agree-tos \ 10 # EFF(Electronic Frontier Foundation) ๋‰ด์Šค๋ ˆํ„ฐ๋ฅผ ๋ฐ›์ง€ ์•Š๋„๋ก ์„ค์ • 11 --no-eff-email \ 12 # SSL ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•  ๋„๋ฉ”์ธ ์ด๋ฆ„์„ ์ง€์ • 13 -d {๋„๋ฉ”์ธ ์ด๋ฆ„} 4. Nginx ์›น ์„œ๋ฒ„์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  SSL ์„ค์ • ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋‹ค์šด ๋ฐ›์€ ํ›„ ํŒŒ์ผ์„ ์•Œ๋งž์€ ์œ„์น˜๋กœ ์ด๋™์‹œํ‚จ๋‹ค. ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋Š” /etc/letsencrypt/๋กœ ์ด๋™์‹œ์ผฐ๋‹ค. 1sudo curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "./options-ssl-nginx.conf" 2 3sudo curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "./ssl-dhparams.pem" 5. nginx.conf๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค. server { listen 80; charset utf-8; server_name {๋„๋ฉ”์ธ ์ด๋ฆ„}; # HTTP ์š”์ฒญ์„ HTTPS๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; charset utf-8; server_name { ๋„๋ฉ”์ธ ์ด๋ฆ„ }; # SSL ์ธ์ฆ์„œ ์„ค์ • ssl_certificate /etc/letsencrypt/live/api.forest-of-thoughts.site/fullchain.pem; # SSL ์ธ์ฆ์„œ ํ‚ค ์„ค์ • ssl_certificate_key /etc/letsencrypt/live/api.forest-of-thoughts.site/privkey.pem; # SSL ์„ค์ • ํŒŒ์ผ ํฌํ•จ include /etc/letsencrypt/options-ssl-nginx.conf; # Diffie-Hellman ํ‚ค ์„ค์ • ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } 6. nginx ์ปจํ…Œ์ด๋„ˆ ์„ค์ •์„ ์ˆ˜์ •ํ•œ๋‹ค. 1nginx: 2 image: nginx:stable 3 ports: 4 - "80:80" 5 - "443:443" 6 volumes: 7 - ./nginx.conf:/etc/nginx/nginx.conf 8 - ./certbot/conf:/etc/letsencrypt 9 - ./certbot/www:/var/www/certbot ํ•ด ํšŒ๊ณ  ๋ณดํ†ต crontab์„ ํ™œ์šฉํ•ด์„œ ์ž๋™์œผ๋กœ ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ๋ฐ›๋Š”๋‹ค. ์ด๋ฒˆ์—๋Š” ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„์ด ๊ธธ์ง€ ์•Š์•„์„œ, ์ˆ˜๋™์œผ๋กœ ์ง„ํ–‰ํ–ˆ๋‹ค. ๋‹ค์Œ์—๋Š” ์ž๋™์œผ๋กœ ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ๋ฐ›๋Š” ๊ฒƒ๋„ ๋„์ „ํ•ด๋ณด์ž.
new Issue - yaml ๋ฌธ์ž์—ด ์† colon(์ฝœ๋ก )
๐ŸŽธ ๊ธฐํƒ€
๋ฌธ์ œ์ƒํ™ฉ TIL ๋ธ”๋กœ๊ทธ ์ž๋™ ๋ฐฐํฌ github action ์ฝ”๋“œ์— yaml ํŒŒ์ผ์— ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค ์ถ”๊ฐ€ํ•˜๋Š” ๋ฌธ์ž์—ด์— ์ฝœ๋ก ์ด ํฌํ•จ๋˜์–ด ์žˆ์–ด์„œ action์—์„œ ์—๋Ÿฌ๋ฅผ ๋„์› ๋‹ค ๋ฌธ์ œ์˜ ์ฝ”๋“œ 1- name: Add google analytics id 2 run: echo -e "\nparams:\n googleAnalytics : \"$GA_TRACKING_ID\"" >> config.yaml ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์šฐ์—ฌ๊ณก์ ˆ ๋์— ์œ„์™€ ๊ฐ™์ด 2์ค„๋กœ ๋‚˜๋ˆ„์–ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค 1 - name: Add google analytics id 2 run: | 3 echo -e "\nparams:" >> config.yaml 4 echo -e " googleAnalytics: \"$GA_TRACKING_ID\"" >> config.yaml
new [๋ชจ๊ฐ์ฝ”24ํ•˜๊ณ„] 01 : ๊ฒฐ๊ณผ
๐Ÿ‘จโ€๐Ÿ’ป ๋ชจ๊ฐ์ฝ”
django์—์„œ swagger ๋ฌธ์„œํ™” ๊ตฌํ˜„ํ•˜๊ธฐ ๊ฐœ์š” ์žฅ๊ณ  ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ์ ์ธ CRUD ๊ธฐ๋Šฅ๊ณผ, REST API๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ 1. 2โ”œโ”€โ”€ db.sqlite3 3โ”œโ”€โ”€ djtest (๋ฉ”์ธ ์•ฑ) 4โ”‚ โ”œโ”€โ”€ __init__.py 5โ”‚ โ”œโ”€โ”€ asgi.py 6โ”‚ โ”œโ”€โ”€ settings.py 7โ”‚ โ”œโ”€โ”€ urls.py 8โ”‚ โ”œโ”€โ”€ views.py 9โ”‚ โ””โ”€โ”€ wsgi.py 10โ”œโ”€โ”€ manage.py 11โ”œโ”€โ”€ paste (์ƒ์„ฑํ•œ ์•ฑ) 12โ”‚ โ”œโ”€โ”€ __init__.py 13โ”‚ โ”œโ”€โ”€ admin.py 14โ”‚ โ”œโ”€โ”€ apps.py 15โ”‚ โ”œโ”€โ”€ migrations 16โ”‚ โ”œโ”€โ”€ models.py 17โ”‚ โ”œโ”€โ”€ serializers.py 18โ”‚ โ”œโ”€โ”€ tests.py 19โ”‚ โ”œโ”€โ”€ urls.py 20โ”‚ โ””โ”€โ”€ views.py 21โ””โ”€โ”€ requirements.txt ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” Django ๋ช…๋ น์ž 1# ์ƒˆ๋กœ์šด Django ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑ 2python manage.py startproject 3# ์ƒˆ๋กœ์šด Django ์•ฑ์„ ์ƒ์„ฑ 4python manage.py startapp 5# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ์šฉํ•  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ์ƒ์„ฑ 6python manage.py makemigrations 7# ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ์šฉ 8python manage.py migrate 9# ๊ด€๋ฆฌ์ž(superuser) ๊ณ„์ •์„ ์ƒ์„ฑ 10python manage.py createsuperuser 11# ํ”„๋กœ์ ํŠธ์˜ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์‹คํ–‰ 12python manage.py test 13# ํ…Œ์ŠคํŠธ์šฉ ์„œ๋ฒ„๋ฅผ ํŠน์ • ์„ค์ •์œผ๋กœ ์‹คํ–‰ 14python manage.py testserver CRUD ๊ตฌํ˜„ Paste ๋ชจ๋ธ ์ •์˜ 1from django.db import models 2 3class Paste(models.Model): 4 title = models.CharField(max_length=100) 5 content = models.TextField() 6 # auto_now_add : ๊ฐ์ฒด๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ๋งŒ ํ˜„์žฌ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ์ž๋™์œผ๋กœ ์„ค์ • 7 created_at = models.DateTimeField(auto_now_add=True) 8 # auto_now : ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋  ๋•Œ๋งˆ๋‹ค ํ˜„์žฌ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ์ž๋™์œผ๋กœ ์„ค์ • 9 updated_at = models.DateTimeField(auto_now=True) 10 class Meta: 11 ordering = ['-created_at'] 12 def __str__(self): 13 return self.title Serializer ์ •์˜ 1from rest_framework import serializers 2from .models import Paste 3 4class PasteSerializer(serializers.ModelSerializer): 5 class Meta: 6 model = Paste 7 fields = '__all__' 8 # ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• 9 # fields = ['title', 'content'] View ๊ตฌํ˜„ PasteView 1class PasteView(APIView): 2 def get(self, _): 3 pastes = Paste.objects.all() 4 serializer = PasteSerializer(pastes, many=True) 5 return Response(serializer.data, status=status.HTTP_200_OK) 6 7 def post(self, request): 8 serializer = PasteSerializer(data=request.data) 9 if serializer.is_valid(): 10 serializer.save(user=request.user) 11 return Response(serializer.data, status=status.HTTP_201_CREATED) 12 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) PasteDetailView 1class PasteDetailView(APIView): 2 def get(self, _, pk): 3 try: 4 paste = Paste.objects.get(pk=pk) 5 serializer = PasteSerializer(paste) 6 return Response(serializer.data, status=status.HTTP_200_OK) 7 except Paste.DoesNotExist: 8 return Response(status=status.HTTP_404_NOT_FOUND) 9 10 def put(self, request, pk): 11 try: 12 paste = Paste.objects.get(pk=pk) 13 except Paste.DoesNotExist: 14 return Response(status=status.HTTP_404_NOT_FOUND) 15 16 if paste.user != request.user: 17 return Response(status=status.HTTP_403_FORBIDDEN) 18 19 serializer = PasteSerializer(paste, data=request.data) 20 if serializer.is_valid(): 21 serializer.save() 22 return Response(serializer.data, status=status.HTTP_200_OK) 23 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 24 25 def delete(self, request, pk): 26 try: 27 paste = Paste.objects.get(pk=pk) 28 except Paste.DoesNotExist: 29 return Response(status=status.HTTP_404_NOT_FOUND) 30 31 paste.delete() 32 return Response(status=status.HTTP_204_NO_CONTENT) urls.py 1from django.urls import path 2from paste.views import * 3 4urlpatterns = [ 5 path('', PasteView.as_view(), name='paste_list_create'), 6 path('<int:pk>', PasteDetailView.as_view(), name='paste_get_update_delete'), 7] Swagger ์ ์šฉ PasteView PasteView 1class PasteView(APIView): 2 @swagger_auto_schema( 3 operation_description="Get list of pastes", 4 operation_summary="Get list of pastes", 5 responses={200: PasteSerializer(many=True)}, 6 ) 7 def get(self, _): 8 ... 9 10 @swagger_auto_schema( 11 operation_description="Create a new paste", 12 operation_summary="Create a new paste", 13 request_body=PasteSerializer, 14 responses={201: PasteSerializer, 400: "Bad Request"}, 15 ) 16 def post(self, request): 17 ... PasteDetailView 1class PasteDetailView(APIView): 2 @swagger_auto_schema( 3 operation_description="Get a paste by ID", 4 operation_summary="Get a paste by ID", 5 responses={200: PasteSerializer, 404: "Not Found"}, 6 ) 7 def get(self, _, pk): 8 ... 9 10 @swagger_auto_schema( 11 operation_description="Update a paste by ID", 12 operation_summary="Update a paste by ID", 13 request_body=PasteSerializer, 14 responses={ 15 200: PasteSerializer, 16 400: "Bad Request", 17 403: "Forbidden", 18 404: "Not Found", 19 }, 20 ) 21 def put(self, request, pk): 22 ... 23 24 @swagger_auto_schema( 25 operation_description="Delete a paste by ID", 26 operation_summary="Delete a paste by ID", 27 responses={204: "No Content", 404: "Not Found"}, 28 ) 29 def delete(self, request, pk): 30 ... swagger ์ ์šฉ ๊ฒฐ๊ณผ django์—์„œ JWT ์ธ์ฆ ๊ตฌํ˜„ํ•˜๊ธฐ ์žฅ๊ณ ์—์„œ๋Š” djangorestframework-simplejwt ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JWT ์ธ์ฆ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. requirements 1pip install djangorestframework-simplejwt settings.py 1INSTALLED_APPS = [ 2 ... 3 'rest_framework', 4 'rest_framework_simplejwt', 5] 1REST_FRAMEWORK = { 2 # ๊ธฐ๋ณธ ์ธ์ฆ ํด๋ž˜์Šค๋ฅผ ์„ค์ • 3 'DEFAULT_AUTHENTICATION_CLASSES': ( 4 'rest_framework_simplejwt.authentication.JWTAuthentication', 5 ), 6 # ๊ธฐ๋ณธ ์Šคํ‚ค๋งˆ ํด๋ž˜์Šค๋ฅผ ์„ค์ •, CoreAPI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ API ๋ฌธ์„œํ™”๋ฅผ ์ƒ์„ฑ 7 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', 8 # ๊ธฐ๋ณธ ๊ถŒํ•œ ํด๋ž˜์Šค๋ฅผ ์„ค์ •, AllowAny๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์š”์ฒญ์„ ํ—ˆ์šฉ 9 'DEFAULT_PERMISSION_CLASSES': ( 10 'rest_framework.permissions.AllowAny', 11 ), 12} 1from datetime import timedelta 2 3SIMPLE_JWT = { 4 # ์•ก์„ธ์Šค ํ† ํฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์„ค์ • 5 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30), 6 # ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์„ค์ • 7 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), 8 # ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๊ฐฑ์‹ ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ค์ • 9 'ROTATE_REFRESH_TOKENS': False, 10 # ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๊ฐฑ์‹ ๋œ ํ›„ ์ด์ „ ํ† ํฐ์„ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ค์ • 11 'BLACKLIST_AFTER_ROTATION': True, 12 13 # JWT ํ† ํฐ์˜ ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค์ • 14 'ALGORITHM': 'HS256', 15 # JWT ํ† ํฐ์„ ์„œ๋ช…ํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ‚ค๋ฅผ ์„ค์ • 16 'SIGNING_KEY': SECRET_KEY, 17 # ํ† ํฐ ๊ฒ€์ฆ์— ์‚ฌ์šฉํ•  ๊ณต๊ฐœ ํ‚ค๋ฅผ ์„ค์ • 18 'VERIFYING_KEY': None, 19 # ํ† ํฐ์˜ ๋Œ€์ƒ์ž(aud) ํด๋ ˆ์ž„์„ ์„ค์ • 20 'AUDIENCE': None, 21 # ํ† ํฐ์˜ ๋ฐœ๊ธ‰์ž(iss) ํด๋ ˆ์ž„์„ ์„ค์ • 22 'ISSUER': None, 23 24 # ์ธ์ฆ ํ—ค๋” ํƒ€์ž…์„ ์„ค์ • 25 'AUTH_HEADER_TYPES': ('Bearer',), 26 # ์ธ์ฆ ํ—ค๋”์˜ ์ด๋ฆ„์„ ์„ค์ • 27 'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', 28 # ์‚ฌ์šฉ์ž ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉ์ž ID ํ•„๋“œ๋ฅผ ์„ค์ • 29 'USER_ID_FIELD': 'id', 30 # JWT ํ† ํฐ์—์„œ ์‚ฌ์šฉ์ž ID๋ฅผ ์ €์žฅํ•  ํด๋ ˆ์ž„์„ ์„ค์ • 31 'USER_ID_CLAIM': 'user_id', 32 33 # ์ธ์ฆ์— ์‚ฌ์šฉํ•  ํ† ํฐ ํด๋ž˜์Šค๋“ค์„ ์„ค์ • 34 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), 35 # ํ† ํฐ์˜ ์œ ํ˜•์„ ์ €์žฅํ•  ํด๋ ˆ์ž„์„ ์„ค์ • 36 'TOKEN_TYPE_CLAIM': 'token_type', 37} urls.py 1from django.urls import path 2from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView 3from rest_framework_simplejwt.authentication import JWTAuthentication 4 5urlpatterns = [ 6 # JWT ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•˜๋Š” ๋ทฐ 7 path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), 8 # JWT ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๋ทฐ 9 path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), 10] views.py 1from rest_framework import permissions 2from rest_framework_simplejwt.authentication import JWTAuthentication 3from drf_yasg.utils import swagger_auto_schema 4 5 6class PasteView(APIView): 7 8 def get(self, request): 9 ... 10 11 def post(self, request): 12 ... 13 14 def get_permissions(self): 15 # SAFE_METHODS : GET, HEAD, OPTIONS 16 if self.request.method in permissions.SAFE_METHODS: 17 self.permission_classes = [permissions.AllowAny] 18 else: 19 self.authentication_classes = [JWTAuthentication] 20 self.permission_classes = [permissions.IsAuthenticated] 21 return super().get_permissions() 22 23 24class PasteDetailView(APIView): 25 26 def get(self, request, pk): 27 ... 28 29 def put(self, request, pk): 30 ... 31 32 def delete(self, request, pk): 33 ... 34 35 def get_permissions(self): 36 # SAFE_METHODS : GET, HEAD, OPTIONS 37 if self.request.method in permissions.SAFE_METHODS: 38 self.permission_classes = [permissions.AllowAny] 39 else: 40 self.authentication_classes = [JWTAuthentication] 41 self.permission_classes = [permissions.IsAuthenticated] 42 return super().get_permissions() ๊ฒฐ๊ณผ TokenObtainPairView๋ฅผ ํ†ตํ•ด access token๊ณผ refresh token์„ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. TokenRefreshView๋ฅผ ํ†ตํ•ด refresh token์„ ์‚ฌ์šฉํ•˜์—ฌ access token์„ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค. access token๊ณผ refresh token์€ settings.py์—์„œ ์„ค์ •ํ•œ ์œ ํšจ ๊ธฐ๊ฐ„์— ๋”ฐ๋ผ ๋งŒ๋ฃŒ๋œ๋‹ค. Blacklist ์ ์šฉ settings.py 1INSTALLED_APPS = [ 2 ... 3 'rest_framework_simplejwt.token_blacklist', 4] 1SIMPLE_JWT = { 2 ... 3 # ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ์— ํ† ํฐ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ•  ๋ชจ๋ธ์„ ์„ค์ • 4 'BLACKLIST_AFTER_ROTATION': True, 5} ๊ฒฐ๊ณผ TokenRefreshView๋ฅผ ํ†ตํ•ด ํ† ํฐ์ด ์žฌ๋ฐœ๊ธ‰๋  ๋•Œ, ์ด์ „ refresh token์„ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
new Fastapi - ํ†ตํ•ฉํ…Œ์ŠคํŠธ In-Memory DB์—์„œ ํ…Œ์ด๋ธ”์ด ์—†๋‹ค๋Š” ๋ฌธ์ œ
๐Ÿ Python
์ƒํ™ฉ ํ…Œ์ปค ๋ถ€ํŠธ์บ ํ”„์—์„œ ํŒ€ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ์ค‘์ด๋‹ค. ๋‹จ์œ„ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ์ž‘์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ๊ณ , ํ†ตํ•ฉํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ์ค‘์ด๋‹ค. sqlite in-memory db๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ ์ค‘์ธ๋ฐ, ํ…Œ์ด๋ธ”์ด ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ „์— ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋จ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ธ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ๋ฌธ์ œ์˜ ์›์ธ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ฝ”๋“œ 1from database import Base, engine 2from fastapi.testclient import TestClient 3 4from main import app 5from models import * 6 7# ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค 8Base.metadata.create_all(bind=engine) 9 10client = TestClient(app) 11 12 13class TestUserApi: 14 15 def test_create_user(self): 16 test_nickname = "test_nickname" 17 # ์•„๋ž˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค 18 response = client.post( 19 "/api/users", 20 json={"nickname": test_nickname}, 21 ) 22 assert response.status_code == 200 23 assert response.json()["nickname"] == test_nickname ์›์ธ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ• ๋•Œ ๋งŒ๋“ค์–ด์ง€๋Š” ์„ธ์…˜๊ณผ TestClient๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์„ธ์…˜์ด ๋‹ค๋ฅด๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• TestClient๋‚ด์— get_db() ํ•จ์ˆ˜๋ฅผ ์ž„์˜๋กœ ์ฃผ์ž…ํ•œ๋‹ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ• ๋•Œ, ๋‹จ์ผ ์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค. 1from database import Base, engine, get_db 2from sqlalchemy.orm import sessionmaker 3from fastapi.testclient import TestClient 4 5from main import app 6from models import * 7 8Base.metadata.create_all(bind=engine) 9 10client = TestClient(app) 11 12# ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•  ์„ธ์…˜์„ ์ƒ์„ฑํ•œ๋‹ค 13TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 14 15 16Base.metadata.create_all(bind=engine) 17 18# get_db() ํ•จ์ˆ˜๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค 19def override_get_db(): 20 try: 21 db = TestingSessionLocal() 22 yield db 23 finally: 24 db.close() 25 26# get_db() ํ•จ์ˆ˜๋ฅผ ์žฌ์ •์˜ํ•œ ํ•จ์ˆ˜๋ฅผ ์ฃผ์ž…ํ•œ๋‹ค 27app.dependency_overrides[get_db] = override_get_db 28 29 30class TestUserApi: 31 32 def test_create_user(self): 33 test_nickname = "test_nickname" 34 response = client.post( 35 "/api/users", 36 json={"nickname": test_nickname}, 37 ) 38 assert response.status_code == 201 39 assert response.json()["nickname"] == test_nickname 1engine = create_engine( 2 os.getenv("DATABASE_URL"), 3 # sqlite๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ์—ฐ๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค 4 connect_args={"check_same_thread": False}, 5 # ๋‹จ์ผ ์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค 6 poolclass=StaticPool, 7)
new Issue - fastapi์—์„œ websocket 404 ๋ฌธ์ œ
๐Ÿ Python
๋ฐฐ๊ฒฝ ํ…Œ์ปค ๋ถ€ํŠธ์บ ํ”„ ์ตœ์ข…๋ฐœํ‘œ ์ „๋‚ ์ด๋‹ค. gpt ํ”„๋กฌํ”„ํŠธ ๋ถ€๋ถ„ ์ˆ˜์ •์„ main ๋ธŒ๋žœ์น˜์— ๋ฐ˜์˜ํ•˜๊ณ , EC2 ์„œ๋ฒ„์— ๋ฐฐํฌํ–ˆ๋‹ค. ๋ฌธ์ œ ๋ฐฐํฌํ•œ ์„œ๋ฒ„์—์„œ websocket ์—ฐ๊ฒฐ์ด 404 ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (๋‚ด์ผ์ด ์ตœ์ข… ๋ฐœํ‘œ์ธ๋ฐ,,,) ๋‹ค๋ฅธ http ์š”์ฒญ์€ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์ง€๋งŒ ์›น์†Œ์ผ“๋งŒ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. nginx์˜ log 1{IP์ฃผ์†Œ} - - [02/Aug/2024:10:59:04 +0000] "GET /ws/chatrooms/294?user_id=296 HTTP/1.1" 404 22 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15" 2{IP์ฃผ์†Œ} - - [02/Aug/2024:10:59:05 +0000] "GET /ws/chatrooms/294?user_id=296 HTTP/1.1" 404 22 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15" ์‚ฌ๊ณ ํ๋ฆ„ nginx ์„ค์ • ๋ฌธ์ œ์ธ๊ฐ€? X nginx ์„ค์ •์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค. ๋ฐฐํฌํ™˜๊ฒฝ์˜ ๋ฌธ์ œ์ธ๊ฐ€? X ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•œ ์„œ๋ฒ„์—์„œ๋„ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค. ์ด๋ฒˆ ๋ฐฐํฌ์—์„œ ๋ณ€๊ฒฝ๋œ ์†Œ์Šค์ฝ”๋“œ๊ฐ€ ๋ฌธ์ œ์ธ๊ฐ€? X ์œก์•ˆ์œผ๋กœ ํ™•์ธํ–ˆ์„ ๋•Œ๋Š”, ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์ด ์›น์†Œ์ผ“๊ณผ ๊ด€๋ จ์ด ์—†๋‹ค. ๋กœ์ปฌ์—์„œ ์ด์ „ ๋ฒ„์ „์œผ๋กœ reset ํ›„ ์‹œ๋„ ํ•ด๋ณด์•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค. Docker image ๋ฌธ์ œ์ธ๊ฐ€? X ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋Š” python:slim ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ์ด๋ฏธ์ง€๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๋กœ์ปฌ์—์„œ docker image๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•ด๋ณด์•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค. ์ด๋•Œ, ๋กœ๊ทธ์—์„œ warning ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ–ˆ๋‹ค. WARNING: No supported WebSocket library detected. Please use "pip install 'uvicorn[standard]'", or install 'websockets' or 'wsproto' manually. ์›์ธ ๋ชจ์ข…์˜ ์ด์œ ๋กœ, ์ด์ „์— ๊ฐœ๋ฐœ/๋ฐฐํฌํ• ๋•Œ์—๋Š” ์กด์žฌํ–ˆ๋˜ ์›น์†Œ์ผ“ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์‚ฌ๋ผ์ง„ ๊ฒƒ์ด๋‹ค. ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์กฐ์‚ฌํ•ด๋ณธ ๊ฒฐ๊ณผ fastapi ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— 6์‹œ๊ฐ„ ์ „ merge๋œ PR์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. (https://github.com/fastapi/fastapi/pull/11935) ํ•ด๋‹น PR์—์„œ๋Š” pip install fastapi[standard] ๋ฅผ ํ†ตํ•ด ํ‘œ์ค€ ์ข…์† ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค. ์ด๋กœ ์ธํ•ด, uvicorn[standard] ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š์•˜์„ ๋•Œ, ์›น์†Œ์ผ“ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•„ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์˜€๋‹ค. ํ•ด๊ฒฐ requirements.txt์— websockets๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋ฐฐ์šด ์  ์ค‘์š”ํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•  ๋•Œ requirements.txt์— ํ•ญ์ƒ ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋ฒ„์ „์„ ๋ช…์‹œํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ์ด๋ฒˆ์—๋„ ๋ฒ„์ „์„ ๋ช…์‹œํ–ˆ๋‹ค๋ฉด, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋”๋ผ๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ด๋‹ค. ๋˜ํ•œ, ๋กœ๊ทธ๋ฅผ ์ž˜ ํ™•์ธํ•˜๊ณ , warning ๋ฉ”์‹œ์ง€๋ฅผ ๋†“์น˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ๊ฒ ๋‹ค.
new Spring ๊ฐœ๋… - DI (Dependency Injection)
๐Ÿƒ Spring
์˜์กด ์ฃผ์ž… (DI : Dependency Injection)์„ ํ•˜๋Š” ๋ฐฉ๋ฒ• Assembler๋ผ๋Š” ๋ณ„๋„์˜ ํด๋ž˜์Šค ์ƒ์„ฑ 1public class Assembler { 2 private MemberDao memberDao; 3 private MemberRegisterService regSvc; 4 5 public Assembler() { 6 memberDao = new MemberDao(); 7 regSvc = new MemberRegisterService(memberDao); 8 } 9 10 public MemberDao getMemberDao() { 11 return memberDao; 12 } 13 14 public MemberRegisterService getMemberRegisterService() { 15 return regSvc; 16 } 17} Spring์—์„œ ์ง€์›ํ•˜๋Š” DI ์‚ฌ์šฉ 1@Configuration 2public class AppCtx { 3 @Bean 4 public MemberDao memberDao() { 5 return new MemberDao(); 6 } 7 @Bean 8 public MemberRegisterService memberRegSvc() { 9 return new MemberRegisterService(memberDao()); 10 } 11} DI ๋ฐฉ์‹ Constructor ๋ฐฉ์‹ 1@Bean 2 public MemberListPrinter listPrinter() { 3 return new MemberListPrinter(memberDao(), memberPrinter()); 4 } Setter method ๋ฐฉ์‹ 1@Bean 2public MemberInfoPrinter infoPrinter() { 3 MemberInfoPrinter infoPrinter = new MemberInfoPrinter(); 4 infoPrinter.setMemberDao(memberDao()); 5 infoPrinter.setPrinter(memberPrinter()); 6 return infoPrinter; 7} constructor ๋ฐฉ์‹์ด ํ›จ์”ฌ ๊น”๋”ํ•ด๋ณด์ธ๋‹ค. java bean์—์„œ๋Š” getter์™€ setter๋ฅผ ์ด์šฉํ•ด์„œ property๋ฅผ ์ •์˜ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ๋‘ ๊ฐœ ์ด์ƒ์˜ Configuration ํŒŒ์ผ ์‚ฌ์šฉ : @Autowired ํ™œ์šฉ AppConf1.java 1@Configuration 2public class AppConf1 { 3 ... 4} AppConf2.java 1import org.springframework.beans.factory.annotation.Autowired; 2 3@Configuration 4public class AppConf2 { 5 @Autowired 6 private MemberDao memberDao; 7 @Autowired 8 private MemberPrinter memberPrinter; 9 10 ... 11} MainForSpring.java 1ctx = new AnnotationConfigApplicationContext(AppConf1.class, AppConf2.class); Autowired annotation์„ ํ†ตํ•ด ๋‹ค๋ฅธ ์„ค์ • ํŒŒ์ผ์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๋‘ ๊ฐœ ์ด์ƒ์˜ Configuration ํŒŒ์ผ ์‚ฌ์šฉ : @Import ํ™œ์šฉ AppConfImport.java 1import org.springframework.context.annotation.Import; 2 3@Configuration 4@Import(AppConf2.class) 5public class AppConfImport { MainForSpring.java 1ctx = new AnnotationConfigApplicationContext(AppConfImport.class); 2// ํด๋ž˜์Šค ํ•œ ๊ฐœ๋งŒ ๋ช…์‹œํ•ด์ค˜๋„ ๊ฐ€๋Šฅ ํƒ€์ž…๋งŒ์œผ๋กœ ๋นˆ์„ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค 1VersionPrinter versionPrinter = ctx.getBean(MemberPrinter.class); ๋‹ค๋งŒ, ๊ฐ™์€ ํƒ€์ž…์˜ ๋นˆ ๊ฐ์ฒด๊ฐ€ 2๊ฐœ ์ด์ƒ ์กด์žฌํ•œ๋‹ค๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ
new Spring ๊ฐœ๋… - Testing
๐Ÿƒ Spring
Unit Test (๋‹จ์œ„ ํ…Œ์ŠคํŠธ) ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„ (ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์†Œ๋“œ)๋ฅผ ๊ณ ๋ฆฝ์‹œ์ผœ์„œ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ์‹ ๊ด€๋ จ ์šฉ์–ด SUT (Sytem Under Test) ํ…Œ์ŠคํŠธํ•˜๊ณ ์žํ•˜๋Š” ์ฃผ์š” ๋Œ€์ƒ์ด ๋˜๋Š” Unit DOC (Depended On Component) SUT๊ฐ€ ์˜์กดํ•˜๋Š” ๊ฐ์ฒด Test double DOC๋ฅผ ๋Œ€์‹ ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด Test double์˜ ์ข…๋ฅ˜ : Mock, Stub Mock ํ–‰์œ„ ๊ฒ€์ฆ (๊ฐ์ฒด๊ฐ€ ํŠน์ • ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ๊ฒ€์ฆ) ์‚ฌ์šฉ test framework : Mockito, JMock, EasyMock Stub ์ƒํƒœ ๊ฒ€์ฆ (๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜์—ฌ ๊ฒ€์ •) ์‚ฌ์šฉ Integration Test (ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ) ์—ฌ๋Ÿฌ ๊ฐœ์˜ Unit์„ ํ†ตํ•ฉํ•ด์„œ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ์‹ JUnit ๋งค ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ -> ๋…๋ฆฝ์ ์ธ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ Annotation ์ œ๊ณต -> ํ…Œ์ŠคํŠธ life cycle ๊ด€๋ฆฌ assert ๋ฉ”์†Œ๋“œ ์ œ๊ณต -> ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ํŒ๋ณ„ JUnit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage JUnit Platform : JVM ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŒ… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ ๊ธฐ๋ฐ˜ ๋ชจ๋“ˆ JUnit Jupiter : JUnit5๋ฅผ ์œ„ํ•œ Test Engine API ์ œ๊ณต JUnit Vintage : JUnit3, JUnit4๋ฅผ ์œ„ํ•œ Test Engine API ์ œ๊ณต org.junit.jupiter.api.Assertions.* assertEquals 1assertEquals(0, 1+1); assertThrows, assertAll org.hamcrest.MatcherAssert.* assertThat 1// assertEquals ๋ณด๋‹ค ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค 2assertThat(1+1, equalTo(2)); org.hamcrest.Matchers.* equalTo, is, not anyOf, everyItem hasSize, containsInAnyOrder, hasItem (collection์— ๋Œ€ํ•ด ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ง€์›ํ•œ๋‹ค)
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ์‹œ์†Œ ์ง๊ฟ (L2)
๐Ÿง  Algorithm
1def solution(weights): 2 answer = 0 3 wdict = {} 4 5 weights.sort(reverse=True) 6 for i in weights: 7 if i in wdict: 8 answer += wdict[i] 9 if i*3/2 in wdict: 10 answer += wdict[i*3/2] 11 if i*2 in wdict: 12 answer += wdict[i*2] 13 if i*4/3 in wdict: 14 answer += wdict[i*4/3] 15 16 wdict[i] = wdict[i]+1 if i in wdict else 1 17 return answer ๋ฌธ์ œ ์‹œ์†Œ์—๋Š” ์ค‘์‹ฌ์œผ๋กœ๋ถ€ํ„ฐ 2m, 3m, 4m ๋–จ์–ด์ง„ ๊ฑฐ๋ฆฌ์— ์ขŒ์„์ด ์กด์žฌํ•œ๋‹ค ์–‘์ชฝ์˜ ํƒ‘์Šนํ•œ ์‚ฌ๋žŒ์˜ ๋ฌด๊ฒŒ์™€ ์‹œ์†Œ ์ถ•๊ณผ ์ขŒ์„ ๊ฐ„์˜ ๊ฑฐ๋ฆฌ์˜ ๊ณฑ์ด ๊ฐ™์•„์„œ ์‹œ์†Œ๊ฐ€ ํ‰ํ–‰์„ ์ด๋ฃฌ๋‹ค๋ฉด ๊ทธ ๋‘˜์„ ์‹œ์†Œ ์ง๊ฟ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค ์‚ฌ๋žŒ๋“ค์˜ ๋ชธ๋ฌด๊ฒŒ ๋ฐฐ์—ด์ด ์ฃผ์–ด์งˆ ๋•Œ, ์‹œ์†Œ ์ง๊ฟ์ด ๋ช‡ ์Œ ์กด์žฌํ•˜๋Š”์ง€ ๊ตฌํ•˜๋ผ TC input [100,180,360,100,270] ouput 4 {(100, 100), (180, 360), (180, 270), (270, 360)} ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๋ชธ๋ฌด๊ฒŒ ๋ฐฐ์—ด์„ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ ๋’ค ๋น„์œจ์„ ๊ณ„์‚ฐํ•˜์—ฌ ๋น„๊ตํ•˜์˜€๋‹ค ์ด๋•Œ dict์˜ key์—๋Š” ๋ชธ๋ฌด๊ฒŒ, value์—๋Š” ํ•ด๋‹น ๋ชธ๋ฌด๊ฒŒ๋ฅผ ๊ฐ€์ง„ ์ˆ˜๋ฅผ ์ €์žฅํ•˜์—ฌ ๋ชธ๋ฌด๊ฒŒ ๊ฐ™์€ ์‚ฌ๋žŒ๋„ ๊ณ ๋ คํ•˜์˜€๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ์ˆซ์ž ๋ณ€ํ™˜ํ•˜๊ธฐ (L2)
๐Ÿง  Algorithm
1from collections import deque 2 3def solution(x, y, n): 4 q = deque() 5 visited = [False] * 1000001 6 q.append((x, 0)) 7 8 while q: 9 cx, cnt = q.popleft() 10 if cx == y: 11 return cnt 12 13 if cx + n <= y and not visited[cx+n]: 14 q.append((cx+n, cnt+1)) 15 visited[cx+n] = True 16 if cx * 2 <= y and not visited[cx*2]: 17 q.append((cx*2, cnt+1)) 18 visited[cx*2] = True 19 if cx * 3 <= y and not visited[cx*3]: 20 q.append((cx*3, cnt+1)) 21 visited[cx*3] = True 22 return -1 ๋ฌธ์ œ ์ž์—ฐ์ˆ˜ x๋ฅผ y๋กœ ๋ณ€ํ™˜์‹œํ‚ฌ๋ ค๊ณ  ํ•œ๋‹ค ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์€ 3๊ฐ€์ง€ (x์— n์„ ๊ณฑํ•œ๋‹ค, x์— 2๋ฅผ ๊ณฑํ•œ๋‹ค, x์— 3์„ ๊ณฑํ•œ๋‹ค) ํ•„์š”ํ•œ ์ตœ์†Œ ์—ฐ์‚ฐ ํšŸ์ˆ˜๋ฅผ ๊ตฌํ•˜์—ฌ๋ผ TC input 10(x), 40(y), 5(n) ouput 2 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• BFS๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค, ์ด๋•Œ ๋ฐฉ๋ฌธํ•œ ์ˆซ์ž๋Š” ๋‹ค์‹œ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š๋Š”๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋’ค์— ์žˆ๋Š” ํฐ ์ˆ˜ ์ฐพ๊ธฐ (L2)
๐Ÿง  Algorithm
1def solution(numbers): 2 stack = [] 3 answer = [-1] * len(numbers) 4 5 for i in range(len(numbers)): 6 while stack and stack[-1][1] < numbers[i]: 7 answer[stack[-1][0]] = numbers[i] 8 stack.pop() 9 stack.append((i, numbers[i])) 10 print(stack) 11 12 return answer ๋ฌธ์ œ ์ •์ˆ˜๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด numbers๊ฐ€ ์ฃผ์–ด์ง„๋‹ค ์ž์‹  ๋ณด๋‹ค ๋’ค์— ์žˆ๋Š” ์ˆซ์ž ์ค‘ ๊ฐ€์žฅ ํฌ๋ฉด์„œ ๊ฐ€๊นŒ์šด ์ˆ˜๋ฅผ ๋’ท ํฐ์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค ๋ชจ๋“  ์›์†Œ์— ๋Œ€ํ•ด์„œ ๋’ท ํฐ์ˆ˜๋ฅผ ๊ตฌํ•˜์—ฌ๋ผ (์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด -1) TC input [2, 3, 3, 5] ouput [3, 5, 5, -1] ํ•ด๊ฒฐ๋ฐฉ๋ฒ• numbers๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ์ˆ˜ํ–‰ํ•œ๋‹ค stack์˜ top์ด ํ˜„์žฌ ์›์†Œ๋ณด๋‹ค ์ž‘์œผ๋ฉด ๋’ท ํฐ์ˆ˜๋ฅผ ์ฐพ์€ ๊ฒƒ์ด๋ฏ€๋กœ stack์—์„œ popํ•˜๊ณ , answer์— ํ˜„์žฌ ์›์†Œ๋ฅผ ์ €์žฅํ•œ๋‹ค stack์— ํ˜„์žฌ ์›์†Œ์™€ ๊ทธ ์ธ๋ฑ์Šค๋ฅผ pushํ•œ๋‹ค ๋‹ค๋ฅธ ์‚ฌ๋žŒ ํ’€์ด stack์— index๋งŒ ์ €์žฅํ•˜์—ฌ ๊ทธ๋•Œ๊ทธ๋•Œ numbers์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค 1def solution(numbers): 2 answer = [-1] * len(numbers) 3 stack = [] 4 5 for i in range(len(numbers)): 6 while stack and numbers[stack[-1]] < numbers[i]: 7 answer[stack.pop()] = numbers[i] 8 stack.append(i) 9 10 return answer
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋ฌด์ธ๋„ ์—ฌํ–‰ (L2)
๐Ÿง  Algorithm
1from collections import deque 2 3vx = [0, 0, -1, 1] 4vy = [-1, 1, 0, 0] 5 6def solution(maps): 7 N = len(maps) 8 M = len(maps[0]) 9 answer = [] 10 11 visited = [[False]*M for _ in range(N)] 12 13 for i in range(N): 14 for j in range(M): 15 if maps[i][j] != 'X' and not visited[i][j]: 16 cnt = 0 17 q = deque() 18 q.append((j, i)) 19 visited[i][j] = True 20 while q: 21 cx, cy = q.popleft() 22 cnt += int(maps[cy][cx]) 23 for k in range(4): 24 nx = cx + vx[k] 25 ny = cy + vy[k] 26 if 0 <= nx < M and 0 <= ny < N and maps[ny][nx] != 'X' and not visited[ny][nx]: 27 q.append((nx, ny)) 28 visited[ny][nx] = True 29 answer.append(cnt) 30 if len(answer) == 0: 31 return [-1] 32 return sorted(answer) ๋ฌธ์ œ ๋ฌธ์ž์—ด ๋ฐฐ์—ด maps๊ฐ€ ์ฃผ์–ด์ง„๋‹ค ๋ฐ”๋‹ค๋Š” ‘X’, ์„ฌ์€ ์ˆซ์ž๋กœ ํ‘œํ˜„๋˜๋Š”๋ฐ, ์ˆซ์ž๋Š” ์„ฌ์—์„œ ์ตœ๋Œ€ํ•œ ๋ณด๋‚ผ์ˆ˜ ์žˆ๋Š” ๋‚ ์งœ ์ˆ˜์ด๋‹ค ๊ฐ ์„ฌ์—์„œ ์ตœ๋Œ€ํ•œ ๋ฉฐ์น ์”ฉ ๋จธ๋ฌด๋ฅผ ์ˆ˜ ์žˆ๋Š”์ง€ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋ผ ์—†๋‹ค๋ฉด -1์„ ๋ฐฐ์—ด์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•˜๋ผ TC input [“X591X”,“X1X5X”,“X231X”, “1XXX1”] ouput [1, 1, 27] ํ•ด๊ฒฐ๋ฐฉ๋ฒ• BFS๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ’€์—ˆ๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ํ˜ธํ…” ๋Œ€์‹ค (L2)
๐Ÿง  Algorithm
1import heapq 2 3def time_calc(time): 4 time_split = time.split(':') 5 return int(time_split[0])*60 + int(time_split[1]) 6 7def solution(book_time): 8 time = [] 9 q = [] 10 for start, end in book_time: 11 time.append((time_calc(start), time_calc(end))) 12 time.sort(key=lambda x: x[0]) 13 print (time) 14 for start, end in time: 15 if q: 16 top = heapq.heappop(q) 17 if top > start: 18 heapq.heappush(q, top) 19 heapq.heappush(q, end+10) 20 else: 21 heapq.heappush(q, end+10) 22 return len(q) ๋ฌธ์ œ ํ˜ธํ…”์˜ ์˜ˆ์•ฝ์‹œ๊ฐ„์ด ๋‹ด๊ธด 2์ฐจ์› ๋ฐฐ์—ด์ด ์ฃผ์–ด์ง„๋‹ค ex) [[“12:00”, “12:30”], [“15:00”, “16:00”]] ํ‡ด์‹ค ์‹œ๊ฐ„ 10๋ถ„ ์ดํ›„์— ๋‹ค์Œ ์†๋‹˜์ด ์ž…์‹ค ํ•  ์ˆ˜ ์žˆ๋‹ค ์ตœ์†Œ ๊ฐ์‹ค์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜์—ฌ๋ผ TC input [[“15:00”, “17:00”], [“16:40”, “18:20”], [“14:20”, “15:20”], [“14:10”, “19:20”], [“18:20”, “21:20”]] ouput 3 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ตœ์†Œ ํž™์— ํ‡ด์‹ค์‹œ๊ฐ„ + 10๋ถ„ ์„ ๋„ฃ๋Š”๋‹ค ๋‹ค์Œ ์†๋‹˜์˜ ์ž…์‹ค์‹œ๊ฐ„๊ณผ ๋น„๊ตํ•ด์„œ ํ‡ด์‹ค์‹œ๊ฐ„์ด ๋” ๋น ๋ฅด๋ฉด ํ‡ด์‹ค์‹œ๊ฐ„์„ ๋นผ๊ณ  ๋‹ค์‹œ ๋„ฃ๋Š”๋‹ค ํž™์— ๋‚จ์•„์žˆ๋Š” ํ‡ด์‹ค์‹œ๊ฐ„์˜ ๊ฐœ์ˆ˜๊ฐ€ ๊ฐ์‹ค์˜ ๊ฐœ์ˆ˜์ด๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋ฏธ๋กœ ํƒˆ์ถœ (L2)
๐Ÿง  Algorithm
1from collections import deque 2 3vx = [0, 0, -1, 1] 4vy = [-1, 1, 0, 0] 5 6def bfs(maps, N, M, p1, p2): 7 visited = [[False]*M for _ in range(N)] 8 q = deque() 9 q.append(list(p1)+[0]) 10 11 while q: 12 curY, curX, cnt = q.popleft() 13 14 if p2 == (curY, curX): 15 return cnt 16 17 for i in range(4): 18 x = curX + vx[i] 19 y = curY + vy[i] 20 if 0 <= x < M and 0 <= y < N and not visited[y][x] and maps[y][x] != 'X': 21 visited[y][x] = True 22 q.append([y, x, cnt+1]) 23 return -1 24 25def solution(maps): 26 answer = 0 27 N = len(maps) 28 M = len(maps[0]) 29 30 sp = (0, 0) 31 lp = (0, 0) 32 ep = (0, 0) 33 34 for i in range(N): 35 for j in range(M): 36 if maps[i][j] == 'S': 37 sp = (i, j) 38 elif maps[i][j] == 'L': 39 lp = (i, j) 40 elif maps[i][j] == 'E': 41 ep = (i, j) 42 43 tmp = bfs(maps, N, M, sp, lp) 44 if tmp == -1: 45 return -1 46 47 answer += tmp 48 49 tmp = bfs(maps, N, M, lp, ep) 50 if tmp == -1: 51 return -1 52 53 answer += tmp 54 55 return answer ๋ฌธ์ œ ๋ฏธ๋กœ๋ฅผ ๋‚˜ํƒ€๋‚ธ ๋ฌธ์ž์—ด ๋ฐฐ์—ด maps๊ฐ€ ์ฃผ์–ด์ง„๋‹ค S: ์‹œ์ž‘์ง€์ , E: ์ถœ๊ตฌ, L: ๋ ˆ๋ฒ„, O: ํ†ต๋กœ, X: ๋ฒฝ์ด๋ผ๊ณ  ํ•˜์ž ์‹œ์ž‘์ง€์ ์—์„œ ์ถœ๋ฐœํ•ด์„œ ๋ ˆ๋ฒ„๋ฅผ ๊ฒฝ์œ ํ•˜์—ฌ ์ถœ๊ตฌ๊นŒ์ง€ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋ผ ํƒˆ์ถœ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉด -1์„ ๋ฐ˜ํ™˜ํ•˜๋ผ TC input [“SOOOL”,“XXXXO”,“OOOOO”,“OXXXX”,“OOOOE”] ouput 16 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• BFS๋กœ ์‹œ์ž‘์ง€์  -> ๋ ˆ๋ฒ„, ๋ ˆ๋ฒ„ -> ์ถœ๊ตฌ ๋‘ ๊ฐ€์ง€๋ฅผ ๋”ฐ๋กœ ๊ตฌํ•ด์„œ ๋”ํ•œ๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ํ˜ผ์ž์„œ ํ•˜๋Š” ํ‹ฑํƒํ†  (L2)
๐Ÿง  Algorithm
1V = [[(-1, 0), (1, 0)], [(0, -1), (0, 1)], [(-1, -1), (1, 1)], [(-1, 1), (1, -1)]] 2P = [[(1, 0), (1, 1), (1, 2)], [(0, 1), (1, 1), (2, 1)], [(1, 1)], [(1, 1)]] 3 4def solution(board): 5 answer = -1 6 o_line = 0 7 x_line = 0 8 9 for i, p_list in enumerate(P): 10 for p in p_list: 11 if board[p[0]][p[1]] != '.' and board[p[0]][p[1]]== board[p[0]+V[i][0][0]][p[1]+V[i][0][1]] == board[p[0]+V[i][1][0]][p[1]+V[i][1][1]]: 12 if board[p[0]][p[1]] == 'O': 13 o_line += 1 14 elif board[p[0]][p[1]] == 'X': 15 x_line += 1 16 17 o_cnt = 0 18 x_cnt = 0 19 20 21 for i in ''.join(board): 22 if i == 'O': 23 o_cnt += 1 24 elif i == 'X': 25 x_cnt += 1 26 27 if not (0 <= o_cnt - x_cnt <= 1): 28 return 0 29 if o_line == 1: 30 if o_cnt - x_cnt != 1: 31 return 0 32 if x_line == 1: 33 if o_cnt != x_cnt: 34 return 0 35 if o_line != 0 and o_line == x_line: 36 return 0 37 38 return 1 ๋ฌธ์ œ ํ‹ฑํƒํ†  3X3 ๋ณด๋“œํŒ์ด ์ฃผ์–ด์ง„๋‹ค. (‘O’, ‘X’, ‘.’) ๊ทœ์น™์„ ์ง€์ผœ์„œ ๋‚˜์˜ฌ์ˆ˜ ์žˆ๋Š” ๋ณด๋“œ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ๋ผ TC input [“O.X”, “.O.”, “..X”] ouput 1 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• O์˜ ์ค„ ์ˆ˜, X์˜ ์ค„ ์ˆ˜, O์˜ ๊ฐœ์ˆ˜, X์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ–ˆ๋‹ค ํŠนํžˆ, ๋ˆ„๊ฐ€ ์ด๊ฒผ๋Š”์ง€์— ๋”ฐ๋ผ์„œ ์กฐ๊ฑด์„ ๋”ฐ์ ธ์•ผํ•œ๋‹ค ์˜ˆ) O๊ฐ€ ์ด๊ธด ๊ฒฝ์šฐ -> O์˜ ๊ฐœ์ˆ˜ = X์˜ ๊ฐœ์ˆ˜ + 1
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋‹น๊ตฌ ์—ฐ์Šต (L2)
๐Ÿง  Algorithm
1def solution(m, n, startX, startY, balls): 2 answer = [] 3 for bx, by in balls: 4 tmp = [] 5 for x, y in [(-1*startX, startY), (startX, -1*startY), (startX, 2*n-startY), (2*m-startX, startY)]: 6 if bx==x and (y < 0 < by < startY or startY < by < n < y): 7 continue 8 if by==y and (x < 0 < bx < startX or startX < bx < m < x): 9 continue 10 tmp.append ((x-bx)**2+(y-by)**2) 11 answer.append(min(tmp)) 12 13 14 return answer ๋ฌธ์ œ ์ˆ˜๊ตฌ์™€ ์ ๊ตฌ์˜ ์ขŒํ‘œ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค ์›์ฟ ์…˜์œผ๋กœ ์ ๊ตฌ๋ฅผ ๋งžํžˆ๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋ผ TC input 10, 10, 3, 7, [[7, 7], [2, 7], [7, 3]] ouput [52, 37, 116] ํ•ด๊ฒฐ๋ฐฉ๋ฒ• [์งˆ๋ฌธํ•˜๊ธฐ]์—์„œ ์ ๋Œ€์นญ์— ๊ด€ํ•œ ํžŒํŠธ๋ฅผ ์–ป๊ณ , ์ˆ˜๊ตฌ๋ฅผ ๋‹ค์ด ๋ฐ–์œผ๋กœ ๋ณด๋‚ด์„œ ์ง์„ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜์˜€๋‹ค ๊ณต์ด ์ผ์ง์„ ์œผ๋กœ ์žˆ์„๋•Œ ๋‹ค์ด๋ณด๋‹ค ๊ณต์— ๋จผ์ € ๋ถ€๋”ชํžˆ์ง€ ์•Š๋„๋ก ์‹ ๊ฒฝ์จ์•ผํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ˆ˜๊ตฌ๋ฅผ ์™ผ์ชฝ์œผ๋กœ ์น  ๋•Œ ๋‹ค์ด <- ์ ๊ตฌ <- ์ˆ˜๊ตฌ (X) ๋‹ค์ด <- ์ˆ˜๊ตฌ <- ์ ๊ตฌ (O)
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋ฆฌ์ฝ”์ณ‡ ๋กœ๋ด‡ (L2)
๐Ÿง  Algorithm
1from collections import deque 2visited = [] 3vx = [0, 0, -1, 1] 4vy = [-1, 1, 0, 0] 5 6def bfs(board, N, M, sp): 7 global visited 8 q = deque() 9 q.append(sp+[1]) 10 11 while q: 12 cy, cx, cnt = q.popleft() 13 visited[cy][cx] = True 14 for i in range(4): 15 x = cx 16 y = cy 17 while True: 18 x += vx[i] 19 y += vy[i] 20 if not (0 <= x < N and 0 <= y < M) or board[y][x] == 'D': 21 x -= vx[i] 22 y -= vy[i] 23 break 24 if board[y][x] == 'G': 25 return cnt 26 if not visited[y][x]: 27 q.append([y, x, cnt+1]) 28 return -1 29 30def solution(board): 31 global visited 32 N = len(board[0]) 33 M = len(board) 34 35 visited = [[False] * len(board[0]) for _ in range(len(board))] 36 for i in range(M): 37 for j in range(N): 38 if board[i][j] == 'R': 39 sp = [i, j] 40 41 return bfs(board, N, M, sp) ๋ฌธ์ œ 2์ฐจ์› ๋ฆฌ์ŠคํŠธ board๊ฐ€ ์ฃผ์–ด์ง„๋‹ค ‘.‘์€ ๋นˆ๊ณต๊ฐ„, ‘R’์€ ์ฒ˜์Œ์œ„์น˜, ‘D’๋Š” ์žฅ์• ๋ฌผ, ‘G’๋Š” ๋ชฉํ‘œ์ง€์  ์ด๋‹ค ์žฅ์• ๋ฌผ์ด๋‚˜ ๋งจ ๋๊นŒ์ง€ ๋ถ€๋”ชํž๋•Œ๊นŒ์ง€ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•œ๋‹ค ๋ชฉํ‘œ์ง€์ ์— ์ •ํ™•์ด ๋ฉˆ์ถฐ์„ค๋•Œ๊นŒ์ง€ ๋ช‡๋ฒˆ ์ด๋™ํ•ด์•ผํ•˜๋Š”์ง€ ๊ตฌํ•˜๋ผ, ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋‹ค๋ฉด -1์„ ๋ฐ˜ํ™˜ํ•˜๋ผ TC input ["…D..R", “.D.G…”, “….D.D”, “D….D.”, “..D….”] ouput 7 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• bfs๋กœ ํ’€์—ˆ๋‹ค ์ด๋•Œ queue์•ˆ์— cnt๋ณ€์ˆ˜๋„ ๋„ฃ์–ด์„œ ๋ช‡๋ฒˆ ์ด๋™ํ–ˆ๋Š”์ง€ ์ €์žฅํ•œ๋‹ค.
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๊ด‘๋ฌผ ์บ๊ธฐ (L2)
๐Ÿง  Algorithm
1def solution(picks, minerals): 2 bundles = [] 3 tmp = [0, 0, 0] 4 DATA = [[1, 1, 1], [5, 1, 1], [25, 5, 1]] 5 answer = 0 6 7 for i in range(len(minerals)): 8 if minerals[i] == "diamond": 9 for j in range(3): 10 tmp[j] += DATA[j][0] 11 elif minerals[i] == "iron": 12 for j in range(3): 13 tmp[j] += DATA[j][1] 14 elif minerals[i] == "stone": 15 for j in range(3): 16 tmp[j] += DATA[j][2] 17 18 if (i+1) % 5 == 0 or i == len(minerals)-1: 19 bundles.append(tmp) 20 tmp = [0, 0, 0] 21 bundles = bundles[:sum(picks)] 22 bundles.sort(key= lambda x: -x[2]) 23 24 for i in bundles: 25 for j in range(3): 26 if picks[j] != 0: 27 answer += i[j] 28 picks[j] -= 1 29 break 30 31 return answer ๋ฌธ์ œ 3๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๊ณก๊ดญ์ด ๊ฐœ์ˆ˜์™€, ๊ด‘๋ฌผ์˜ ๋ฐฐ์—ด์ด ์ฃผ์–ด์ง„๋‹ค ๊ด‘๋ฌผ์„ ์บ๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ํ”ผ๋กœ๋„๋ฅผ ๊ตฌํ•˜๋ผ ํ”ผ๋กœ๋„ (์ˆœ์„œ๋Œ€๋กœ ๋‹ค์ด์•„๋ชฌ๋“œ, ์ฒ , ๋Œ์„ ์บ๋Š”๋ฐ ํ•„์š”ํ•œ ํ”ผ๋กœ๋„์ด๋‹ค) ๋‹ค์ด์•„๊ณก๊ดญ์ด (1, 1, 1), ์ฒ ๊ณก๊ดญ์ด (5, 1, 1), ๋Œ๊ณก๊ดญ์ด (25, 5, 1) ๊ทœ์น™ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ณก๊ดญ์ด์ค‘ ์•„๋ฌด๊ฑฐ๋‚˜ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด ๊ด‘๋ฌผ์„ ์บ”๋‹ค ํ•œ ๋ฒˆ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•œ ๊ณก๊ดญ์ด๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€ ์‚ฌ์šฉํ•œ๋‹ค ๊ด‘๋ฌผ์€ ์ฃผ์–ด์ง„ ์ˆœ์„œ๋Œ€๋กœ๋งŒ ์บ˜ ์ˆ˜ ์žˆ๋‹ค ๊ด‘์‚ฐ์— ์žˆ๋Š” ๋ชจ๋“  ๊ด‘๋ฌผ์„ ์บ๊ฑฐ๋‚˜, ๋” ์‚ฌ์šฉํ•  ๊ณก๊ดญ์ด๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ด‘๋ฌผ์„ ์บ”๋‹ค. TC input [1, 3, 2] [“diamond”, “diamond”, “diamond”, “iron”, “iron”, “diamond”, “iron”, “stone”] ouput 12 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๊ทธ๋ฆฌ๋””๋กœ ํ‘ธ๋Š” ๋ฌธ์ œ์ด๋‹ค 5๊ฐœ๋กœ ๋ฌถ์–ด์„œ ๊ณก๊ดญ์ด๋ณ„ ํ•„์š”ํ•œ ํ”ผ๋กœ๋„๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ , ํ”ผ๋กœ๋„๊ฐ€ ๋งŽ์ด๋“œ๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌํ•˜์˜€๋‹ค (๋‹ค์ด์•„ ์šฐ์„ ) ์ถ”๊ฐ€๋กœ ๊ณ ๋ คํ•ด์•ผํ•  ์‚ฌํ•ญ ๋งŒ์•ฝ, ๊ณก๊ดญ์ด ๊ฐœ์ˆ˜๊ฐ€ 3๊ฐœ๋ผ๋ฉด 15๊ฐœ์˜ ๊ด‘๋ฌผ๋งŒ ์บ˜ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋’ค์˜ ๊ด‘๋ฌผ์€ ๋ฒ„๋ฆฐ๋‹ค.
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๊ณผ์ œ ์ง„ํ–‰ํ•˜๊ธฐ (L2)
๐Ÿง  Algorithm
๋‚ด ๋‹ต์•ˆ 1def solution(plans): 2 q = [] 3 answer = [] 4 for plan in plans: 5 h, m = map(int, plan[1].split(':')) 6 plan[1] = h*60 + m 7 plan[2] = int(plan[2]) 8 plans.sort(key = lambda x: x[1]) 9 10 for plan in plans: 11 if q: 12 free_time = plan[1] - q[-1][1] 13 while q: 14 q[-1][2] -= free_time 15 free_time = -1 * q[-1][2] 16 17 print (free_time, q[-1][2]) 18 if free_time < 0: 19 break 20 21 if q[-1][2] <= 0: 22 answer.append(q.pop()[0]) 23 24 q.append(plan) 25 while q: 26 answer.append(q.pop()[0]) 27 28 return answer ๋‹ค๋ฅธ ์‚ฌ๋žŒ ๋‹ต์•ˆ 1def solution(plans): 2 plans = sorted(map(lambda x: [x[0], int(x[1][:2]) * 60 + int(x[1][3:]), int(x[2])], plans), key=lambda x: -x[1]) 3 q = [] 4 5 while plans: 6 cur = plans.pop() 7 8 for idx, item in enumerate(q): 9 if item[0] > cur[1]: 10 q[idx][0] += cur[2] 11 12 q.append([cur[1]+cur[2], cur[0]]) 13 14 q.sort() 15 return list(map(lambda x: x[1], q)) ๋ฌธ์ œ ๊ณผ์ œ ์ •๋ณด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. (๊ณผ์ œ : [์ด๋ฆ„, ์‹œ์ž‘์‹œ๊ฐ„, ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„]) ์ง„ํ–‰ ์ค‘์ธ ๊ณผ์ œ์™€ ์ƒ๊ด€์—†์ด ๊ณผ์ œ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ๋˜๋ฉด ๋ฌด์กฐ๊ฑด ์‹œ์ž‘ํ•œ๋‹ค ์ง„ํ–‰ ์ค‘์ธ ๊ณผ์ œ๋ฅผ ๋๋ƒˆ์„๋•Œ ์ด์ „์— ๋ฉˆ์ถฐ๋‘์—ˆ๋˜ ๊ณผ์ œ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค TC input [[“korean”, “11:40”, “30”], [“english”, “12:10”, “20”], [“math”, “12:30”, “40”]] ouput [“korean”, “english”, “math”] ํ•ด๊ฒฐ๋ฐฉ๋ฒ• (๋‹ค๋ฅธ ์‚ฌ๋žŒ ๋‹ต์•ˆ ๊ธฐ์ค€) ๊ณผ์ œ ์‹œ๊ฐ„ ์ „์ฒ˜๋ฆฌ ํ›„ ์‹œ์ž‘์‹œ๊ฐ„ ๊ธฐ์ค€ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค ๊ฐ€์žฅ ๋จผ์ € ์‹œ์ž‘ํ•˜๋Š” ๊ณผ์ œ๋ถ€ํ„ฐ popํ•œ๋‹ค ํ์— ์ €์žฅํ•˜๋Š”๋ฐ, ๋น„์–ด์žˆ์œผ๋ฉด ์‹œ์ž‘์‹œ๊ฐ„+๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„ (๋๋‚˜๋Š” ์‹œ๊ฐ„)์„ ๋ฐ”๋กœ ์ €์žฅํ•œ๋‹ค ํ์— ์›์†Œ๊ฐ€ ์žˆ์œผ๋ฉด ํ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ํ˜„์žฌ popํ•œ ๊ณผ์ œ๋ณด๋‹ค ๋Šฆ๊ฒŒ ๋๋‚˜๋Š” ๊ณผ์ œ์— ์ง„ํ–‰์‹œ๊ฐ„์„ ๋”ํ•ด์ค€๋‹ค ์œ„ ๋ฐ˜๋ณต๋ฌธ์„ ๋‹ค ๋Œ๋ฉด [๋๋‚˜๋Š” ์‹œ๊ฐ„, ๊ณผ์ œ ์ด๋ฆ„]์˜ ํ˜•ํƒœ๋กœ ๊ณผ์ œ๋“ค์ด ์ €์žฅ๋˜์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค ๋๋‚˜๋Š” ์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•ด์„œ ๊ณผ์ œ ์ด๋ฆ„๋งŒ ๋ฝ‘์•„๋‚ธ๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ์—ฐ์†๋œ ๋ถ€๋ถ„ ์ˆ˜์—ด์˜ ํ•ฉ (L2)
๐Ÿง  Algorithm
1def solution(sequence, k): 2 answer = [] 3 e = len(sequence)-1 4 s = len(sequence) 5 cur = 0 6 7 while s >= 0: 8 if cur < k: 9 s -= 1 10 cur += sequence[s] 11 elif cur > k: 12 cur -= sequence[e] 13 e -= 1 14 else: 15 answer.append((s, e)) 16 s -= 1 17 cur += sequence[s] 18 answer.sort(key=lambda x: (x[1]-x[0], x[0])) 19 return answer[0] ๋ฌธ์ œ ์ˆ˜์—ด๊ณผ k๊ฐ€ ์ฃผ์–ด์ง„๋‹ค ์ˆ˜์—ด์˜ ๋ถ€๋ถ„ํ•ฉ์ด k๊ฐ€ ๋˜๊ฒŒ ํ•˜๋Š” ์‹œ์ž‘์ธ๋ฑ์Šค์™€ ๋์ธ๋ฑ์Šค๋ฅผ ๊ตฌํ•˜๋ผ ์ด๋•Œ, ๊ธธ์ด๊ฐ€ ์งง์€ ์ˆ˜์—ด์„ ์ฐพ๋Š”๋‹ค, ๊ธธ์ด๊ฐ€ ๊ฐ™์€๊ฒƒ์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€๋ผ๋ฉด ์‹œ์ž‘์ธ๋ฑ์Šค๊ฐ€ ์ž‘์€ ๊ฒƒ์„ ์ฐพ๋Š”๋‹ค TC input [1, 2, 3, 4, 5], 7 ouput [2, 3] ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ํˆฌํฌ์ธํ„ฐ๋ฅผ ํ™œ์šฉํ•ด ๋‹ต์ด ๋˜๋Š” ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ answer์— ์ €์žฅํ•œ๋‹ค answer๋ฅผ ๋ฌธ์ œ์˜ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ์ •๋ ฌํ•œ๋’ค ์ฒซ๋ฒˆ์งธ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ๋‘ ์› ์‚ฌ์ด์˜ ์ •์ˆ˜ ์Œ (L2)
๐Ÿง  Algorithm
1import math 2 3def calc1(r): 4 result = 0 5 for i in range(1, r): 6 result += math.floor(math.sqrt(r**2 - i**2)) 7 return result*4 + r*4 + 1 8 9def calc2(r): 10 result = 0 11 for i in range(1, r): 12 a = math.sqrt(r**2 - i**2) 13 result += math.floor(a) 14 if a % 1 == 0: 15 result -= 1 16 return result*4 + r*4 + 1 17 18def solution(r1, r2): 19 return calc1(r2)-calc2(r1)+4 ๋ฌธ์ œ ๋‘ ์›์˜ ๋ฐ˜์ง€๋ฆ„ r1, r2๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๋‘ ์› ์‚ฌ์ด์˜ ๊ณต๊ฐ„์— x์ขŒํ‘œ์™€ y์ขŒํ‘œ๊ฐ€ ๋ชจ๋‘ ์ •์ˆ˜์ธ ์ ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜๋ผ ์ด๋•Œ, ๊ฐ ์› ์œ„์˜ ์ ๋„ ํฌํ•จํ•˜์—ฌ ์„ผ๋‹ค. TC input r1:2, r2:3 ouput 20 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ( ์›์˜ 1์‚ฌ๋ถ„๋ฉด์— ์กด์žฌํ•˜๋Š” ์ ์˜ ๊ฐœ์ˆ˜ * 4 + ์ถ•์— ์žˆ๋Š” ์  + ์›์ ) ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ•œ๋‹ค ํฐ ์›๊ณผ ์ž‘์€ ์›์„ ๊ณ„์‚ฐํ•  ๋•Œ ๋กœ์ง์ด ์กฐ๊ธˆ ๋‹ค๋ฅธ๋ฐ, ์ž‘์€ ์›์˜ ํ…Œ๋‘๋ฆฌ์— ๊ฑธ์นœ ์ ์€ ๋‹ต์— ํฌํ•จ์‹œ์ผœ์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ฃผ์˜ํ•œ๋‹ค. ๋А๋‚€ ์  ์ž‘์€ ์›์—์„œ ๊ณ ๋ คํ•ด์•ผํ•˜๋Š” ์‚ฌํ•ญ์„ ์ƒ๊ฐํ•ด๋‚ด์ง€๋ชปํ•ด ์˜ค๋ž˜ ๊ฑธ๋ ธ๋‹ค.
new ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค - ์š”๊ฒฉ ์‹œ์Šคํ…œ (L2)
๐Ÿง  Algorithm
1def solution(targets): 2 answer = 0 3 targets.sort(key=lambda x:x[1]) 4 cur = 0 5 6 for i in targets: 7 if i[0] >= cur: 8 answer += 1 9 cur = i[1] 10 11 return answer ๋ฌธ์ œ ๊ฐœ๊ตฌ๊ฐ„ (s, e)์˜ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์ด๋•Œ, ๋ชจ๋“  ๊ฐœ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋Š” ์ตœ์†Œ ์ˆซ์ž์˜ ์ˆ˜๋ฅผ ๊ตฌํ•˜์—ฌ๋ผ TC input [[4,5],[4,8],[10,14],[11,13],[5,12],[3,7],[1,4]] ouput 3 ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๊ฐœ๊ตฌ๊ฐ„์„ (s, e)์—์„œ e๋ฅผ ์ •๋ ฌํ•˜์—ฌ ํ•ด๊ฒฐํ•˜์˜€๋‹ค. s ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•ด๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š”๋ฐ ๋‚˜๋Š” e๋กœ ์ •๋ ฌํ•˜๋Š”๊ฒŒ ํŽธํ–ˆ๋‹ค
new 230315 ๊ธฐํ”„๋žฉ Design Thinking ๋ฐฉ๋ฒ•๋ก  - ๊น€์žฌ์ • ๊ต์ˆ˜๋‹˜
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
๋””์ž์ธ ์”ฝํ‚น์ด๋ž€ ๊ณต๊ฐ์˜ ๊ณผ์ •์„ ํ†ตํ•ด ๋ฌธ์ œ์ ์„ ์ฐพ์•„๋‚ด๊ณ , ์•„์ด๋””์–ด๋ฅผ ๋ฐœ์‚ฐํ•˜๊ณ , ํ”„๋กœํ† ํƒ€์ž…์„ ๋งŒ๋“ค์–ด ๊ฒ€์ฆ ๊ณผ์ •์„ ๊ฑฐ์น˜๋Š”, ๋ฐ˜๋ณต์  ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ•๋ก  ๋ฐ ์‚ฌ๊ณ ๋ฐฉ์‹ ๋””์ž์ธ ์”ฝํ‚น ํ”„๋กœ์„ธ์Šค ๊ณต๊ฐ - ๋ฌธ์ œ ์ •์˜ - ์•„์ด๋””์–ด ๋„์ถœ - ํ”„๋กœํ† ํƒ€์ดํ•‘ - ํ…Œ์ŠคํŒ… 1. ๊ณต๊ฐ ๊ณต๊ฐ ํ”„๋กœ์„ธ์Šค ๋ฉด๋‹ดํ•˜๊ธฐ ๊ด€์ฐฐํ•˜๊ธฐ ๊ฒฝํ—˜ํ•˜๊ธฐ ๋ฉด๋‹ด์ง€ ์ค€๋น„ํ•˜๊ธฐ ์ˆœ์ฐจ์  ๊ฒฝํ—˜ ์งˆ๋ฌธ : ์–ด๋–ค ์ˆœ์„œ๋กœ ํ–‰๋™ํ•˜๊ณ  ๊ฒฝํ—˜ํ•˜๋Š”์ง€ ๋ฌผ์–ด๋ณด์ž ๊ฐ์ • ์งˆ๋ฌธ ์ด์œ  ์งˆ๋ฌธ : ํ–‰๋™ ๋˜๋Š” ๊ฐ์ •์— ๋Œ€ํ•œ ์ด์œ ๋ฅผ ๋ฌผ์–ด๋ณด์ž ๋˜ ์งˆ๋ฌธ : “๋˜…“๋ผ๋Š” ์งˆ๋ฌธ์„ ๋งŽ์ด ํ•˜์ž ๊ตฌ์ฒดํ™” ์งˆ๋ฌธ ๊ด€์ฐฐํ•˜๊ธฐ | ๋ชจ๋‹ˆํ„ฐ๋ง ํ˜„์žฅ ์ค‘์‹ฌ ๊ด€์ฐฐ : ์„ธ์ƒ์„ ๋„“๊ณ  ๊นŠ๊ฒŒ ๋ฐ”๋ผ๋ณด๊ธฐ ๊ด€์ฐฐํ•˜๊ธฐ | ์‰๋„์ž‰ ์‚ฌ๋žŒ์˜ ์ฒดํ—˜์ด๋‚˜ ํ–‰๋™์„ ๊ทธ์ž๋ฆฌ์—์„œ ๊ด€์ฐฐํ•˜๊ธฐ ๊ด€์ฐฐํ•˜๊ธฐ | ๋งฅ๋ฝ ์งˆ์˜๋ฒ• ํ˜„์žฅ์—์„œ ๊ด€์ฐฐ ๋ฐ ๋ฉด๋‹ด์„ ํ†ตํ•ด ๋Œ€์ƒ์ž์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ํ•˜๋Š” ๋ฐฉ๋ฒ• ๋งฅ๋ฝ ์งˆ์˜๋ฒ•์˜ 4๊ฐ€์ง€ ์›์น™ ๋งฅ๋ฝ : ๋Œ€์ƒ์ž์˜ ์ž‘์—…ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ๋””ํ…Œ์ผ์„ ๊ด€์ฐฐํ•˜๋ผ ํŒŒํŠธ๋„ˆ์‹ญ : ๋Œ€์ƒ์ž๋ฅผ ๊ณต๊ฐํ•˜๋ผ ํ•ด์„ : ์—ฐ๊ตฌ์ž๋Š” ๋Œ€์ƒ์ž์—๊ฒŒ ๋ณธ์ธ์˜ ํ•ด์„์„ ๊ณต์œ ํ•˜๋ผ ํฌ์ปค์Šค : ํ•ต์‹ฌ ๋ชฉํ‘œ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ๋งˆ๋ผ ๋งฅ๋ฝ ์งˆ์˜๋ฒ• ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ค€๋น„ํ•˜๊ธฐ, ๊ธฐ๋กํ•˜๊ธฐ ๋„์ œ๊ด€๊ณ„ ๋ชจ๋ธ (Master-apprentice Model) ๋งˆ์Šคํ„ฐ(๋Œ€์ƒ์ž)๊ฐ€ ํ•ด๋‹น ์—…๋ฌดํ™˜๊ฒฝ์—์„œ ์ž์‹ ์˜ ์ƒ๊ฐ๊ณผ ํ–‰๋™์„ ์†Œ๋ฆฌ๋‚ด์–ด ๋งํ•˜๊ฒŒ ํ•œ๋‹ค ์—ฐ๊ตฌ์ž๋Š” ๊ฒฌ์Šต์ƒ์ด ๋˜์–ด ์ค‘๊ฐ„์ค‘๊ฐ„ ๋ฌผ์–ด๋ณด๋ฉด์„œ ํ•™์Šตํ•œ๋‹ค ์†Œ๋ฆฌ๋‚ด์–ด ์ƒ๊ฐํ•˜๊ธฐ (Think Aloud) ๊ธฐ๋ฒ• ๋ณ‘ํ–‰์‹ : ๊ณผ์—…์„ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ด์•ผ๊ธฐ ํ•œ๋‹ค ํšŒ๊ณ ์‹ : ๋‹จ๊ณ„๋ณ„ ๊ณผ์—…์„ ๋๋‚ด๊ณ  ์ด์•ผ๊ธฐํ•œ๋‹ค ๋ณ‘ํ–‰+ํšŒ๊ณ  ํ•˜์ด๋ธŒ๋ฆฌ๋“œ 2. ๋ฌธ์ œ์ •์˜ ํŽ˜๋ฅด์†Œ๋‚˜ ๋งŒ๋“ค๋ฌผ ํŽ˜๋ฅด์†Œ๋‚˜ : ํŠน์ • ์ƒํ™ฉ์—์„œ ์–ด๋–ป๊ฒŒ ํ–‰๋™ํ•˜๊ณ  ๋ฐ˜์‘ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ๊ฐ€์ƒ์˜ ์ธ๋ฌผ, ์†”๋ฃจ์…˜์˜ ์ˆ˜ํ˜œ์ž POV ์ •์˜ํ•˜๊ธฐ ํŽ˜๋ฅด์†Œ๋‚˜์˜ ๊ด€์ ์—์„œ 1๊ฐœ์˜ POV๋กœ ์••์ถ•ํ•˜์ž POV(Point of View) ํŽ˜๋ฅด์†Œ๋‚˜๋Š” ๋ˆ„๊ตฌ์ธ๊ฐ€? ํŽ˜๋ฅด์†Œ๋‚˜๊ฐ€ ์›ํ•˜๋Š”๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€? ํŽ˜๋ฅด์†Œ๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์ด ์ค‘์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? HMW ์ •์˜ํ•˜๊ธฐ ๊ตฌ์ฒด์ ์ธ ์•„์ด๋””์–ด๋ฅผ ๋‚ด๊ธฐ ์œ„ํ•œ ๋ธŒ๋ ˆ์ธ์Šคํ† ๋ฐ ๊ณผ์ • POV๋กœ ๋ถ€ํ„ฐ ํŒŒ์ƒ๋˜๋ฉฐ “์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•œ ๋‹จ์œ„"๋กœ ์ •์˜ ํ˜•์‹ : (์šฐ๋ฆฌ๋Š”) ์–ด๋–ป๊ฒŒ ~~~ ํ• ๊ฒƒ ์ธ๊ฐ€ ๊ณ ๊ฐ์—ฌ์ • ์ง€๋„ 3. ์•„์ด๋””์–ด ๋„์ถœ ๋ธŒ๋ ˆ์ธ์Šคํ† ๋ฐ ์˜ค์ฆˆ๋ณธ์˜ 4์›์น™ ๋น„ํŒ๊ธˆ์ง€ ์ž์œ ๋ถ„๋ฐฉ ์งˆ๋ณด๋‹ค ์–‘ Idea ํŽธ์Šน ์–ดํ”ผ๋‹ˆํ‹ฐ ๋‹ค์ด์–ด๊ทธ๋ž˜๋ฐ (์นœํ™”๋„๋ฒ•) ์ˆ˜์ง‘ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ• ๋ฐ์ดํ„ฐ์—์„œ ๊ณตํ†ต๋œ ์ด์Šˆ/๋ฌธ์ œ/ํ•„์š”์„ฑ ๋“ฑ์„ ๋„์ถœํ•  ์ˆ˜ ์žˆ์Œ ์š”์•ฝํ•˜์—ฌ ํฌ์ŠคํŠธ์ž‡์— ๊ธฐ๋ก, ์œ ์‚ฌํ•œ ํ…Œ๋งˆ, ํ† ํ”ฝ์œผ๋กœ ๊ทธ๋ฃนํ™” ๋‹ค์–‘ํ•œ ์•„์ด๋””์–ด ๋„์ถœ ๋ฐฉ๋ฒ• ์˜์‚ฌ๊ฒฐ์ • ๊ทธ๋ฆฌ๋“œ (๊ธด๊ธ‰๋„, ์ค‘์š”๋„) 10+10 ๋ฐฉ๋ฒ• (10๊ฐœ์˜ ์•„์ด๋””์–ด, 10๊ฐœ์˜ ์†”๋ฃจ์…˜) ์•„์ด๋””์–ด ํ‰๊ฐ€ ํ…Œ์ด๋ธ” (์ ์ˆ˜ ๋งค๊ธฐ๊ธฐ) ์•„์ด๋””์–ด๋ฅผ ์ปจ์…‰์œผ๋กœ ์—ฎ๊ธฐ 4. Prototype ์Šคํ† ๋ฆฌ๋ณด๋“œ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋Š” ์ œํ’ˆ ์‚ฌ์šฉ์˜ ํ™˜๊ฒฝ, ์ ˆ์ฐจ, ๋‹ˆ์ฆˆ ์ถฉ์กฑ ์š”์†Œ๊ฐ€ ํฌํ•จ๋œ๋‹ค ์Šคํ† ๋ฆฌ๋ณด๋”ฉ ์ ˆ์ฐจ ์Šคํ† ๋ฆฌ๋ผ์ธ ๋งŒ๋“ค๊ธฐ ๋ฉ”์ธ ์„ค์ •์ƒท ๊ทธ๋ฆฌ๊ธฐ ํ•ต์‹ฌ ์•„์ด๋””์–ด์˜ ์ „๋‹ฌ์„ ์œ„ํ•œ ์ ์ ˆํ•œ ์นด๋ฉ”๋ผ ๊ตฌ๋„ ์„ค์ • ๋ฐ ๊ทธ๋ฆฌ๊ธฐ ํ–‰๋™๊ณผ ์›€์ง์ž„ ๊ฐ•์กฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์‹œ์—ฐ ํ›„ ํ”ผ๋“œ๋ฐฑ ๋ฐ›๊ณ  ์ˆ˜์ •ํ•˜๊ธฐ
new ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฐ MSA ํŠน๊ฐ• 4์ผ์ฐจ : MSA๋ž€ ๋ฌด์—‡์ธ๊ฐ€
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
MSA๋ž€ ๋ฌด์—‡์ธ๊ฐ€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ๊ฐœ๋… ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค(microservice)๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋А์Šจํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ์„œ๋น„์Šค์˜ ๋ชจ์ž„์œผ๋กœ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์„œ๋น„์Šค ์ง€ํ–ฅ ์•„ํ‚คํ…์ฒ˜(SOA) ์Šคํƒ€์ผ์˜ ์ผ์ข…์ธ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ๊ธฐ๋ฒ•์ด๋‹ค ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์—์„œ ์„œ๋น„์Šค๋“ค์€ ์„ฌ์„ธ(fine-grained)ํ•˜๊ณ  ํ”„๋กœํ† ์ฝœ์€ ๊ฐ€๋ฒผ์šด ํŽธ์ด๋‹ค. ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ํŠน์ง• ์ž์œจ์„ฑ : ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ ์„œ๋น„์Šค๋Š” ๋‹ค๋ฅธ ์„œ๋น„์Šค์˜ ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ๊ฐœ๋ฐœ, ๋ฐฐํฌ, ์šด์˜ํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅ ์ „๋ฌธ์„ฑ : ๊ฐ ์„œ๋น„์Šค๋Š” ์ผ๋ จ์˜ ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ์„ค๊ณ„๋˜๋ฉฐ ํŠน์ • ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘”๋‹ค ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์˜ ๊ธฐ์ˆ ์  ํŠน์ง• ๊ฐ๊ฐ์˜ ์„œ๋น„์Šค๋Š” ๊ทธ ํฌ๊ธฐ๊ฐ€ ์ž‘์„ ๋ฟ, ์„œ๋น„์Šค ์ž์ฒด๋Š” ํ•˜๋‚˜์˜ ๋ชจ๋…ธ๋ฆฌ์‹ ์•„ํ‚คํ…์ฒ˜์™€ ์œ ์‚ฌํ•œ ๊ตฌ์กฐ๋ฅผ ๊ฐ–๋Š”๋‹ค ๊ฐ๊ฐ์˜ ์„œ๋น„์Šค๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ๋ฐฐํฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค ๊ฐ๊ฐ์˜ ์„œ๋น„์Šค๋Š” ๋‹ค๋ฅธ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์ž‘์•„์•ผ ํ•œ๋‹ค ๊ฐ ์„œ๋น„์Šค๋Š” ๊ฐœ๋ณ„ ํ”„๋กœ์„ธ์Šค๋กœ ๊ตฌ๋™๋˜๋ฉฐ, REST API์™€ ๊ฐ™์€ ๊ฐ€๋ฒผ์šด ๋ฐฉ์‹์œผ๋กœ ํ†ต์‹ ๋˜์–ด์•ผ ํ•œ๋‹ค ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์ด์  ๋ฏผ์ฒฉ์„ฑ : ์†Œ๊ทœ๋ชจ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ํ™œ๋™ํ•˜๋ฉฐ ๋” ๋…๋ฆฝ์ ์ด๋ฉด์„œ ์‹ ์†ํ•˜๊ฒŒ ์—…๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค ์œ ์—ฐํ•œ ํ™•์žฅ์„ฑ : ์„œ๋น„์Šค๊ฐ€ ์ง€์›ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ธฐ๋Šฅ์˜ ์ˆ˜์š”๋ฅผ ์ถฉ์กฑํ•˜๋„๋ก ํ•ด๋‹น ์„œ๋น„์Šค๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค ์†์‰ฌ์šด ๋ฐฐํฌ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ์œ„ํ•œ ์กฐ๊ฑด ๋น„์šฉ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ ์šด์˜ ์ธํ”„๋ผ ๋ฐฐํฌ ์ฃผ๊ธฐ
new ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฐ MSA ํŠน๊ฐ• 3์ผ์ฐจ : ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ๊ตฌ์ถ• ์‹ค์Šต (ELK), kubernetes
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ๊ตฌ์ถ• ์‹ค์Šต (ELK) ELK๋ž€ ELK๋Š” Elasticsearch, Logstash ๋ฐ Kibana : ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ ์„ธ ๊ฐœ์˜ ๋จธ๋ฆฌ๊ธ€ Elasticserach๋Š” ๊ฒ€์ƒ‰ ๋ฐ ๋ถ„์„ ์—”์ง„ Logstash๋Š” ์—ฌ๋Ÿฌ ์†Œ์Šค์—์„œ ๋™์‹œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜์—ฌ ๋ณ€ํ™˜ํ•œ ํ›„ Elasticsearch ๊ฐ™์€ “stash"๋กœ ์ „์†กํ•˜๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ Kibana๋Š” ์‚ฌ์šฉ์ž๊ฐ€ Elasticsearch์—์„œ ์ฐจํŠธ์™€ ๊ทธ๋ž˜ํ”„๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™” Kibana Elasticsearch์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์›น ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ฐ˜์˜ ์‹œ๊ฐํ™” ํ”Œ๋žซํผ Elasticsearch์— ์žˆ๋Š” ์ธ๋ฑ์Šค์˜ ํŒจํ„ด์„ ์ฐพ์•„์„œ, ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค Logstash ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘, ๋ณ€ํ™˜, ์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ, Jruby(JVM ๊ธฐ๋ฐ˜ Ruby)๋กœ ๊ฐœ๋ฐœ๋˜์—ˆ๋‹ค ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ณผ์ •์€ input, filter, out์˜ ์„ธ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋œ๋‹ค Docker Compose Docker Compose alias ์„ค์ • 1alias dco="docker-compose" 2... Docker-Compose ํŒŒ์ผ docker-compose.yml version:‘3.2’ // docker-compose file format / ๊ฐ ๋ฒ„์ „ ๋ณ„๋กœ ์ œ๊ณต api๊ฐ€ ๋‹ค๋ฅด๋‹ค services: // container ์„œ๋น„์Šค ๊ทธ๋ฃน ports: // ํฌํŠธ ์ง€์ • Host Port : Container Port depends_on: // ์„œ๋น„์Šค๊ฐ„ ์˜์กด๊ด€๊ณ„ ์„ค์ • ELK ์‹ค์Šต docker-compose ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰ docker-compose up docker-compose ์ปจํ…Œ์ด๋„ˆ ์ •์ง€ ๋ฐ ์‚ญ์ œ docker-compose down docker-compose ์ปจํ…Œ์ด๋„ˆ ๋ชฉ๋ก ์กฐํšŒ docker-compose ps docker-compose ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์กฐํšŒ docker-compose logs ElasticSearch ํ™•์ธ open http://localhost:9200/_cat/indices Kibana ํ™•์ธ http://localhost:5601/app/kibana container ์ ‘์† docker-compose exec logstash sh ์ฐธ๊ณ  : PoC (Proof of Concept) ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ˜„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š”๊ฐ€, ํšจ๊ณผ์™€ ํšจ์šฉ, ๊ธฐ์ˆ ์ ์ธ ๊ด€์ ์—์„œ๋ถ€ํ„ฐ ๊ฒ€์ฆ์„ ํ•˜๋Š” ๊ณผ์ • Kubernetes ์ดํ•ดํ•˜๊ธฐ Kubernetes๊ฐ€ ํ•„์š”ํ•œ ์ด์œ  ๋Œ€๋ถ€๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ : ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค ๋˜๋Š” ๋ช‡๊ฐœ์˜ ์„œ๋ฒ„์— ๋ถ„์‚ฐ๋œ ํ”„๋กœ์„ธ์Šค๋กœ ์‹คํ–‰๋˜๋Š” ๊ฑฐ๋Œ€ํ•œ ๋ชจ๋†€๋ฆฌ์Šค ์ด๋Ÿฌํ•œ ์‹œ์Šคํ…œ์€ ๋ฆด๋ฆฌ์ฆˆ ์ฃผ๊ธฐ๊ฐ€ ๋А๋ฆฌ๊ณ  ์—…๋ฐ์ดํŠธ๊ฐ€ ์ž์ฃผ ์ผ์–ด๋‚˜์ง€ ์•Š์Œ ๊ฐœ๋ฐœ์ž๋Š” ์ „์ฒด ๋ฆด๋ฆฌ์ฆˆ ์ฃผ๊ธฐ๊ฐ€ ๋๋‚ ๋•Œ ๋งˆ๋‹ค ์ „์ฒด ์‹œ์Šคํ…œ์„ ํŒจํ‚ค์ง•ํ•˜๊ณ  ์šด์˜ํŒ€์€ ์ด๋ฅผ ๋ฐฐํฌํ•˜๊ณ  ๋ชจ๋‹ˆํ„ฐ๋งํ•œ๋‹ค ์šด์˜ํŒ€์€ ํ•˜๋“œ์›จ์–ด ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์„œ๋ฒ„๋กœ ์ง์ ‘ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•œ๋‹ค ๊ฑฐ๋Œ€ํ•œ ๋ชจ๋†€๋ฆฌ์Šค ๋ ˆ๊ฑฐ์‹œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ ์  MSA๋กœ ๋” ์ž‘์€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์„ธ๋ถ„ํ™” ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค๋Š” ์„œ๋กœ ๋ถ„๋ฆฌ๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ณ„์ ์œผ๋กœ ๊ฐœ๋ฐœ, ๋ฐฐํฌ, ์—…๋ฐ์ดํŠธ, ํ™•์žฅ ๊ฐ€๋Šฅ ๋ฐฐํฌ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ๋งŽ์•„์ง€๊ณ  ๋ฐ์ดํ„ฐ์„ผํ„ฐ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด์„œ ์ „์ฒด ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑ, ๊ด€๋ฆฌ, ์œ ์ง€ํ•˜๊ธฐ๋Š” ์‰ฝ์ง€ ์•Š์€ ์ผ ๋ฆฌ์†Œ์Šค ํ™œ์šฉ์„ ๋†’์ด๊ณ  ํ•˜๋“œ์›จ์–ด ๋น„์šฉ์„ ๋‚ฎ์ถ”๊ณ  ๊ฐ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๋ฐฐ์น˜ํ•  ์œ„์น˜๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ์— ๋„ˆ๋ฌด ์–ด๋ ค์›€ ์ˆ˜๋™์œผ๋กœ ๋ถˆ๊ฐ€๋Šฅ ์ด๋Ÿฐ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์ž๋™์œผ๋กœ ์Šค์ผ€์ฅด๋งํ•˜๊ณ  ๊ตฌ์„ฑ, ๊ด€๋ฆฌ, ์žฅ์• ์ฒ˜๋ฆฌ๋ฅผ ํฌํ•จํ•˜๋Š” ์ž๋™ํ™”๊ฐ€ ํ•„์š” => ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ํ•„์š”ํ•œ ์ด์œ  ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ๋ฐฐํฌ ๋‹จ์  ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋ฐฐํฌ ์กฐํ•ฉ์˜ ์ˆ˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ„์˜ ์ƒํ˜ธ ์ข…์†์„ฑ ์ˆ˜๊ฐ€ ํ›จ์”ฌ ๋งŽ์•„์ง€๋ฏ€๋กœ ๋ฐฐํฌ ๊ด€๋ จ ๊ฒฐ์ •์ด ์–ด๋ ต๋‹ค ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค์™€ ์‹œ์Šคํ…œ์— ๋ถ„์‚ฐ๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ–‰ ํ˜ธ์ถœ์„ ๋””๋ฒ„๊น…ํ•˜๊ณ  ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค Kubernetes ๊ฐœ๋… ๊ตฌ๊ธ€์€ Borg๋ผ๋Š” ์‹œ์Šคํ…œ์„ ๊ฐœ๋ฐœํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์ž์™€ ์‹œ์Šคํ…œ ๊ด€๋ฆฌ์ž๊ฐ€ ์ˆ˜์ฒœ ๊ฐœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์„œ๋น„์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ๋„์›€์„ ์ค€๋‹ค ๊ตฌ๊ธ€ 10๋…„๊ฐ„ ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ 2014๋…„์— kubernetes ํ”„๋กœ์ ํŠธ๋ฅผ ์˜คํ”ˆ์†Œ์Šคํ™” ํ•œ๋‹ค ๋ณ„๋ช…์€ k8s์ด๋‹ค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์“ฐ๋Š” ์ด์œ  ๊ฒฝ๋Ÿ‰, ์ด์‹์„ฑ ๋ฐ ํ”Œ๋žซํผ ๋…๋ฆฝ์„ฑ, ์ตœ์‹ ํ˜• ๊ฐœ๋ฐœ ๋ฐ ์•„ํ‚คํ…์ฒ˜ ์ง€์›, ํ™œ์šฉ๋„ ํ–ฅ Kubernetes ์•„ํ‚คํ…์ฒ˜ ๋งˆ์Šคํ„ฐ ๋…ธ๋“œ : ์ „์ฒด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์‹œ์Šคํ…œ์„ ์ œ์–ดํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ์„ ์‹คํ–‰ ์›Œ์ปค ๋…ธ๋“œ : ์‹ค์ œ ๋ฐฐํฌ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ kubernetes ์‹ค์Šต 1 minikube start kubectl run ntest --image=develo0100/node --port 8080 curl localhost:8080 kubernetes pod ์†Œ๊ฐœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๊ฐœ๋ณ„ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์ง์ ‘ ๋‹ค๋ฃจ์ง€ ์•Š๊ณ , ํ•จ๊ป˜ ๋ฐฐ์น˜๋œ ๋‹ค์ˆ˜์˜ ์ปจํ…Œ์ด๋„ˆ๋ผ๋Š” ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ๋‹ค kubernetes ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋™์ž‘ ๋„์ปค ๋ฐ๋ชฌ์ด ์‹คํ–‰ ์ค‘์ธ ๋‹ค๋ฅธ ์›Œ์ปค ๋…ธ๋“œ์—์„œ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋กœ ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋„์ปคํ—ˆ๋ธŒ์— ์ด๋ฏธ์ง€๊ฐ€ ์˜ฌ๋ ค์ ธ์žˆ์–ด์•ผ ํ•œ๋‹ค kubectl ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API ์„œ๋ฒ„๋กœ kubernetes ์›Œํฌ๋กœ๋“œ ์šฉ์–ด Daemon set Deployment Job Pod Replica set Replication controller
new ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฐ MSA ํŠน๊ฐ• 2์ผ์ฐจ : Docker ์‹ค์Šต
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
Docker ์‹ค์Šต Docker๋ž€ ๋ฌด์—‡์ธ๊ฐ€ Docker๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹ ์†ํ•˜๊ฒŒ ๊ตฌ์ถ•, ํ…Œ์ŠคํŠธ ๋ฐ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํ”Œ๋žซํผ Docker๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  ๊ฐœ์„ ๋˜๊ณ  ์™„๋ฒฝํ•œ ์ด์‹์„ฑ ๊ฒฝ๋Ÿ‰์˜ ์ค‘๋Ÿ‰, ๋ฏธ์„ธํ•œ ์—…๋ฐ์ดํŠธ ์ž๋™ํ™”๋œ ์ปจํ…Œ์ด๋„ˆ ์ž‘์„ฑ ์ปจํ…Œ์ด๋„ˆ ๋ฒ„์ „ํ™” ์ปจํ…Œ์ด๋„ˆ ์žฌ์‚ฌ์šฉ ๊ณต์œ  ์ปจํ…Œ์ด๋„ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Docker ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ - Kubernetes Kubernetes๋Š” Google์—์„œ ๋‚ด๋ถ€์šฉ์œผ๋กœ ๊ฐœ๋ฐœ๋œ ํ”„๋กœ์ ํŠธ์—์„œ ํŒŒ์ƒ๋œ ์˜คํ”ˆ์†Œ์Šค ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ํ”Œ๋žซํผ Docker์— ์ž์ฒด ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ํˆด (Docker Swarm)์ด ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋ฐœ์ž๋Š” ๊ทธ ๋Œ€์‹  Kubernetes๋ฅผ ์„ ํƒํ•œ๋‹ค Kubernetes๋Š” ์ปจํ…Œ์ด๋„ˆ ๋ฐฐ์น˜, ์—…๋ฐ์ดํŠธ, ์„œ๋น„์Šค๊ฐ์ง€, ์Šคํ† ๋ฆฌ์ง€ ํ”„๋กœ๋น„์ €๋‹, ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ, ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ์„ ํฌํ•จํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜์˜ ๊ด€๋ฆฌ์— ํ•„์ˆ˜์ ์ธ ํƒœ์Šคํฌ๋ฅผ ์Šค์ผ€์ค„๋งํ•˜๊ณ  ์ž๋™ํ™”ํ•œ๋‹ค
new ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฐ MSA ํŠน๊ฐ• 1์ผ์ฐจ : ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ… ๊ฐœ๋… ๋ฐ ์—ญ์‚ฌ
๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€
ํด๋ผ์šฐ๋“œ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ ํด๋ผ์šฐ๋“œ๋ž€ ๊ฐœ์ธ์ด ๊ฐ€์ง„ ๋‹จ๋ง๊ธฐ๋ฅผ ํ†ตํ•ด์„œ๋Š” ์ฃผ๋กœ ์ž…/์ถœ๋ ฅ ์ž‘์—…๋งŒ ์ด๋ฃจ์–ด์ง€๊ณ , ์ •๋ณด๋ถ„์„ ๋ฐ ์ฒ˜๋ฆฌ, ์ €์žฅ, ๊ด€๋ฆฌ ์œ ํ†ต ๋“ฑ์˜ ์ž‘์—…์€ ํด๋ผ์šฐ๋“œ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ œ3์˜ ๊ณต๊ฐ„์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ์ปดํ“จํŒ… ์‹œ์Šคํ…œ ํ˜•ํƒœ ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ…์ด ํ•„์š”ํ•œ ์ด์œ  ๋น„์šฉ์ ˆ๊ฐ ์†๋„ํ–ฅ์ƒ ํ™•์žฅ์„ฑ ์ƒ์‚ฐ์„ฑ ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ… ์„œ๋น„์Šค๋ชจ๋ธ Infrastructure as a Service (IaaS) : IT๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์œ ์—ฐ์„ฑ๊ณผ ๊ด€๋ฆฌ ์ œ์–ด ๊ธฐ๋Šฅ์„ ์ œ๊ณต GCE, AWS, Azure Platform as a Service (Paas) : ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ํ™˜๊ฒฝ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณต Openshift, Github, docker, kubernetes Software as a a Service (Saas) : ์™„์ „ํ•œ ์ œํ’ˆ ์ œ๊ณต GShift ๋น„๊ต On-site < Iaas < Paas < Saas ์›นํ˜ธ์ŠคํŒ… vs ์„œ๋ฒ„ํ˜ธ์ŠคํŒ… vs ํด๋ผ์šฐ๋“œ ์ฐจ์ด์  ์›นํ˜ธ์ŠคํŒ… : ํ˜ธ์ŠคํŒ… ์—…์ฒด์˜ ์„œ๋ฒ„ ์ค‘ ์ผ๋ถ€๋งŒ ์ž„๋Œ€ํ•˜์—ฌ ์‚ฌ์šฉ ํ™ˆํŽ˜์ด์ง€ ์šด์˜ ์„œ๋ฒ„ํ˜ธ์ŠคํŒ… : ํ˜ธ์ŠคํŒ… ์—…์ฒด์˜ ๋ฌผ๋ฆฌ ์„œ๋ฒ„๋ฅผ ๋‹จ๋…์œผ๋กœ ์ž„๋Œ€/๊ตฌ๋งคํ•˜์—ฌ ์‚ฌ์šฉ ERP, ์ธํŠธ๋ผ๋„ท ๋“ฑ ์šด์˜ ํด๋ผ์šฐ๋“œ ๋‹จ๊ธฐ ์ด๋ฒคํŠธ ๋“ฑ ์œ ๋™์ ์ธ ์„œ๋น„์Šค ์šด์˜ On-premise๋ž€ ์ž์ฒด์ ์œผ๋กœ ๋ณด์œ ํ•œ ์ „์‚ฐ์‹ค์— ์ง์ ‘ ์„ค์น˜ํ•ด ์šด์˜ํ•˜๋Š” ๋ฐฉ์‹ Private, Public, Hybrid Cloud ๋น„๊ต Private cloud ์ธํ”„๋ผ๊ฐ€ ์กฐ์ง ์ „์šฉ์ธ ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ… ๋ชจ๋ธ ํ•ด๋‹น ์‚ฌ์šฉ์ž ๋˜๋Š” ๊ทธ๋ฃน์˜ ๋ฐฉํ™”๋ฒฝ์œผ๋กœ ๋ณดํ˜ธ๋œ๋‹ค Public cloud ์ตœ์ข… ์‚ฌ์šฉ์ž๊ฐ€ ์†Œ์œ ํ•˜์ง€ ์•Š์€ IT์ธํ”„๋ผ์—์„œ ์ƒ์„ฑ๋˜๋Š” ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ Alibaba Cloud, AWS, GCP, IBM Cloud, Microsft Azure ๋“ฑ์ด ์žˆ๋‹ค Hybrid cloud ๋‹จ์ผ ITํ™˜๊ฒฝ ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์ด ์—ฐ๊ฒฐ๋œ ํ˜•ํƒœ ์—…์ฒด๋ณ„ ํด๋ผ์šฐ๋“œ ์‹œ์žฅ GCP, Azure, AWS ํด๋ผ์šฐ๋“œ ๊ด€๋ จ ์ง๊ตฐ ํด๋ผ์šฐ๋“œ ์—”์ง€๋‹ˆ์–ด ํด๋ผ์šฐ๋“œ ์‹œ์Šคํ…œ ์—”์ง€๋‹ˆ์–ด ํด๋ผ์šฐ๋“œ ์ธํ”„๋ผ ๋ณด์•ˆ ๋‹ด๋‹น์ž ๋ฐ๋ธŒ์˜ต์Šค ํด๋ผ์šฐ๋“œ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž
  • ««
  • «
  • 8
  • 9
  • 10
  • 11
  • 12
  • »
  • »»
๐Ÿง  Algorithm (104) ๐ŸŒŠ C/CPP (2) โ˜• Java (8) ๐ŸŒ Javascript (9) ๐Ÿ Python (9) ๐Ÿƒ Spring (30) ๐Ÿ”จ ๊ฐœ๋ฐœ ๋„๊ตฌ (2) ๐ŸŽธ ๊ธฐํƒ€ (7) ๐Ÿ‘จโ€๐Ÿ’ป ๋ชจ๊ฐ์ฝ” (38) ๐Ÿค– ์ธ๊ณต์ง€๋Šฅ (2) ๐Ÿซ ํ•™๊ณผ ๊ณต๋ถ€ (28)
๐Ÿท๏ธ boj (53) ๐Ÿท๏ธ c (5) ๐Ÿท๏ธ c++ (4) ๐Ÿท๏ธ celery (2) ๐Ÿท๏ธ cs (18) ๐Ÿท๏ธ django (3) ๐Ÿท๏ธ docker (2) ๐Ÿท๏ธ docker compose (1) ๐Ÿท๏ธ elk (1) ๐Ÿท๏ธ fastapi (4) ๐Ÿท๏ธ git (2) ๐Ÿท๏ธ github actions (5) ๐Ÿท๏ธ hackerrank (3) ๐Ÿท๏ธ https (2) ๐Ÿท๏ธ java (37) ๐Ÿท๏ธ javascript (2) ๐Ÿท๏ธ jwt (1) ๐Ÿท๏ธ kubernetes (4) ๐Ÿท๏ธ nginx (2) ๐Ÿท๏ธ ocaml (1) ๐Ÿท๏ธ open source (2) ๐Ÿท๏ธ programmers (48) ๐Ÿท๏ธ pytest (1) ๐Ÿท๏ธ python (111) ๐Ÿท๏ธ rabbitmq (2) ๐Ÿท๏ธ rag (3) ๐Ÿท๏ธ react (6) ๐Ÿท๏ธ security (3) ๐Ÿท๏ธ software-engineering (3) ๐Ÿท๏ธ spring (31) ๐Ÿท๏ธ sql (5) ๐Ÿท๏ธ ssl (1) ๐Ÿท๏ธ testing (4) ๐Ÿท๏ธ typescript (1) ๐Ÿท๏ธ vercel (1) ๐Ÿท๏ธ websocket (1)