/images/profile.png

์ž๋ฐ” ๊ฐ์ฒด ๋ณต์‚ฌํ•˜๊ธฐ ( feat. how to use CloneUtils? )

์ž๋ฐ”(Java)๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด ํ•œ๋ฒˆ์ฏค ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๋กœ์ง์„ ์ž‘์„ฑํ• ๋•Œ๊ฐ€ ์žˆ๋‹ค. ๊ทธ๋•Œ๋งˆ๋‹ค ๋‚˜์˜ค๋Š” ์ด์•ผ๊ธฐ์ธ Shalldow Copy ์™€ Deep Copy. ํ•œ๊ตญ์–ด๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์–•์€ ๋ณต์‚ฌ์™€ ๊นŠ์€ ๋ณต์‚ฌ๋ผ๊ณ  ์ด์•ผ๊ธฐ๋ฅผ ํ•˜๋Š”๋ฐ ์ด ๋‘ ๊ฐœ๋…์˜ ์ฐจ์ด๋Š” ์•„์ฃผ ๊ฐ„๋‹จํ•˜๋‹ค. ๊ฐ์ฒด์˜ ์ฃผ์†Œ๊ฐ’์„ ๋ณต์‚ฌํ•˜๋Š”์ง€, ์•„๋‹ˆ๋ฉด ๊ฐ์ฒด์˜ ์‹ค์ œ ๊ฐ’(value)๋ฅผ ๋ณต์‚ฌํ•˜๋Š”์ง€. ์ด ๋‘˜์˜ ์ฐจ์ด์ ์„ ์†Œ๊ฐœํ•˜๋Š” ๊ธ€๋“ค์€ ์›Œ๋‚™ ๋งŽ์œผ๋‹ˆ ํŒจ์Šคํ•˜๋„๋ก ํ•˜๊ณ  ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” Deep Copy๋ฅผ ํ• ๋•Œ org.apache.http.client.utils ํ•˜์œ„์— ์žˆ๋Š” CloneUtils ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌ ํ•˜๊ณ ์ž ํ•œ๋‹ค.

๊ทธ๋ƒฅ ์“ฐ๋ฉด ๋˜๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€? ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ (๋ณ„๊ฑฐ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ) ํ•ด๋ณด๊ณ  ์•ˆํ•ด๋ณด๊ณ ์˜ ์ฐจ์ด๋Š” ์—„์ฒญ์ปธ๊ณ  ์‚ฌ์šฉํ• ๋•Œ ์ฃผ์˜์ ์ด ๋ช‡๊ฐ€์ง€ ์žˆ์–ด ์ •๋ฆฌ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

์˜ˆ์ œ์— ์•ž์„œ ๋ณธ ํฌ์ŠคํŒ…์—์„œ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋ฅผ ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. (ํ•™๊ต์—์„œ ํ•™์ƒ ์‹ ์ƒ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.)

public class Student {
	String name; // ์ด๋ฆ„
	int age; // ๋‚˜์ด
	Family family; // ๊ฐ€์กฑ
}

public class Family {
	String name;  // ์ด๋ฆ„
	int age; // ๋‚˜์ด
	boolean isOfficeWorkers; // ์ง์žฅ์ธ ์—ฌ๋ถ€
}

public class PhysicalInformation {
	int height; // ํ‚ค
	int weight; // ๋ชธ๋ฌด๊ฒŒ
}

๊ฐ์ฒด๋Š” Cloneable interface ๋ฅผ implement ํ•ด์•ผํ•˜๊ณ  clone ๋ฉ”์†Œ๋“œ๋ฅผ public ์œผ๋กœ override ํ•ด์•ผํ•œ๋‹ค.

๋‹น์—ฐํ•œ ์ด์•ผ๊ธฐ๊ฐ€ ๋ ์ˆ˜๋„ ์žˆ์œผ๋‚˜ CloneUtils๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ๊ฐ์ฒด๋Š” Cloneable interface ๋ฅผ implement ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ clone ๋ฉ”์†Œ๋“œ๋ฅผ override ํ•ด์•ผ๋˜๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ์ ์€ ์™ธ๋ถ€์—์„œ๋„ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— public ์œผ๋กœ override๋ฅผ ํ•ด์•ผํ•œ๋‹ค. (๊ธฐ๋ณธ์€ protected ๋กœ ๋˜์–ด์žˆ๋‹ค.) ์šฐ์„  ๊ฐ„๋‹จํžˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ถœ๋ ฅ๋ถ€ํ„ฐ ํ•ด๋ณด์ž. (์ถœ๋ ฅ์„ ์ด์˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ToStringBuilder.reflectionToString์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.)

PhysicalInformation physicalInformation = new PhysicalInformation();
physicalInformation.height = 180;
physicalInformation.weight = 70;

System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));

๊ฒฐ๊ณผ๋Š” ๋‹น์—ฐํžˆ

PhysicalInformation@5d6f64b1[height=180,weight=70]

์ด์ œ Cloneable interface ๋ฅผ implement ํ•˜๊ณ  clone ๋ฉ”์†Œ๋“œ๋ฅผ public ์œผ๋กœ override ํ•œ๋’ค, CloneUtils๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•ด๋ณด์ž. ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋ฉด์„œ Shalldow Copy๋„ ํ•ด๋ณด์ž.

// class setting
public class PhysicalInformation implements Cloneable{
	int height;
	int weight;

	@Override
	public Object clone() throws CloneNotSupportedException { // public ์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์ž.
		return super.clone();
	}
}

// test code
PhysicalInformation physicalInformation = new PhysicalInformation();
physicalInformation.height = 180;
physicalInformation.weight = 70;

PhysicalInformation physicalInformationShalldowCopy = physicalInformation;
PhysicalInformation physicalInformationDeepCopy = null;
try {
	physicalInformationDeepCopy = (PhysicalInformation)CloneUtils.clone(physicalInformation);
} catch (CloneNotSupportedException e) {
	e.printStackTrace();
}

// ์›๋ณธ
System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));
// ์–•์€ ๋ณต์‚ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationShalldowCopy, ToStringStyle.DEFAULT_STYLE));
// ๊นŠ์€ ๋ณต์‚ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationDeepCopy, ToStringStyle.DEFAULT_STYLE));

// ๊ฐ’ ๋ณ€๊ฒฝ
physicalInformation.weight = 80;
physicalInformation.height = 170;

// ์›๋ณธ
System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));
// ์–•์€ ๋ณต์‚ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationShalldowCopy, ToStringStyle.DEFAULT_STYLE));
// ๊นŠ์€ ๋ณต์‚ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationDeepCopy, ToStringStyle.DEFAULT_STYLE));

๊ฒฐ๊ณผ๋Š” ์›๋ณธ๊ณผ ์–•์€ ๋ณต์‚ฌ๋ฅผ ํ•œ๊ฒƒ์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ(?)๊ฐ€ ๊ฐ™์œผ๋‚˜ ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ํ•œ๊ฒƒ์€ ๋ฐ์ดํ„ฐ๋Š” ๊ฐ™์ง€๋งŒ ์ฃผ์†Œ๊ฐ€ ๋‹ค๋ฅด๊ณ  ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด๋„ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. (์™„์ „ํžˆ ์„œ๋กœ๋‹ค๋ฅธ ๊ฐ์ฒด์ธ๊ฒƒ์„ ์ฆ๋ช…)

PhysicalInformation@1376c05c[height=180,weight=70]
PhysicalInformation@1376c05c[height=180,weight=70]
PhysicalInformation@1b4fb997[height=180,weight=70]

PhysicalInformation@1376c05c[height=170,weight=80]
PhysicalInformation@1376c05c[height=170,weight=80]
PhysicalInformation@1b4fb997[height=180,weight=70]

๋งŒ์•ฝ ์œ„์—์„œ clone์„ ๊ธฐ๋ณธ๊ฐ’์ธ protected๋กœ override๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ฌ๊นŒ?

Exception in thread "main" java.lang.NoSuchMethodError: com.PhysicalInformation.clone()
	at org.apache.http.client.utils.CloneUtils.cloneObject(CloneUtils.java:55)
	at org.apache.http.client.utils.CloneUtils.clone(CloneUtils.java:77)
	at com.Test.main(Test.java:16)

์ ‘๊ทผ์ œํ•œ์ž์—์„œ ๋ˆˆ์น˜๋ฅผ ์ฑŒ์ˆ˜๋„ ์žˆ์—ˆ๊ฒ ์ง€๋งŒ ์ ‘๊ทผ์„ ํ• ์ˆ˜์—†์–ด CloneUtils ์ด ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ•˜๋Š” ๊ณผ์ •์—์„œ Exception์„ ๋ฐœ์ƒํ•œ๋‹ค. ๊ผญ! public ์œผ๋กœ override๋ฅผ ํ•ด์ฃผ์ž.

๊ฐ์ฒด ๋‚ด์— clone์ด ์•ˆ๋˜๋Š” ๋ณ€์ˆ˜๋Š” ๋ณ„๋„ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๊ฐ์ฒด ๋‚ด์— ์žˆ๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋Š” ์›์‹œ ๋ณ€์ˆ˜(int, char, float ๋“ฑ) , Immutable Class (String, Boolean, Integer ๋“ฑ) ๋˜๋Š” Enum ํ˜•์‹์ผ ๋•Œ๋Š” ์›๋ณธ์˜ ๊ฐ’์„ ๋ฐ”๋กœ ๋Œ€์ž…ํ•ด๋„ ๋˜์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์„ ๋•Œ๋Š” ๋ฉค๋ฒ„๋ณ€์ˆ˜์˜ clone์„ ํ˜ธ์ถœํ•˜์—ฌ ๋ณต์‚ฌํ•ด์•ผ ํ•œ๋‹ค. ๋ง๋กœ๋งŒ ๋ณด๋ฉด ๋ฌด์Šจ์ด์•ผ๊ธฐ ์ธ์ง€ ๋ชจ๋ฅด๋‹ˆ ์˜ˆ์ œ๋ฅผ ๋ณด์ž.

public class Student implements Cloneable {
	String name;
	int age;
	Family family;

	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

Student ํด๋ž˜์Šค์—์„œ Cloneable ๋ฅผ implements ํ•˜๊ณ  clone ๋ฉ”์†Œ๋“œ๋ฅผ override ํ•˜์˜€๋‹ค. (์—ฌ๊ธฐ์„œ ๊ตฌ๋ฉ์ด ์žˆ๋‹ค!!) ๊ทธ๋‹ค์Œ Family ํด๋ž˜์Šค๋Š” ์ดˆ๊ธฐ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  CloneUtils์„ ์‚ฌ์šฉํ•ด์„œ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž.

๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ ๊ตฌ๋…์„œ๋น„์Šค ๊ฐœ๋ฐœ ํ›„๊ธฐ - 2๋ถ€

1๋ถ€์—์„œ๋Š” ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ ๊ตฌ๋…์„œ๋น„์Šค(์ดํ•˜ ์„œ๋น„์Šค)๋ฅผ ์™œ ๋งŒ๋“ค๊ฒŒ ๋˜์—ˆ๊ณ  ์–ด๋–ค๊ตฌ์กฐ๋กœ ๋งŒ๋“ค๊ฐ€์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ๋ฅผ ํ•ด๋ณด์•˜๋‹ค๋ฉด, ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋งŒ๋“ค๋ฉด์„œ ๋งŒ๋‚˜๊ฒŒ ๋œ ๊ฐ์ข… ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ์ข…ํ•ฉ์„ธํŠธ(?)๋ฅผ ํ•˜๋‚˜์”ฉ ํ’€์–ด๋ณด๊ณ ์ž ํ•œ๋‹ค. ๋ฌผ๋ก  ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ์•„๋ฌด ๋ฌธ์ œ ์—†์ด ์ž˜ ๋˜๋ฉด ๋‹น์—ฐํžˆ ์ข‹๊ฒ ์œผ๋‚˜ ์ž˜๋˜๋„ ์ด์ƒํ•œ๊ฒŒ ๊ฐœ๋ฐœ์ด๋ผ๋Š” ์„ธ๊ณ„๊ฐ€ ์•„๋‹ˆ๋˜๊ฐ€.

/images/daily-dev-blog-2/why_normal.png
์ž˜ ์•ˆ๋˜๋ฉด ๋ฌธ์ œ, ์ž˜ ๋˜๋„ ๋ฌธ์ œ ใ… ใ…  ์ถœ์ฒ˜ : https://www.clien.net/service/board/park/9111495

์ง€๋‚œ 1๋ถ€์—์„œ ์ด์•ผ๊ธฐ ํ–ˆ๋˜๊ฒƒ์ฒ˜๋Ÿผ ๋ฌธ์ œ - ํ•ด๊ฒฐ, ๋ฌธ์ œ - ํ•ด๊ฒฐ ์‹์œผ๋กœ ๋‚˜์—ดํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค. ๋‹ค์†Œ ๊ธ€์˜ ์ „๊ฐœ๊ฐ€ ๋’ค์ฃฝ๋ฐ•์ฃฝ์ผ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ ๋ง ๊ทธ๋Œ€๋กœ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ์ข…ํ•ฉ์„ธํŠธ์ด๋‹ˆ ๋…์ž๋“ค์˜ ์–‘ํ•ด๋ฅผ ๋ฏธ๋ฆฌ ๊ตฌํ•œ๋‹ค.

ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ฆฌ์ŠคํŠธ

10์‹œ์— ๋กœ์ง์ด ์‹คํ–‰๋˜์—ˆ์ง€๋งŒ ๋ฉ”์ผ์„ 11์‹œ ๋„˜์–ด์„œ ๋ฐ›๊ฒŒ ๋œ๋‹ค.

๐Ÿ‘‰ ํ•ด๊ฒฐ๋ฐฉ์•ˆ : Divide and Conquer

๋ณธ ์„œ๋น„์Šค์˜ ์š”๊ตฌ์‚ฌํ•ญ์ค‘ ํ•˜๋‚˜๋Š” ๋งค์ผ ์˜ค์ „ 10์‹œ, ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ์–ด์ œ ๋“ฑ๋ก๋œ ๊ธ€์„ ์ˆ˜์ง‘ํ•˜์—ฌ ๋ฉ”์ผ๋กœ ๋ณด๋‚ด์ฃผ๋Š”๊ฒŒ ์žˆ๋‹ค. ์šฐ์„  ๋กœ์ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ง„ํ–‰๋˜๊ฒŒ ๊ฐœ๋ฐœํ•˜์˜€๊ณ , jenkins ๋“ฑ ๋ณ„๋„์˜ ์Šค์ผ€์ฅด๋Ÿฌ ๊ด€๋ฆฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์˜ํ•ด ํ• ์ˆ˜๋„ ์žˆ์—ˆ์œผ๋‚˜ ์ด ๋˜ํ•œ ์‹ฌํ”Œํ•˜๊ฒŒ crontab ์— ๋“ฑ๋กํ•˜์—ฌ ๋งค์ผ ์˜ค์ „ 10์‹œ์— ์‹คํ–‰๋˜๋„๋ก ํ•˜์˜€๋‹ค.

1. awesome-devblog ์—์„œ ๋ธ”๋กœ๊ฑฐ๋“ค์˜ RSS ํ”ผ๋“œ๋ฅผ ์กฐํšŒํ•œ๋‹ค.
2. ์–ด์ œ ๋“ฑ๋ก๋œ ๊ธ€์ด ์žˆ๋‹ค๋ฉด ๋ฆฌ์ŠคํŠธ์— ๋‹ด๋Š”๋‹ค.
3. ์กฐํšŒ๊ฐ€ ๋๋‚˜๋ฉด ๋ฉ”์ผํ˜•์‹์— ๋งž์ถ”์–ด html ๋ฌธ์ž์—ด์„ ๋งŒ๋“ ๋‹ค.
4. ๋งŒ๋“ค์–ด์ง„ ๋ฌธ์ž์—ด์„ ๊ฐ€์ง€๊ณ  ๋“ฑ๋ก๋œ ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ๋ฉ”์ผ์„ ๋ณด๋‚ธ๋‹ค.

๋กœ์ง์€ ์•„์ฃผ ๊ฐ„๋‹จํ–ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‚˜ ๋ฉ”์ผํ˜•์‹์— ๋งž์ถ”์–ด html๋ฌธ์ž์—ด์„ ๋งŒ๋“œ๋Š” ๋“ฑ ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์†Œ ๋ณต์žกํ•œ ๋ถ€๋ถ„๋งŒ ๋นผ๋ฉด ๋‹จ์ˆœํžˆ for๋ฌธ๊ณผ if๋ฌธ์„ ์กฐํ•ฉํ•ด์„œ ๋กœ์ง์„ ๊ตฌ์„ฑํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค. ํ—Œ๋ฐ, 10์‹œ์— ํ•ด๋‹น๋กœ์ง์ด ์‹คํ–‰๋˜์—ˆ์ง€๋งŒ ์ตœ๋Œ€ 1์‹œ๊ฐ„์ด ์ง€๋‚˜๊ณ ์„œ์•ผ ๋ฉ”์ผ์„ ๋ฐ›๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์—ˆ๋‹ค. ์ด๊ฒŒ ๋ฌด์Šจ์ผ์ผ๊นŒ!? ๋ˆˆ์น˜๋ฅผ ์ฑ˜์„์ˆ˜๋„ ์žˆ์ง€๋งŒ RSS ํ”ผ๋“œ๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ณณ์—์„œ ์˜ค๋ž˜๊ฑธ๋ฆฐ ๊ฒƒ์ด๋‹ค. ํ‹ฐ์Šคํ† ๋ฆฌ๋‚˜ ๋„ค์ด๋ฒ„๋“ฑ ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ๋“ค์€ RSS๋ฅผ ์ฝ๊ณ  ํŒŒ์‹ฑํ•˜๋Š” ์†๋„๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜๋Š”๋ฐ (1์ดˆ ์ด๋‚ด) ์œ ๋… ์ด๊ธ€๋ฃจ์Šค ๋ธ”๋กœ๊ทธ์˜ RSSํŒŒ์‹ฑ์ด ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š”๊ฑด 1๋ถ„๊นŒ์ง€๋„ ๊ฑธ๋ฆฌ๋˜ ๊ฒƒ์ด์˜€๋‹ค. ( ์ฐธ๊ณ ๋กœ RSS ํŒŒ์‹ฑ๋ชจ๋“ˆ, yaml ํŒŒ์‹ฑ๋ชจ๋“ˆ ์„ ์‚ฌ์šฉํ–ˆ๋‹ค. ) ์•„๋งˆ RSS์˜ ํ˜•์‹์ด ์•ฝ๊ฐ„ ๋‹ฌ๋ผ์„œ ๊ทธ๋Ÿฐ๊ฒƒ ๊ฐ™๊ธด ํ•œ๋ฐ ๊ทธ๋ ‡๋‹ค๊ณ  ์ด๊ธ€๋ฃจ์Šค ์ผ ๊ฒฝ์šฐ์— ํŒŒ์‹ฑ์„ ๋‹ค๋ฅด๊ฒŒ ํ•˜๋Š”๊ฑด ์ข€ ๊ทธ๋ ‡๊ณ … ์ถ”ํ›„ ์ด๊ธ€๋ฃจ์Šค๊ฐ€ ์•„๋‹Œ ๋˜๋‹ค๋ฅธ ํŒŒ์‹ฑ์†๋„๊ฐ€ ๋А๋ฆฐ ๋ธ”๋กœ๊ทธ์˜ RSS๋ฅผ ๋งŒ๋‚ ์ˆ˜๋„ ์žˆ๊ธฐ์— RSS ํƒ€์ž…๋ณ„๋กœ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”๊ฑด ์ข€ ์•„๋‹Œ๊ฒƒ ๊ฐ™์•˜๋‹ค. ์ด๋Ÿฐ์ €๋Ÿฐ ๊ณ ๋ฏผ๋์— ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ๋„ ์ž„๋ฌด(?)๋ฅผ ๋‚˜๋ˆ„๋Š”์‹์œผ๋กœ ํ•ด๊ฒฐ ํ•˜์˜€๋‹ค. ์ฆ‰, RSS๋ฅผ ์ฝ๊ณ  ๋ฉ”์ผ์— ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“œ๋Š” job ํ•˜๋‚˜์™€ ๋งŒ๋“ค์–ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์ด๋ฉ”์ผ์„ ๋ณด๋‚ด๋Š” job ์œผ๋กœ ๋‚˜๋ˆˆ๋’ค RSS๋ฅผ ๋ถ„์„ํ•˜๋Š” job์€ 9์‹œ์—, ๋ฉ”์ผ๋ณด๋‚ด๋Š” job์€ 10์‹œ์— ๋ณด๋‚ด๋„๋ก ํ•ด์„œ ์ƒ๊ฐ๋ณด๋‹ค ์•„์ฃผ ์‹ฌํ”Œํ•˜๊ฒŒ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์šด ๋ฌธ์ œ๋ฅผ ๊ผญ ๋ณต์žกํ•˜๊ณ  ์–ด๋ ต๊ฒŒ๋งŒ ํ•ด๊ฒฐํ•ด์•ผํ•˜๋Š” ๋ฒ•์€ ์—†๋Š”๊ฒƒ ๊ฐ™๋‹ค. ๋ชจ๋กœ ๊ฐ€๋„ ์„œ์šธ๋งŒ ๊ฐ€๋ฉด ๋œ๋‹ค๋ผ๋Š” ์†๋‹ด์ด ์žˆ์ง€ ์•Š๋Š”๊ฐ€.

์ œ๋ชฉ์—†๋Š” ๊ธ€? ๋ธ”๋กœ๊ทธ RSSํŒŒ์‹ฑ ์˜ค๋ฅ˜? ๊ฐ„ํ—์ ์œผ๋กœ ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธด๋‹ค.

๐Ÿ‘‰ ํ•ด๊ฒฐ๋ฐฉ์•ˆ : ์–ธ์ œ๋‚˜ ์‹ ๊ฒฝ์จ์•ผ ํ•˜๋Š” ์˜ˆ์™ธ์ฒ˜๋ฆฌ(try-catch)

๋‚ด๊ฐ€ ๋งŒ๋“  ์ฝ”๋“œ๋Š” ์–ธ์ œ๋‚˜ ๋‚ด ์ƒ๊ฐ๋Œ€๋กœ๋งŒ ๋Œ์•„๊ฐ”์œผ๋ฉด ํ•˜๋Š”๊ฑด ๋ชจ๋“  ๊ฐœ๋ฐœ์ž์˜ ๋งˆ์Œ๊ณผ ๊ฐ™๋‹ค.

/images/daily-dev-blog-2/deploy_pray.jpg
ํ”ํ•œ IT ์ข…์‚ฌ์ž๋“ค.deploy ์ถœ์ฒ˜ : https://9gag.com/gag/a0Yxw4B/operations-team-before-leaving-for-holidays

ํ•˜์ง€๋งŒ ๊ทธ์ƒ๊ฐ๋„ ์ž ์‹œ ์–ธ์ œ๋‚˜ ์˜ˆ์™ธ๋Š” ๋ฐœ์ƒํ•˜๊ธฐ ๋งˆ๋ จ. ( ๋ฌผ๋ก  ์ „ํ˜€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒ ์•ˆํ• ์ˆ˜๋„ ์žˆ์œผ๋‚˜ ๋งŒ์•ฝ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜๋‹ค ํ• ์ง€๋ผ๋„ ๋ฐœ์ƒํ• ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์€ ์—ผ๋‘ํ•ด๋‘ฌ์•ผ ํ•œ๋‹ค. ) ํŒŒ์‹ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ์ œ๋ชฉ์ด ์—†๋Š”๊ธ€๋กœ ์˜จ๋‹ค๊ฑฐ๋‚˜, ๊ฐ€๋” RSS url ์‘๋‹ต์ด 404 ๋˜๋Š” 503 ์ธ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ๋‹ค.

๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ ๊ตฌ๋…์„œ๋น„์Šค ๊ฐœ๋ฐœ ํ›„๊ธฐ - 1๋ถ€

์ด๋ฒˆ ํฌ์ŠคํŒ…์€ ์•ฝ๊ฐ„์˜ ์žํˆฌ๋ฆฌ ์‹œ๊ฐ„์„ ํ™œ์šฉํ•˜์—ฌ ์ด๊ฒƒ์ €๊ฒƒ ๋งŒ์ ธ๋ณด๋‹ค ๋งŒ๋“ค๊ฒŒ ๋œ Daily DevBlog(๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ ๊ตฌ๋…์„œ๋น„์Šค)์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ํ•˜๋‚˜์˜ ๊ธ€์— ๊ด€๋ จ ๋‚ด์šฉ์„ ๋ชจ๋‘ ๋‹ด๊ธฐ์—๋Š” ์–‘์ด ๋งŽ์•„์„œ ์ฝ๋Š”์‚ฌ๋žŒ๋„ ์ง€๋ฃจํ•˜๊ณ , ๊ธ€์„ ์“ฐ๋Š” ํ•„์ž ๋˜ํ•œ ์–ด๋ถˆ์„ฑ์„ค ํ• ๊ฒƒ๊ฐ™์•„ ํฌ๊ฒŒ 3๊ฐœ์˜ ์‹œ๋ฆฌ์ฆˆ๋กœ ๋‚˜๋ˆ ์„œ ์ตœ๋Œ€ํ•œ ์ž์„ธํ•˜๊ณ  ํ˜„์žฅ๊ฐ(?)์žˆ๊ฒŒ ๊ธ€์„ ์จ๋ณด๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ๋‹ค.

๊ธ€์— ๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ ์ตœ์ข… ๊ฒฐ๊ณผ๋Š” http://daily-devblog.com ์—์„œ ํ™•์ธํ• ์ˆ˜ ์žˆ๋‹ค.


๋ฌด์—‡์ด ๋‚˜๋ฅผ ์›€์ง์ด๊ฒŒ ํ–ˆ๋Š”๊ฐ€

์–ผ๋งˆ์ „๊นŒ์ง€ ์˜คํ”ˆ์†Œ์Šค๋Š” ์ •๋ง ์‹ค๋ ฅ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋‚˜ ์œ ๋ช…ํ•œ ์‚ฌ๋žŒ๋“ค ๋ง๊ณ ๋Š” ๊ธˆ๊ธฐ์˜ ์˜์—ญ(?)์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์—ˆ์ง€๋งŒ ์ตœ๊ทผ ์˜คํ”ˆ์†Œ์Šค ๊ฐœ๋ฐœ์ž ์ด์•ผ๊ธฐ ์„ธ๋ฏธ๋‚˜๋ฅผ ๋‹ค๋…€์˜จ๋’ค ๋งˆ์Œ์†์— ์žˆ์—ˆ๋˜ ๋ฒฝ์ด ์‚ฌ๋ผ์ง€๋Š”๋“ฏ ํ–ˆ๋‹ค. ์„ธ๋ฏธ๋‚˜๋ฅผ ๋“ค์œผ๋ฉด์„œ ‘๋‚˜๋„ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด ๋ณผ์ˆ˜๋Š” ์—†์„๊นŒ?’, ‘ํšŒ์‚ฌ๋ผ๋Š” ๋ช…์ฐฐ์„ ๋–ผ๋ฉด ๋‚œ ์–ด๋А ์ˆ˜์ค€์—์„œ ๊ฐœ๋ฐœ์„ ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ผ๊นŒ?’ ๋“ฑ ์—ฌ๋Ÿฌ ์ƒ๊ฐ๋“ค์ด ๋จธ๋ฆฌ๋ฅผ ๋ฉค๋Œ๋‹ค ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ๊ธ€์“ฐ๊ธฐ๋ผ๋Š” ๊ธ€์—์„œ ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ๋“ค์„ ๋ชจ์•„๋†“์€ awesome-devblog๋ฅผ ์†Œ๊ฐœํ•˜๋Š” ๊ธ€์„ ๋ณด๊ฒŒ ๋˜์—ˆ๊ณ  ๋‚ด ๋จธ๋ฆฟ์†์— ์ •๋ฆฌ์•ˆ๋˜๋˜ ๊ทธ ์ƒ๊ฐ๋“ค์€ “์ด ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!“๋กœ ๊ท€๊ฒฐ๋˜์—ˆ๋‹ค.

๋‹ค๋ฅธ ์ด์•ผ๊ธฐ ์ด์ง€๋งŒ, awesome-devblog ์„ ๋ณด๊ณ  ๋‹น์žฅ ๋‚ด ๋ธ”๋กœ๊ทธ๋„ ๋“ฑ๋กํ•ด์•ผ์ง€ ํ–ˆ์—ˆ๋Š”๋ฐ ์ด๋ฏธ ๋“ฑ๋ก์ด ๋˜์–ด ์žˆ์—ˆ๋‹ค;; ๋“ฑ๋กํ•ด์ฃผ์‹  ๋ถ„๊ป˜ ๊ฐ์‚ฌํ•˜๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค๊ธฐ์ „์— ๋‚ด ๋ธ”๋กœ๊ทธ๊ฐ€ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋ณด์—ฌ์ง€๊ณ  ์žˆ๊ตฌ๋‚˜ ํ•˜๋ฉฐ ์ƒˆ์‚ผ ๋†€๋ผ์›€์ด ๋” ์ปธ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ๊ณผ ๋„๊ตฌ ๊ทธ๋ฆฌ๊ณ  ์„ค๊ณ„

๋งŒ๋“ค๋ ค๊ณ  ์ƒ๊ฐํ•ด๋ดค๋˜ ์š”๊ตฌ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ๋งˆ์น˜ ํšŒ์‚ฌ์—์„œ ๊ฐœ๋ฐœ์ „ ์ŠคํŽ™์„ ์ •๋ฆฌํ•˜๋“ฏ…

  1. ์›นํŽ˜์ด์ง€๋ฅผ ํ™œ์šฉํ•ด์„œ ๊ตฌ๋…ํ•˜๊ณ ์ž ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์ด๋ฉ”์ผ์„ ์ˆ˜์ง‘ํ• ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  2. ๋งค์ผ ์ „๋‚  ์ž‘์„ฑ๋œ ๊ธ€์„ ์ˆ˜์ง‘ํ•˜๊ณ  ์กฐํ•ฉํ•˜์—ฌ ๊ตฌ๋…ํ•˜๊ณ ์ž ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ฉ”์ผ์„ ๋ณด๋‚ผ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์œ„ ๋‘๊ฐ€์ง€๋งŒ ๋ณด๋ฉด ๋„ˆ๋ฌด ๊ฐ„๋‹จํ–ˆ๋‹ค. ๋˜ํ•œ ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋˜ ๊ธฐ์ˆ ๋“ค์„ ์‚ฌ์šฉํ•ด๋ณด๋ฉด์„œ ์ตœ๋Œ€ํ•œ ์‹ฌํ”Œํ•˜๊ฒŒ ๊ฐœ๋ฐœํ•˜๋Š”๊ฒƒ์„ ์ฒซ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋กœ ํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค. ํ•˜์—ฌ ์ƒ๊ฐํ•œ ์•„ํ‚คํ…์ฒ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

/images/daily-dev-blog-1/architecture.png
์ตœ๋Œ€ํ•œ ์‹ฌํ”Œํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด๋ณด์ž.

๋ฐ์ดํ„ฐ๋Š” ํ•ด๋‹น github์— ์žˆ๊ธธ๋ž˜ ๊ทธ๋ƒฅ ๊ฐ€์ ธ๋‹ค ์“ฐ๋ ค๊ณ  ํ–ˆ์œผ๋‚˜ ๊ทธ๋ž˜๋„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜์‹œ๋Š” ๋ถ„๊ป˜ ํ—ˆ๋ฝ์„ ๋ฐ›๊ณ  ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ƒ๋„๋•(?)์ธ๊ฒƒ ๊ฐ™์•„ ์ˆ˜์†Œ๋ฌธ๋์— ์—ฐ๋ฝ์„ ํ•ด์„œ ํ—ˆ๋ฝ๋ฐ›๋Š”๋ฐ ์„ฑ๊ณตํ•˜์˜€๋‹ค.

/images/daily-dev-blog-1/message.png
๋ฐ์ดํ„ฐ ์‚ฌ์šฉ์„ ํ—ˆ๋ฝํ•ด์ฃผ์‹  ์ฒœ์‚ฌ๊ฐ™์œผ์‹ ๋ถ„…

์ด ์ž๋ฆฌ๋ฅผ ๋นŒ์–ด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ๋ฝํ•ด์ฃผ์‹ ๋ถ„ ๊ป˜ ๊ฐ์‚ฌ์ธ์‚ฌ๋ฅผ ํ‘œํ•ฉ๋‹ˆ๋‹ค.

ํ™ˆํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด์ œ๊ป ์‚ผ๊ฒน์‚ด์— ์†Œ์ฃผ์ฒ˜๋Ÿผ(์‘?) Java์— Spring์„ ์‚ฌ์šฉํ•ด ์™”์—ˆ์ง€๋งŒ ์ด๋ฒˆ์—” ์ข€ ๋‹ค๋ฅธ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

/images/daily-dev-blog-1/language_framework.png
๋ฌผ๋ก  ์‚ผ๊ฒน์‚ด์— ๋งฅ์ฃผ, ์น˜ํ‚จ์— ์†Œ์ฃผ๋ฅผ ๋จน์–ด๋„ ๋˜๊ธด ํ•˜์ง€๋งŒ…

์ตœ๊ทผ์— Flask๋ผ๋Š” python๊ธฐ๋ฐ˜ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ์ ธ๋ณธ ๊ฒฝํ—˜์ด ์žˆ์–ด์„œ ์ด๋ ‡๋‹คํ•  ๊ณ ๋ฏผ์—†์ด ๋น ๋ฅธ ๊ฒฐ์ •์„ ํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋˜ํ•œ DB๋Š” mysql ์ด๋‚˜ ๊ธฐํƒ€ memory DB๋ฅผ ์‚ฌ์šฉํ• ๊นŒ ํ–ˆ์ง€๋งŒ ์ด๋˜ํ•œ ์‹ฌํ”Œํ•˜๊ฒŒ ํŒŒ์ผ์„ ํ™œ์šฉํ•˜๋Š” sqlite3 ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜์˜€๋‹ค.

์›น์„œ๋ฒ„_์ตœ์ข…_์ˆ˜์ •_ํŒŒ์ด๋„_์ง„์งœ_ํ™•์ •

Flask๋ฅผ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹น์—ฐํžˆ ์›น์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค. ์ฒ˜์Œ์—” awesome-devblog์—์„œ๋„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ https://www.heroku.com/ ๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๋ณด๋ ค ํ–ˆ์œผ๋‚˜ ๋งค์ผ ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ๋ฉ”์ผ์„ ๋ณด๋‚ด๋Š” ๋“ฑ ์Šค์ผ€์ฅด๋Ÿฌ ๊ธฐ๋Šฅ๊ฐ™์€๊ฑด ๊ตฌํ˜„ํ•˜๊ธฐ ํž˜๋“ค์—ˆ๊ณ  ์ธ์Šคํ„ดํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋“ฑ๋กํ•˜๋Š” ํ˜•ํƒœ๋ผ ์‚ฌ์šฉ์ž์˜ ๋ฉ”์ผ์„ ์ž…๋ ฅ๋ฐ›๊ณ  ์ €์žฅํ•˜๋Š” ๋กœ์ง์„ ๋งŒ๋“ค๊ธฐ๋Š” ์–ด๋ ค์›Œ ๋ณด์˜€๋‹ค. (ํ•„์ž๊ฐ€ heroku๋ฅผ ๋„ˆ๋ฌด ์ˆ˜๋ฐ• ๊ฒ‰ํ•ฅ๊ธฐ์‹์œผ๋กœ ๋ด์„œ ์ผ์ˆ˜๋„ ์žˆ๋‹ค…) ์ข€๋” ์ฐพ์•„๋ณด๋‹ˆ https://www.pythonanywhere.com/ ๋ผ๋Š” ์ œํ•œ์ ์ด์ง€๋งŒ ๋ฌด๋ฃŒ ์„œ๋น„์Šค๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ ์›น์ฝ˜์†”๋„ ์ง€์›ํ•˜๊ณ  ์ƒ๋‹นํžˆ ๋งค๋ ฅ์žˆ์–ด ๋ณด์—ฌ์„œ ์ด๊ฑฐ๋‹ค! ํ•˜๋ฉฐ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘์„ ํ–ˆ์œผ๋‚˜ (๋‚˜๋ฆ„ ๋„๋ฉ”์ธ๊นŒ์ง€ ๊ทธ๋Ÿด์‹ธํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์ง€๋งŒ… http://dailydevblog.pythonanywhere.com/ ) ์„ธ์ƒ์— ๊ณต์งœ๋Š” ์—†๋‹ค๋Š” ๋ง์„ ์‹ค๊ฐํ•˜๋ฉฐ ์•ž์„œ ๋งํ–ˆ๋˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ์™„๋ฒฝํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด์˜€๋‹ค.(request ์ œํ•œ, ์Šค์ผ€์ฅด๋Ÿฌ ๋“ฑ๋ก ๊ฐœ์ˆ˜ ์ œํ•œ ๋“ฑ ๋ณด๋‹ค ์—ฌ๋Ÿฌ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ˆ์„ ๋‚ด๊ณ  ์จ์•ผ…) ๋งˆ์ง€๋ง‰ ํฌ๋ง์œผ๋กœ ์–ธ์ œ์ƒ€๋Š”์ง€ ์„œ๋ž์† ๊นŠ์ด ์ž๊ณ ์žˆ๋˜ ๋ผ์ฆˆ๋ฒ ๋ฆฌ ํŒŒ์ด๋ฅผ ๊บผ๋‚ด์„œ ๊ณต์œ ๊ธฐ DDNS์„ค์ •์„ ํ•˜๊ณ  ๋ผ์ฆˆ๋ฒ ๋ฆฌ์•ˆ์„ ์„ค์น˜ํ•˜๋ฉฐ ์›น์„œ๋ฒ„๋ฅผ ์œ„ํ•œ ์…‹ํŒ…์„ ์‹œ๋„ํ•ด๋ณด์•˜์œผ๋‚˜ ์–ธ์ œ๋‚˜ ๊ทธ๋ ‡๋“ฏ (์‹œํ—˜๊ณต๋ถ€ ํ•˜๊ธฐ์ „์— ์ฑ…์ƒ ์ •๋ฆฌํ•˜๊ณ  ๊ดœํžˆ ๋ฐฉ์ฒญ์†Œ๊นŒ์ง€ ํ•˜๋‹ค๊ฐ€ ํ”ผ๊ณคํ•ด์„œ ์ž๋ฒ„๋ฆฌ๋Š”๋“ฏํ•œ ๋А๋‚Œ) ๋ฐฐ๋ณด๋‹ค ๋ฐฐ๊ผฝ์ด ํด๊ฒƒ๊ฐ™์•„ ์ด๋˜ํ•œ ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ ์ค‘๋‹จํ•˜๊ฒŒ ๋œ๋‹ค. ๊ฒฐ๊ตญ AWS์—์„œ 1๋…„๋™์•ˆ์€ ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋Š” Free Tier ๋ผ๋Š”๊ฑธ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ด์ฐธ์— ๋‚˜๋„ํ•œ๋ฒˆ ์‚ฌ์šฉํ•ด๋ณด์ž๋ผ๋Š” ๋งˆ์Œ์„ ๊ฐ€์ง€๊ณ  ๊ณผ๊ธˆ๋˜์ง€ ์•Š๊ฒŒ ์กฐ์‹ฌ์กฐ์‹ฌ ์…‹ํŒ…์„ ํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋ฌผ๋ก  ๋’ค์—์„œ ์ด์•ผ๊ธฐ ํ•˜๊ฒ ์ง€๋งŒ ์•ฝ๊ฐ„์˜ ๊ณผ๊ธˆ์€ ํ•„์š”ํ–ˆ๋‹คใ…  (๋‚˜๋ฆ„ ์‹ฌ๋„๊นŠ์—ˆ๋˜ ๊ณ ๋ฏผ์„ ํ•œ๋ฐฉ์— ํ•ด๊ฒฐํ•ด๋ฒ„๋ฆฌ๋Š” AWS ์งฑ;; ์ด๋ž˜์„œ AWS~ AWS~ ํ•˜๋Š”๊ฐ€ ์‹ถ์—ˆ๋‹ค.)

2018 ์˜คํ”ˆ์†Œ์Šค๊ฐœ๋ฐœ์ž์ด์•ผ๊ธฐ ํ›„๊ธฐ

Facebook๊ทธ๋ฃน๋“ค์„ ๋ˆˆํŒ…ํ•˜๋‹ค(?) OSS๊ฐœ๋ฐœ์ž ํฌ๋Ÿผ์—์„œ ์˜คํ”ˆ์†Œ์Šค ๊ฐœ๋ฐœ์ž์ด์•ผ๊ธฐ๋ผ๋Š” ์ฃผ์ œ๋กœ ์„ธ๋ฏธ๋‚˜๋ฅผ ์ฃผ์ตœํ•œ๋‹ค๋Š” ๊ณต์ง€๋ฅผ ๋ณด๊ฒŒ๋˜์—ˆ๋‹ค. ์–ธ์ œ๋ถ€ํ„ด๊ฐ€ ํŠธ๋žœ๋“œ์— ๋’ค์ณ์ง€์ง€ ์•Š์œผ๋ ค๋Š” ๋ชธ๋ถ€๋ฆผ์ค‘ ์„ธ๋ฏธ๋‚˜๊ฐ™์€ ์™ธ๋ถ€ ๊ฐœ๋ฐœ ํ–‰์‚ฌ์— ์ฐธ์—ฌํ•ด๋ณด์ž๋Š” ๋งˆ์Œ์œผ๋กœ ๊ณต์ง€๋ฅผ ๋ณด์ž๋งˆ์ž ํ™€๋ฆฐ๋“ฏ์ด ์‹ ์ฒญ์„ ํ•˜๊ฒŒ ๋˜์—ˆ๊ณ  ์„ธ๋ฏธ๋‚˜๋ฅผ ๋“ฃ๊ณ  ๊ฐํฅ์ด ๊ฐ€์‹œ๊ธฐ ์ „์— ํ›„๊ธฐ๋ฅผ ์ ๊ณ ์ž ํ•œ๋‹ค.(์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์žŠ์–ด๋ฒ„๋ฆด๊ฒƒ๋งŒ๊ฐ™์€, ๋ณด๊ณ  ๋“ค์€ ์ƒ์ƒํ•œ ๊ทธ ๋ฌด์–ธ๊ฐ€๋ฅผ ์–ป์—ˆ๊ธฐ์—…)

/images/open-source-software-develpoer-story-review/first.png

๋น„๊ฐ€์˜ค๋Š” ์ฃผ๋ง์ด์˜€์ง€๋งŒ ๋งŽ์ด ๋ฐฐ์šฐ๊ณ  ์˜ค์ž๋Š” ์„ค๋ ˆ์ž„์„ ๊ฐ–๊ณ  ์„œ์šธ ๊ด‘ํ™”๋ฌธ ๊ทผ์ฒ˜์— ์žˆ๋Š” ํ•œ๊ตญ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ๋กœ ๊ฐ€๊ฒŒ๋˜์—ˆ๋‹ค. ๋ง๋กœ๋งŒ ๋“ฃ๋˜ MS์‚ฌ ๋กœ๊ณ ๋ฅผ ๋ณด๊ณ  ์‚ฌ๋žŒ๋“ค์ด ํ•˜๋‚˜๋‘˜์”ฉ ๋ชจ์ด๋Š”๊ฑธ ๋ณด๋‹ˆ ๋ญ”๊ฐ€ ๋ฐฐ์šธ์ˆ˜ ์žˆ๊ฒ ๊ตฌ๋‚˜ ํ•˜๋Š” ๊ธฐ๋Œ€๊ฐ์ด ์ƒ๊ฒผ๋‹ค. ์‚ฌ์‹ค ์˜คํ”ˆ์†Œ์Šค๋ฅผ ์‚ฌ์šฉ๋งŒ ํ•ด๋ณธ ์ž…์žฅ์ด๋ผ ์‹ค์ œ ์˜คํ”ˆ์†Œ์Šค์— ๊ธฐ์—ฌํ•˜์‹œ๋Š” ๋ถ„๋“ค์€ ์–ด๋–ค ์ƒ๊ฐ๋“ค์„ ๊ฐ–๊ณ  ๊ณ„์‹œ๋Š”์ง€๊ฐ€ ๊ฐ€์žฅ ๊ถ๊ธˆํ–ˆ๊ณ  ๊ฐœ๋ฐœ์ž์ธ ๋‚˜๋„ ์–ธ์  ๊ฐ„ ์˜คํ”ˆ์†Œ์Šค์— ๊ธฐ์—ฌํ• ์ˆ˜์žˆ์ง€ ์•Š์„๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์„ ํ•˜๋ฉฐ ๋ฐœํ‘œ๋ฅผ ๋“ค์—ˆ๋‹ค.

# ํšŒ์ƒ‰์ง€๋Œ€ : ์ด์ƒ๊ณผ ํ˜„์‹ค - ์˜คํ”ˆ์†Œ์Šค ์ €์ž‘๊ถŒ / ์‹ ์ •๊ทœ ๋‹˜

/images/open-source-software-develpoer-story-review/01.png

์˜คํ”ˆ์†Œ์Šค๋Š” ์•„๋ฌด๋ฆฌ ๋ง๊ทธ๋Œ€๋กœ Open์ด์ง€๋งŒ ์˜คํ”ˆ์†Œ์Šค๋งˆ๋‹ค ๋‹ค์–‘ํ•œ ์ €์ž‘๊ถŒ์„ ๊ฐ–๊ณ ์žˆ๊ณ  ์„œ๋กœ ์Ÿ์ทจํ•˜๋ ค๋Š” ์‹ธ์›€์ด ๋งŽ์ด ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ์–ด๋– ํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ  ์˜คํ”ˆ์†Œ์Šคํ™” ์‹œํ‚ฌ๋•Œ๋„ ๋ผ์ด์„ผ์Šค์˜ ์ข…๋ฅ˜๋ฅผ ์ž˜ ๊ฒฐ์ •ํ•ด์•ผ ์ถ”ํ›„ ๋ถˆ์ด์ต์„ ๋‹นํ•˜๋Š” ์ƒํ™ฉ์„ ๋ชจ๋ฉดํ• ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ํŠนํ—ˆ์™€ ๋ผ์ด์„ผ์Šค๋Š” ๊ฐ™์€ ๋ง์ด๋ฉด์„œ๋„ ๋‹ค๋ฅธ๋ฐ ์•„๋ž˜ ํ‘œ์ฒ˜๋Ÿผ ๊ฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ํ™•์ธํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค.

ํŠนํ—ˆ๋ผ์ด์„ผ์Šค
๊ถŒ๋ฆฌ๋ฐœ์ƒ์ถœ์›, ์‹ฌ์‚ฌ, ๋“ฑ๋ก์ฐฝ์ž‘๊ณผ ๋™์‹œ ๋ฐœ์ƒ
๊ถŒ๋ฆฌ๋‚ด์šฉ๋…์ ๋ฐฐํƒ€์  ์‹ค์‹œ๊ถŒ์ธ๊ฒฉ๊ถŒ/์žฌ์‚ฐ๊ถŒ
ํšจ๋ ฅ๋ฒ”์œ„์•„์ด๋””์–ด์˜ ๋™์ผ์„ฑํ‘œํ˜„์˜ ์‹ค์งˆ์  ์œ ์‚ฌ์„ฑ

์ฒซ ์‹œ๊ฐ„์ด๊ธฐ๋„ ํ•˜์˜€๊ณ  ์•„๋ฌด๋ž˜๋„ ์ฃผ์ œ๊ฐ€ ๋์žฅํ† ๋ก ์„ ํ•ด๋„ ์•ˆ๋๋‚  ์ฃผ์ œ์˜€๋˜์ง€๋ผ ์ •ํ•ด์ง„ ์‹œ๊ฐ„์„ ๋„˜๊ธธ์ •๋„๋กœ ์ด์•ผ๊ธฐ๋ฅผ ๋งŽ์ด ํ•ด์ฃผ์…จ๋‹ค. ํŠนํžˆ ์˜คํ”ˆ์†Œ์Šค ๊ด€๋ จ๋œ ์ด์•ผ๊ธฐ๋Š” ์‚ฌ๋ก€๋ฅผ ์ด์•ผ๊ธฐ ํ•ด์•ผ ์žฌ๋ฐŒ๋‹ค๊ณ  ํ•˜์…จ๋Š”๋ฐ ์‹œ๊ฐ„๊ด€๊ณ„์ƒ ๋ช‡๊ฐ€์ง€๋งŒ ๋ง์”€ํ•ด์ฃผ์…จ๋‹ค.

์˜คํ”ˆ์†Œ์Šค ๊ฐœ๋ฐœ์— ๋Œ€ํ•ด ๋‹จ์ˆœํ•˜๊ฒŒ ๋ˆ„๊ตฌ๋‚˜ ์ˆ˜์ •ํ• ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ ์ด๋ผ๊ณ ๋งŒ ์ƒ๊ฐ์„ ํ•˜๊ณ ์žˆ๋‹ค๊ฐ€ ์ด๋Ÿฐ ๋ณต์žกํ•œ ๋ผ์ด์„ผ์Šค ๋ฌธ์ œ๊ฐ€ ๋‚˜์˜ค๋‹ˆ ์•ฝ๊ฐ„ ์–ด๋ ค์› ์ง€๋งŒ, ์˜คํ”ˆ์†Œ์Šค์˜ ์ƒํƒœ๊ณ„๋ฅผ ์•Œ๊ณ  ๋ฐœ์„ ๋“ค์ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋А์ •๋„์˜ ํžˆ์Šคํ† ๋ฆฌ๋Š” ์•Œ์•„์•ผ ๊ฒ ๋‹ค๊ณ  ๋А๋ผ๊ฒŒ ๋˜์—ˆ๋‹ค.

Elastic ์—์„œ Remote ๋กœ ์ผํ•˜๊ธฐ / ๊น€์ข…๋ฏผ ๋‹˜

/images/open-source-software-develpoer-story-review/02.png

๊ทธ์ „๋ถ€ํ„ฐ Elastic ์ œํ’ˆ๋“ค์„ ์‹ค๋ฌด์—์„œ๋„ ์‚ฌ์šฉํ•ด ์™”์—ˆ๊ธฐ์— ๊ฐœ์ธ์ ์œผ๋กœ ์˜ค๋Š˜ ๋ฐœํ‘œ์ค‘์— ๊ฐ€์žฅ ๊ถ๊ธˆํ–ˆ์—ˆ๊ณ , ๊ด€์‹ฌ์ด ์žˆ๋˜ ์‹œ๊ฐ„์ด์˜€๋‹ค. ๋ฐœํ‘œ์— ์•ž์„œ ์–ด๋–ป๊ฒŒ Elastic์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜์…จ๊ณ  ํšŒ์‚ฌ ์†Œ๊ฐœ๋ฅผ ๊ฐ„๋‹จํžˆ ํ•ด์ฃผ์…จ๋Š”๋ฐ ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋งˆ์–ด๋งˆํ•œ ํšŒ์‚ฌ๋‹ค๊ณ  ๋А๋‚„์ˆ˜ ์žˆ์—ˆ๋‹ค.(800์—ฌ๋ช…์ค‘ ํ•œ๊ตญ์—” 9๋ช… / ๋„ค๋œ๋ž€๋“œ ์ถœ์‹  ์Šคํƒ€ํŠธ์—… ์ธ๋ฐ ๋ณธ์‚ฌ๋Š” ์บ˜๋ฆฌํฌ๋‹ˆ์•„ ๋งˆ์šดํ‹ด๋ทฐ์— ์žˆ๊ณ  ๋“ฑ๋“ฑ) ์›๊ฒฉ๊ทผ๋ฌด๋Š” ํŽธํ•˜๊ณ  ๋น„์šฉ์ด ์ ˆ์•ฝ๋˜๋Š” ์žฅ์ ์ด ์žˆ์œผ๋‚˜ ๋™๋ฃŒ๋“ค๊ฐ„์˜ ์œ ๋Œ€๊ฐํ˜•์„ฑ์ด ํž˜๋“ค๊ฑฐ๋‚˜ ํšŒ์˜์‹œ ์ง‘์ค‘์ด ํž˜๋“  ๋‹จ์ ๋„ ์žˆ๋‹ค๋Š” ์ ์„ ๋ง์”€ํ•ด ์ฃผ์…จ๋‹ค. ์‹œ๊ฐ„๊ด€๊ณ„์ƒ ๋ช‡๊ฐ€์ง€ ๋งํฌ๋“ค์„ ์†Œ๊ฐœํ•ด์ฃผ์…จ๋Š”๋ฐ ๋‚˜์ค‘์— ๋ด๋ณผ ์ƒ๊ฐ์ด๋‹ค.

์›๊ฒฉ ํˆด๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

  • github : ์Šฌ๋ž™์—ฐ๋™, ๊ฐœ๋ฐœ๋ฟ ์•„๋‹ˆ๋ผ ์šด์˜/๊ธฐํš/์ด๋ฒคํŠธ ๊ณต์œ ์‹œ ํ™œ์šฉ
  • Google Apps
  • Slack : ๋ด‡ ํ™œ์šฉ (๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ด‡, ์ƒํ™ฉ๋งˆ๋‹ค ํŠน์ • ์•Œ๋ฆผ์„ ์ค€๋‹ค.)
  • salesforce : CRM ํˆด
  • zoom : ํ™”์ƒํšŒ์˜ 200๋ช… ๋™์‹œ์ฝœ ๊ฐ€๋Šฅ, ํšŒ์˜๊ฐ€ ๋๋‚˜๋ฉด ๋…น์Œ/๋…นํ™”/์Šคํฌ๋ฆฝํŒ…๊นŒ์ง€ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ํ•œ๋‹ค (wow)
  • pinboard : ๊ทผํƒœ/์ธ์‚ฌ ๊ด€๋ฆฌ์šฉ ์•ฑ
  • jira๋Š” ์‚ฌ์šฉ ์ž˜ ์•ˆํ•จ

๋‚˜์ค‘์— ํŒ€ ๋‚ด Slack ๋ด‡์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋‹ค์–‘ํ•œ ์ž๋™ํ™”๋ฅผ ๊ตฌ์„ฑํ• ์ˆ˜ ์žˆ์„๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

์˜คํ”ˆ์†Œ์Šค ์ƒํƒœ๊ณ„ ์ผ์›์œผ๋กœ์„œ์˜ ๊ฐœ๋ฐœ์ž / ๋ณ€์ •ํ›ˆ ๋‹˜

/images/open-source-software-develpoer-story-review/03.png

์‚ฌํšŒ์ž๋ถ„์ด “์•„์›ƒ์‚ฌ์ด๋”๋‹˜"์ด๋ผ๊ณ  ํ•˜์‹œ๊ธธ๋ž˜ ์„ค๋งˆ ํ–ˆ๋‹ค. ๋ญ๊ฐ€ ์ž˜ ์•ˆ๋˜๋ฉด ๊ตฌ๊ธ€๋ง์„ ํ•˜๊ฒŒ๋˜๋Š”๋ฐ ๋‚ด๊ฐ€ ์ž์ฃผ ๋ณด๋˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์šด์˜ํ•˜์…จ๋˜ ๋ถ„์ด ๋‚ด๋ˆˆ์•ž์— ใ„ทใ„ท… ์–ธ์ œ๋ถ€ํ„ฐ ํ•ด์•ผ์ง€~๊ฐ€ ์•„๋‹ˆ๊ณ  ๊ฐœ๋ฐœํ•˜๋‹ค๋ณด๋‹ˆ ์–ด๋А์ƒˆ ์˜คํ”ˆ์†Œ์Šค์— ์ฐธ์—ฌํ•˜๊ณ  ์žˆ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ๋˜ํ•œ ์ฐธ์—ฌํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๊ณ  ์ด๋ฏธ ์˜คํ”ˆ์†Œ์Šค ์ƒํƒœ๊ณ„์†์—์„œ ์‚ด๊ณ ์žˆ๋Š” ์šฐ๋ฆฌ๋“ค์ด๋ผ ๋ง์”€ํ•˜์‹œ๊ณ , ์˜คํ”ˆ์†Œ์Šค Contribution ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์‚ฌ์šฉ/ํ™๋ณด/๋ฒˆ์—ญ/๋ฆฌํฌํŒ…/๋ฌธ์„œํ™”/์ฝ”๋“œ์ œ์ถœ ๋“ฑ ๋‹ค์–‘ํ•˜๊ฒŒ ์žˆ์œผ๋‹ˆ ์–ด๋ ต๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ๋ง์ž ๋ผ๊ณ  ํ•˜์…จ๋‹ค. ์˜คํ”ˆ์†Œ์Šค์—์„œ ๋ฐฐ์šธ์ˆ˜ ์žˆ๋Š”์ ์€ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์˜ ๋ฐฉ๋ฒ•, ํ˜‘์—…์˜ ๋ฐฉ๋ฒ•๊ณผ ์ค‘์š”์„ฑ, ํ…Œ์ŠคํŠธ์ฝ”๋“œ์˜ ์ค‘์š”์„ฑ, ์ง€์†์  ํ†ตํ•ฉ/์ง€์†์  ๋ฐฐํฌ, ์ฝ”๋“œ์˜ ํ’ˆ์งˆ๊ด€๋ฆฌ ๋ผ๊ณ  ํ•œ๋‹ค. ์ ์  ๋ฐœํ‘œ๋ฅผ ๋“ค์œผ๋ฉด์„œ ์˜คํ”ˆ์†Œ์Šค์— ๋Œ€ํ•œ ์ƒ๊ฐ์ด ๋ฐ”๋€Œ๊ณ  ์žˆ๋Š” ๋‚ด ์ž์‹ ์„ ๋А๋‚„์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋„ˆ๋ฌด ์–ด๋ ต๊ฒŒ๋งŒ ์ƒ๊ฐํ•ด ์˜จ๊ฒƒ ๊ฐ™๋‹ค๋Š”.

์ดˆ๊ฐ„๋‹จ API์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ - 2๋ถ€ (Python + Flask + Nginx)

์ง€๋‚œํฌ์ŠคํŒ…์— ์ด์–ด ์ด๋ฒˆ์—” Flask์™€ Nginx๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค. Apache๋กœ ์—ฐ๋™ํ–ˆ๋Š”๋ฐ ์™œ ๋˜ Nginx๋กœ ์—ฐ๋™ํ•˜๋Š”๊ฑธ ์ •๋ฆฌํ•˜์ง€(?)ํ•˜๋ฉฐ ์˜๋ฌธ์ด ๋“ค์ˆ˜ ์žˆ๋Š”๋ฐ ๋‹ค๋ฅธ ํฌ์ŠคํŒ…์„ ๋ด๋„ Apache + Flask ์กฐํ•ฉ๋ณด๋‹ค Nginx + Flask ์กฐํ•ฉ์ด ๋” ๋งŽ๊ณ  ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ๋„ ์•Œ์ˆ˜์žˆ์—ˆ๋“ฏ์ด (Apache VS Nginx) ๋‘˜์ค‘ ์–ด๋А๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ํ• ์ˆ˜๋„ ์—†๊ณ  ๊ฐ ์ƒํ™ฉ์—์„œ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์ด ๋˜ํ•œ ๋‚˜๋งŒ์˜ ๋ฌด๊ธฐ๊ฐ€ ๋ ๊ฒƒ๊ฐ™์•„ Nginx๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•œ๋‹ค.

1๋ถ€์—์„œ ์™œ Flask์ธ๊ฐ€, Flask์˜ ์žฅ์ ์— ๋Œ€ํ•ด ์ •๋ฆฌ๋ฅผ ํ–ˆ์œผ๋‹ˆ ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋ณ„๋„๋กœ ์ž‘์„ฑํ•˜์ง„ ์•Š๋Š”๋‹ค.

Nginx ์„ค์น˜ ( https://nginx.org/en/ )

์—ญ์‹œ ์†Œ์Šค์„ค์น˜๋ฅผ ํ•œ๋‹ค.

- ๋‹ค์šด์„ ๋ฐ›๊ณ 
$ https://nginx.org/download/nginx-1.14.0.tar.gz
- ์••์ถ•์„ ํ‘ผ ๋‹ค์Œ
$ tar -zxvf nginx-1.14.0.tar.gz
- ํด๋”๋กœ ์ด๋™ํ•ด์„œ 
$ cd nginx-1.14.0
- ์„ค์น˜ํ•  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜๊ณ 
$ ./configure --prefix=/~~~/apps/nginx
- make ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ 
$ make
- ์„ค์น˜๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.
$ make install

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ผ๋‹จ Nginx๋Š” ์„ค์น˜๊ฐ€ ๋˜์—ˆ๋‹ค.

uWSGI ์„ค์น˜ ( https://uwsgi-docs.readthedocs.io/ )

์•ž์„œ Apache์™€ ์—ฐ๋™ํ• ๋•Œ๋Š” ๋ณ„๋„์˜ ๋ชจ๋“ˆ์„ Apache์—๊ฒŒ ๋“ฑ๋กํ•˜๋Š” ํ˜•ํƒœ์˜€๋‹ค๋ฉด Nginx๋Š” WSGIํ”„๋กœํ† ์ฝœ์„ ํ™œ์šฉํ•˜๋Š” WSGI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•œ๋‹ค.

- ๋‹ค์šด์„ ๋ฐ›๊ณ 
$ wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz
- ์••์ถ•์„ ํ’€๊ณ 
$ tar zxvf uwsgi-latest.tar.gz
- ํด๋”๋กœ ์ด๋™ํ•˜์—ฌ
$ cd uwsgi-2.0.17
- make ๋ช…๋ น์–ด๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด 'uwsgi'์ด๋ผ๋Š” ์‹คํ–‰ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ๋‹ค.
$ make

Nginx ์„ค์ •

Apache์™€ ๋น„์Šทํ•˜๊ฒŒ uWSGI ๊ด€๋ จ ์„ค์ •์„ ํ•ด์ค€๋‹ค.

server {
  listen       80;
  server_name  localhost;

  location / { # ( / ) ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ
    include uwsgi_params; # GET/POST ๋“ฑ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ include ํ•ด์ค€๋‹ค.
    uwsgi_pass 127.0.0.1:3031; # ์š”์ฒญ์„ IP:PORT๋กœ ์ „๋‹ฌํ•œ๋‹ค.
  }
}

๋ณ„๋„์˜ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ๋•Œ๋ฌธ์— ์ „๋‹ฌํ•ด์ฃผ๋Š” (proxy๋А๋‚Œ) ์„ค์ •์„ ํ•ด์ค€๋‹ค.

uWSGI ์‹คํ–‰ ๋ฐ Nginx ์žฌ์‹œ์ž‘

์•ž์„œ ์„ค์น˜ํ•œ uwsgi๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ IP:port ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ ์–ด์ฃผ๊ณ  (์œ„์—์„œ ์ „๋‹ฌ๋ฐ›์€ IP:PORT์™€ ๋™์ผํ•˜๊ฒŒ) Apache ์—ฐ๋™์‹œ ํ™œ์šฉํ–ˆ๋˜ wsgiํŒŒ์ผ์„ ์ด๋ฒˆ์—๋„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ด์„œ ์‹คํ–‰ํ•œ๋‹ค.

$ ./uwsgi -s 127.0.0.1:3031 --wsgi-file /~~~/python_app/hello_world.wsgi

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด background๋กœ ์‹คํ–‰๋˜๋Š”๊ฒŒ ์•„๋‹Œ foreground๋กœ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— &์„ ์‚ฌ์šฉํ•œ๋‹ค๋˜์ง€ ํ•ด์„œ background๋กœ ์‹คํ–‰๋˜๋„๋ก ํ•ด์ค€๋‹ค. ๊ทธํ›„ Nginx๋ฅผ ์žฌ์‹œ์ž‘ ํ•ด์ฃผ๋ฉด ์›ํ•˜๋Š” ๊ทธํ† ๋ก ์›ํ–ˆ๋˜ Hello World!๋ฅผ ๋งŒ๋‚ ์ˆ˜๊ฐ€ ์žˆ๊ฒŒ ๋œ๋‹ค.

Apache์—ฐ๋™๊ณผ ์กฐ๊ธˆ ๋‹ค๋ฅธ์ ์€ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์ง€์•Š๊ณ  ๋ณ„๋„์˜ ์ „๋‹ฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜(?)์ด ํ•„์š”ํ•˜๋‹ค๋Š”์ ์ด๋‹ค. ๊ฐ„๋‹จํžˆ Apache์ฒ˜๋Ÿผ ๋ชจ๋“ˆ๋งŒ ๋„ฃ์œผ๋ฉด ๋˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ์„œ ๋ถˆํŽธํ• ์ˆ˜๋„ ์žˆ์„๊ฒƒ ๊ฐ™์ง€๋งŒ ํ•œํŽธ์œผ๋กœ๋Š” ๊ด€๋ฆฌํ• ์ˆ˜์žˆ๋Š” ํฌ์ธํŠธ๊ฐ€ ๋” ๋Š˜์–ด๋‚œ ์…ˆ์ด๋ผ ์–ด๋–ค ์ธก๋ฉด์—์„œ๋Š” ํ™œ์šฉํ• ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•˜๋‚˜ ๋Š˜์–ด๋‚œ๊ฒƒ์œผ๋กœ ๋ณผ์ˆ˜๋„ ์žˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

๋ง‰์ƒ ์ •๋ฆฌํ•˜๊ณ  ๋‚˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•„๋‹Œ๋ฐ ์•Œ๊ธฐ ์œ„ํ•ด์„œ ๋ชธ๋ถ€๋ฆผ์„ ์ณ๊ฐ€๋ฉฐ ์ฑ…์ด๋ฉฐ ๊ตฌ๊ธ€๋ง์„ ํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด ์ ์  ์„ฑ์žฅ์„ ํ•˜๋Š”๊ฒƒ ๊ฐ™๋‹ค. (์„ฑ์žฅํ†ต์ด๋ผ๊ณ ๋‚˜ ํ• ๊นŒ) ์ด๋ ‡๊ฒŒ ๋‹จ์ˆœํžˆ Flask๋ฅผ ํ• ์ˆ˜์žˆ๋‹ค ๊ฐ€ ์•„๋‹Œ ์›น์„œ๋ฒ„๋ฅผ ์—ฐ๋™ํ• ์ˆ˜์žˆ๋‹ค. ๊ทธ๊ฒƒ๋„ Apache์™€ Nginx ๋‘๊ฐœ๋‚˜. ์ด๊ฒƒ๋„ ์–ธ์  ๊ฐ„ ๋‚˜๋งŒ์˜ ๋ฌด๊ธฐ๊ฐ€ ๋˜์ง€ ์•Š์„๊นŒ?

์ดˆ๊ฐ„๋‹จ API์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ - 1๋ถ€ (Python + Flask + Apache)

Staticํ•œ HTML์ด ์•„๋‹Œ ๋กœ์ง์ด ํ•„์š”ํ•œ API์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. (์ด์ œ๊นŒ์ง€ ์ง€์‹์œผ๋กœ)์ฒ˜์Œ ๋จธ๋ฆฟ์†์— ๋– ์˜ค๋ฅด๋Š”๊ฑด Java๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์Šคํ”„๋ง์œผ๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๊ณ  apache์— tomcat์„ ์—ฐ๋™ํ•œ ๋‹ค์Œ … ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ API์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ• ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ ํ”„๋กœํ† ํƒ€์ดํ•‘ ๋˜๋Š” ํ…Œ์ŠคํŠธ ๋ชฉ์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„ค์ •ํ•˜๋Š” ์‹œ๊ฐ„์ด ์€๊ทผ ๋งŽ์ด ์†Œ์š”๋œ๋‹ค. (๋ฌผ๋ก  Java Config, Spring Boot ๋“ฑ ๊ฐ„์†Œํ•ด์กŒ์ง€๋งŒ…) ์–ผ๋งˆ์ „๋ถ€ํ„ฐ Python์— ๋Œ€ํ•œ ๋งค๋ ฅ์„ ๋ผˆ์ €๋ฆฌ๊ฒŒ ๋А๋ผ๊ณ  ์žˆ๋‹ค๋ณด๋‹ˆ Python์œผ๋กœ API์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ• ์ˆœ ์—†์„๊นŒ ์•Œ์•„๋ดค๊ณ  (๋ชจ๋ฐ”์ผ ๊ฒŒ์ž„ ๋“€๋ž‘๊ณ  ์„œ๋ฒ„๊ฐ€ python์ด๋ผ๊ณ  ํ•˜๊ธฐ๋„ ํ•˜๊ณ …) Flask์™€ Django๊ฐ€ ์žˆ์–ด์„œ ๋‘˜๋‹ค ์จ๋ณธ ๊ฒฐ๊ณผ ํ•„์ž๋Š” Flask๊ฐ€ ๋งž๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ์ •๋ฆฌ๋ฅผ ํ•ด๋ณผ๊นŒ ํ•œ๋‹ค.

‘์žฅ๊ณ ’๋ผ๊ณ ๋„ ๋ถˆ๋ฆฌ๋Š” Django์—๋Š” ๋ชจ๋“ ๊ฒƒ๋“ค์ด ๋‹ค ๋“ค์–ด๊ฐ€ ์žˆ์–ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ ๋„ˆ๋ฌด ํŽธ๋ฆฌํ•˜๋‹ค. (DB, ์–ด๋“œ๋ฏผ ๋“ฑ ) ํ•˜์ง€๋งŒ Flask๋Š” ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•  ๊ฒƒ๋“ค๋งŒ importํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ ์–ด๋–ค ์ธก๋ฉด์—์„œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค ํ• ์ˆ˜ ์žˆ๊ฒ ์œผ๋‚˜ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์— ์šฉ์ดํ•˜๋‹ค๊ณ  ๋ณผ์ˆ˜ ์žˆ์—ˆ๊ธฐ์— Flask๋ฅผ ์„ ํƒํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. (Django๊ฐ€ Flask๋ณด๋‹ค ์•ˆ์ข‹๋‹ค๋Š” ๋ง์€ ์•„๋‹ˆ๋‹ˆ ์˜คํ•ด๋Š” ํ•˜์ง€ ๋งˆ์‹œ๊ธธ…)

๊ธ€์“ฐ๊ธฐ์— ์•ž์„œ ๋ณธ ํฌ์ŠคํŒ…์€ 2๊ฐœ์˜ ํฌ์ŠคํŒ…์— ๊ฑธ์ณ ์‹œ๋ฆฌ์ฆˆ(?)ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•  ์˜ˆ์ •์ด๋‹ค. 1๋ถ€์—์„œ๋Š” Flask๊ฐ€ ๋ฌด์—‡์ด๊ณ  ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉฐ Apache์™€ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ณ , 2๋ถ€์—์„œ๋Š” Nginx์™€ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•œ๋‹ค. ํ™˜๊ฒฝ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • CentOS 7.4
  • Python 3.6 (๊ธฐ๋ณธ์€ 2.7์ด์˜€์œผ๋‚˜ ์ถ”๊ฐ€๋กœ ์„ค์น˜)

Flask ( http://flask.pocoo.org/ )

๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ๋„ ๋ณด๋ฉด ์•Œ์ˆ˜ ์žˆ๋“ฏ์ด ๋„ˆ~๋ฌด ๊ฐ„๋‹จํ•˜๋‹ค. ๋‹จ์ง€ ์•„๋ž˜ ์ฝ”๋“œ ๋ช‡์ค„๋งŒ ์ž‘์„ฑํ•˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ ์ดˆ๊ธฐ ์ž‘์„ฑ์‹œ ํ•ญ์ƒ ๋งŒ๋‚˜๋Š” “Hello World"๋ฅผ ๋ณผ์ˆ˜ ์žˆ๋‹ค.

#hello_world.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

์œ„์™€๊ฐ™์ด ์ž‘์„ฑํ•˜๊ณ  python hello.py๋กœ ์‹คํ–‰ํ•ด๋‘๊ณ  ๋ธŒ๋ผ์šฐ์ €์—์„œ http://127.0.0.1:5000 ์„ ์š”์ฒญํ•˜๋ฉด ๋ฐ˜๊ฐ€์šด Hello World๋ฅผ ๋งŒ๋‚ ์ˆ˜ ์žˆ๋‹ค. (๋„ˆ๋ฌด ๊ฐ„๋‹จ;;) ์ž์„ธํ•œ ๋ฌธ๋ฒ•์€ ๋„ํ๋จผํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ๋ ๋“ฏํ•˜๊ณ  ์ด Flask๋ฅผ ์ž˜๋งŒ ํ™œ์šฉํ•œ๋‹ค๋ฉด ๋ณด๋‹ค ๋น ๋ฅด๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ API์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ• ์ˆ˜ ์žˆ์„๊ฑฐ๋ผ ์ƒ๊ฐํ•œ๋‹ค.

Hello World๋ฅผ ์ฐ์—ˆ์œผ๋ฉด ๋œ๊ฑฐ ์•„๋‹Œ๊ฐ€ ๋ผ๊ณ  ์งˆ๋ฌธํ• ์ˆ˜๋„ ์žˆ๊ฒ ์œผ๋‚˜ ์‹ค์ œ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•ž๋‹จ์— ์›น์„œ๋ฒ„๋ฅผ ๋‘๋Š”๊ฒŒ ์—ฌ๋Ÿฌ ์ธก๋ฉด์—์„œ ํšจ์œจ์ ์ด๋‹ค. ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์›น์„œ๋ฒ„๋Š” Apache ์™€ Nginx๊ฐ€ ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ๋Š” Apache์™€ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌ ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

Apache ์„ค์น˜ ( http://archive.apache.org/ )

์šฐ์„  ํ•„์ž๋Š” yum ์ด๋‚˜ apt-get์ฒ˜๋Ÿผ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋กœ ์„ค์น˜ํ•˜๋Š”๊ฒƒ์„ ๊ทธ๋ ‡๊ฒŒ ์ข‹์•„ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด์œ ๋Š” ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•  ๊ฒฝ์šฐ ์‹œ์Šคํ…œ ์–ด๋А๊ณณ์— ์„ค์น˜๋˜์–ด์žˆ๋Š”์ง€๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๊ณ  ์œˆ๋„์šฐ๊ฒฝ์šฐ Program Files์ฒ˜๋Ÿผ ๋‚ด๊ฐ€ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ํ•œ๊ณณ์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์‹ถ๊ธฐ์— ์™ ๋งŒํ•˜๋ฉด ์†Œ์Šค๋ฅผ ์ง์ ‘ ์ปดํŒŒ์ผํ•˜์—ฌ ์„ค์น˜ํ•˜๊ณค ํ•œ๋‹ค. ์ด๋ฒˆ ์—ญ์‹œ ์•„ํŒŒ์น˜๋„ ์†Œ์Šค๋กœ ์„ค์น˜ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ํ˜„์žฌ ์•„ํŒŒ์น˜๋Š” 2.4๋ฒ„์ „์ด Stable๋ฒ„์ „์œผ๋กœ ๋˜์–ด์žˆ์ง€๋งŒ ๋ณด๋‹ค ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๋งŽ์€ 2.2๋ฒ„์ „์œผ๋กœ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋ ต๊ฒŒ ์•„์นด์ด๋น™๋œ ๊ฒฝ๋กœ๋ฅผ ํ†ตํ•ด ๋‹ค์šด์„ ๋ฐ›๊ณ  ์„ค์น˜๋ฅผ ํ•œ๋‹ค.

- ๋‹ค์šด์„ ๋ฐ›๊ณ 
$ wget http://archive.apache.org/dist/httpd/httpd-2.2.29.tar.gz 
- ์••์ถ•์„ ํ‘ผ ๋‹ค์Œ
$ tar xvzf httpd-2.2.29.tar.gz
- ํ•ด๋‹น ํด๋”๋กœ ๋“ค์–ด๊ฐ€
$ cd httpd-2.2.29
- ์ปดํŒŒ์ผ ํ›„ ์„ค์น˜ ๊ฒฝ๋กœ๋ฅผ ์ •ํ•ด์ฃผ๊ณ 
$ ./configure --prefix=/~~~/apps/apache
- make ํŒŒ์ผ์„ ๋งŒ๋“ ๋‹ค์Œ
$ make
- ์„ค์น˜๋ฅผ ํ•ด์ค€๋‹ค.
$ make install

์ด๋ ‡๊ฒŒ ๋˜๋ฉด /~~~/apps/apache/ ํ•˜์œ„์— ํ•„์š”ํ•œ ํŒŒ์ผ๋“ค์ด ์„ค์น˜๊ฐ€ ๋˜๋Š”๋ฐ root๊ณ„์ •์ด ์•„๋‹Œ ์ผ๋ฐ˜๊ณ„์ •์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” /binํ•˜์œ„์— ์žˆ๋Š” httpd์— ๋Œ€ํ•œ ์‹คํ–‰/์†Œ์œ ๊ถŒํ•œ์„ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•œ๋‹ค. (์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ root๊ถŒํ•œ์œผ๋กœ ์‹œ์ž‘/์ข…๋ฃŒ. ์™œ? Apache๋Š” 80port๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฆฌ๋ˆ…์Šค์—์„œ๋Š” 1024 ์•„๋ž˜ port๋ฅผ ์ปจํŠธ๋กค ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” root๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅ, ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ์ด์ฒ˜๋Ÿผ ๋ณ„๋„์˜ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.)

$ sudo chown root:๊ณ„์ •๋ช… httpd
$ sudo chmod +s httpd

mod_wsgi ์„ค์น˜ ( https://code.google.com/archive/p/modwsgi/ )

์›น ์„œ๋ฒ„ ๊ฒŒ์ดํŠธ์›จ์ด ์ธํ„ฐํŽ˜์ด์Šค(WSGI, Web Server Gateway Interface)๋Š” ์›น์„œ๋ฒ„์™€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ„ํ•œ ํŒŒ์ด์„  ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค. ๋ผ๊ณ  ์ •์˜๋˜์–ด์žˆ๋‹ค. ์ฆ‰, ์›น์„œ๋ฒ„(Apache)์™€ ์œ„์—์„œ ๋งŒ๋“  Flask ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—ฐ๋™ํ•ด์ฃผ๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค. ์ด๋˜ํ•œ ์†Œ์Šค๋กœ ์„ค์น˜ํ•ด๋ณด์ž. (์œ„์™€ ๊ฐ™์€ ์ด์œ ๋กœ~)

- ๋‹ค์šด์„ ๋ฐ›๊ณ 
$ wget https://github.com/GrahamDumpleton/mod_wsgi/archive/3.5.tar.gz
- ์••์ถ•์„ ํ‘ผ ๋‹ค์Œ
$ tar -zxvf 3.5.tar.gz
- ํด๋”์— ๋“ค์–ด๊ฐ€์„œ
$ cd mod_wsgi-3.5
- ์•„ํŒŒ์น˜์˜ ๋นŒ๋“œํˆด์ธ apxs์˜ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ 
- ํ•„์ž์™€ ๊ฐ™์ด ๊ธฐ๋ณธ python ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๊บผ๋ผ๋ฉด ๊ผญ python๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค! (์ค‘์š”)
$ ./configure --with-apxs=/~~~/apps/apache/bin/apxs --with-python=/usr/bin/python3.6
- make ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ 
$ make
- ์„ค์น˜~
$ make install

์ด๋ ‡๊ฒŒ ์„ค์น˜๋ฅผ ํ•˜๋ฉด ์ž๋™์œผ๋กœ ์•„ํŒŒ์น˜ ํ•˜์œ„ /modules ํด๋”์•ˆ์— mod_wsgi.so ํŒŒ์ผ์ด ์ƒ๊ธด๋‹ค. (ํ•„์ž๋Š” ์ด๊ฒƒ๋„ ๋ชจ๋ฅด๊ณ  mod_wsgi.soํŒŒ์ผ์„ ๋‹ค์šด ๋ฐ›์œผ๋ ค๊ณ  ๊ตฌ๊ธ€๋ง์„ ๋ช‡์ผ์งธ ํ–ˆ๋˜ ๊ธฐ์–ต์ด ใ… )